1 // Created on: 2000-06-16
2 // Copyright (c) 2000-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <Graphic3d_ArrayOfPrimitives.hxx>
17 #include <Graphic3d_ArrayOfPoints.hxx>
18 #include <Graphic3d_ArrayOfSegments.hxx>
19 #include <Graphic3d_ArrayOfPolylines.hxx>
20 #include <Graphic3d_ArrayOfTriangles.hxx>
21 #include <Graphic3d_ArrayOfTriangleStrips.hxx>
22 #include <Graphic3d_ArrayOfTriangleFans.hxx>
23 #include <Graphic3d_ArrayOfQuadrangles.hxx>
24 #include <Graphic3d_ArrayOfQuadrangleStrips.hxx>
25 #include <Graphic3d_ArrayOfPolygons.hxx>
26 #include <Graphic3d_AttribBuffer.hxx>
27 #include <Graphic3d_MutableIndexBuffer.hxx>
29 #include <TCollection_AsciiString.hxx>
34 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPrimitives, Standard_Transient)
36 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPoints, Graphic3d_ArrayOfPrimitives)
37 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfSegments, Graphic3d_ArrayOfPrimitives)
38 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolylines, Graphic3d_ArrayOfPrimitives)
39 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangles, Graphic3d_ArrayOfPrimitives)
40 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangleStrips, Graphic3d_ArrayOfPrimitives)
41 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangleFans, Graphic3d_ArrayOfPrimitives)
42 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangles, Graphic3d_ArrayOfPrimitives)
43 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangleStrips, Graphic3d_ArrayOfPrimitives)
44 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolygons, Graphic3d_ArrayOfPrimitives)
46 // =======================================================================
47 // function : CreateArray
49 // =======================================================================
50 Handle(Graphic3d_ArrayOfPrimitives) Graphic3d_ArrayOfPrimitives::CreateArray (Graphic3d_TypeOfPrimitiveArray theType,
51 Standard_Integer theMaxVertexs,
52 Standard_Integer theMaxBounds,
53 Standard_Integer theMaxEdges,
54 Graphic3d_ArrayFlags theArrayFlags)
58 case Graphic3d_TOPA_UNDEFINED:
59 return Handle(Graphic3d_ArrayOfPrimitives)();
60 case Graphic3d_TOPA_POINTS:
61 return new Graphic3d_ArrayOfPoints (theMaxVertexs, theArrayFlags);
62 case Graphic3d_TOPA_SEGMENTS:
63 return new Graphic3d_ArrayOfSegments (theMaxVertexs, theMaxEdges, theArrayFlags);
64 case Graphic3d_TOPA_POLYLINES:
65 return new Graphic3d_ArrayOfPolylines (theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
66 case Graphic3d_TOPA_TRIANGLES:
67 return new Graphic3d_ArrayOfTriangles (theMaxVertexs, theMaxEdges, theArrayFlags);
68 case Graphic3d_TOPA_TRIANGLESTRIPS:
69 return new Graphic3d_ArrayOfTriangleStrips (theMaxVertexs, theMaxBounds, theArrayFlags);
70 case Graphic3d_TOPA_TRIANGLEFANS:
71 return new Graphic3d_ArrayOfTriangleFans (theMaxVertexs, theMaxBounds, theArrayFlags);
72 case Graphic3d_TOPA_LINES_ADJACENCY:
73 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
74 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
75 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
76 return new Graphic3d_ArrayOfPrimitives (theType, theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
77 case Graphic3d_TOPA_QUADRANGLES:
78 return new Graphic3d_ArrayOfQuadrangles (theMaxVertexs, theMaxEdges, theArrayFlags);
79 case Graphic3d_TOPA_QUADRANGLESTRIPS:
80 return new Graphic3d_ArrayOfQuadrangleStrips (theMaxVertexs, theMaxBounds, theArrayFlags);
81 case Graphic3d_TOPA_POLYGONS:
82 return new Graphic3d_ArrayOfPolygons (theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
84 return Handle(Graphic3d_ArrayOfPrimitives)();
87 // =======================================================================
90 // =======================================================================
91 void Graphic3d_ArrayOfPrimitives::init (Graphic3d_TypeOfPrimitiveArray theType,
92 Standard_Integer theMaxVertexs,
93 Standard_Integer theMaxBounds,
94 Standard_Integer theMaxEdges,
95 Graphic3d_ArrayFlags theArrayOptions)
105 const Handle(NCollection_BaseAllocator)& anAlloc = Graphic3d_Buffer::DefaultAllocator();
106 if ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) != 0
107 || (theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) != 0)
109 Graphic3d_AttribBuffer* anAttribs = new Graphic3d_AttribBuffer (anAlloc);
110 anAttribs->SetMutable ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) != 0);
111 anAttribs->SetInterleaved ((theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) == 0);
112 myAttribs = anAttribs;
116 myAttribs = new Graphic3d_Buffer (anAlloc);
118 if (theMaxVertexs < 1)
125 if ((theArrayOptions & Graphic3d_ArrayFlags_IndexesMutable) != 0)
127 myIndices = new Graphic3d_MutableIndexBuffer (anAlloc);
131 myIndices = new Graphic3d_IndexBuffer (anAlloc);
133 if (theMaxVertexs < Standard_Integer(USHRT_MAX))
135 if (!myIndices->Init<unsigned short> (theMaxEdges))
143 if (!myIndices->Init<unsigned int> (theMaxEdges))
149 myIndices->NbElements = 0;
152 Graphic3d_Attribute anAttribs[4];
153 Standard_Integer aNbAttribs = 0;
154 anAttribs[aNbAttribs].Id = Graphic3d_TOA_POS;
155 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
157 if ((theArrayOptions & Graphic3d_ArrayFlags_VertexNormal) != 0)
159 anAttribs[aNbAttribs].Id = Graphic3d_TOA_NORM;
160 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
163 if ((theArrayOptions & Graphic3d_ArrayFlags_VertexTexel) != 0)
165 anAttribs[aNbAttribs].Id = Graphic3d_TOA_UV;
166 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC2;
169 if ((theArrayOptions & Graphic3d_ArrayFlags_VertexColor) != 0)
171 anAttribs[aNbAttribs].Id = Graphic3d_TOA_COLOR;
172 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC4UB;
176 if (!myAttribs->Init (theMaxVertexs, anAttribs, aNbAttribs))
183 Standard_Integer anAttribDummy = 0;
184 myAttribs->ChangeAttributeData (Graphic3d_TOA_POS, anAttribDummy, myPosStride);
185 myNormData = myAttribs->ChangeAttributeData (Graphic3d_TOA_NORM, anAttribDummy, myNormStride);
186 myTexData = myAttribs->ChangeAttributeData (Graphic3d_TOA_UV, anAttribDummy, myTexStride);
187 myColData = myAttribs->ChangeAttributeData (Graphic3d_TOA_COLOR, anAttribDummy, myColStride);
189 memset (myAttribs->ChangeData(), 0, size_t(myAttribs->Stride) * size_t(myAttribs->NbMaxElements()));
190 if ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) == 0
191 && (theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) == 0)
193 myAttribs->NbElements = 0;
196 if (theMaxBounds > 0)
198 myBounds = new Graphic3d_BoundBuffer (anAlloc);
199 if (!myBounds->Init (theMaxBounds, (theArrayOptions & Graphic3d_ArrayFlags_BoundColor) != 0))
206 myBounds->NbBounds = 0;
210 // =======================================================================
211 // function : ~Graphic3d_ArrayOfPrimitives
213 // =======================================================================
214 Graphic3d_ArrayOfPrimitives::~Graphic3d_ArrayOfPrimitives()
221 // =======================================================================
222 // function : AddBound
224 // =======================================================================
225 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber)
227 Standard_OutOfRange_Raise_if (myBounds.IsNull() || myBounds->NbBounds >= myBounds->NbMaxBounds, "TOO many BOUND");
228 myBounds->Bounds[myBounds->NbBounds] = theEdgeNumber;
229 return ++myBounds->NbBounds;
232 // =======================================================================
233 // function : AddBound
235 // =======================================================================
236 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber,
237 const Standard_Real theR,
238 const Standard_Real theG,
239 const Standard_Real theB)
241 Standard_OutOfRange_Raise_if (myBounds.IsNull() || myBounds->NbBounds >= myBounds->NbMaxBounds, "TOO many BOUND");
242 myBounds->Bounds[myBounds->NbBounds] = theEdgeNumber;
243 ++myBounds->NbBounds;
244 SetBoundColor (myBounds->NbBounds, theR, theG, theB);
245 return myBounds->NbBounds;
248 // =======================================================================
249 // function : AddEdge
251 // =======================================================================
252 Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge (const Standard_Integer theVertexIndex)
254 Standard_OutOfRange_Raise_if (myIndices.IsNull() || myIndices->NbElements >= myIndices->NbMaxElements(), "TOO many EDGE");
255 Standard_OutOfRange_Raise_if (theVertexIndex < 1 || theVertexIndex > myAttribs->NbElements, "BAD VERTEX index");
256 const Standard_Integer aVertIndex = theVertexIndex - 1;
257 myIndices->SetIndex (myIndices->NbElements, aVertIndex);
258 return ++myIndices->NbElements;
261 // =======================================================================
262 // function : AddTriangleStripEdges
264 // =======================================================================
265 void Graphic3d_ArrayOfPrimitives::AddTriangleStripEdges (Standard_Integer theVertexLower,
266 Standard_Integer theVertexUpper)
268 if (myType != Graphic3d_TOPA_TRIANGLES)
270 throw Standard_TypeMismatch ("Not array of triangles");
273 Standard_Boolean isOdd = Standard_True;
274 for (Standard_Integer aNodeIter = theVertexLower + 2; aNodeIter <= theVertexUpper; ++aNodeIter)
278 AddTriangleEdges (aNodeIter - 2, aNodeIter - 1, aNodeIter);
282 AddTriangleEdges (aNodeIter - 1, aNodeIter - 2, aNodeIter);
288 // =======================================================================
289 // function : AddTriangleFanEdges
291 // =======================================================================
292 void Graphic3d_ArrayOfPrimitives::AddTriangleFanEdges (Standard_Integer theVertexLower,
293 Standard_Integer theVertexUpper,
294 Standard_Boolean theToClose)
296 if (myType != Graphic3d_TOPA_TRIANGLES)
298 throw Standard_TypeMismatch ("Not array of triangles");
301 for (Standard_Integer aNodeIter = theVertexLower + 1; aNodeIter <= theVertexUpper; ++aNodeIter)
303 AddTriangleEdges (theVertexLower, aNodeIter - 1, aNodeIter);
307 AddTriangleEdges (theVertexLower, theVertexUpper, theVertexLower + 1);
311 // =======================================================================
312 // function : AddPolylineEdges
314 // =======================================================================
315 void Graphic3d_ArrayOfPrimitives::AddPolylineEdges (Standard_Integer theVertexLower,
316 Standard_Integer theVertexUpper,
317 Standard_Boolean theToClose)
319 if (myType != Graphic3d_TOPA_SEGMENTS)
321 throw Standard_TypeMismatch ("Not array of segments");
324 for (Standard_Integer aNodeIter = theVertexLower; aNodeIter < theVertexUpper; ++aNodeIter)
326 AddSegmentEdges (aNodeIter, aNodeIter + 1);
330 AddSegmentEdges (theVertexUpper, theVertexLower);
334 // =======================================================================
335 // function : StringType
337 // =======================================================================
338 Standard_CString Graphic3d_ArrayOfPrimitives::StringType() const
342 case Graphic3d_TOPA_POINTS: return "ArrayOfPoints";
343 case Graphic3d_TOPA_SEGMENTS: return "ArrayOfSegments";
344 case Graphic3d_TOPA_POLYLINES: return "ArrayOfPolylines";
345 case Graphic3d_TOPA_TRIANGLES: return "ArrayOfTriangles";
346 case Graphic3d_TOPA_TRIANGLESTRIPS: return "ArrayOfTriangleStrips";
347 case Graphic3d_TOPA_TRIANGLEFANS: return "ArrayOfTriangleFans";
348 case Graphic3d_TOPA_LINES_ADJACENCY: return "ArrayOfLinesAdjacency";
349 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY: return "ArrayOfLineStripAdjacency";
350 case Graphic3d_TOPA_TRIANGLES_ADJACENCY: return "ArrayOfTrianglesAdjacency";
351 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY: return "ArrayOfTriangleStripAdjacency";
352 case Graphic3d_TOPA_QUADRANGLES: return "ArrayOfQuadrangles";
353 case Graphic3d_TOPA_QUADRANGLESTRIPS: return "ArrayOfQuadrangleStrips";
354 case Graphic3d_TOPA_POLYGONS: return "ArrayOfPolygons";
355 case Graphic3d_TOPA_UNDEFINED: return "UndefinedArray";
357 return "UndefinedArray";
360 // =======================================================================
361 // function : ItemNumber
363 // =======================================================================
364 Standard_Integer Graphic3d_ArrayOfPrimitives::ItemNumber() const
366 if (myAttribs.IsNull())
373 case Graphic3d_TOPA_POINTS: return myAttribs->NbElements;
374 case Graphic3d_TOPA_POLYLINES:
375 case Graphic3d_TOPA_POLYGONS: return !myBounds.IsNull() ? myBounds->NbBounds : 1;
376 case Graphic3d_TOPA_SEGMENTS: return myIndices.IsNull() || myIndices->NbElements < 1
377 ? myAttribs->NbElements / 2
378 : myIndices->NbElements / 2;
379 case Graphic3d_TOPA_TRIANGLES: return myIndices.IsNull() || myIndices->NbElements < 1
380 ? myAttribs->NbElements / 3
381 : myIndices->NbElements / 3;
382 case Graphic3d_TOPA_QUADRANGLES: return myIndices.IsNull() || myIndices->NbElements < 1
383 ? myAttribs->NbElements / 4
384 : myIndices->NbElements / 4;
385 case Graphic3d_TOPA_TRIANGLESTRIPS: return !myBounds.IsNull()
386 ? myAttribs->NbElements - 2 * myBounds->NbBounds
387 : myAttribs->NbElements - 2;
388 case Graphic3d_TOPA_QUADRANGLESTRIPS: return !myBounds.IsNull()
389 ? myAttribs->NbElements / 2 - myBounds->NbBounds
390 : myAttribs->NbElements / 2 - 1;
391 case Graphic3d_TOPA_TRIANGLEFANS: return !myBounds.IsNull()
392 ? myAttribs->NbElements - 2 * myBounds->NbBounds
393 : myAttribs->NbElements - 2;
394 case Graphic3d_TOPA_LINES_ADJACENCY: return myIndices.IsNull() || myIndices->NbElements < 1
395 ? myAttribs->NbElements / 4
396 : myIndices->NbElements / 4;
397 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY: return !myBounds.IsNull()
398 ? myAttribs->NbElements - 4 * myBounds->NbBounds
399 : myAttribs->NbElements - 4;
400 case Graphic3d_TOPA_TRIANGLES_ADJACENCY: return myIndices.IsNull() || myIndices->NbElements < 1
401 ? myAttribs->NbElements / 6
402 : myIndices->NbElements / 6;
403 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY: return !myBounds.IsNull()
404 ? myAttribs->NbElements - 4 * myBounds->NbBounds
405 : myAttribs->NbElements - 4;
406 case Graphic3d_TOPA_UNDEFINED: return -1;
411 // =======================================================================
412 // function : IsValid
414 // =======================================================================
415 Standard_Boolean Graphic3d_ArrayOfPrimitives::IsValid()
417 if (myAttribs.IsNull())
419 return Standard_False;
422 Standard_Integer nvertexs = myAttribs->NbElements;
423 Standard_Integer nbounds = myBounds.IsNull() ? 0 : myBounds->NbBounds;
424 Standard_Integer nedges = myIndices.IsNull() ? 0 : myIndices->NbElements;
427 case Graphic3d_TOPA_POINTS:
430 return Standard_False;
433 case Graphic3d_TOPA_POLYLINES:
437 return Standard_False;
441 return Standard_False;
444 case Graphic3d_TOPA_SEGMENTS:
447 return Standard_False;
450 case Graphic3d_TOPA_POLYGONS:
454 return Standard_False;
458 return Standard_False;
461 case Graphic3d_TOPA_TRIANGLES:
469 return Standard_False;
471 myIndices->NbElements = 3 * (nedges / 3);
474 else if (nvertexs < 3
475 || nvertexs % 3 != 0 )
479 return Standard_False;
481 myAttribs->NbElements = 3 * (nvertexs / 3);
484 case Graphic3d_TOPA_QUADRANGLES:
492 return Standard_False;
494 myIndices->NbElements = 4 * (nedges / 4);
497 else if (nvertexs < 4
498 || nvertexs % 4 != 0)
502 return Standard_False;
504 myAttribs->NbElements = 4 * (nvertexs / 4);
507 case Graphic3d_TOPA_TRIANGLEFANS:
508 case Graphic3d_TOPA_TRIANGLESTRIPS:
511 return Standard_False;
514 case Graphic3d_TOPA_QUADRANGLESTRIPS:
517 return Standard_False;
520 case Graphic3d_TOPA_LINES_ADJACENCY:
521 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
524 return Standard_False;
527 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
528 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
531 return Standard_False;
534 case Graphic3d_TOPA_UNDEFINED:
536 return Standard_False;
539 // total number of edges(vertices) in bounds should be the same as variable
540 // of total number of defined edges(vertices); if no edges - only vertices
541 // could be in bounds.
544 Standard_Integer n = 0;
545 for (Standard_Integer aBoundIter = 0; aBoundIter < nbounds; ++aBoundIter)
547 n += myBounds->Bounds[aBoundIter];
554 return Standard_False;
556 myIndices->NbElements = n;
563 return Standard_False;
565 myAttribs->NbElements = n;
569 // check that edges (indexes to an array of vertices) are in range.
572 for (Standard_Integer anEdgeIter = 0; anEdgeIter < nedges; ++anEdgeIter)
574 if (myIndices->Index (anEdgeIter) >= myAttribs->NbElements)
576 return Standard_False;
580 return Standard_True;