From 5ef06dca64530cd5c135f591ca27526a3e0695ee Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Thu, 27 Oct 2011 20:42:51 +0000 Subject: [PATCH] - Calculate normals (incorrectly for curved surfaces) --- src/ifcgeom/IfcGeomObjects.cpp | 55 ++++++++++++++++++++++++++++++---- src/ifcgeom/IfcGeomObjects.h | 1 + src/ifcobj/IfcObj.cpp | 12 ++++++-- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/src/ifcgeom/IfcGeomObjects.cpp b/src/ifcgeom/IfcGeomObjects.cpp index 993ac82a62..4b8f194c9b 100644 --- a/src/ifcgeom/IfcGeomObjects.cpp +++ b/src/ifcgeom/IfcGeomObjects.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -34,19 +35,22 @@ #include #include #include +#include #include #include #include +#include #include "../ifcparse/IfcException.h" #include "../ifcgeom/IfcGeomObjects.h" #include "../ifcgeom/IfcGeom.h" // Welds vertices that belong to different faces -bool weld_vertices = true; +bool weld_vertices = false; + int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) { const float X = (float)p.X();const float Y = (float)p.Y();const float Z = (float)p.Z(); - int i = verts.size() / 3; + int i = (int) verts.size() / 3; if ( weld_vertices ) { const VertKey key = VertKey(X,std::pair(Y,Z)); VertKeyMap::const_iterator it = welds.find(key); @@ -60,6 +64,8 @@ int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) { return i; } +bool use_world_coords = false; + IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) { id = i; @@ -85,6 +91,11 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) { Handle_Poly_Triangulation tri = BRep_Tool::Triangulation(face,loc); if ( ! tri.IsNull() ) { + + // A 3x3 matrix to rotate the vertex normals + const gp_Mat rotation_matrix = use_world_coords + ? trsf.VectorialPart() * loc.Transformation().VectorialPart() + : loc.Transformation().VectorialPart(); // Keep track of the number of times an edge is used // Manifold edges (i.e. edges used twice) are deemed invisible @@ -92,11 +103,29 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) { std::vector > edges_temp; const TColgp_Array1OfPnt& nodes = tri->Nodes(); + const TColgp_Array1OfPnt2d& uvs = tri->UVNodes(); + std::vector coords; + BRepGProp_Face prop(face); std::map dict; + + // Vertex normals are only calculated if vertices are not welded + const bool calculate_normals = ! weld_vertices; + for( int i = 1; i <= nodes.Length(); ++ i ) { - gp_XYZ xyz = nodes(i).Transformed(loc).XYZ(); - trsf.Transforms(xyz); - dict[i] = addvert(xyz); + coords.push_back(nodes(i).Transformed(loc).XYZ()); + trsf.Transforms(*coords.rbegin()); + dict[i] = addvert(*coords.rbegin()); + + if ( calculate_normals ) { + const gp_Pnt2d& uv = uvs(i); + gp_Pnt p; + gp_Vec normal_direction; + prop.Normal(uv.X(),uv.Y(),p,normal_direction); + gp_Dir normal = gp_Dir(normal_direction.XYZ() * rotation_matrix); + normals.push_back((float)normal.X()); + normals.push_back((float)normal.Y()); + normals.push_back((float)normal.Z()); + } } const Poly_Array1OfTriangle& triangles = tri->Triangles(); @@ -105,6 +134,21 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) { if ( face.Orientation() == TopAbs_REVERSED ) triangles(i).Get(n3,n2,n1); else triangles(i).Get(n1,n2,n3); + + /* An alternative would be to calculate normals based + * on the coordinates of the mesh vertices */ + /* + const gp_XYZ pt1 = coords[n1-1]; + const gp_XYZ pt2 = coords[n2-1]; + const gp_XYZ pt3 = coords[n3-1]; + const gp_XYZ v1 = pt2-pt1; + const gp_XYZ v2 = pt3-pt2; + gp_Dir normal = gp_Dir(v1^v2); + normals.push_back((float)normal.X()); + normals.push_back((float)normal.Y()); + normals.push_back((float)normal.Z()); + */ + faces.push_back(dict[n1]); faces.push_back(dict[n2]); faces.push_back(dict[n3]); @@ -162,7 +206,6 @@ IfcGeomObjects::IfcGeomObject* current_geom_obj; Ifc2x3::IfcProduct::list entities; Ifc2x3::IfcProduct::it inner; -bool use_world_coords; int done; int total; diff --git a/src/ifcgeom/IfcGeomObjects.h b/src/ifcgeom/IfcGeomObjects.h index c85a16baf7..6e28a71a93 100644 --- a/src/ifcgeom/IfcGeomObjects.h +++ b/src/ifcgeom/IfcGeomObjects.h @@ -80,6 +80,7 @@ namespace IfcGeomObjects { std::vector verts; std::vector faces; std::vector edges; + std::vector normals; VertKeyMap welds; IfcMesh(int i, const IfcGeom::ShapeList& s); diff --git a/src/ifcobj/IfcObj.cpp b/src/ifcobj/IfcObj.cpp index 68e4402161..a4fb1bb71a 100644 --- a/src/ifcobj/IfcObj.cpp +++ b/src/ifcobj/IfcObj.cpp @@ -72,7 +72,9 @@ int main ( int argc, char** argv ) { do { const IfcGeomObjects::IfcGeomObject* o = IfcGeomObjects::Get(); if ( o->type == "IfcSpace" || o->type == "IfcOpeningElement" ) continue; - fObj << "o " << o->name << std::endl; + const std::string name = o->name.empty() ? o->guid : o->name; + fObj << "g " << name << std::endl; + fObj << "s 1" << std::endl; fObj << "usemtl " << o->type << std::endl; materials.insert(o->type); const int vcount = o->mesh->verts.size() / 3; @@ -82,11 +84,17 @@ int main ( int argc, char** argv ) { const float z = *(it++); fObj << "v " << x << " " << y << " " << z << std::endl; } + for ( IfcGeomObjects::FltIt it = o->mesh->normals.begin(); it != o->mesh->normals.end(); ) { + const float x = *(it++); + const float y = *(it++); + const float z = *(it++); + fObj << "vn " << x << " " << y << " " << z << std::endl; + } for ( IfcGeomObjects::IntIt it = o->mesh->faces.begin(); it != o->mesh->faces.end(); ) { const int v1 = *(it++)-vcount; const int v2 = *(it++)-vcount; const int v3 = *(it++)-vcount; - fObj << "f " << v1 << " " << v2 << " " << v3 << std::endl; + fObj << "f " << v1 << "//" << v1 << " " << v2 << "//" << v2 << " " << v3 << "//" << v3 << std::endl; } const int progress = IfcGeomObjects::Progress() / 2;