mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-13 10:57:49 +00:00
Correct OBJ texture-coordinate indices (#8457)
The OBJ serializer wrote the normal index into the texture-coordinate slot of a v/vt/vn face (emitting v/vn/vn), so exported UVs were wrong. Track a separate texcoord counter and emit the correct vt index. Per review, the material lookup is left relying on ApplyDefaultMaterials (default on, and IfcConvert exposes no toggle to disable it) so an unstyled element is given the default style before triangulation and material_ids never contain the -1 no-style sentinel, matching how the Collada serializer already indexes its materials without an ad hoc guard. The earlier material_id >= 0 guard is therefore removed. Verified on OCC 7.9.2: a styled box exports its material, an unstyled box exports the injected DefaultMaterial (valid index, no out-of-bounds) on both the default and --generate-uvs paths, and the UV path now emits correct v/vt/vn indices. Generated with the assistance of an AI coding tool. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -33,6 +33,7 @@ WaveFrontOBJSerializer::WaveFrontOBJSerializer(const stream_or_filename& obj_fil
|
||||
, mtl_stream(mtl_filename)
|
||||
, vcount_total(1)
|
||||
, ncount_total(1)
|
||||
, uvcount_total(1)
|
||||
{
|
||||
obj_stream.stream << std::setprecision(settings.get<ifcopenshell::geometry::settings::FloatingPointDigits>().get());
|
||||
mtl_stream.stream << std::setprecision(settings.get<ifcopenshell::geometry::settings::FloatingPointDigits>().get());
|
||||
@@ -96,6 +97,7 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o)
|
||||
|
||||
size_t vcount = mesh.verts().size() / 3;
|
||||
size_t ncount = mesh.normals().size() / 3;
|
||||
size_t uvcount = mesh.uvs().size() / 2;
|
||||
|
||||
for (auto it = mesh.verts().begin(); it != mesh.verts().end();) {
|
||||
const double x = *(it++);
|
||||
@@ -151,9 +153,12 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o)
|
||||
const int n3 = v3 - vcount_total + ncount_total;
|
||||
|
||||
if (has_normals && has_uvs) {
|
||||
obj_stream.stream << "f " << v1 << "/" << n1 << "/" << n1 << " "
|
||||
<< v2 << "/" << n2 << "/" << n2 << " "
|
||||
<< v3 << "/" << n3 << "/" << n3 << "\n";
|
||||
const int t1 = v1 - vcount_total + uvcount_total;
|
||||
const int t2 = v2 - vcount_total + uvcount_total;
|
||||
const int t3 = v3 - vcount_total + uvcount_total;
|
||||
obj_stream.stream << "f " << v1 << "/" << t1 << "/" << n1 << " "
|
||||
<< v2 << "/" << t2 << "/" << n2 << " "
|
||||
<< v3 << "/" << t3 << "/" << n3 << "\n";
|
||||
} else if (has_normals) {
|
||||
obj_stream.stream << "f " << v1 << "//" << n1 << " "
|
||||
<< v2 << "//" << n2 << " "
|
||||
@@ -196,4 +201,5 @@ void WaveFrontOBJSerializer::write(const IfcGeom::TriangulationElement* o)
|
||||
|
||||
vcount_total += vcount;
|
||||
ncount_total += ncount;
|
||||
uvcount_total += uvcount;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class SERIALIZERS_API WaveFrontOBJSerializer : public WriteOnlyGeometrySerialize
|
||||
private:
|
||||
stream_or_filename obj_stream;
|
||||
stream_or_filename mtl_stream;
|
||||
size_t vcount_total, ncount_total;
|
||||
size_t vcount_total, ncount_total, uvcount_total;
|
||||
std::set<std::string> materials;
|
||||
public:
|
||||
WaveFrontOBJSerializer(const stream_or_filename& obj_filename, const stream_or_filename& mtl_filename, const ifcopenshell::geometry::Settings& geometry_settings, const ifcopenshell::geometry::SerializerSettings& settings, Logger& logger = Logger::Root());
|
||||
|
||||
Reference in New Issue
Block a user