Integration of OCCT 6.5.0 from SVN
[occt.git] / src / VrmlConverter / VrmlConverter_ShadedShape.cxx
diff --git a/src/VrmlConverter/VrmlConverter_ShadedShape.cxx b/src/VrmlConverter/VrmlConverter_ShadedShape.cxx
new file mode 100755 (executable)
index 0000000..400c2c3
--- /dev/null
@@ -0,0 +1,453 @@
+#include <VrmlConverter_Drawer.hxx>
+#include <VrmlConverter_ShadedShape.hxx>
+#include <Vrml_Normal.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS.hxx>
+#include <TopAbs.hxx>
+#include <Poly_Connect.hxx>
+#include <TColgp_Array1OfDir.hxx>
+#include <TColgp_HArray1OfVec.hxx>
+#include <Poly_Triangle.hxx>
+#include <Poly_Triangulation.hxx>
+#include <BRepTools.hxx>
+#include <BRepMesh.hxx>
+#include <BRep_Tool.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopLoc_Location.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <Poly_Array1OfTriangle.hxx>
+#include <Vrml_IndexedFaceSet.hxx>
+#include <Vrml_Coordinate3.hxx>
+#include <BRepBndLib.hxx>
+#include <Bnd_Box.hxx>
+#include <math.hxx>
+#include <TColStd_HArray1OfInteger.hxx>
+#include <Geom_Surface.hxx>
+#include <CSLib_DerivativeStatus.hxx>
+#include <CSLib_NormalStatus.hxx>
+#include <CSLib.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <TColgp_Array1OfPnt2d.hxx>
+#include <Precision.hxx>
+#include <Vrml_Material.hxx>
+#include <VrmlConverter_ShadingAspect.hxx>
+#include <Vrml_ShapeHints.hxx>
+#include <Vrml_MaterialBindingAndNormalBinding.hxx>
+#include <Vrml_NormalBinding.hxx>
+#include <Vrml_Separator.hxx>
+#include <Vrml_NormalBinding.hxx>
+
+
+//=========================================================================
+// function: Add
+// purpose
+//=========================================================================
+void VrmlConverter_ShadedShape::Add( Standard_OStream& anOStream, 
+                                     const TopoDS_Shape& aShape,
+                                     const Handle(VrmlConverter_Drawer)& aDrawer )
+  {
+
+  // here the triangulation is computed on the whole shape
+  //  if it does not yet exist
+
+
+    Standard_Real theRequestedDeflection;
+    if(aDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE)   // TOD_RELATIVE, TOD_ABSOLUTE
+      {
+       Bnd_Box box;
+       BRepBndLib::AddClose(aShape, box);
+
+       Standard_Real  Xmin, Xmax, Ymin, Ymax, Zmin, Zmax, diagonal;
+       box.Get( Xmin, Ymin, Zmin, Xmax, Ymax, Zmax );
+       if (!(box.IsOpenXmin() || box.IsOpenXmax() ||
+             box.IsOpenYmin() || box.IsOpenYmax() ||
+             box.IsOpenZmin() || box.IsOpenZmax()))
+           {
+
+           diagonal = Sqrt ((Xmax - Xmin)*( Xmax - Xmin) + ( Ymax - Ymin)*( Ymax - Ymin) + ( Zmax - Zmin)*( Zmax - Zmin));
+           diagonal = Max(diagonal, Precision::Confusion());
+           theRequestedDeflection = aDrawer->DeviationCoefficient() * diagonal;      
+         }
+       else
+         {
+           diagonal =1000000.;
+           theRequestedDeflection = aDrawer->DeviationCoefficient() * diagonal;  
+         }
+//     cout << "diagonal = "<< diagonal << endl;
+//     cout << "theRequestedDeflection = "<< theRequestedDeflection << endl;
+
+      }
+    else 
+      {
+       theRequestedDeflection = aDrawer->MaximalChordialDeviation(); 
+      }
+
+    if (!BRepTools::Triangulation(aShape,theRequestedDeflection)) 
+      BRepMesh::Mesh(aShape,theRequestedDeflection); // computes and save the triangulation in the face.
+  
+  
+  Handle(Poly_Triangulation) T;
+  TopLoc_Location theLocation;
+  Standard_Integer i, j, k, decal, nnv, EI;
+  
+  Standard_Integer t[3], n[3];
+  gp_Pnt p;
+  TopExp_Explorer ex;
+
+  // counting phasis. This phasis will count the valid triangle
+  // and the vertices to allocate the correct size for the arrays: 
+  
+  Standard_Integer nbTriangles = 0, nbVertices = 0;
+  
+  Standard_Integer nt, nnn, n1, n2, n3;
+    
+  // iterating on each face of the shape:
+  for (ex.Init(aShape, TopAbs_FACE); ex.More(); ex.Next()) {  
+    // getting the face:
+    const TopoDS_Face& F = TopoDS::Face(ex.Current());
+    // getting the triangulation of the face. The triangulation may not exist:
+    T = BRep_Tool::Triangulation(F, theLocation);
+      // number of triangles:
+    if (T.IsNull()) continue; //smh 
+      nnn = T->NbTriangles();            
+    
+    const TColgp_Array1OfPnt& Nodes = T->Nodes(); 
+    // getting a triangle. It is  a triplet of indices in the node table:      
+    const Poly_Array1OfTriangle& triangles = T->Triangles(); 
+    
+    // Taking the nodes of the triangle, taking into account the orientation
+    // of the triangle.
+    for (nt = 1; nt <= nnn; nt++) {
+      if (F.Orientation() == TopAbs_REVERSED) 
+       triangles(nt).Get(n1,n3,n2);
+      else 
+       triangles(nt).Get(n1,n2,n3);
+      
+      const gp_Pnt& P1 = Nodes(n1);
+      const gp_Pnt& P2 = Nodes(n2);
+      const gp_Pnt& P3 = Nodes(n3);
+      // controlling whether the triangle correct from a 3d point of 
+      // view: (the triangle may exist in the UV space but the
+      // in the 3d space a dimension is null for example)
+      gp_Vec V1(P1,P2);
+      if (V1.SquareMagnitude() > 1.e-10) {
+       gp_Vec V2(P2,P3);
+       if (V2.SquareMagnitude() > 1.e-10) {
+         gp_Vec V3(P3,P1);
+         if (V3.SquareMagnitude() > 1.e-10) {
+           V1.Normalize();
+           V2.Normalize();
+           V1.Cross(V2);
+           if (V1.SquareMagnitude() > 1.e-10) {
+             nbTriangles++;
+             }
+         }
+       }
+      }
+    }
+    nbVertices += T->NbNodes();
+  }      
+
+//     cout << "nbTriangles = "<< nbTriangles << endl;
+//     cout  << "nbVertices = "<< nbVertices << endl << endl;  
+
+//----------------------------
+  // now we are going to iterate again to build graphic data from the triangle.   
+  if (nbVertices > 2 && nbTriangles > 0) {
+    // allocating the graphic arrays.
+
+     Handle(VrmlConverter_ShadingAspect) SA = new VrmlConverter_ShadingAspect;
+     SA = aDrawer->ShadingAspect();
+
+     Handle(TColgp_HArray1OfVec) HAV1 = new TColgp_HArray1OfVec(1, nbVertices);
+     Handle(TColgp_HArray1OfVec) HAV2 = new TColgp_HArray1OfVec(1, nbVertices);
+     
+     gp_Vec V, VV;
+
+     Handle(TColStd_HArray1OfInteger) HAI1 = new TColStd_HArray1OfInteger(1,4*nbTriangles);
+     Handle(TColStd_HArray1OfInteger) HAI3 = new TColStd_HArray1OfInteger(1,(nbVertices/3*4+nbVertices%3));
+     Handle(TColStd_HArray1OfInteger) HAI2 = new TColStd_HArray1OfInteger(1,1);
+     Handle(TColStd_HArray1OfInteger) HAI4 = new TColStd_HArray1OfInteger(1,1);
+
+       HAI2->SetValue (1,-1);
+       HAI4->SetValue (1,-1);
+
+// !! Specialize HAI2 -  materialIndex  HAI4 - textureCoordinateIndex
+
+    EI = 1;
+    nnv = 1;
+
+    for (ex.Init(aShape, TopAbs_FACE); ex.More(); ex.Next()) {
+      const TopoDS_Face& F = TopoDS::Face(ex.Current());
+      T = BRep_Tool::Triangulation(F, theLocation);
+      if (!T.IsNull()) {
+       Poly_Connect pc(T);
+       
+       // 1 -  Building HAV1 -  array of all XYZ of nodes for Vrml_Coordinate3 from the triangles
+       //            and HAV2 - array of all normals of nodes for Vrml_Normal
+       
+       const TColgp_Array1OfPnt& Nodes = T->Nodes();
+       TColgp_Array1OfDir NORMAL(Nodes.Lower(), Nodes.Upper());
+
+         decal = nnv-1;
+       
+       for (j= Nodes.Lower(); j<= Nodes.Upper(); j++) {
+         p = Nodes(j).Transformed(theLocation.Transformation());
+
+          V.SetX(p.X()); V.SetY(p.Y()); V.SetZ(p.Z());
+          HAV1->SetValue(nnv,V);
+
+         if(SA->HasNormals())
+           {
+               // to compute the normal.
+             ComputeNormal(F, pc, NORMAL);
+
+             VV.SetX(NORMAL(j).X());  VV.SetY(NORMAL(j).Y());  VV.SetZ(NORMAL(j).Z());
+             HAV2->SetValue(nnv,VV);
+           }
+          nnv++;
+       }
+       
+       // 2 -   Building HAI1 - array of indexes of all triangles and
+       //        HAI3 - array of indexes of all normales  for Vrml_IndexedFaceSet
+        nbTriangles = T->NbTriangles();
+       const Poly_Array1OfTriangle& triangles = T->Triangles();        
+        for (i = 1; i <= nbTriangles; i++) {
+          pc.Triangles(i,t[0],t[1],t[2]);
+          if (F.Orientation() == TopAbs_REVERSED) 
+            triangles(i).Get(n[0],n[2],n[1]);
+          else 
+            triangles(i).Get(n[0],n[1],n[2]);
+          const gp_Pnt& P1 = Nodes(n[0]);
+          const gp_Pnt& P2 = Nodes(n[1]);
+          const gp_Pnt& P3 = Nodes(n[2]);
+          gp_Vec V1(P1,P2);
+          if (V1.SquareMagnitude() > 1.e-10) {
+            gp_Vec V2(P2,P3);
+            if (V2.SquareMagnitude() > 1.e-10) {
+              gp_Vec V3(P3,P1);
+              if (V3.SquareMagnitude() > 1.e-10) {
+               V1.Normalize();
+               V2.Normalize();
+               V1.Cross(V2);
+               if (V1.SquareMagnitude() > 1.e-10) {
+                 for (j = 0; j < 3; j++) {
+                  
+                   HAI1->SetValue(EI, n[j]+decal-1);   // array of indexes of all triangles
+                   EI++;
+                 }
+
+                 HAI1->SetValue(EI, -1);                   
+                 EI++;           
+               }
+             }
+           }
+         }
+       }
+      }
+    }
+  
+
+     if(SA->HasNormals())
+       {
+        j=1;
+        for (i=HAI3->Lower(); i <= HAI3->Upper(); i++)
+          {
+            k = i % 4;
+            if (k == 0)
+              {
+                HAI3->SetValue(i, -1);
+                j++;
+              }
+            else
+              {
+                HAI3->SetValue(i, i-j);   
+              }
+          }
+       }
+
+//-----------------------------
+/*
+  cout  << " ******************** " << endl;  
+     cout  << " Array HAV1 - Coordinare3 " << endl;  
+
+     for ( i=HAV1->Lower(); i <= HAV1->Upper(); i++ )
+       {
+        cout << HAV1->Value(i).X() << " " << HAV1->Value(i).Y()<< " " << HAV1->Value(i).Z() << endl; 
+       }
+
+     if(SA->HasNormals())
+       {
+
+        cout  << " ******************** " << endl;         
+        cout  << " Array HAV2 - Normals " << endl;  
+
+        for ( i=HAV2->Lower(); i <= HAV2->Upper(); i++ )
+          {
+            cout << HAV2->Value(i).X() << " " << HAV2->Value(i).Y()<< " " << HAV2->Value(i).Z() << endl; 
+          }
+
+        cout  << " ******************** " << endl;  
+        cout  << " Array HAI3 - normalIndex " << endl;  
+
+        for ( i=HAI3->Lower(); i <= HAI3->Upper(); i++ )
+          {
+            cout << HAI3->Value(i) << endl;
+          }
+
+       }
+
+     cout  << " ******************** " << endl;         
+     cout  << " Array HAI1 - coordIndex " << endl;  
+       
+     for ( i=HAI1->Lower(); i <= HAI1->Upper(); i++ )
+       {
+        cout << HAI1->Value(i) << endl;
+       }
+   
+     cout  << " ******************** " << endl;       
+*/
+//----------------------------
+
+// creation of Vrml objects
+
+     Vrml_ShapeHints  SH; 
+     SH = SA->ShapeHints();
+
+     if(SA->HasNormals())
+       {
+// Separator 1 {
+     Vrml_Separator SE1;
+     SE1.Print(anOStream);
+// Material
+  if (SA->HasMaterial()){
+
+     Handle(Vrml_Material) M;
+     M = SA->FrontMaterial();
+
+     M->Print(anOStream);
+   }
+
+// Coordinate3
+     Handle(Vrml_Coordinate3)  C3 = new Vrml_Coordinate3(HAV1);
+     C3->Print(anOStream);
+// ShapeHints
+     SH.Print(anOStream);
+// NormalBinding
+     Vrml_MaterialBindingAndNormalBinding MBNB1 = Vrml_PER_VERTEX_INDEXED;
+     Vrml_NormalBinding   NB(MBNB1);
+     NB.Print(anOStream);
+// Separator 2 {
+     Vrml_Separator SE2;
+     SE2.Print(anOStream);
+// Normal
+     Vrml_Normal  N(HAV2);
+     N.Print(anOStream);
+// IndexedFaceSet
+     Vrml_IndexedFaceSet  IFS;
+     IFS.SetCoordIndex(HAI1);
+     IFS.SetNormalIndex(HAI3);
+     IFS.Print(anOStream);
+// Separator 2 }     
+     SE2.Print(anOStream);
+// Separator 1 }
+     SE1.Print(anOStream);
+        }
+     else 
+       { 
+// Separator 1 {
+     Vrml_Separator SE1;
+     SE1.Print(anOStream);
+// Material
+  if (SA->HasMaterial()){
+
+     Handle(Vrml_Material) M;
+     M = SA->FrontMaterial();
+
+     M->Print(anOStream);
+   }
+// Coordinate3
+     Handle(Vrml_Coordinate3)  C3 = new Vrml_Coordinate3(HAV1);
+     C3->Print(anOStream);
+// ShapeHints
+     SH.Print(anOStream);
+// IndexedFaceSet
+     Vrml_IndexedFaceSet  IFS;
+     IFS.SetCoordIndex(HAI1);
+     IFS.Print(anOStream);
+// Separator 1 }
+     SE1.Print(anOStream);
+       }
+  }
+}
+
+
+//--------- Notes -------------
+
+// the necessary of calculation of Normals and Textures must be define in Drawer
+// likes tolerance
+
+//---------- End on notes ------------
+
+
+
+//----------------------------
+// Computing the normal
+//-----------------------------
+
+void VrmlConverter_ShadedShape::ComputeNormal(const TopoDS_Face& aFace, 
+                                             Poly_Connect& pc, 
+                                             TColgp_Array1OfDir& Nor)
+{
+  const Handle(Poly_Triangulation)& T = pc.Triangulation();
+  BRepAdaptor_Surface S;
+  Standard_Boolean hasUV = T->HasUVNodes();
+  Standard_Integer i;
+  TopLoc_Location l;
+  Handle(Geom_Surface) GS = BRep_Tool::Surface(aFace, l);
+
+  if (hasUV && !GS.IsNull()) {
+    Standard_Boolean OK = Standard_True;
+    gp_Vec D1U,D1V;
+    gp_Vec D2U,D2V,D2UV;
+    gp_Pnt P;
+    Standard_Real U, V;
+    CSLib_DerivativeStatus Status;
+    CSLib_NormalStatus NStat;
+    S.Initialize(aFace);
+    const TColgp_Array1OfPnt2d& UVNodes = T->UVNodes();
+    for (i = UVNodes.Lower(); i <= UVNodes.Upper(); i++) {
+      U = UVNodes(i).X();
+      V = UVNodes(i).Y();
+      S.D1(U,V,P,D1U,D1V);
+      CSLib::Normal(D1U,D1V,Precision::Angular(),Status,Nor(i));
+      if (Status != CSLib_Done) {
+       S.D2(U,V,P,D1U,D1V,D2U,D2V,D2UV);
+       CSLib::Normal(D1U,D1V,D2U,D2V,D2UV,Precision::Angular(),OK,NStat,Nor(i));
+      }
+      if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse();
+    }
+  }
+  else {
+    const TColgp_Array1OfPnt& Nodes = T->Nodes();
+    Standard_Integer n[3];
+    const Poly_Array1OfTriangle& triangles = T->Triangles();
+
+    for (i = Nodes.Lower(); i <= Nodes.Upper(); i++) {
+      gp_XYZ eqPlan(0, 0, 0);
+      for (pc.Initialize(i);  pc.More(); pc.Next()) {
+       triangles(pc.Value()).Get(n[0], n[1], n[2]);
+       gp_XYZ v1(Nodes(n[1]).Coord()-Nodes(n[0]).Coord());
+       gp_XYZ v2(Nodes(n[2]).Coord()-Nodes(n[1]).Coord());
+       eqPlan += (v1^v2).Normalized();
+      }
+      Nor(i) = gp_Dir(eqPlan);
+      if (aFace.Orientation() == TopAbs_REVERSED) (Nor(i)).Reverse();
+    }
+  }
+}
+
+