1 // Created on: 2006-11-04
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2006-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <VrmlData_IndexedFaceSet.hxx>
17 #include <VrmlData_InBuffer.hxx>
18 #include <VrmlData_UnknownNode.hxx>
19 #include <Poly_Triangulation.hxx>
20 #include <BRep_TFace.hxx>
21 #include <VrmlData_Coordinate.hxx>
22 #include <VrmlData_Color.hxx>
23 #include <VrmlData_Normal.hxx>
24 #include <VrmlData_TextureCoordinate.hxx>
25 #include <VrmlData_Scene.hxx>
26 #include <Precision.hxx>
27 #include <NCollection_Vector.hxx>
28 #include <NCollection_DataMap.hxx>
30 #include <TShort_HArray1OfShortReal.hxx>
32 IMPLEMENT_STANDARD_RTTIEXT(VrmlData_IndexedFaceSet,VrmlData_Faceted)
35 #define _CRT_SECURE_NO_DEPRECATE
36 #pragma warning (disable:4996)
42 //=======================================================================
45 //=======================================================================
47 VrmlData_ErrorStatus VrmlData_Faceted::readData (VrmlData_InBuffer& theBuffer)
49 VrmlData_ErrorStatus aStatus (VrmlData_EmptyData);
50 Standard_Boolean aBool;
51 if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ccw")) {
52 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
54 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "convex")) {
55 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
57 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "solid")) {
58 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
60 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "creaseAngle")) {
61 Standard_Real anAngle;
62 if (OK(aStatus, Scene().ReadReal (theBuffer, anAngle,
63 Standard_False, Standard_False))) {
64 if (anAngle < -Precision::Confusion()*0.001)
65 aStatus = VrmlData_IrrelevantNumber;
67 myCreaseAngle = anAngle;
73 //=======================================================================
74 //function : VrmlData_IndexedFaceSet::TShape
76 //=======================================================================
78 const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
80 if (myNbPolygons == 0)
82 else if (myIsModified) {
83 // Create an empty topological Face
84 const gp_XYZ * arrNodes = myCoords->Values();
85 Standard_Integer i, nTri(0);
87 NCollection_DataMap <int, int> mapNodeId;
89 // Count non-degenerated triangles
90 const int nNodes = (int)myCoords->Length();
91 for (i = 0; i < (int)myNbPolygons; i++) {
92 const Standard_Integer * arrIndice;
93 if (Polygon(i, arrIndice) == 3) {
94 //Check indices for out of bound
95 if (arrIndice[0] < 0 ||
96 arrIndice[0] >= nNodes ||
97 arrIndice[1] >= nNodes ||
98 arrIndice[2] >= nNodes)
102 const gp_XYZ aVec[2] = {
103 arrNodes[arrIndice[1]] - arrNodes[arrIndice[0]],
104 arrNodes[arrIndice[2]] - arrNodes[arrIndice[0]]
106 if ((aVec[0] ^ aVec[1]).SquareModulus() >
107 Precision::SquareConfusion())
110 const_cast<Standard_Integer&> (arrIndice[0]) = -1;
114 if (mapNodeId.IsBound (arrIndice[0]) == Standard_False)
115 mapNodeId.Bind (arrIndice[0], 0);
116 if (mapNodeId.IsBound (arrIndice[1]) == Standard_False)
117 mapNodeId.Bind (arrIndice[1], 0);
118 if (mapNodeId.IsBound (arrIndice[2]) == Standard_False)
119 mapNodeId.Bind (arrIndice[2], 0);
121 const Standard_Integer nbNodes (mapNodeId.Extent());
124 myIsModified = Standard_False;
129 Handle(Poly_Triangulation) aTriangulation =
130 new Poly_Triangulation (nbNodes, nTri, Standard_False);
131 Handle(BRep_TFace) aFace = new BRep_TFace();
132 aFace->Triangulation (aTriangulation);
135 // Copy the triangulation vertices
136 TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
137 NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId);
138 for (i = 1; anIterN.More(); anIterN.Next()) {
139 const int aKey = anIterN.Key();
140 const gp_XYZ& aNodePnt = arrNodes[aKey];
141 aNodes(i) = gp_Pnt (aNodePnt);
142 anIterN.ChangeValue() = i++;
145 // Copy the triangles. Only the triangle-type polygons are supported.
146 // In this loop we also get rid of any possible degenerated triangles.
147 Poly_Array1OfTriangle& aTriangles = aTriangulation->ChangeTriangles();
149 for (i = 0; i < (int)myNbPolygons; i++) {
150 const Standard_Integer * arrIndice;
151 if (Polygon (i, arrIndice) == 3)
152 if (arrIndice[0] >= 0 &&
153 arrIndice[0] < nNodes &&
154 arrIndice[1] < nNodes &&
155 arrIndice[2] < nNodes) // check to avoid previously skipped faces
156 aTriangles(++nTri).Set (mapNodeId(arrIndice[0]),
157 mapNodeId(arrIndice[1]),
158 mapNodeId(arrIndice[2]));
161 // Normals should be defined; if they are not, compute them
162 if (myNormals.IsNull ()) {
163 //aTriangulation->ComputeNormals();
164 Poly::ComputeNormals(aTriangulation);
167 // Copy the normals. Currently only normals-per-vertex are supported.
168 Handle(TShort_HArray1OfShortReal) Normals =
169 new TShort_HArray1OfShortReal (1, 3*nbNodes);
170 if (myNormalPerVertex) {
171 if (myArrNormalInd == 0L) {
172 NCollection_DataMap <int, int>::Iterator anIterNN (mapNodeId);
173 for (; anIterNN.More (); anIterNN.Next ()) {
174 Standard_Integer anIdx = (anIterNN.Value() - 1) * 3 + 1;
175 const gp_XYZ& aNormal = myNormals->Normal (anIterNN.Key ());
176 Normals->SetValue (anIdx + 0, Standard_ShortReal (aNormal.X ()));
177 Normals->SetValue (anIdx + 1, Standard_ShortReal (aNormal.Y ()));
178 Normals->SetValue (anIdx + 2, Standard_ShortReal (aNormal.Z ()));
183 for (i = 0; i < (int)myNbPolygons; i++)
185 const Standard_Integer * anArrNodes;
186 if (Polygon(i, anArrNodes) == 3 &&
187 anArrNodes[0] >= 0 &&
188 anArrNodes[0] < nNodes &&
189 anArrNodes[1] < nNodes &&
190 anArrNodes[2] < nNodes) // check to avoid previously skipped faces
192 const Standard_Integer * arrIndice;
193 if (IndiceNormals(i, arrIndice) == 3) {
194 for (Standard_Integer j = 0; j < 3; j++) {
195 const gp_XYZ& aNormal = myNormals->Normal (arrIndice[j]);
196 Standard_Integer anInd = (mapNodeId(anArrNodes[j]) - 1) * 3 + 1;
197 Normals->SetValue (anInd + 0, Standard_ShortReal (aNormal.X()));
198 Normals->SetValue (anInd + 1, Standard_ShortReal (aNormal.Y()));
199 Normals->SetValue (anInd + 2, Standard_ShortReal (aNormal.Z()));
208 aTriangulation->SetNormals(Normals);
211 myIsModified = Standard_False;
216 //=======================================================================
217 //function : VrmlData_IndexedFaceSet::Clone
219 //=======================================================================
221 Handle(VrmlData_Node) VrmlData_IndexedFaceSet::Clone
222 (const Handle(VrmlData_Node)& theOther) const
224 Handle(VrmlData_IndexedFaceSet) aResult =
225 Handle(VrmlData_IndexedFaceSet)::DownCast (VrmlData_Node::Clone(theOther));
226 if (aResult.IsNull())
228 new VrmlData_IndexedFaceSet(theOther.IsNull()? Scene(): theOther->Scene(),
231 if (&aResult->Scene() == &Scene()) {
232 aResult->SetCoordinates (myCoords);
233 aResult->SetNormals (myNormals);
234 aResult->SetColors (myColors);
235 aResult->SetPolygons (myNbPolygons, myArrPolygons);
236 aResult->SetNormalInd (myNbNormals, myArrNormalInd);
237 aResult->SetColorInd (myNbColors, myArrColorInd);
238 aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
240 // Create a dummy node to pass the different Scene instance to methods Clone
241 const Handle(VrmlData_UnknownNode) aDummyNode =
242 new VrmlData_UnknownNode (aResult->Scene());
243 if (myCoords.IsNull() == Standard_False)
244 aResult->SetCoordinates (Handle(VrmlData_Coordinate)::DownCast
245 (myCoords->Clone (aDummyNode)));
246 if (myNormals.IsNull() == Standard_False)
247 aResult->SetNormals (Handle(VrmlData_Normal)::DownCast
248 (myNormals->Clone (aDummyNode)));
249 if (myColors.IsNull() == Standard_False)
250 aResult->SetColors (Handle(VrmlData_Color)::DownCast
251 (myColors->Clone (aDummyNode)));
252 //TODO: Replace the following lines with the relevant copying
253 aResult->SetPolygons (myNbPolygons, myArrPolygons);
254 aResult->SetNormalInd (myNbNormals, myArrNormalInd);
255 aResult->SetColorInd (myNbColors, myArrColorInd);
256 aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
258 aResult->SetNormalPerVertex (myNormalPerVertex);
259 aResult->SetColorPerVertex (myColorPerVertex);
263 //=======================================================================
264 //function : VrmlData_IndexedFaceSet::Read
266 //=======================================================================
268 VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Read(VrmlData_InBuffer& theBuffer)
270 VrmlData_ErrorStatus aStatus;
271 const VrmlData_Scene& aScene = Scene();
272 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
274 if (OK(aStatus, VrmlData_Faceted::readData (theBuffer)))
276 if (aStatus != VrmlData_EmptyData)
278 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorPerVertex"))
279 aStatus = ReadBoolean (theBuffer, myColorPerVertex);
280 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalPerVertex"))
281 aStatus = ReadBoolean (theBuffer, myNormalPerVertex);
282 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coordIndex"))
283 aStatus = aScene.ReadArrIndex (theBuffer, myArrPolygons, myNbPolygons);
284 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorIndex"))
285 aStatus = aScene.ReadArrIndex (theBuffer, myArrColorInd, myNbColors);
286 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalIndex"))
287 aStatus = aScene.ReadArrIndex (theBuffer, myArrNormalInd, myNbNormals);
288 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoordIndex"))
289 aStatus = aScene.ReadArrIndex (theBuffer, myArrTextureInd, myNbTextures);
290 // These four checks should be the last one to avoid their interference
291 // with the other tokens (e.g., coordIndex)
292 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoord"))
294 Handle(VrmlData_Node) aNode;
295 aStatus = ReadNode (theBuffer, aNode,
296 STANDARD_TYPE(VrmlData_TextureCoordinate));
297 myTxCoords = Handle(VrmlData_TextureCoordinate)::DownCast (aNode);
299 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "color"))
301 Handle(VrmlData_Node) aNode;
302 aStatus = ReadNode (theBuffer, aNode,
303 STANDARD_TYPE(VrmlData_Color));
304 myColors = Handle(VrmlData_Color)::DownCast (aNode);
306 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coord"))
308 Handle(VrmlData_Node) aNode;
309 aStatus = ReadNode (theBuffer, aNode,
310 STANDARD_TYPE(VrmlData_Coordinate));
311 myCoords = Handle(VrmlData_Coordinate)::DownCast (aNode);
313 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normal"))
315 Handle(VrmlData_Node) aNode;
316 aStatus = ReadNode (theBuffer, aNode,
317 STANDARD_TYPE(VrmlData_Normal));
318 myNormals = Handle(VrmlData_Normal)::DownCast (aNode);
323 // Read the terminating (closing) brace
324 if (OK(aStatus) || aStatus == VrmlData_EmptyData)
325 if (OK(aStatus, readBrace (theBuffer))) {
332 // //=======================================================================
333 // //function : dummyReadBrackets
334 // //purpose : static (local) function
335 // //=======================================================================
337 // VrmlData_ErrorStatus dummyReadBrackets (VrmlData_InBuffer& theBuffer)
339 // VrmlData_ErrorStatus aStatus;
340 // Standard_Integer aLevelCounter (0);
341 // // This loop searches for any opening bracket.
342 // // Such bracket increments the level counter. A closing bracket decrements
343 // // the counter. The loop terminates when the counter becomes zero.
344 // while ((aStatus = VrmlData_Scene::ReadLine(theBuffer)) == VrmlData_StatusOK)
347 // while ((aChar = theBuffer.LinePtr[0]) != '\0') {
348 // theBuffer.LinePtr++;
349 // if (aChar == '[') {
352 // } else if (aChar == ']') {
357 // if (aLevelCounter <= 0)
363 //=======================================================================
364 //function : IsDefault
366 //=======================================================================
368 Standard_Boolean VrmlData_IndexedFaceSet::IsDefault () const
370 Standard_Boolean aResult (Standard_True);
372 aResult = Standard_False;
373 else if (myCoords.IsNull() == Standard_False)
374 aResult = myCoords->IsDefault();
378 //=======================================================================
381 //=======================================================================
383 VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Write
384 (const char * thePrefix) const
386 static char header[] = "IndexedFaceSet {";
387 const VrmlData_Scene& aScene = Scene();
388 VrmlData_ErrorStatus aStatus;
389 if (OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent()))) {
391 // Write the attributes of interface "VrmlData_Faceted"
392 if (IsCCW() == Standard_False)
393 aStatus = aScene.WriteLine ("ccw FALSE");
394 if (OK(aStatus) && IsSolid() == Standard_False)
395 aStatus = aScene.WriteLine ("solid FALSE");
396 if (OK(aStatus) && IsConvex() == Standard_False)
397 aStatus = aScene.WriteLine ("convex FALSE");
398 if (OK(aStatus) && CreaseAngle() > Precision::Confusion()) {
400 Sprintf (buf, "%.9g", CreaseAngle());
401 aStatus = aScene.WriteLine ("creaseAngle", buf);
404 if (OK(aStatus) && myCoords.IsNull() == Standard_False)
405 aStatus = aScene.WriteNode ("coord", myCoords);
407 aStatus = aScene.WriteArrIndex ("coordIndex", myArrPolygons,myNbPolygons);
409 if (OK(aStatus) && myNormalPerVertex == Standard_False)
410 aStatus = aScene.WriteLine ("normalPerVertex FALSE");
411 if (OK(aStatus) && myNormals.IsNull() == Standard_False)
412 aStatus = aScene.WriteNode ("normal", myNormals);
414 aStatus = aScene.WriteArrIndex ("normalIndex",myArrNormalInd,myNbNormals);
416 if (OK(aStatus) && myColorPerVertex == Standard_False)
417 aStatus = aScene.WriteLine ("colorPerVertex FALSE");
418 if (OK(aStatus) && myColors.IsNull() == Standard_False)
419 aStatus = aScene.WriteNode ("color", myColors);
421 aStatus = aScene.WriteArrIndex ("colorIndex", myArrColorInd, myNbColors);
423 if (OK(aStatus) && myTxCoords.IsNull() == Standard_False)
424 aStatus = aScene.WriteNode ("texCoord", myTxCoords);
426 aStatus = aScene.WriteArrIndex ("texCoordIndex", myArrTextureInd,
429 aStatus = WriteClosing();
434 //=======================================================================
435 //function : GetColor
437 //=======================================================================
439 Quantity_Color VrmlData_IndexedFaceSet::GetColor
440 (const Standard_Integer /*iFace*/,
441 const Standard_Integer /*iVertex*/)
444 return Quantity_NOC_BLACK;