How to get triangles vertices data in absolute coords for native OpenGL rendering?

Hi. For example, i have TopoDS_Shape and i have my own 3D engine on OpenGL. I need pure faces data, to put it into the VertexBuffer on GPU and draw it via OpenGl. (i don't use cascade viewer) I need:

1. Triangles collection of 3D model

2. 3 vertices data per each triangle (each triangle have 3 points :-) ) in absolute world coords

3. Normal vector to face for each vertex

4. good, if i will have UVs coords too :-)

 

So, guys, how to get pure vertices data?

 

 

 

Malcolm Revenge's picture

I solved my problem myself, as always :-)   I know that many newcomers will have similar questions, therefore I insert here the complete code:

std::vector<QVector3D> vertices;
    std::vector<QVector3D> normals;
    std::vector<QVector2D> uvs2;
    std::vector<unsigned int> indices;
    unsigned int idxCounter = 0;

 
    TopoDS_Shape shape = MakeBottle(100, 300, 20);

 
    Standard_Real aDeflection = 0.1;
    BRepMesh_IncrementalMesh(shape, 1);
    Standard_Integer aIndex = 1, nbNodes = 0;    
    TColgp_SequenceOfPnt aPoints, aPoints1;    
    for(TopExp_Explorer aExpFace(shape,TopAbs_FACE); aExpFace.More(); aExpFace.Next())
    {
        TopoDS_Face aFace = TopoDS::Face(aExpFace.Current());        
        TopAbs_Orientation faceOrientation = aFace.Orientation();

 
        TopLoc_Location aLocation;        
        Handle(Poly_Triangulation) aTr = BRep_Tool::Triangulation(aFace,aLocation);

 
        if(!aTr.IsNull())
        {
            const TColgp_Array1OfPnt& aNodes = aTr->Nodes();
            const Poly_Array1OfTriangle& triangles = aTr->Triangles();
            const TColgp_Array1OfPnt2d & uvNodes = aTr->UVNodes();

 
            TColgp_Array1OfPnt aPoints(1, aNodes.Length());
            for(Standard_Integer i = 1; i < aNodes.Length()+1; i++)
                aPoints(i) = aNodes(i).Transformed(aLocation);

 
            Standard_Integer nnn = aTr->NbTriangles();
            Standard_Integer nt,n1,n2,n3;

 
            for( nt = 1 ; nt < nnn+1 ; nt++)
            {
                triangles(nt).Get(n1,n2,n3);
                gp_Pnt aPnt1 = aPoints(n1);
                gp_Pnt aPnt2 = aPoints(n2);
                gp_Pnt aPnt3 = aPoints(n3);

 
                gp_Pnt2d uv1 = uvNodes(n1);
                gp_Pnt2d uv2 = uvNodes(n2);
                gp_Pnt2d uv3 = uvNodes(n3);

 
                QVector3D p1, p2, p3;
                if(faceOrientation == TopAbs_Orientation::TopAbs_FORWARD)
                {
                    p1 = QVector3D(aPnt1.X(), aPnt1.Y(), aPnt1.Z());
                    p2 = QVector3D(aPnt2.X(), aPnt2.Y(), aPnt2.Z());
                    p3 = QVector3D(aPnt3.X(), aPnt3.Y(), aPnt3.Z());
                }
                else
                {
                    p1 = QVector3D(aPnt3.X(), aPnt3.Y(), aPnt3.Z());
                    p2 = QVector3D(aPnt2.X(), aPnt2.Y(), aPnt2.Z());
                    p3 = QVector3D(aPnt1.X(), aPnt1.Y(), aPnt1.Z());
                }

 
                vertices.push_back(p1);
                vertices.push_back(p2);
                vertices.push_back(p3);

 
                QVector3D dir1 = p2 - p1;
                QVector3D dir2 = p3 - p1;
                QVector3D normal = QVector3D::crossProduct(dir1, dir2);

 
                normals.push_back(normal);
                normals.push_back(normal);
                normals.push_back(normal);

 
                uvs2.push_back(QVector2D(uv1.X(), uv1.Y()));
                uvs2.push_back(QVector2D(uv2.X(), uv2.Y()));
                uvs2.push_back(QVector2D(uv3.X(), uv3.Y()));

 
                indices.push_back(idxCounter++);
                indices.push_back(idxCounter++);
                indices.push_back(idxCounter++);
            }
        }
    }

