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 | |
28 | IMPLEMENT_STANDARD_HANDLE (VrmlData_Faceted, VrmlData_Geometry) |
29 | IMPLEMENT_STANDARD_RTTIEXT (VrmlData_Faceted, VrmlData_Geometry) |
30 | IMPLEMENT_STANDARD_HANDLE (VrmlData_IndexedFaceSet, VrmlData_Faceted) |
31 | IMPLEMENT_STANDARD_RTTIEXT (VrmlData_IndexedFaceSet, VrmlData_Faceted) |
32 | |
33 | //======================================================================= |
34 | //function : readData |
35 | //purpose : |
36 | //======================================================================= |
37 | |
38 | VrmlData_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 | |
68 | const 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 | |
195 | Handle(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 | |
242 | VrmlData_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 | |
326 | Standard_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 | |
341 | VrmlData_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 | |
397 | Quantity_Color VrmlData_IndexedFaceSet::GetColor |
398 | (const Standard_Integer /*iFace*/, |
399 | const Standard_Integer /*iVertex*/) |
400 | { |
401 | //TODO |
402 | return Quantity_NOC_BLACK; |
403 | } |
404 | |