0024521: Visualization - automatic back face culling is not turned on for Solids...
[occt.git] / src / StdPrs / StdPrs_ToolShadedShape.cxx
CommitLineData
b311480e 1// Created on: 1993-10-27
2// Created by: Jean-LOuis FRENKEL
3// Copyright (c) 1993-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
973c2be1 8// This library is free software; you can redistribute it and / or modify it
9// under the terms of the GNU Lesser General Public version 2.1 as published
10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
7fd59977 17#include <StdPrs_ToolShadedShape.ixx>
9447f912 18
19#include <BRep_Tool.hxx>
20#include <BRepAdaptor_Surface.hxx>
21#include <GeomAbs_SurfaceType.hxx>
22#include <GeomLib.hxx>
23#include <gp_Vec.hxx>
24#include <Poly_Connect.hxx>
7fd59977 25#include <Poly_Triangulation.hxx>
9447f912 26#include <Precision.hxx>
7fd59977 27#include <TColgp_HArray1OfPnt.hxx>
28#include <TColgp_Array1OfPnt.hxx>
29#include <TColgp_Array1OfPnt2d.hxx>
7fd59977 30#include <TopAbs_Orientation.hxx>
7fd59977 31#include <TopLoc_Location.hxx>
32#include <TShort_HArray1OfShortReal.hxx>
33#include <TShort_Array1OfShortReal.hxx>
34
3b1817a9 35namespace
36{
37 //=======================================================================
38 //function : isTriangulated
39 //purpose : Returns true if all faces within shape are triangulated.
40 // Same as BRepTools::Triangulation() but without extra checks.
41 //=======================================================================
42 static Standard_Boolean isTriangulated (const TopoDS_Shape& theShape)
43 {
44 TopLoc_Location aLocDummy;
45 for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
46 {
47 const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
48 const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation (aFace, aLocDummy);
49 if (aTri.IsNull())
50 {
51 return Standard_False;
52 }
53 }
54 return Standard_True;
55 }
56}
57
7fd59977 58//=======================================================================
59//function : IsClosed
9447f912 60//purpose :
7fd59977 61//=======================================================================
9447f912 62Standard_Boolean StdPrs_ToolShadedShape::IsClosed (const TopoDS_Shape& theShape)
7fd59977 63{
3b1817a9 64 if (theShape.IsNull())
65 {
66 return Standard_True;
67 }
68
69 switch (theShape.ShapeType())
70 {
71 case TopAbs_COMPOUND:
72 case TopAbs_COMPSOLID:
73 default:
74 {
75 // check that compound consists of closed solids
76 for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
77 {
78 const TopoDS_Shape& aShape = anIter.Value();
79 if (!IsClosed (aShape))
80 {
81 return Standard_False;
82 }
83 }
84 return Standard_True;
85 }
86 case TopAbs_SOLID:
87 {
88 for (TopoDS_Iterator anIter (theShape); anIter.More(); anIter.Next())
89 {
90 const TopoDS_Shape& aShape = anIter.Value();
91 if (aShape.IsNull())
92 {
93 continue;
94 }
95
96 if (aShape.ShapeType() == TopAbs_SHELL
97 && !aShape.Closed())
98 {
99 return Standard_False;
100 }
101 else if (aShape.ShapeType() == TopAbs_FACE)
102 {
103 // invalid solid
104 return Standard_False;
105 }
106 else if (!isTriangulated (aShape))
107 {
108 // mesh contains holes
109 return Standard_False;
110 }
111 }
112 return Standard_True;
113 }
114 case TopAbs_SHELL:
115 case TopAbs_FACE:
116 {
117 // free faces / shell are not allowed
118 return Standard_False;
119 }
120 case TopAbs_WIRE:
121 case TopAbs_EDGE:
122 case TopAbs_VERTEX:
123 {
124 // ignore
125 return Standard_True;
126 }
127 }
7fd59977 128}
129
7fd59977 130//=======================================================================
131//function : Triangulation
9447f912 132//purpose :
7fd59977 133//=======================================================================
9447f912 134Handle(Poly_Triangulation) StdPrs_ToolShadedShape::Triangulation (const TopoDS_Face& theFace,
135 TopLoc_Location& theLoc)
7fd59977 136{
9447f912 137 return BRep_Tool::Triangulation (theFace, theLoc);
7fd59977 138}
139
7fd59977 140//=======================================================================
141//function : Normal
9447f912 142//purpose :
7fd59977 143//=======================================================================
9447f912 144void StdPrs_ToolShadedShape::Normal (const TopoDS_Face& theFace,
145 Poly_Connect& thePolyConnect,
146 TColgp_Array1OfDir& theNormals)
7fd59977 147{
9447f912 148 const Handle(Poly_Triangulation)& aPolyTri = thePolyConnect.Triangulation();
149 const TColgp_Array1OfPnt& aNodes = aPolyTri->Nodes();
150 if (aPolyTri->HasNormals())
151 {
152 // normals pre-computed in triangulation structure
153 const TShort_Array1OfShortReal& aNormals = aPolyTri->Normals();
154 const Standard_ShortReal* aNormArr = &(aNormals.Value (aNormals.Lower()));
155 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
156 {
157 const Standard_Integer anId = 3 * (aNodeIter - aNodes.Lower());
158 const gp_Dir aNorm (aNormArr[anId + 0],
159 aNormArr[anId + 1],
160 aNormArr[anId + 2]);
161 theNormals (aNodeIter) = aNorm;
7fd59977 162 }
163
9447f912 164 if (theFace.Orientation() == TopAbs_REVERSED)
165 {
166 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
167 {
168 theNormals.ChangeValue (aNodeIter).Reverse();
7fd59977 169 }
170 }
9447f912 171 return;
7fd59977 172 }
7fd59977 173
9447f912 174 // take in face the surface location
175 const TopoDS_Face aZeroFace = TopoDS::Face (theFace.Located (TopLoc_Location()));
176 Handle(Geom_Surface) aSurf = BRep_Tool::Surface (aZeroFace);
177 const Standard_Real aTol = Precision::Confusion();
178 Handle(TShort_HArray1OfShortReal) aNormals = new TShort_HArray1OfShortReal (1, aPolyTri->NbNodes() * 3);
179 const Poly_Array1OfTriangle& aTriangles = aPolyTri->Triangles();
180 const TColgp_Array1OfPnt2d* aNodesUV = aPolyTri->HasUVNodes() && !aSurf.IsNull()
181 ? &aPolyTri->UVNodes()
182 : NULL;
183 Standard_Integer aTri[3];
184 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
185 {
186 // try to retrieve normal from real surface first, when UV coordinates are available
187 if (aNodesUV == NULL
188 || GeomLib::NormEstim (aSurf, aNodesUV->Value (aNodeIter), aTol, theNormals (aNodeIter)) > 1)
189 {
190 // compute flat normals
191 gp_XYZ eqPlan (0.0, 0.0, 0.0);
192 for (thePolyConnect.Initialize (aNodeIter); thePolyConnect.More(); thePolyConnect.Next())
193 {
194 aTriangles (thePolyConnect.Value()).Get (aTri[0], aTri[1], aTri[2]);
195 const gp_XYZ v1 (aNodes (aTri[1]).Coord() - aNodes (aTri[0]).Coord());
196 const gp_XYZ v2 (aNodes (aTri[2]).Coord() - aNodes (aTri[1]).Coord());
197 const gp_XYZ vv = v1 ^ v2;
198 const Standard_Real aMod = vv.Modulus();
199 if (aMod >= aTol)
200 {
201 eqPlan += vv / aMod;
202 }
7fd59977 203 }
9447f912 204 const Standard_Real aModMax = eqPlan.Modulus();
205 theNormals (aNodeIter) = (aModMax > aTol) ? gp_Dir (eqPlan) : gp::DZ();
7fd59977 206 }
207
9447f912 208 const Standard_Integer anId = (aNodeIter - aNodes.Lower()) * 3;
209 aNormals->SetValue (anId + 1, (Standard_ShortReal )theNormals (aNodeIter).X());
210 aNormals->SetValue (anId + 2, (Standard_ShortReal )theNormals (aNodeIter).Y());
211 aNormals->SetValue (anId + 3, (Standard_ShortReal )theNormals (aNodeIter).Z());
7fd59977 212 }
9447f912 213 aPolyTri->SetNormals (aNormals);
7fd59977 214
9447f912 215 if (theFace.Orientation() == TopAbs_REVERSED)
216 {
217 for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
218 {
219 theNormals.ChangeValue (aNodeIter).Reverse();
7fd59977 220 }
7fd59977 221 }
7fd59977 222}