And about boutle generation functions (from tuturial):

TopoDS_Shape RenderItem::MakeBottle(const Standard_Real myWidth, const Standard_Real myHeight, const Standard_Real myThickness)
{
    // Profile : Define Support Points
      gp_Pnt aPnt1(-myWidth / 2., 0, 0);
      gp_Pnt aPnt2(-myWidth / 2., -myThickness / 4., 0);
      gp_Pnt aPnt3(0, -myThickness / 2., 0);
      gp_Pnt aPnt4(myWidth / 2., -myThickness / 4., 0);
      gp_Pnt aPnt5(myWidth / 2., 0, 0);

 
      // Profile : Define the Geometry
      Handle(Geom_TrimmedCurve) anArcOfCircle = GC_MakeArcOfCircle(aPnt2,aPnt3,aPnt4);
      Handle(Geom_TrimmedCurve) aSegment1 = GC_MakeSegment(aPnt1, aPnt2);
      Handle(Geom_TrimmedCurve) aSegment2 = GC_MakeSegment(aPnt4, aPnt5);

 
      // Profile : Define the Topology
      TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aSegment1);
      TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(anArcOfCircle);
      TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(aSegment2);
      TopoDS_Wire aWire  = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3);

 
      // Complete Profile
      gp_Ax1 xAxis = gp::OX();
      gp_Trsf aTrsf;

 
      aTrsf.SetMirror(xAxis);
      BRepBuilderAPI_Transform aBRepTrsf(aWire, aTrsf);
      TopoDS_Shape aMirroredShape = aBRepTrsf.Shape();
      TopoDS_Wire aMirroredWire = TopoDS::Wire(aMirroredShape);

 
      BRepBuilderAPI_MakeWire mkWire;
      mkWire.Add(aWire);
      mkWire.Add(aMirroredWire);
      TopoDS_Wire myWireProfile = mkWire.Wire();

 
      // Body : Prism the Profile
      TopoDS_Face myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile);
      gp_Vec aPrismVec(0, 0, myHeight);
      TopoDS_Shape myBody = BRepPrimAPI_MakePrism(myFaceProfile, aPrismVec);

 
      // Body : Apply Fillets
      BRepFilletAPI_MakeFillet mkFillet(myBody);
      TopExp_Explorer anEdgeExplorer(myBody, TopAbs_EDGE);
      while(anEdgeExplorer.More()){
        TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExplorer.Current());
        //Add edge to fillet algorithm
        mkFillet.Add(myThickness / 12., anEdge);
        anEdgeExplorer.Next();
      }

 
      myBody = mkFillet.Shape();

 
      // Body : Add the Neck
      gp_Pnt neckLocation(0, 0, myHeight);
      gp_Dir neckAxis = gp::DZ();
      gp_Ax2 neckAx2(neckLocation, neckAxis);

 
      Standard_Real myNeckRadius = myThickness / 4.;
      Standard_Real myNeckHeight = myHeight / 10.;

 
      BRepPrimAPI_MakeCylinder MKCylinder(neckAx2, myNeckRadius, myNeckHeight);
      TopoDS_Shape myNeck = MKCylinder.Shape();

 
      myBody = BRepAlgoAPI_Fuse(myBody, myNeck);

 
      // Body : Create a Hollowed Solid
      TopoDS_Face   faceToRemove;
      Standard_Real zMax = -1;

 
      for(TopExp_Explorer aFaceExplorer(myBody, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next()){
        TopoDS_Face aFace = TopoDS::Face(aFaceExplorer.Current());
        // Check if <aFace> is the top face of the bottle’s neck
        Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
        if(aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane)){
          Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface);
          gp_Pnt aPnt = aPlane->Location();
          Standard_Real aZ   = aPnt.Z();
          if(aZ > zMax){
            zMax = aZ;
            faceToRemove = aFace;
          }
        }
      }

 
      TopTools_ListOfShape facesToRemove;
      facesToRemove.Append(faceToRemove);
      myBody = BRepOffsetAPI_MakeThickSolid(myBody, facesToRemove, -myThickness / 50, 1.e-3);
      // Threading : Create Surfaces
      Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);
      Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);

 
      // Threading : Define 2D Curves
      gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.);
      gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.);
      gp_Ax2d anAx2d(aPnt, aDir);

 
      Standard_Real aMajor = 2. * M_PI;
      Standard_Real aMinor = myNeckHeight / 10;

 
      Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);
      Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4);
      Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI);
      Handle(Geom2d_TrimmedCurve) anArc2 = new Geom2d_TrimmedCurve(anEllipse2, 0, M_PI);
      gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0);
      gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI);

 
      Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2);
      // Threading : Build Edges and Wires
      TopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1);
      TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1);
      TopoDS_Edge anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2);
      TopoDS_Edge anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment, aCyl2);
      TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1);
      TopoDS_Wire threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2, anEdge2OnSurf2);
      BRepLib::BuildCurves3d(threadingWire1);
      BRepLib::BuildCurves3d(threadingWire2);

 
      // Create Threading
      BRepOffsetAPI_ThruSections aTool(Standard_True);
      aTool.AddWire(threadingWire1);
      aTool.AddWire(threadingWire2);
      aTool.CheckCompatibility(Standard_False);

 
      TopoDS_Shape myThreading = aTool.Shape();

 
      // Building the Resulting Compound
      TopoDS_Compound aRes;
      BRep_Builder aBuilder;
      aBuilder.MakeCompound (aRes);
      aBuilder.Add (aRes, myBody);
      aBuilder.Add (aRes, myThreading);

 
      return aRes;
}

