1 // =============================================================================
2 // PROJECT CHRONO - http://projectchrono.org
3 //
4 // Copyright (c) 2014 projectchrono.org
5 // All rights reserved.
6 //
7 // Use of this source code is governed by a BSD-style license that can be found
8 // in the LICENSE file at the top level of the distribution and at
9 // http://projectchrono.org/license-chrono.txt.
10 //
11 // =============================================================================
12 // Authors: Alessandro Tasora
13 // =============================================================================
14 
15 #ifndef CHIRRCASCADEMESHTOOLS_H
16 #define CHIRRCASCADEMESHTOOLS_H
17 
18 
19 #include <irrlicht.h>
20 
21 #include "chrono_cascade/ChCascadeDoc.h"
22 #include "chrono_cascade/ChCascadeMeshTools.h"
23 
24 #include <TopoDS_Shape.hxx>
25 #include <TopoDS.hxx>
26 #include <TopoDS_HShape.hxx>
27 #include <TopoDS_Edge.hxx>
28 #include <TopoDS_Face.hxx>
29 #include <TopoDS_Compound.hxx>
30 #include <BRep_Builder.hxx>
31 #include <BRepTools.hxx>
32 #include <BRep_Tool.hxx>
33 #include <BRepBuilderAPI_MakeEdge.hxx>
34 #include <BRepBuilderAPI_MakeVertex.hxx>
35 #include <TopExp_Explorer.hxx>
36 #include <TopLoc_Location.hxx>
37 #include <TopoDS_Iterator.hxx>
38 #include <BRepAdaptor_HSurface.hxx>
39 #include <Poly.hxx>
40 #include <Poly_Connect.hxx>
41 #include <Poly_Triangle.hxx>
42 #include <Poly_Triangulation.hxx>
43 #include <TColgp_Array1OfDir.hxx>
44 #include <BRepMesh_IncrementalMesh.hxx>
45 #include <TShort_Array1OfShortReal.hxx>
46 
47 namespace irr {
48 namespace scene {
49 
50 /// @addtogroup cascade_module
51 /// @{
52 
53 /// Tools to convert an OpenCASCADE shapes into
54 /// 'Irrlicht' triangle meshes.
55 
56 class ChIrrCascadeMeshTools {
57   public:
58     //---------------------------------------------------------------------------------
59     // CONVERSION TO 'IRRLICHT' MESHES
60 
61     /// Function to use to convert a OpenCASCADE face into a Irrlicht mesh,
62     /// so that it can be used for visualizing it.
63 
64     static void fillIrrlichtMeshFromCascadeFace(scene::IMesh* pMesh,
65                                                 const TopoDS_Face& F,
66                                                 video::SColor clr = video::SColor(255, 255, 255, 255)) {
67         BRepAdaptor_Surface BS(F, Standard_False);
68         Handle(BRepAdaptor_HSurface) gFace = new BRepAdaptor_HSurface(BS);
69 
70         Handle(Poly_Triangulation) T;
71         TopLoc_Location theLocation;
72         T = BRep_Tool::Triangulation(F, theLocation);
73 
74         if (!T.IsNull()) {
75 
76             irr::scene::SMeshBuffer* buffer = new irr::scene::SMeshBuffer();
77 
78             buffer->Vertices.set_used(T->NbNodes());
79             buffer->Indices.set_used(T->NbTriangles() * 3);
80 
81             const TColgp_Array1OfPnt& mNodes = T->Nodes();
82 
83             Poly::ComputeNormals(T);
84             const TShort_Array1OfShortReal& mNormals = T->Normals();
85 
86 
87             int ivert = 0;
88             for (int j = mNodes.Lower(); j <= mNodes.Upper(); j++) {
89                 gp_Pnt p;
90                 gp_Dir pn;
91                 p = mNodes(j).Transformed(theLocation.Transformation());
92 
93                 chrono::ChVector<> pos(p.X(), p.Y(), p.Z());
94                 chrono::ChVector<> nor(mNormals((j-1)*3+1), mNormals((j-1)*3+2), mNormals((j-1)*3+3));
95                 if (F.Orientation() == TopAbs_REVERSED)
96                     nor*= -1;
97 
98                 buffer->Vertices[ivert] =
99                     irr::video::S3DVertex((irr::f32)pos.x(), (irr::f32)pos.y(), (irr::f32)pos.z(), (irr::f32)nor.x(),
100                                           (irr::f32)nor.y(), (irr::f32)nor.z(), clr, 0, 0);
101                 ivert++;
102             }
103 
104             int itri = 0;
105             for (int j = T->Triangles().Lower(); j <= T->Triangles().Upper(); j++) {
106                 Standard_Integer n[3];
107                 if (F.Orientation() == TopAbs_REVERSED)
108                     T->Triangles()(j).Get(n[0], n[2], n[1]);
109                 else
110                     T->Triangles()(j).Get(n[0], n[1], n[2]);
111                 int ia = (n[0]) - 1;
112                 int ib = (n[1]) - 1;
113                 int ic = (n[2]) - 1;
114 
115                 buffer->Indices[itri * 3 + 0] = ia;
116                 buffer->Indices[itri * 3 + 1] = ib;
117                 buffer->Indices[itri * 3 + 2] = ic;
118 
119                 itri++;
120             }
121 
122             irr::scene::SMesh* mmesh = dynamic_cast<irr::scene::SMesh*>(pMesh);
123             mmesh->addMeshBuffer(buffer);
124             mmesh->recalculateBoundingBox();
125         }
126 
127     }
128 
129     /// Function to use to convert a OpenCASCADE shape into a Irrlicht mesh,
130     /// so that it can be used for visualizing it.
131 
132     static void fillIrrlichtMeshFromCascade(scene::IMesh* pMesh,
133                                             const TopoDS_Shape& mshape,
134                                             double deflection = 1,
135                                             bool  relative_deflection = false,
136                                             double angulardeflection = 0.5,
137                                             video::SColor clr = video::SColor(255, 255, 255, 255)) {
138         BRepTools::Clean(mshape);
139         BRepMesh_IncrementalMesh M(mshape, deflection, relative_deflection , angulardeflection,true);
140         // GetLog() << "    ..tesselation done \n";
141 
142         // Loop on faces..
143         TopExp_Explorer ex;
144         for (ex.Init(mshape, TopAbs_FACE); ex.More(); ex.Next()) {
145             const TopoDS_Face& F = TopoDS::Face(ex.Current());
146             fillIrrlichtMeshFromCascadeFace(pMesh, F, clr);
147         }
148     }
149 };
150 
151 /// @} cascade_module
152 
153 }  // END_OF_NAMESPACE____
154 }  // END_OF_NAMESPACE____
155 
156 #endif  // END of header
157