Skip to content

Commit 5ef06dc

Browse files
committed
- Calculate normals (incorrectly for curved surfaces)
1 parent ac155dc commit 5ef06dc

File tree

3 files changed

+60
-8
lines changed

3 files changed

+60
-8
lines changed

src/ifcgeom/IfcGeomObjects.cpp

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
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>
@@ -34,19 +35,22 @@
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+
4751
int 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+
6369
IfcGeomObjects::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;
162206
Ifc2x3::IfcProduct::list entities;
163207
Ifc2x3::IfcProduct::it inner;
164208

165-
bool use_world_coords;
166209
int done;
167210
int total;
168211

src/ifcgeom/IfcGeomObjects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ namespace IfcGeomObjects {
8080
std::vector<float> verts;
8181
std::vector<int> faces;
8282
std::vector<int> edges;
83+
std::vector<float> normals;
8384
VertKeyMap welds;
8485

8586
IfcMesh(int i, const IfcGeom::ShapeList& s);

src/ifcobj/IfcObj.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ int main ( int argc, char** argv ) {
7272
do {
7373
const IfcGeomObjects::IfcGeomObject* o = IfcGeomObjects::Get();
7474
if ( o->type == "IfcSpace" || o->type == "IfcOpeningElement" ) continue;
75-
fObj << "o " << o->name << std::endl;
75+
const std::string name = o->name.empty() ? o->guid : o->name;
76+
fObj << "g " << name << std::endl;
77+
fObj << "s 1" << std::endl;
7678
fObj << "usemtl " << o->type << std::endl;
7779
materials.insert(o->type);
7880
const int vcount = o->mesh->verts.size() / 3;
@@ -82,11 +84,17 @@ int main ( int argc, char** argv ) {
8284
const float z = *(it++);
8385
fObj << "v " << x << " " << y << " " << z << std::endl;
8486
}
87+
for ( IfcGeomObjects::FltIt it = o->mesh->normals.begin(); it != o->mesh->normals.end(); ) {
88+
const float x = *(it++);
89+
const float y = *(it++);
90+
const float z = *(it++);
91+
fObj << "vn " << x << " " << y << " " << z << std::endl;
92+
}
8593
for ( IfcGeomObjects::IntIt it = o->mesh->faces.begin(); it != o->mesh->faces.end(); ) {
8694
const int v1 = *(it++)-vcount;
8795
const int v2 = *(it++)-vcount;
8896
const int v3 = *(it++)-vcount;
89-
fObj << "f " << v1 << " " << v2 << " " << v3 << std::endl;
97+
fObj << "f " << v1 << "//" << v1 << " " << v2 << "//" << v2 << " " << v3 << "//" << v3 << std::endl;
9098
}
9199

92100
const int progress = IfcGeomObjects::Progress() / 2;

0 commit comments

Comments
 (0)