Just for a testig, i hardcoded this in PRO file (Qt project):

win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKernel
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKMath
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKService
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKV3d
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKBRep
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKIGES
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKSTL
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKVRML
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKSTEP
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKSTEPAttr
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKSTEP209
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKSTEPBase
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKGeomBase
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKGeomAlgo
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKG3d
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKG2d
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKXSBase
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKShHealing
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKHLR
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKTopAlgo
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKMesh
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKPrim
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKCDF
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKBool
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKBO
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKFillet
win32: LIBS += -L$$PWD/../../opencascade-7.1.0/win64/vc14/libd/ -lTKOffset

 
INCLUDEPATH += $$PWD/../../opencascade-7.1.0/inc
DEPENDPATH += $$PWD/../../opencascade-7.1.0/inc

OpenCASCADE was builded by mysalf via VisualStudio 2017

Guido van Hilst not specified's picture

I know that many newcomers will have similar questions, therefore I insert here the complete code:

I have made an online application(specially for newcomers :)) here you can see lot of code snippets, edit , and run it from the browser:

Have a look at:

MakeMesh

MakeBottle

Hope you enjoy it?

Guido

Malcolm Revenge's picture

Hope you enjoy it?

Hmm, good, but my 3D engine looks better :-)

You can watch some videos about my Mirage Engine there https://www.youtube.com/watch?v=fvaRIc73Oi8 or there https://www.youtube.com/watch?v=hwuvALgRNec or there :-)  https://www.youtube.com/watch?v=SNE1uOfCTMY

 But now I'm doing CAD system and I would like to adapt Open CASCADE to it. There's another problem, how do you get smoothed normals for each triangle vertex? If you calculate them yourself, you get a flat shading...

Malcolm Revenge's picture

Hope you enjoy it?

Hmm, good, but my 3D engine looks better :-)

You can watch some videos about my Mirage Engine there https://www.youtube.com/watch?v=fvaRIc73Oi8 or there https://www.youtube.com/watch?v=hwuvALgRNec or there :-)  https://www.youtube.com/watch?v=SNE1uOfCTMY

 But now I'm doing CAD system and I would like to adapt Open CASCADE to it. There's another problem, how do you get smoothed normals for each triangle vertex? If you calculate them yourself, you get a flat shading...

Guido van Hilst not specified's picture

Hi Malcolm,

Thank you for your complete code yes

I was wondering should UV points also not be reversed? ( if if(faceOrientation == TopAbs_Orientation::TopAbs_FORWARD))

It may be easier to swap the indices n1 and n3 ?

Best regards,

Guido

Malcolm Revenge's picture

I was wondering should UV points also not be reversed? ( if if(faceOrientation == TopAbs_Orientation::TopAbs_FORWARD))

It may be easier to swap the indices n1 and n3 ?

