gp_Vec normalToFaceAtUV(const TopoDS_Face& face, double u, double v) { BRepLProp_SLProps localSurfaceProps(1, 1e-6); localSurfaceProps.SetSurface(BRepAdaptor_Surface(face)); localSurfaceProps.SetParameters(u, v); if (localSurfaceProps.IsNormalDefined()) { const gp_Dir& nc = localSurfaceProps.Normal(); if (face.Orientation() == TopAbs_REVERSED) return gp_Vec(-nc.X(), -nc.Y(), -nc.Z()); else return gp_Vec(nc.X(), nc.Y(), nc.Z()); } return gp_Vec(0., 0., 1.); //return normalToSurfaceAtUV(BRep_Tool::Surface(face), u, v); }
void BuildShapeMesh(osg::Geode *geode, const TopoDS_Shape &shape, const osg::Vec4 &color, double deflection) { bool bSetNormal = true; osg::ref_ptr<deprecated_osg::Geometry> triGeom = new deprecated_osg::Geometry(); osg::ref_ptr<osg::Vec3Array> theVertices = new osg::Vec3Array(); osg::ref_ptr<osg::Vec3Array> theNormals = new osg::Vec3Array(); BRepMesh::Mesh(shape, deflection); TopExp_Explorer faceExplorer; for (faceExplorer.Init(shape, TopAbs_FACE); faceExplorer.More(); faceExplorer.Next()) { TopLoc_Location theLocation; TopoDS_Face theFace = TopoDS::Face(faceExplorer.Current()); if (theFace.IsNull()) continue; const Handle_Poly_Triangulation &theTriangulation = BRep_Tool::Triangulation(theFace, theLocation); BRepLProp_SLProps theProp(BRepAdaptor_Surface(theFace), 1, Precision::Confusion()); Standard_Integer nTriangles = theTriangulation->NbTriangles(); for (Standard_Integer i = 1; i <= nTriangles; i++) { const Poly_Triangle& theTriangle = theTriangulation->Triangles().Value(i); gp_Pnt theVertex1 = theTriangulation->Nodes().Value(theTriangle(1)); gp_Pnt theVertex2 = theTriangulation->Nodes().Value(theTriangle(2)); gp_Pnt theVertex3 = theTriangulation->Nodes().Value(theTriangle(3)); const gp_Pnt2d &theUV1 = theTriangulation->UVNodes().Value(theTriangle(1)); const gp_Pnt2d &theUV2 = theTriangulation->UVNodes().Value(theTriangle(2)); const gp_Pnt2d &theUV3 = theTriangulation->UVNodes().Value(theTriangle(3)); theVertex1.Transform(theLocation.Transformation()); theVertex2.Transform(theLocation.Transformation()); theVertex3.Transform(theLocation.Transformation()); // find the normal for the triangle mesh. gp_Vec V12(theVertex1, theVertex2); gp_Vec V13(theVertex1, theVertex3); gp_Vec theNormal = V12 ^ V13; gp_Vec theNormal1 = theNormal; gp_Vec theNormal2 = theNormal; gp_Vec theNormal3 = theNormal; if (theNormal.Magnitude() > Precision::Confusion()) { theNormal.Normalize(); theNormal1.Normalize(); theNormal2.Normalize(); theNormal3.Normalize(); } theProp.SetParameters(theUV1.X(), theUV1.Y()); if (theProp.IsNormalDefined()) { theNormal1 = theProp.Normal(); } theProp.SetParameters(theUV2.X(), theUV2.Y()); if (theProp.IsNormalDefined()) { theNormal2 = theProp.Normal(); } theProp.SetParameters(theUV3.X(), theUV3.Y()); if (theProp.IsNormalDefined()) { theNormal3 = theProp.Normal(); } if (theFace.Orientation() == TopAbs_REVERSED) { theNormal.Reverse(); theNormal1.Reverse(); theNormal2.Reverse(); theNormal3.Reverse(); } theVertices->push_back(osg::Vec3(theVertex1.X(), theVertex1.Y(), theVertex1.Z())); theVertices->push_back(osg::Vec3(theVertex2.X(), theVertex2.Y(), theVertex2.Z())); theVertices->push_back(osg::Vec3(theVertex3.X(), theVertex3.Y(), theVertex3.Z())); if (bSetNormal) { theNormals->push_back(osg::Vec3(theNormal1.X(), theNormal1.Y(), theNormal1.Z())); theNormals->push_back(osg::Vec3(theNormal2.X(), theNormal2.Y(), theNormal2.Z())); theNormals->push_back(osg::Vec3(theNormal3.X(), theNormal3.Y(), theNormal3.Z())); } else { theNormals->push_back(osg::Vec3(theNormal.X(), theNormal.Y(), theNormal.Z())); theNormals->push_back(osg::Vec3(theNormal.X(), theNormal.Y(), theNormal.Z())); theNormals->push_back(osg::Vec3(theNormal.X(), theNormal.Y(), theNormal.Z())); } } } triGeom->setVertexArray(theVertices.get()); triGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES, 0, theVertices->size())); triGeom->setNormalArray(theNormals); triGeom->setNormalBinding(deprecated_osg::Geometry::BIND_PER_VERTEX); osg::ref_ptr<osg::Vec4Array> colArr = new osg::Vec4Array(); colArr->push_back(color); triGeom->setColorArray(colArr, osg::Array::BIND_OVERALL); geode->addDrawable(triGeom); }