mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
- Calculate normals (incorrectly for curved surfaces)
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user