0022683: Incorrect result of Select3D_Projector::Project() in the case of perspective...
[occt.git] / src / VrmlData / VrmlData_IndexedFaceSet.cxx
CommitLineData
7fd59977 1// File: VrmlData_IndexedFaceSet.cxx
2// Created: 04.11.06 21:28
3// Author: Alexander GRIGORIEV
4// Copyright: Open Cascade 2006
5
6
7#include <VrmlData_IndexedFaceSet.hxx>
8#include <VrmlData_InBuffer.hxx>
9#include <VrmlData_UnknownNode.hxx>
10#include <Poly_Triangulation.hxx>
11#include <BRep_TFace.hxx>
12#include <VrmlData_Coordinate.hxx>
13#include <VrmlData_Color.hxx>
14#include <VrmlData_Normal.hxx>
15#include <VrmlData_TextureCoordinate.hxx>
16#include <VrmlData_Scene.hxx>
17#include <Precision.hxx>
18#include <NCollection_Vector.hxx>
19#include <NCollection_DataMap.hxx>
20#include <Poly.hxx>
21#include <TShort_HArray1OfShortReal.hxx>
22
23#ifdef WNT
24#define _CRT_SECURE_NO_DEPRECATE
25#pragma warning (disable:4996)
26#endif
27
28IMPLEMENT_STANDARD_HANDLE (VrmlData_Faceted, VrmlData_Geometry)
29IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Faceted, VrmlData_Geometry)
30IMPLEMENT_STANDARD_HANDLE (VrmlData_IndexedFaceSet, VrmlData_Faceted)
31IMPLEMENT_STANDARD_RTTIEXT (VrmlData_IndexedFaceSet, VrmlData_Faceted)
32
33//=======================================================================
34//function : readData
35//purpose :
36//=======================================================================
37
38VrmlData_ErrorStatus VrmlData_Faceted::readData (VrmlData_InBuffer& theBuffer)
39{
40 VrmlData_ErrorStatus aStatus (VrmlData_EmptyData);
41 Standard_Boolean aBool;
42 if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ccw")) {
43 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
44 myIsCCW = aBool;
45 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "convex")) {
46 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
47 myIsConvex = aBool;
48 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "solid")) {
49 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
50 myIsSolid = aBool;
51 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "creaseAngle")) {
52 Standard_Real anAngle;
53 if (OK(aStatus, Scene().ReadReal (theBuffer, anAngle,
54 Standard_False, Standard_False)))
55 if (anAngle < -Precision::Confusion()*0.001)
56 aStatus = VrmlData_IrrelevantNumber;
57 else
58 myCreaseAngle = anAngle;
59 }
60 return aStatus;
61}
62
63//=======================================================================
64//function : VrmlData_IndexedFaceSet::TShape
65//purpose :
66//=======================================================================
67
68const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
69{
70 if (myNbPolygons == 0)
71 myTShape.Nullify();
72 else if (myIsModified) {
73 // Create an empty topological Face
74 const gp_XYZ * arrNodes = myCoords->Values();
75 Standard_Integer i, nTri(0);
76
77 NCollection_DataMap <int, int> mapNodeId;
78
79 // Count non-degenerated triangles
80 for (i = 0; i < (int)myNbPolygons; i++) {
81 const Standard_Integer * arrIndice;
82 if (Polygon(i, arrIndice) == 3) {
83 if (arrIndice[0] < 0)
84 continue;
85 const gp_XYZ aVec[2] = {
86 arrNodes[arrIndice[1]] - arrNodes[arrIndice[0]],
87 arrNodes[arrIndice[2]] - arrNodes[arrIndice[0]]
88 };
89 if ((aVec[0] ^ aVec[1]).SquareModulus() >
90 Precision::Confusion()*Precision::Confusion())
91 ++nTri;
92 else {
93 const_cast<Standard_Integer&> (arrIndice[0]) = -1;
94 continue;
95 }
96 }
97 if (mapNodeId.IsBound (arrIndice[0]) == Standard_False)
98 mapNodeId.Bind (arrIndice[0], 0);
99 if (mapNodeId.IsBound (arrIndice[1]) == Standard_False)
100 mapNodeId.Bind (arrIndice[1], 0);
101 if (mapNodeId.IsBound (arrIndice[2]) == Standard_False)
102 mapNodeId.Bind (arrIndice[2], 0);
103 }
104 const Standard_Integer nbNodes (mapNodeId.Extent());
105 const Standard_Integer nNodesTri
106 (myNormalPerVertex && myArrNormalInd==0L ? nbNodes : nTri * 3);
107 // Create the CasCade triangulation
108 //Handle(BRep_Triangulation) aTriangulation =
109 //new BRep_Triangulation (nbNodes, nTri,
110 //myNormalPerVertex && myArrNormalInd==0L);
111 Handle(Poly_Triangulation) aTriangulation =
112 new Poly_Triangulation (nNodesTri, nTri, Standard_False);
113 Handle(BRep_TFace) aFace = new BRep_TFace();
114 aFace->Triangulation (aTriangulation);
115 myTShape = aFace;
116
117 TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
118 Poly_Array1OfTriangle& aTriangles = aTriangulation->ChangeTriangles();
119 const Handle(TShort_HArray1OfShortReal) aNormals =
120 new TShort_HArray1OfShortReal(1, 3*nNodesTri);
121 aTriangulation->SetNormals(aNormals);
122 nTri = 0;
123
124 // Copy the triangulation vertices
125 // This is only the case when normals are defined by node so each
126 // node can be shared by several triangles
127 if (nNodesTri == nbNodes)
128 {
129 NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId);
130 for (i = 1; anIterN.More(); anIterN.Next()) {
131 const int aKey = anIterN.Key();
132 const gp_XYZ& aNodePnt = arrNodes[aKey];
133 aNodes(i) = gp_Pnt (aNodePnt);
134 anIterN.ChangeValue() = i++;
135 }
136 // Fill the array of triangles
137 for (i = 0; i < (int)myNbPolygons; i++) {
138 const Standard_Integer * arrIndice;
139 if (Polygon(i, arrIndice) == 3)
140 if (arrIndice[0] >= 0) // check to avoid previously skipped faces
141 aTriangles(++nTri).Set (mapNodeId(arrIndice[0]),
142 mapNodeId(arrIndice[1]),
143 mapNodeId(arrIndice[2]));
144 }
145 // Normals should be defined; if they are not, compute them
146 if (myNormals.IsNull()) {
147 //aTriangulation->ComputeNormals();
148 Poly::ComputeNormals(aTriangulation);
149 } else {
150 // Copy the normals-per-vertex.
151 NCollection_DataMap <int, int>::Iterator anIterNN (mapNodeId);
152 for (; anIterNN.More(); anIterNN.Next()) {
153 const Standard_Integer ind = (anIterNN.Value() - 1) * 3 + 1;
154 const gp_XYZ& aNormal = myNormals->Normal(anIterNN.Key());
155 aNormals->SetValue(ind + 0, Standard_ShortReal(aNormal.X()));
156 aNormals->SetValue(ind + 1, Standard_ShortReal(aNormal.Y()));
157 aNormals->SetValue(ind + 2, Standard_ShortReal(aNormal.Z()));
158 }
159 }
160 }
161 else {
162 // Copy the triangles. Only the triangle-type polygons are supported.
163 // In this loop we also get rid of any possible degenerated triangles.
164 for (i = 0; i < (int)myNbPolygons; i++) {
165 const Standard_Integer * arrIndice;
166 if (Polygon(i, arrIndice) == 3)
167 if (arrIndice[0] >= 0) { // check to avoid previously skipped faces
168 // normals by triangle - each node belongs to a perticular triangle
169 nTri++;
170 aTriangles(nTri).Set (nTri*3 - 2, nTri*3 - 1, nTri*3);
171 aNodes(nTri*3 - 2) = arrNodes[arrIndice[0]];
172 aNodes(nTri*3 - 1) = arrNodes[arrIndice[1]];
173 aNodes(nTri*3 - 0) = arrNodes[arrIndice[2]];
174 if (IndiceNormals(i, arrIndice) == 3) {
175 for (Standard_Integer j = 0; j < 3; j++) {
176 const Standard_Integer ind = ((nTri-1)*3 + j) * 3;
177 const gp_XYZ& aNormal = myNormals->Normal(arrIndice[j]);
178 aNormals->SetValue(ind + 1, Standard_ShortReal(aNormal.X()));
179 aNormals->SetValue(ind + 2, Standard_ShortReal(aNormal.Y()));
180 aNormals->SetValue(ind + 3, Standard_ShortReal(aNormal.Z()));
181 }
182 }
183 }
184 }
185 }
186 }
187 return myTShape;
188}
189
190//=======================================================================
191//function : VrmlData_IndexedFaceSet::Clone
192//purpose :
193//=======================================================================
194
195Handle(VrmlData_Node) VrmlData_IndexedFaceSet::Clone
196 (const Handle(VrmlData_Node)& theOther) const
197{
198 Handle(VrmlData_IndexedFaceSet) aResult =
199 Handle(VrmlData_IndexedFaceSet)::DownCast (VrmlData_Node::Clone(theOther));
200 if (aResult.IsNull())
201 aResult =
202 new VrmlData_IndexedFaceSet(theOther.IsNull()? Scene(): theOther->Scene(),
203 Name());
204
205 if (&aResult->Scene() == &Scene()) {
206 aResult->SetCoordinates (myCoords);
207 aResult->SetNormals (myNormals);
208 aResult->SetColors (myColors);
209 aResult->SetPolygons (myNbPolygons, myArrPolygons);
210 aResult->SetNormalInd (myNbNormals, myArrNormalInd);
211 aResult->SetColorInd (myNbColors, myArrColorInd);
212 aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
213 } else {
214 // Create a dummy node to pass the different Scene instance to methods Clone
215 const Handle(VrmlData_UnknownNode) aDummyNode =
216 new VrmlData_UnknownNode (aResult->Scene());
217 if (myCoords.IsNull() == Standard_False)
218 aResult->SetCoordinates (Handle(VrmlData_Coordinate)::DownCast
219 (myCoords->Clone (aDummyNode)));
220 if (myNormals.IsNull() == Standard_False)
221 aResult->SetNormals (Handle(VrmlData_Normal)::DownCast
222 (myNormals->Clone (aDummyNode)));
223 if (myColors.IsNull() == Standard_False)
224 aResult->SetColors (Handle(VrmlData_Color)::DownCast
225 (myColors->Clone (aDummyNode)));
226 //TODO: Replace the following lines with the relevant copying
227 aResult->SetPolygons (myNbPolygons, myArrPolygons);
228 aResult->SetNormalInd (myNbNormals, myArrNormalInd);
229 aResult->SetColorInd (myNbColors, myArrColorInd);
230 aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
231 }
232 aResult->SetNormalPerVertex (myNormalPerVertex);
233 aResult->SetColorPerVertex (myColorPerVertex);
234 return aResult;
235}
236
237//=======================================================================
238//function : VrmlData_IndexedFaceSet::Read
239//purpose :
240//=======================================================================
241
242VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Read(VrmlData_InBuffer& theBuffer)
243{
244 VrmlData_ErrorStatus aStatus;
245 const VrmlData_Scene& aScene = Scene();
246 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
247 {
248 if (OK(aStatus, VrmlData_Faceted::readData (theBuffer)))
249 continue;
250 if (aStatus != VrmlData_EmptyData)
251 break;
252 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorPerVertex"))
253 aStatus = ReadBoolean (theBuffer, myColorPerVertex);
254 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalPerVertex"))
255 aStatus = ReadBoolean (theBuffer, myNormalPerVertex);
256 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coordIndex"))
257 aStatus = aScene.ReadArrIndex (theBuffer, myArrPolygons, myNbPolygons);
258 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorIndex"))
259 aStatus = aScene.ReadArrIndex (theBuffer, myArrColorInd, myNbColors);
260 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalIndex"))
261 aStatus = aScene.ReadArrIndex (theBuffer, myArrNormalInd, myNbNormals);
262 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoordIndex"))
263 aStatus = aScene.ReadArrIndex (theBuffer, myArrTextureInd, myNbTextures);
264 // These four checks should be the last one to avoid their interference
265 // with the other tokens (e.g., coordIndex)
266 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoord"))
267 aStatus = ReadNode (theBuffer, myTxCoords,
268 STANDARD_TYPE(VrmlData_TextureCoordinate));
269 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "color"))
270 aStatus = ReadNode (theBuffer, myColors,
271 STANDARD_TYPE(VrmlData_Color));
272 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coord"))
273 aStatus = ReadNode (theBuffer, myCoords,
274 STANDARD_TYPE(VrmlData_Coordinate));
275 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normal"))
276 aStatus = ReadNode (theBuffer, myNormals,
277 STANDARD_TYPE(VrmlData_Normal));
278 if (!OK(aStatus))
279 break;
280 }
281 // Read the terminating (closing) brace
282 if (OK(aStatus) || aStatus == VrmlData_EmptyData)
283 if (OK(aStatus, readBrace (theBuffer))) {
284 // Post-processing
285 ;
286 }
287 return aStatus;
288}
289
290// //=======================================================================
291// //function : dummyReadBrackets
292// //purpose : static (local) function
293// //=======================================================================
294
295// VrmlData_ErrorStatus dummyReadBrackets (VrmlData_InBuffer& theBuffer)
296// {
297// VrmlData_ErrorStatus aStatus;
298// Standard_Integer aLevelCounter (0);
299// // This loop searches for any opening bracket.
300// // Such bracket increments the level counter. A closing bracket decrements
301// // the counter. The loop terminates when the counter becomes zero.
302// while ((aStatus = VrmlData_Scene::ReadLine(theBuffer)) == VrmlData_StatusOK)
303// {
304// int aChar;
305// while ((aChar = theBuffer.LinePtr[0]) != '\0') {
306// theBuffer.LinePtr++;
307// if (aChar == '[') {
308// aLevelCounter++;
309// break;
310// } else if (aChar == ']') {
311// aLevelCounter--;
312// break;
313// }
314// }
315// if (aLevelCounter <= 0)
316// break;
317// }
318// return aStatus;
319// }
320
321//=======================================================================
322//function : IsDefault
323//purpose :
324//=======================================================================
325
326Standard_Boolean VrmlData_IndexedFaceSet::IsDefault () const
327{
328 Standard_Boolean aResult (Standard_True);
329 if (myNbPolygons)
330 aResult = Standard_False;
331 else if (myCoords.IsNull() == Standard_False)
332 aResult = myCoords->IsDefault();
333 return aResult;
334}
335
336//=======================================================================
337//function : Write
338//purpose :
339//=======================================================================
340
341VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Write
342 (const char * thePrefix) const
343{
344 static char header[] = "IndexedFaceSet {";
345 const VrmlData_Scene& aScene = Scene();
346 VrmlData_ErrorStatus aStatus;
347 if (OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent()))) {
348
349 // Write the attributes of interface "VrmlData_Faceted"
350 if (IsCCW() == Standard_False)
351 aStatus = aScene.WriteLine ("ccw FALSE");
352 if (OK(aStatus) && IsSolid() == Standard_False)
353 aStatus = aScene.WriteLine ("solid FALSE");
354 if (OK(aStatus) && IsConvex() == Standard_False)
355 aStatus = aScene.WriteLine ("convex FALSE");
356 if (OK(aStatus) && CreaseAngle() > Precision::Confusion()) {
357 char buf[64];
358 sprintf (buf, "%.9g", CreaseAngle());
359 aStatus = aScene.WriteLine ("creaseAngle", buf);
360 }
361
362 if (OK(aStatus) && myCoords.IsNull() == Standard_False)
363 aStatus = aScene.WriteNode ("coord", myCoords);
364 if (OK(aStatus))
365 aStatus = aScene.WriteArrIndex ("coordIndex", myArrPolygons,myNbPolygons);
366
367 if (OK(aStatus) && myNormalPerVertex == Standard_False)
368 aStatus = aScene.WriteLine ("normalPerVertex FALSE");
369 if (OK(aStatus) && myNormals.IsNull() == Standard_False)
370 aStatus = aScene.WriteNode ("normal", myNormals);
371 if (OK(aStatus))
372 aStatus = aScene.WriteArrIndex ("normalIndex",myArrNormalInd,myNbNormals);
373
374 if (OK(aStatus) && myColorPerVertex == Standard_False)
375 aStatus = aScene.WriteLine ("colorPerVertex FALSE");
376 if (OK(aStatus) && myColors.IsNull() == Standard_False)
377 aStatus = aScene.WriteNode ("color", myColors);
378 if (OK(aStatus))
379 aStatus = aScene.WriteArrIndex ("colorIndex", myArrColorInd, myNbColors);
380
381 if (OK(aStatus) && myTxCoords.IsNull() == Standard_False)
382 aStatus = aScene.WriteNode ("texCoord", myTxCoords);
383 if (OK(aStatus))
384 aStatus = aScene.WriteArrIndex ("texCoordIndex", myArrTextureInd,
385 myNbTextures);
386
387 aStatus = WriteClosing();
388 }
389 return aStatus;
390}
391
392//=======================================================================
393//function : GetColor
394//purpose :
395//=======================================================================
396
397Quantity_Color VrmlData_IndexedFaceSet::GetColor
398 (const Standard_Integer /*iFace*/,
399 const Standard_Integer /*iVertex*/)
400{
401 //TODO
402 return Quantity_NOC_BLACK;
403}
404