- Calculate normals (incorrectly for curved surfaces)

This commit is contained in:
Thomas Krijnen
2011-10-27 20:42:51 +00:00
parent ac155dc810
commit 5ef06dca64
3 changed files with 60 additions and 8 deletions
+49 -6
View File
@@ -25,6 +25,7 @@
#include <gp_GTrsf2d.hxx>
#include <gp_Trsf.hxx>
#include <gp_Trsf2d.hxx>
#include <gp_Quaternion.hxx>
#include <TopoDS_Compound.hxx>
#include <BRep_Builder.hxx>
#include <BRepTools.hxx>
@@ -34,19 +35,22 @@
#include <Poly_Triangulation.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TShort_Array1OfShortReal.hxx>
#include <Poly_Array1OfTriangle.hxx>
#include <StdFail_NotDone.hxx>
#include <BRepGProp_Face.hxx>
#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<float,float>(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<std::pair<int,int> > edges_temp;
const TColgp_Array1OfPnt& nodes = tri->Nodes();
const TColgp_Array1OfPnt2d& uvs = tri->UVNodes();
std::vector<gp_XYZ> coords;
BRepGProp_Face prop(face);
std::map<int,int> 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;
+1
View File
@@ -80,6 +80,7 @@ namespace IfcGeomObjects {
std::vector<float> verts;
std::vector<int> faces;
std::vector<int> edges;
std::vector<float> normals;
VertKeyMap welds;
IfcMesh(int i, const IfcGeom::ShapeList& s);
+10 -2
View File
@@ -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;