hehe  i don't know, I copied the code for the texture coordinates from one example, so far I have not even tested it :-)

I'm now interested in another problem at now (I'll figure out the textures later), how do I get smoothed normals for each vertex of the triangle? If you calculate the normal for the entire triangle and substitute it for each of the three points of the triangle, It looks very bad... 

Здесь русские есть? :-D

Attachments: 
Qr Qr's picture

Есть!

Kirill Gavrilov's picture

If you want smoothed normals (which contradicts to your first post) - why you don't use StdPrs_ShadedShape tool (or its source code if you really want using std::vector<QVector3D> instead of OCCT graphic arrays used by OpenGL viewer)?

Guido van Hilst not specified's picture

You have to combine all the normals of the triangles sharing a vertex.

Thus for each vertex get the "parent" triangles, and combine the normals.

I don't know if you use plain OpenGL?

Malcolm Revenge's picture

I don't know if you use plain OpenGL?

Yes, i use native OpenGL rendering.  Hmm... Do you understand what I am talking about? For smoothed shading, I need smoothed normals in order to correctly calculate PBR lighting ... I have enough 3 normals for each vertex of triangle, all other normals will be interpolated in an fragment  shader..

По поводу русских, это очень хорошо, что вы здесь есть, надо бы создать ветку для русских и общаться на нормальном языке :-)  Не, ну согласитесь, на русском языке мы сможем намного быстрее друг друга понять :-)

Qr Qr's picture

Русский -- это хорошо, но идея англоязычного общения состоит в том, что накапливается база знаний по каскейду, доступная всему миру. Подумайте о страждущих в Бразилии, Венесуэле и Иране. Они тоже хотят знать, как сглаживаются нормали! На русском, кстати, есть отличный форум http://cccp3d.ru/ Там можно отрастить веточку.

Guido van Hilst not specified's picture

Согласен -)

Guido van Hilst not specified's picture

No Rusian here, only Google translate :-)

Malcolm Revenge's picture

So... guys, how to get smothed normals for each vertex of triangle? 

Guido van Hilst not specified's picture

You need to combine the normal of each triangle sharing the vertex.

See:http://www.opengl-tutorial.org/beginners-tutorials/tutorial-8-basic-shad...

vertex v1, v2, v3, ....
triangle tr1, tr2, tr3 // all share vertex v1
v1.normal = normalize( tr1.normal + tr2.normal + tr3.normal )

So you need a normal for each vertex, then OpenGL can smooth them with shader.

Malcolm Revenge's picture

You need to combine the normal of each triangle sharing the vertex.

I know it :-) But for this, i need to get different directions of normals for each vertex (smoothed normals), at now, i calc only one normal for my triangle trough cross product of (p2-1, p3-p1).  3DS max, when export normals, he exporting smoothed normals on OBJ files, but how i can to enable this in OCC? 

Guido van Hilst not specified's picture

You get best results if you split the mesh by faces. Then sharp edges remain sharp if you combine the normals.

Guido van Hilst not specified's picture

you can have only one normal attribute per vertex in OpenGL

i calc only one normal for my triangle trough cross product of (p2-1, p3-p1).

 Use the normals you have calculate for each triangle.

3DS max is doing the same when exporting

Malcolm Revenge's picture

guys, for smoothed normals, i need adjacent triangles date to calc mind normals. I can calc it by mysalf in geom shader, but maybe CCT do it?

