2525#include < gp_GTrsf2d.hxx>
2626#include < gp_Trsf.hxx>
2727#include < gp_Trsf2d.hxx>
28+ #include < gp_Quaternion.hxx>
2829#include < TopoDS_Compound.hxx>
2930#include < BRep_Builder.hxx>
3031#include < BRepTools.hxx>
3435#include < Poly_Triangulation.hxx>
3536#include < Poly_PolygonOnTriangulation.hxx>
3637#include < TColgp_Array1OfPnt.hxx>
38+ #include < TColgp_Array1OfPnt2d.hxx>
3739#include < TShort_Array1OfShortReal.hxx>
3840#include < Poly_Array1OfTriangle.hxx>
3941#include < StdFail_NotDone.hxx>
42+ #include < BRepGProp_Face.hxx>
4043
4144#include " ../ifcparse/IfcException.h"
4245#include " ../ifcgeom/IfcGeomObjects.h"
4346#include " ../ifcgeom/IfcGeom.h"
4447
4548// Welds vertices that belong to different faces
46- bool weld_vertices = true ;
49+ bool weld_vertices = false ;
50+
4751int IfcGeomObjects::IfcMesh::addvert (const gp_XYZ& p) {
4852 const float X = (float )p.X ();const float Y = (float )p.Y ();const float Z = (float )p.Z ();
49- int i = verts.size () / 3 ;
53+ int i = ( int ) verts.size () / 3 ;
5054 if ( weld_vertices ) {
5155 const VertKey key = VertKey (X,std::pair<float ,float >(Y,Z));
5256 VertKeyMap::const_iterator it = welds.find (key);
@@ -60,6 +64,8 @@ int IfcGeomObjects::IfcMesh::addvert(const gp_XYZ& p) {
6064 return i;
6165}
6266
67+ bool use_world_coords = false ;
68+
6369IfcGeomObjects::IfcMesh::IfcMesh (int i, const IfcGeom::ShapeList& shapes) {
6470 id = i;
6571
@@ -85,18 +91,41 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
8591 Handle_Poly_Triangulation tri = BRep_Tool::Triangulation (face,loc);
8692
8793 if ( ! tri.IsNull () ) {
94+
95+ // A 3x3 matrix to rotate the vertex normals
96+ const gp_Mat rotation_matrix = use_world_coords
97+ ? trsf.VectorialPart () * loc.Transformation ().VectorialPart ()
98+ : loc.Transformation ().VectorialPart ();
8899
89100 // Keep track of the number of times an edge is used
90101 // Manifold edges (i.e. edges used twice) are deemed invisible
91102 std::map<std::pair<int ,int >,int > edgecount;
92103 std::vector<std::pair<int ,int > > edges_temp;
93104
94105 const TColgp_Array1OfPnt& nodes = tri->Nodes ();
106+ const TColgp_Array1OfPnt2d& uvs = tri->UVNodes ();
107+ std::vector<gp_XYZ> coords;
108+ BRepGProp_Face prop (face);
95109 std::map<int ,int > dict;
110+
111+ // Vertex normals are only calculated if vertices are not welded
112+ const bool calculate_normals = ! weld_vertices;
113+
96114 for ( int i = 1 ; i <= nodes.Length (); ++ i ) {
97- gp_XYZ xyz = nodes (i).Transformed (loc).XYZ ();
98- trsf.Transforms (xyz);
99- dict[i] = addvert (xyz);
115+ coords.push_back (nodes (i).Transformed (loc).XYZ ());
116+ trsf.Transforms (*coords.rbegin ());
117+ dict[i] = addvert (*coords.rbegin ());
118+
119+ if ( calculate_normals ) {
120+ const gp_Pnt2d& uv = uvs (i);
121+ gp_Pnt p;
122+ gp_Vec normal_direction;
123+ prop.Normal (uv.X (),uv.Y (),p,normal_direction);
124+ gp_Dir normal = gp_Dir (normal_direction.XYZ () * rotation_matrix);
125+ normals.push_back ((float )normal.X ());
126+ normals.push_back ((float )normal.Y ());
127+ normals.push_back ((float )normal.Z ());
128+ }
100129 }
101130
102131 const Poly_Array1OfTriangle& triangles = tri->Triangles ();
@@ -105,6 +134,21 @@ IfcGeomObjects::IfcMesh::IfcMesh(int i, const IfcGeom::ShapeList& shapes) {
105134 if ( face.Orientation () == TopAbs_REVERSED )
106135 triangles (i).Get (n3,n2,n1);
107136 else triangles (i).Get (n1,n2,n3);
137+
138+ /* An alternative would be to calculate normals based
139+ * on the coordinates of the mesh vertices */
140+ /*
141+ const gp_XYZ pt1 = coords[n1-1];
142+ const gp_XYZ pt2 = coords[n2-1];
143+ const gp_XYZ pt3 = coords[n3-1];
144+ const gp_XYZ v1 = pt2-pt1;
145+ const gp_XYZ v2 = pt3-pt2;
146+ gp_Dir normal = gp_Dir(v1^v2);
147+ normals.push_back((float)normal.X());
148+ normals.push_back((float)normal.Y());
149+ normals.push_back((float)normal.Z());
150+ */
151+
108152 faces.push_back (dict[n1]);
109153 faces.push_back (dict[n2]);
110154 faces.push_back (dict[n3]);
@@ -162,7 +206,6 @@ IfcGeomObjects::IfcGeomObject* current_geom_obj;
162206Ifc2x3::IfcProduct::list entities;
163207Ifc2x3::IfcProduct::it inner;
164208
165- bool use_world_coords;
166209int done;
167210int total;
168211
0 commit comments