// File: Prs3d_ShadedShape.gxx // Created: Thu Sep 23 18:47:22 1993 // Author: Jean-Louis FRENKEL // //#define BUC60488//GG_081199 Enable the SuppressBackface() ShadingAspect attribute #define G005 //ATS,GG 04/01/01 Use ArrayOfPrimitives instead Sets of primitives // for performance improvment #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef G005 #include #endif #define MAX2(X, Y) ( Abs(X) > Abs(Y)? Abs(X) : Abs(Y) ) #define MAX3(X, Y, Z) ( MAX2 ( MAX2(X,Y) , Z) ) static Standard_Real GetDeflection(const anyShape& aShape, const Handle(Prs3d_Drawer)& aDrawer) { Standard_Real aDeflection = aDrawer->MaximalChordialDeviation(); if (aDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE) { Bnd_Box B; BRepBndLib::Add(aShape, B, Standard_False); if ( ! B.IsVoid() ) { Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax; B.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); aDeflection = MAX3( aXmax-aXmin , aYmax-aYmin , aZmax-aZmin) * aDrawer->DeviationCoefficient()*4; } } return aDeflection; } static Standard_Boolean ShadeFromShape(const anyShape& aShape, const Standard_Real /*defle*/, const Standard_Boolean /*share*/, const Handle (Prs3d_Presentation)& aPresentation, const Handle (Prs3d_Drawer)& aDrawer) { anyShadedShapeTool SST; Handle(Poly_Triangulation) T; TopLoc_Location loc; gp_Pnt p; Standard_Integer i,j,k,decal ; Standard_Integer t[3], n[3]; Standard_Integer nbTriangles = 0, nbVertices = 0; // precision for compare square distances double dPreci = Precision::Confusion()*Precision::Confusion(); if ( !aDrawer->ShadingAspectGlobal() ) { Handle(Graphic3d_AspectFillArea3d) Asp = aDrawer->ShadingAspect()->Aspect(); if(anyShadedShapeTool::IsClosed(aShape)) { Asp->SuppressBackFace(); } else { Asp->AllowBackFace(); } Prs3d_Root::CurrentGroup(aPresentation)->SetPrimitivesAspect(Asp); } #ifdef G005 if( Graphic3d_ArrayOfPrimitives::IsEnable() ) { for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) { const anyTopFace& F = SST.CurrentFace(); T = SST.Triangulation(F, loc); if (!T.IsNull()) { nbTriangles += T->NbTriangles(); nbVertices += T->NbNodes(); } } if (nbVertices > 2 && nbTriangles > 0) { Handle(Graphic3d_ArrayOfTriangles) parray = new Graphic3d_ArrayOfTriangles(nbVertices,3*nbTriangles, Standard_True,Standard_False,Standard_False,Standard_True); for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) { const anyTopFace& F = SST.CurrentFace(); T = SST.Triangulation(F, loc); if (!T.IsNull()) { const gp_Trsf& trsf = loc.Transformation(); Poly_Connect pc(T); // Extracts vertices & normals from nodes const TColgp_Array1OfPnt& Nodes = T->Nodes(); TColgp_Array1OfDir NORMAL(Nodes.Lower(), Nodes.Upper()); SST.Normal(F, pc, NORMAL); decal = parray->VertexNumber(); for (i= Nodes.Lower(); i<= Nodes.Upper(); i++) { p = Nodes(i); if( !loc.IsIdentity() ) { p.Transform(trsf); NORMAL(i).Transform(trsf); } parray->AddVertex(p,NORMAL(i)); } // Fill parray with vertex and edge visibillity info const Poly_Array1OfTriangle& triangles = T->Triangles(); for (i = 1; i <= T->NbTriangles(); i++) { pc.Triangles(i,t[0],t[1],t[2]); if (SST.Orientation(F) == TopAbs_REVERSED) triangles(i).Get(n[0],n[2],n[1]); else triangles(i).Get(n[0],n[1],n[2]); gp_Pnt P1 = Nodes(n[0]); gp_Pnt P2 = Nodes(n[1]); gp_Pnt P3 = Nodes(n[2]); gp_Vec V1(P1,P2); if ( V1.SquareMagnitude() > dPreci ) { gp_Vec V2(P2,P3); if ( V2.SquareMagnitude() > dPreci ) { gp_Vec V3(P3,P1); if ( V3.SquareMagnitude() > dPreci ) { V1.Normalize(); V2.Normalize(); V1.Cross(V2); if ( V1.SquareMagnitude() > dPreci ) { parray->AddEdge(n[0]+decal,t[0] == 0); parray->AddEdge(n[1]+decal,t[1] == 0); parray->AddEdge(n[2]+decal,t[2] == 0); } } } } } } } Prs3d_Root::CurrentGroup(aPresentation)->BeginPrimitives(); Prs3d_Root::CurrentGroup(aPresentation)->AddPrimitiveArray(parray); Prs3d_Root::CurrentGroup(aPresentation)->EndPrimitives(); } return Standard_True; } #endif // phase de comptage: Standard_Integer nt, nnn, n1, n2, n3, nnv, EI; static Standard_Integer plus1mod3[3] = {1, 2, 0}; for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) { const anyTopFace& F = SST.CurrentFace(); T = SST.Triangulation(F, loc); if (!T.IsNull()) { nnn = T->NbTriangles(); const TColgp_Array1OfPnt& Nodes = T->Nodes(); const Poly_Array1OfTriangle& triangles = T->Triangles(); for (nt = 1; nt <= nnn; nt++) { if (SST.Orientation(F) == 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); gp_Vec V1(P1,P2); if ( V1.SquareMagnitude() > dPreci ) { gp_Vec V2(P2,P3); if (V2.SquareMagnitude() > dPreci ) { gp_Vec V3(P3,P1); if (V3.SquareMagnitude() > dPreci ) { V1.Normalize(); V2.Normalize(); V1.Cross(V2); if (V1.SquareMagnitude() > dPreci ) { nbTriangles++; } } } } } nbVertices += T->NbNodes(); } } if (nbVertices > 2 && nbTriangles > 0) { Graphic3d_Array1OfVertexN AVN(1, nbVertices); Aspect_Array1OfEdge AE(1, 3*nbTriangles); EI = 1; nnv = 1; for (SST.Init(aShape); SST.MoreFace(); SST.NextFace()) { const anyTopFace& F = SST.CurrentFace(); T = SST.Triangulation(F, loc); if (!T.IsNull()) { Poly_Connect pc(T); // 1- les noeuds. const TColgp_Array1OfPnt& Nodes = T->Nodes(); TColgp_Array1OfDir NORMAL(Nodes.Lower(), Nodes.Upper()); SST.Normal(F, pc, NORMAL); decal = nnv-1; for (j= Nodes.Lower(); j<= Nodes.Upper(); j++) { p = Nodes(j).Transformed(loc.Transformation()); AVN(nnv).SetCoord(p.X(), p.Y(), p.Z()); AVN(nnv).SetNormal(NORMAL(j).X(), NORMAL(j).Y(), NORMAL(j).Z()); nnv++; } // 2- les edges. 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 (SST.Orientation(F) == 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++) { k = plus1mod3[j]; if (t[j] == 0) AE(EI).SetValues(n[j]+decal, n[k]+decal, Aspect_TOE_VISIBLE); else AE(EI).SetValues(n[j]+decal, n[k]+decal, Aspect_TOE_INVISIBLE); EI++; } } } } } } } } Prs3d_Root::CurrentGroup(aPresentation)->TriangleSet(AVN, AE); } return Standard_True; } void Prs3d_ShadedShape::Add(const Handle (Prs3d_Presentation)& aPresentation, const anyShape& aShape, const Handle (Prs3d_Drawer)& aDrawer) { if (aShape.IsNull()) return; TopAbs_ShapeEnum E = aShape.ShapeType(); if (E == TopAbs_COMPOUND) { TopExp_Explorer ex; ex.Init(aShape, TopAbs_FACE); if (ex.More()) { TopoDS_Compound CO; BRep_Builder B; B.MakeCompound(CO); Standard_Boolean haselement = Standard_False; // il faut presenter les edges isoles. for (ex.Init(aShape, TopAbs_EDGE, TopAbs_FACE); ex.More(); ex.Next()) { haselement = Standard_True; B.Add(CO, ex.Current()); } // il faut presenter les vertex isoles. for (ex.Init(aShape, TopAbs_VERTEX, TopAbs_EDGE); ex.More(); ex.Next()) { haselement = Standard_True; B.Add(CO, ex.Current()); } if (haselement) StdPrs_WFShape::Add(aPresentation, CO, aDrawer); } else { StdPrs_WFShape::Add(aPresentation, aShape, aDrawer); } } Standard_Real aDeflection = GetDeflection(aShape, aDrawer); // Check if it is possible to avoid unnecessary recomputation // of shape triangulation if (!BRepTools::Triangulation (aShape, aDeflection)) { BRepTools::Clean (aShape); // retrieve meshing tool from Factory Handle(BRepMesh_DiscretRoot) aMeshAlgo = BRepMesh_DiscretFactory::Get().Discret (aShape, aDeflection, aDrawer->HLRAngle()); if (!aMeshAlgo.IsNull()) aMeshAlgo->Perform(); } ShadeFromShape(aShape, aDeflection, Standard_True, aPresentation, aDrawer); }