Guido van Hilst not specified's picture

 I have modified your example so you have the smoothed normals for each vertex.

    std::vector<QVector3D> vertices;
    std::vector<QVector3D> normals;
    std::map<int, QVector3D > verticesNormals;
    std::vector<QVector2D> uvs2;
    std::vector<unsigned int> indices;
    unsigned int idxCounter = 0;

 
    TopoDS_Shape shape = MakeBottle(100, 300, 20);

 
    Standard_Real aDeflection = 0.1;
    BRepMesh_IncrementalMesh(shape, 1);
    Standard_Integer aIndex = 1, nbNodes = 0;    
    TColgp_SequenceOfPnt aPoints, aPoints1;    

    for(TopExp_Explorer aExpFace(shape,TopAbs_FACE); aExpFace.More(); aExpFace.Next())
    {
        TopoDS_Face aFace = TopoDS::Face(aExpFace.Current());        
        TopAbs_Orientation faceOrientation = aFace.Orientation();
 
        TopLoc_Location aLocation;        
        Handle(Poly_Triangulation) aTr = BRep_Tool::Triangulation(aFace,aLocation);

         if(!aTr.IsNull())
        {
            const TColgp_Array1OfPnt& aNodes = aTr->Nodes();
            const Poly_Array1OfTriangle& triangles = aTr->Triangles();
            const TColgp_Array1OfPnt2d & uvNodes = aTr->UVNodes();

 
            TColgp_Array1OfPnt aPoints(1, aNodes.Length());
            for(Standard_Integer i = 1; i < aNodes.Length()+1; i++)
                aPoints(i) = aNodes(i).Transformed(aLocation);

 
            Standard_Integer nnn = aTr->NbTriangles();
            Standard_Integer nt,n1,n2,n3;
 
            for( nt = 1 ; nt < nnn+1 ; nt++)
            {
                triangles(nt).Get(n1,n2,n3);


		        if (faceOrientation != TopAbs_Orientation::TopAbs_FORWARD)
		        {
		           int tmp = n1;
		           n1 = n3;
		           n3 = tmp;
	            }

                gp_Pnt aPnt1 = aPoints(n1);
                gp_Pnt aPnt2 = aPoints(n2);
                gp_Pnt aPnt3 = aPoints(n3);

 
                gp_Pnt2d uv1 = uvNodes(n1);
                gp_Pnt2d uv2 = uvNodes(n2);
                gp_Pnt2d uv3 = uvNodes(n3);
 
                QVector3D p1, p2, p3;
			              
		        p1 = QVector3D(aPnt1.X(), aPnt1.Y(), aPnt1.Z());
		        p2 = QVector3D(aPnt2.X(), aPnt2.Y(), aPnt2.Z());
		        p3 = QVector3D(aPnt3.X(), aPnt3.Y(), aPnt3.Z());

                QVector3D dir1 = p2 - p1;
                QVector3D dir2 = p3 - p1;
                QVector3D normal = QVector3D::crossProduct(dir1, dir2);


                //Add the vertices normals, see below
		        AddNormal(verticesNormals, normal, n1);
		        AddNormal(verticesNormals, normal, n2);
		        AddNormal(verticesNormals, normal, n3);


 
                vertices.push_back(p1);
                vertices.push_back(p2);
                vertices.push_back(p3);

 
              
                
 	        
                normals.push_back(normal);
                normals.push_back(normal);
                normals.push_back(normal);

 
                uvs2.push_back(QVector2D(uv1.X(), uv1.Y()));
                uvs2.push_back(QVector2D(uv2.X(), uv2.Y()));
                uvs2.push_back(QVector2D(uv3.X(), uv3.Y()));

 
                indices.push_back(idxCounter++);
                indices.push_back(idxCounter++);
                indices.push_back(idxCounter++);
            }
        }
    }
void AddNormal(std::map<int, QVector3D >& normals, QVector3D& normal, int index)
{
    //maybe only normals[index] = normals[index] + normal; is sufficiant?

	std::map<int, QVector3D >::iterator it = normals.find(index);
	if (it == verticesNormals.end())
	{
		normals.insert(std::pair<int, QVector3D>(index, QVector3D()));
	}

	normals[index] = normals[index] + normal;
}
Guido van Hilst not specified's picture

The problem with the code above is that you put same points multiple times in the std::vector.

You should really make a mesh per face,map same vertices, and not one mesh for the shape. 

Malcolm Revenge's picture

Guido, your code is wrong.

Do you understand, that we need adjacency  triangles, to cacl smoothed normals?

Guido van Hilst not specified's picture

Malcolm, I have done smoothing  : MakeBottle

Guido van Hilst not specified's picture

 Another option would be, if you don't want to map vertices to triangles, to use GeomAPI_ProjectPointOnSurf to project point on the surface and get the normal?

 BRepTools::UVBounds(face,  u1,  u2,  v1,  v2);
 const Handle<Geom_Surface>& surface  = BRep_Tool::Surface(face);
 GeomAPI_ProjectPointOnSurf projector;
 projector.Init(surface, u1, u2, v1, v2);
Malcolm Revenge's picture

So guys...any new ideas, how to take smoothed normals of the shape? laugh