1 // Created on: 2006-11-04
2 // Created by: Alexander GRIGORIEV
3 // Copyright (c) 2006-2012 OPEN CASCADE SAS
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
22 #include <VrmlData_IndexedFaceSet.hxx>
23 #include <VrmlData_InBuffer.hxx>
24 #include <VrmlData_UnknownNode.hxx>
25 #include <Poly_Triangulation.hxx>
26 #include <BRep_TFace.hxx>
27 #include <VrmlData_Coordinate.hxx>
28 #include <VrmlData_Color.hxx>
29 #include <VrmlData_Normal.hxx>
30 #include <VrmlData_TextureCoordinate.hxx>
31 #include <VrmlData_Scene.hxx>
32 #include <Precision.hxx>
33 #include <NCollection_Vector.hxx>
34 #include <NCollection_DataMap.hxx>
36 #include <TShort_HArray1OfShortReal.hxx>
39 #define _CRT_SECURE_NO_DEPRECATE
40 #pragma warning (disable:4996)
43 IMPLEMENT_STANDARD_HANDLE (VrmlData_Faceted, VrmlData_Geometry)
44 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Faceted, VrmlData_Geometry)
45 IMPLEMENT_STANDARD_HANDLE (VrmlData_IndexedFaceSet, VrmlData_Faceted)
46 IMPLEMENT_STANDARD_RTTIEXT (VrmlData_IndexedFaceSet, VrmlData_Faceted)
48 //=======================================================================
51 //=======================================================================
53 VrmlData_ErrorStatus VrmlData_Faceted::readData (VrmlData_InBuffer& theBuffer)
55 VrmlData_ErrorStatus aStatus (VrmlData_EmptyData);
56 Standard_Boolean aBool;
57 if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "ccw")) {
58 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
60 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "convex")) {
61 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
63 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "solid")) {
64 if (OK(aStatus, ReadBoolean (theBuffer, aBool)))
66 } else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "creaseAngle")) {
67 Standard_Real anAngle;
68 if (OK(aStatus, Scene().ReadReal (theBuffer, anAngle,
69 Standard_False, Standard_False)))
70 if (anAngle < -Precision::Confusion()*0.001)
71 aStatus = VrmlData_IrrelevantNumber;
73 myCreaseAngle = anAngle;
78 //=======================================================================
79 //function : VrmlData_IndexedFaceSet::TShape
81 //=======================================================================
83 const Handle(TopoDS_TShape)& VrmlData_IndexedFaceSet::TShape ()
85 if (myNbPolygons == 0)
87 else if (myIsModified) {
88 // Create an empty topological Face
89 const gp_XYZ * arrNodes = myCoords->Values();
90 Standard_Integer i, nTri(0);
92 NCollection_DataMap <int, int> mapNodeId;
94 // Count non-degenerated triangles
95 for (i = 0; i < (int)myNbPolygons; i++) {
96 const Standard_Integer * arrIndice;
97 if (Polygon(i, arrIndice) == 3) {
100 const gp_XYZ aVec[2] = {
101 arrNodes[arrIndice[1]] - arrNodes[arrIndice[0]],
102 arrNodes[arrIndice[2]] - arrNodes[arrIndice[0]]
104 if ((aVec[0] ^ aVec[1]).SquareModulus() >
105 Precision::Confusion()*Precision::Confusion())
108 const_cast<Standard_Integer&> (arrIndice[0]) = -1;
112 if (mapNodeId.IsBound (arrIndice[0]) == Standard_False)
113 mapNodeId.Bind (arrIndice[0], 0);
114 if (mapNodeId.IsBound (arrIndice[1]) == Standard_False)
115 mapNodeId.Bind (arrIndice[1], 0);
116 if (mapNodeId.IsBound (arrIndice[2]) == Standard_False)
117 mapNodeId.Bind (arrIndice[2], 0);
119 const Standard_Integer nbNodes (mapNodeId.Extent());
122 myIsModified = Standard_False;
127 Handle(Poly_Triangulation) aTriangulation =
128 new Poly_Triangulation (nbNodes, nTri, Standard_False);
129 Handle(BRep_TFace) aFace = new BRep_TFace();
130 aFace->Triangulation (aTriangulation);
133 // Copy the triangulation vertices
134 TColgp_Array1OfPnt& aNodes = aTriangulation->ChangeNodes();
135 NCollection_DataMap <int, int>::Iterator anIterN(mapNodeId);
136 for (i = 1; anIterN.More(); anIterN.Next()) {
137 const int aKey = anIterN.Key();
138 const gp_XYZ& aNodePnt = arrNodes[aKey];
139 aNodes(i) = gp_Pnt (aNodePnt);
140 anIterN.ChangeValue() = i++;
143 // Copy the triangles. Only the triangle-type polygons are supported.
144 // In this loop we also get rid of any possible degenerated triangles.
145 Poly_Array1OfTriangle& aTriangles = aTriangulation->ChangeTriangles();
147 for (i = 0; i < (int)myNbPolygons; i++) {
148 const Standard_Integer * arrIndice;
149 if (Polygon (i, arrIndice) == 3)
150 if (arrIndice[0] >= 0) // check to avoid previously skipped faces
151 aTriangles(++nTri).Set (mapNodeId(arrIndice[0]),
152 mapNodeId(arrIndice[1]),
153 mapNodeId(arrIndice[2]));
156 // Normals should be defined; if they are not, compute them
157 if (myNormals.IsNull ()) {
158 //aTriangulation->ComputeNormals();
159 Poly::ComputeNormals(aTriangulation);
162 // Copy the normals. Currently only normals-per-vertex are supported.
163 Handle(TShort_HArray1OfShortReal) Normals =
164 new TShort_HArray1OfShortReal (1, 3*nbNodes);
165 if (myNormalPerVertex) {
166 if (myArrNormalInd == 0L) {
167 NCollection_DataMap <int, int>::Iterator anIterNN (mapNodeId);
168 for (; anIterNN.More (); anIterNN.Next ()) {
169 Standard_Integer anIdx = (anIterNN.Value() - 1) * 3 + 1;
170 const gp_XYZ& aNormal = myNormals->Normal (anIterNN.Key ());
171 Normals->SetValue (anIdx + 0, Standard_ShortReal (aNormal.X ()));
172 Normals->SetValue (anIdx + 1, Standard_ShortReal (aNormal.Y ()));
173 Normals->SetValue (anIdx + 2, Standard_ShortReal (aNormal.Z ()));
177 for (i = 0; i < (int)myNbPolygons; i++) {
178 const Standard_Integer * arrIndice;
179 if (Polygon(i, arrIndice) == 3)
180 if (arrIndice[0] >= 0) // check to avoid previously skipped faces
181 if (IndiceNormals(i, arrIndice) == 3) {
182 Standard_Integer anInd = (++nTri - 1) * 3 + 1;
183 for (Standard_Integer j = 0; j < 3; j++) {
184 const gp_XYZ& aNormal = myNormals->Normal (arrIndice[j]);
185 Normals->SetValue (anInd + 0 + j*3,
186 Standard_ShortReal (aNormal.X ()));
187 Normals->SetValue (anInd + 1 + j*3,
188 Standard_ShortReal (aNormal.Y ()));
189 Normals->SetValue (anInd + 2 + j*3,
190 Standard_ShortReal (aNormal.Z ()));
198 aTriangulation->SetNormals(Normals);
201 myIsModified = Standard_False;
206 //=======================================================================
207 //function : VrmlData_IndexedFaceSet::Clone
209 //=======================================================================
211 Handle(VrmlData_Node) VrmlData_IndexedFaceSet::Clone
212 (const Handle(VrmlData_Node)& theOther) const
214 Handle(VrmlData_IndexedFaceSet) aResult =
215 Handle(VrmlData_IndexedFaceSet)::DownCast (VrmlData_Node::Clone(theOther));
216 if (aResult.IsNull())
218 new VrmlData_IndexedFaceSet(theOther.IsNull()? Scene(): theOther->Scene(),
221 if (&aResult->Scene() == &Scene()) {
222 aResult->SetCoordinates (myCoords);
223 aResult->SetNormals (myNormals);
224 aResult->SetColors (myColors);
225 aResult->SetPolygons (myNbPolygons, myArrPolygons);
226 aResult->SetNormalInd (myNbNormals, myArrNormalInd);
227 aResult->SetColorInd (myNbColors, myArrColorInd);
228 aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
230 // Create a dummy node to pass the different Scene instance to methods Clone
231 const Handle(VrmlData_UnknownNode) aDummyNode =
232 new VrmlData_UnknownNode (aResult->Scene());
233 if (myCoords.IsNull() == Standard_False)
234 aResult->SetCoordinates (Handle(VrmlData_Coordinate)::DownCast
235 (myCoords->Clone (aDummyNode)));
236 if (myNormals.IsNull() == Standard_False)
237 aResult->SetNormals (Handle(VrmlData_Normal)::DownCast
238 (myNormals->Clone (aDummyNode)));
239 if (myColors.IsNull() == Standard_False)
240 aResult->SetColors (Handle(VrmlData_Color)::DownCast
241 (myColors->Clone (aDummyNode)));
242 //TODO: Replace the following lines with the relevant copying
243 aResult->SetPolygons (myNbPolygons, myArrPolygons);
244 aResult->SetNormalInd (myNbNormals, myArrNormalInd);
245 aResult->SetColorInd (myNbColors, myArrColorInd);
246 aResult->SetTextureCoordInd (myNbTextures, myArrTextureInd);
248 aResult->SetNormalPerVertex (myNormalPerVertex);
249 aResult->SetColorPerVertex (myColorPerVertex);
253 //=======================================================================
254 //function : VrmlData_IndexedFaceSet::Read
256 //=======================================================================
258 VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Read(VrmlData_InBuffer& theBuffer)
260 VrmlData_ErrorStatus aStatus;
261 const VrmlData_Scene& aScene = Scene();
262 while (OK(aStatus, VrmlData_Scene::ReadLine(theBuffer)))
264 if (OK(aStatus, VrmlData_Faceted::readData (theBuffer)))
266 if (aStatus != VrmlData_EmptyData)
268 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorPerVertex"))
269 aStatus = ReadBoolean (theBuffer, myColorPerVertex);
270 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalPerVertex"))
271 aStatus = ReadBoolean (theBuffer, myNormalPerVertex);
272 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coordIndex"))
273 aStatus = aScene.ReadArrIndex (theBuffer, myArrPolygons, myNbPolygons);
274 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "colorIndex"))
275 aStatus = aScene.ReadArrIndex (theBuffer, myArrColorInd, myNbColors);
276 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normalIndex"))
277 aStatus = aScene.ReadArrIndex (theBuffer, myArrNormalInd, myNbNormals);
278 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoordIndex"))
279 aStatus = aScene.ReadArrIndex (theBuffer, myArrTextureInd, myNbTextures);
280 // These four checks should be the last one to avoid their interference
281 // with the other tokens (e.g., coordIndex)
282 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "texCoord"))
283 aStatus = ReadNode (theBuffer, myTxCoords,
284 STANDARD_TYPE(VrmlData_TextureCoordinate));
285 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "color"))
286 aStatus = ReadNode (theBuffer, myColors,
287 STANDARD_TYPE(VrmlData_Color));
288 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "coord"))
289 aStatus = ReadNode (theBuffer, myCoords,
290 STANDARD_TYPE(VrmlData_Coordinate));
291 else if (VRMLDATA_LCOMPARE (theBuffer.LinePtr, "normal"))
292 aStatus = ReadNode (theBuffer, myNormals,
293 STANDARD_TYPE(VrmlData_Normal));
297 // Read the terminating (closing) brace
298 if (OK(aStatus) || aStatus == VrmlData_EmptyData)
299 if (OK(aStatus, readBrace (theBuffer))) {
306 // //=======================================================================
307 // //function : dummyReadBrackets
308 // //purpose : static (local) function
309 // //=======================================================================
311 // VrmlData_ErrorStatus dummyReadBrackets (VrmlData_InBuffer& theBuffer)
313 // VrmlData_ErrorStatus aStatus;
314 // Standard_Integer aLevelCounter (0);
315 // // This loop searches for any opening bracket.
316 // // Such bracket increments the level counter. A closing bracket decrements
317 // // the counter. The loop terminates when the counter becomes zero.
318 // while ((aStatus = VrmlData_Scene::ReadLine(theBuffer)) == VrmlData_StatusOK)
321 // while ((aChar = theBuffer.LinePtr[0]) != '\0') {
322 // theBuffer.LinePtr++;
323 // if (aChar == '[') {
326 // } else if (aChar == ']') {
331 // if (aLevelCounter <= 0)
337 //=======================================================================
338 //function : IsDefault
340 //=======================================================================
342 Standard_Boolean VrmlData_IndexedFaceSet::IsDefault () const
344 Standard_Boolean aResult (Standard_True);
346 aResult = Standard_False;
347 else if (myCoords.IsNull() == Standard_False)
348 aResult = myCoords->IsDefault();
352 //=======================================================================
355 //=======================================================================
357 VrmlData_ErrorStatus VrmlData_IndexedFaceSet::Write
358 (const char * thePrefix) const
360 static char header[] = "IndexedFaceSet {";
361 const VrmlData_Scene& aScene = Scene();
362 VrmlData_ErrorStatus aStatus;
363 if (OK (aStatus, aScene.WriteLine (thePrefix, header, GlobalIndent()))) {
365 // Write the attributes of interface "VrmlData_Faceted"
366 if (IsCCW() == Standard_False)
367 aStatus = aScene.WriteLine ("ccw FALSE");
368 if (OK(aStatus) && IsSolid() == Standard_False)
369 aStatus = aScene.WriteLine ("solid FALSE");
370 if (OK(aStatus) && IsConvex() == Standard_False)
371 aStatus = aScene.WriteLine ("convex FALSE");
372 if (OK(aStatus) && CreaseAngle() > Precision::Confusion()) {
374 sprintf (buf, "%.9g", CreaseAngle());
375 aStatus = aScene.WriteLine ("creaseAngle", buf);
378 if (OK(aStatus) && myCoords.IsNull() == Standard_False)
379 aStatus = aScene.WriteNode ("coord", myCoords);
381 aStatus = aScene.WriteArrIndex ("coordIndex", myArrPolygons,myNbPolygons);
383 if (OK(aStatus) && myNormalPerVertex == Standard_False)
384 aStatus = aScene.WriteLine ("normalPerVertex FALSE");
385 if (OK(aStatus) && myNormals.IsNull() == Standard_False)
386 aStatus = aScene.WriteNode ("normal", myNormals);
388 aStatus = aScene.WriteArrIndex ("normalIndex",myArrNormalInd,myNbNormals);
390 if (OK(aStatus) && myColorPerVertex == Standard_False)
391 aStatus = aScene.WriteLine ("colorPerVertex FALSE");
392 if (OK(aStatus) && myColors.IsNull() == Standard_False)
393 aStatus = aScene.WriteNode ("color", myColors);
395 aStatus = aScene.WriteArrIndex ("colorIndex", myArrColorInd, myNbColors);
397 if (OK(aStatus) && myTxCoords.IsNull() == Standard_False)
398 aStatus = aScene.WriteNode ("texCoord", myTxCoords);
400 aStatus = aScene.WriteArrIndex ("texCoordIndex", myArrTextureInd,
403 aStatus = WriteClosing();
408 //=======================================================================
409 //function : GetColor
411 //=======================================================================
413 Quantity_Color VrmlData_IndexedFaceSet::GetColor
414 (const Standard_Integer /*iFace*/,
415 const Standard_Integer /*iVertex*/)
418 return Quantity_NOC_BLACK;