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