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 <NCollection_AlignedAllocator.hxx>
30 #include <TCollection_AsciiString.hxx>
35 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPrimitives, Standard_Transient)
37 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPoints, Graphic3d_ArrayOfPrimitives)
38 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfSegments, Graphic3d_ArrayOfPrimitives)
39 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolylines, Graphic3d_ArrayOfPrimitives)
40 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangles, Graphic3d_ArrayOfPrimitives)
41 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangleStrips, Graphic3d_ArrayOfPrimitives)
42 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfTriangleFans, Graphic3d_ArrayOfPrimitives)
43 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangles, Graphic3d_ArrayOfPrimitives)
44 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangleStrips, Graphic3d_ArrayOfPrimitives)
45 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolygons, Graphic3d_ArrayOfPrimitives)
47 // =======================================================================
48 // function : CreateArray
50 // =======================================================================
51 Handle(Graphic3d_ArrayOfPrimitives) Graphic3d_ArrayOfPrimitives::CreateArray (Graphic3d_TypeOfPrimitiveArray theType,
52 Standard_Integer theMaxVertexs,
53 Standard_Integer theMaxBounds,
54 Standard_Integer theMaxEdges,
55 Graphic3d_ArrayFlags theArrayFlags)
59 case Graphic3d_TOPA_UNDEFINED:
60 return Handle(Graphic3d_ArrayOfPrimitives)();
61 case Graphic3d_TOPA_POINTS:
62 return new Graphic3d_ArrayOfPoints (theMaxVertexs, theArrayFlags);
63 case Graphic3d_TOPA_SEGMENTS:
64 return new Graphic3d_ArrayOfSegments (theMaxVertexs, theMaxEdges, theArrayFlags);
65 case Graphic3d_TOPA_POLYLINES:
66 return new Graphic3d_ArrayOfPolylines (theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
67 case Graphic3d_TOPA_TRIANGLES:
68 return new Graphic3d_ArrayOfTriangles (theMaxVertexs, theMaxEdges, theArrayFlags);
69 case Graphic3d_TOPA_TRIANGLESTRIPS:
70 return new Graphic3d_ArrayOfTriangleStrips (theMaxVertexs, theMaxBounds, theArrayFlags);
71 case Graphic3d_TOPA_TRIANGLEFANS:
72 return new Graphic3d_ArrayOfTriangleFans (theMaxVertexs, theMaxBounds, theArrayFlags);
73 case Graphic3d_TOPA_LINES_ADJACENCY:
74 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
75 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
76 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
77 return new Graphic3d_ArrayOfPrimitives (theType, theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
78 case Graphic3d_TOPA_QUADRANGLES:
79 return new Graphic3d_ArrayOfQuadrangles (theMaxVertexs, theMaxEdges, theArrayFlags);
80 case Graphic3d_TOPA_QUADRANGLESTRIPS:
81 return new Graphic3d_ArrayOfQuadrangleStrips (theMaxVertexs, theMaxBounds, theArrayFlags);
82 case Graphic3d_TOPA_POLYGONS:
83 return new Graphic3d_ArrayOfPolygons (theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
85 return Handle(Graphic3d_ArrayOfPrimitives)();
88 // =======================================================================
91 // =======================================================================
92 void Graphic3d_ArrayOfPrimitives::init (Graphic3d_TypeOfPrimitiveArray theType,
93 Standard_Integer theMaxVertexs,
94 Standard_Integer theMaxBounds,
95 Standard_Integer theMaxEdges,
96 Graphic3d_ArrayFlags theArrayOptions)
106 Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
107 if ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) != 0
108 || (theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) != 0)
110 Graphic3d_AttribBuffer* anAttribs = new Graphic3d_AttribBuffer (anAlloc);
111 anAttribs->SetMutable ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) != 0);
112 anAttribs->SetInterleaved ((theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) == 0);
113 myAttribs = anAttribs;
117 myAttribs = new Graphic3d_Buffer (anAlloc);
119 if (theMaxVertexs < 1)
126 if ((theArrayOptions & Graphic3d_ArrayFlags_IndexesMutable) != 0)
128 myIndices = new Graphic3d_MutableIndexBuffer (anAlloc);
132 myIndices = new Graphic3d_IndexBuffer (anAlloc);
134 if (theMaxVertexs < Standard_Integer(USHRT_MAX))
136 if (!myIndices->Init<unsigned short> (theMaxEdges))
144 if (!myIndices->Init<unsigned int> (theMaxEdges))
150 myIndices->NbElements = 0;
153 Graphic3d_Attribute anAttribs[4];
154 Standard_Integer aNbAttribs = 0;
155 anAttribs[aNbAttribs].Id = Graphic3d_TOA_POS;
156 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
158 if ((theArrayOptions & Graphic3d_ArrayFlags_VertexNormal) != 0)
160 anAttribs[aNbAttribs].Id = Graphic3d_TOA_NORM;
161 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
164 if ((theArrayOptions & Graphic3d_ArrayFlags_VertexTexel) != 0)
166 anAttribs[aNbAttribs].Id = Graphic3d_TOA_UV;
167 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC2;
170 if ((theArrayOptions & Graphic3d_ArrayFlags_VertexColor) != 0)
172 anAttribs[aNbAttribs].Id = Graphic3d_TOA_COLOR;
173 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC4UB;
177 if (!myAttribs->Init (theMaxVertexs, anAttribs, aNbAttribs))
184 Standard_Integer anAttribDummy = 0;
185 myAttribs->ChangeAttributeData (Graphic3d_TOA_POS, anAttribDummy, myPosStride);
186 myNormData = myAttribs->ChangeAttributeData (Graphic3d_TOA_NORM, anAttribDummy, myNormStride);
187 myTexData = myAttribs->ChangeAttributeData (Graphic3d_TOA_UV, anAttribDummy, myTexStride);
188 myColData = myAttribs->ChangeAttributeData (Graphic3d_TOA_COLOR, anAttribDummy, myColStride);
190 memset (myAttribs->ChangeData(), 0, size_t(myAttribs->Stride) * size_t(myAttribs->NbMaxElements()));
191 if ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) == 0
192 && (theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) == 0)
194 myAttribs->NbElements = 0;
197 if (theMaxBounds > 0)
199 myBounds = new Graphic3d_BoundBuffer (anAlloc);
200 if (!myBounds->Init (theMaxBounds, (theArrayOptions & Graphic3d_ArrayFlags_BoundColor) != 0))
207 myBounds->NbBounds = 0;
211 // =======================================================================
212 // function : ~Graphic3d_ArrayOfPrimitives
214 // =======================================================================
215 Graphic3d_ArrayOfPrimitives::~Graphic3d_ArrayOfPrimitives()
222 // =======================================================================
223 // function : AddBound
225 // =======================================================================
226 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber)
228 Standard_OutOfRange_Raise_if (myBounds.IsNull() || myBounds->NbBounds >= myBounds->NbMaxBounds, "TOO many BOUND");
229 myBounds->Bounds[myBounds->NbBounds] = theEdgeNumber;
230 return ++myBounds->NbBounds;
233 // =======================================================================
234 // function : AddBound
236 // =======================================================================
237 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber,
238 const Standard_Real theR,
239 const Standard_Real theG,
240 const Standard_Real theB)
242 Standard_OutOfRange_Raise_if (myBounds.IsNull() || myBounds->NbBounds >= myBounds->NbMaxBounds, "TOO many BOUND");
243 myBounds->Bounds[myBounds->NbBounds] = theEdgeNumber;
244 ++myBounds->NbBounds;
245 SetBoundColor (myBounds->NbBounds, theR, theG, theB);
246 return myBounds->NbBounds;
249 // =======================================================================
250 // function : AddEdge
252 // =======================================================================
253 Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge (const Standard_Integer theVertexIndex)
255 Standard_OutOfRange_Raise_if (myIndices.IsNull() || myIndices->NbElements >= myIndices->NbMaxElements(), "TOO many EDGE");
256 Standard_OutOfRange_Raise_if (theVertexIndex < 1 || theVertexIndex > myAttribs->NbElements, "BAD VERTEX index");
257 const Standard_Integer aVertIndex = theVertexIndex - 1;
258 myIndices->SetIndex (myIndices->NbElements, aVertIndex);
259 return ++myIndices->NbElements;
262 // =======================================================================
263 // function : AddTriangleStripEdges
265 // =======================================================================
266 void Graphic3d_ArrayOfPrimitives::AddTriangleStripEdges (Standard_Integer theVertexLower,
267 Standard_Integer theVertexUpper)
269 if (myType != Graphic3d_TOPA_TRIANGLES)
271 throw Standard_TypeMismatch ("Not array of triangles");
274 Standard_Boolean isOdd = Standard_True;
275 for (Standard_Integer aNodeIter = theVertexLower + 2; aNodeIter <= theVertexUpper; ++aNodeIter)
279 AddTriangleEdges (aNodeIter - 2, aNodeIter - 1, aNodeIter);
283 AddTriangleEdges (aNodeIter - 1, aNodeIter - 2, aNodeIter);
289 // =======================================================================
290 // function : AddTriangleFanEdges
292 // =======================================================================
293 void Graphic3d_ArrayOfPrimitives::AddTriangleFanEdges (Standard_Integer theVertexLower,
294 Standard_Integer theVertexUpper,
295 Standard_Boolean theToClose)
297 if (myType != Graphic3d_TOPA_TRIANGLES)
299 throw Standard_TypeMismatch ("Not array of triangles");
302 for (Standard_Integer aNodeIter = theVertexLower + 1; aNodeIter <= theVertexUpper; ++aNodeIter)
304 AddTriangleEdges (theVertexLower, aNodeIter - 1, aNodeIter);
308 AddTriangleEdges (theVertexLower, theVertexUpper, theVertexLower + 1);
312 // =======================================================================
313 // function : AddPolylineEdges
315 // =======================================================================
316 void Graphic3d_ArrayOfPrimitives::AddPolylineEdges (Standard_Integer theVertexLower,
317 Standard_Integer theVertexUpper,
318 Standard_Boolean theToClose)
320 if (myType != Graphic3d_TOPA_SEGMENTS)
322 throw Standard_TypeMismatch ("Not array of segments");
325 for (Standard_Integer aNodeIter = theVertexLower; aNodeIter < theVertexUpper; ++aNodeIter)
327 AddSegmentEdges (aNodeIter, aNodeIter + 1);
331 AddSegmentEdges (theVertexUpper, theVertexLower);
335 // =======================================================================
336 // function : StringType
338 // =======================================================================
339 Standard_CString Graphic3d_ArrayOfPrimitives::StringType() const
343 case Graphic3d_TOPA_POINTS: return "ArrayOfPoints";
344 case Graphic3d_TOPA_SEGMENTS: return "ArrayOfSegments";
345 case Graphic3d_TOPA_POLYLINES: return "ArrayOfPolylines";
346 case Graphic3d_TOPA_TRIANGLES: return "ArrayOfTriangles";
347 case Graphic3d_TOPA_TRIANGLESTRIPS: return "ArrayOfTriangleStrips";
348 case Graphic3d_TOPA_TRIANGLEFANS: return "ArrayOfTriangleFans";
349 case Graphic3d_TOPA_LINES_ADJACENCY: return "ArrayOfLinesAdjacency";
350 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY: return "ArrayOfLineStripAdjacency";
351 case Graphic3d_TOPA_TRIANGLES_ADJACENCY: return "ArrayOfTrianglesAdjacency";
352 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY: return "ArrayOfTriangleStripAdjacency";
353 case Graphic3d_TOPA_QUADRANGLES: return "ArrayOfQuadrangles";
354 case Graphic3d_TOPA_QUADRANGLESTRIPS: return "ArrayOfQuadrangleStrips";
355 case Graphic3d_TOPA_POLYGONS: return "ArrayOfPolygons";
356 case Graphic3d_TOPA_UNDEFINED: return "UndefinedArray";
358 return "UndefinedArray";
361 // =======================================================================
362 // function : ItemNumber
364 // =======================================================================
365 Standard_Integer Graphic3d_ArrayOfPrimitives::ItemNumber() const
367 if (myAttribs.IsNull())
374 case Graphic3d_TOPA_POINTS: return myAttribs->NbElements;
375 case Graphic3d_TOPA_POLYLINES:
376 case Graphic3d_TOPA_POLYGONS: return !myBounds.IsNull() ? myBounds->NbBounds : 1;
377 case Graphic3d_TOPA_SEGMENTS: return myIndices.IsNull() || myIndices->NbElements < 1
378 ? myAttribs->NbElements / 2
379 : myIndices->NbElements / 2;
380 case Graphic3d_TOPA_TRIANGLES: return myIndices.IsNull() || myIndices->NbElements < 1
381 ? myAttribs->NbElements / 3
382 : myIndices->NbElements / 3;
383 case Graphic3d_TOPA_QUADRANGLES: return myIndices.IsNull() || myIndices->NbElements < 1
384 ? myAttribs->NbElements / 4
385 : myIndices->NbElements / 4;
386 case Graphic3d_TOPA_TRIANGLESTRIPS: return !myBounds.IsNull()
387 ? myAttribs->NbElements - 2 * myBounds->NbBounds
388 : myAttribs->NbElements - 2;
389 case Graphic3d_TOPA_QUADRANGLESTRIPS: return !myBounds.IsNull()
390 ? myAttribs->NbElements / 2 - myBounds->NbBounds
391 : myAttribs->NbElements / 2 - 1;
392 case Graphic3d_TOPA_TRIANGLEFANS: return !myBounds.IsNull()
393 ? myAttribs->NbElements - 2 * myBounds->NbBounds
394 : myAttribs->NbElements - 2;
395 case Graphic3d_TOPA_LINES_ADJACENCY: return myIndices.IsNull() || myIndices->NbElements < 1
396 ? myAttribs->NbElements / 4
397 : myIndices->NbElements / 4;
398 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY: return !myBounds.IsNull()
399 ? myAttribs->NbElements - 4 * myBounds->NbBounds
400 : myAttribs->NbElements - 4;
401 case Graphic3d_TOPA_TRIANGLES_ADJACENCY: return myIndices.IsNull() || myIndices->NbElements < 1
402 ? myAttribs->NbElements / 6
403 : myIndices->NbElements / 6;
404 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY: return !myBounds.IsNull()
405 ? myAttribs->NbElements - 4 * myBounds->NbBounds
406 : myAttribs->NbElements - 4;
407 case Graphic3d_TOPA_UNDEFINED: return -1;
412 // =======================================================================
413 // function : IsValid
415 // =======================================================================
416 Standard_Boolean Graphic3d_ArrayOfPrimitives::IsValid()
418 if (myAttribs.IsNull())
420 return Standard_False;
423 Standard_Integer nvertexs = myAttribs->NbElements;
424 Standard_Integer nbounds = myBounds.IsNull() ? 0 : myBounds->NbBounds;
425 Standard_Integer nedges = myIndices.IsNull() ? 0 : myIndices->NbElements;
428 case Graphic3d_TOPA_POINTS:
431 return Standard_False;
434 case Graphic3d_TOPA_POLYLINES:
438 return Standard_False;
442 return Standard_False;
445 case Graphic3d_TOPA_SEGMENTS:
448 return Standard_False;
451 case Graphic3d_TOPA_POLYGONS:
455 return Standard_False;
459 return Standard_False;
462 case Graphic3d_TOPA_TRIANGLES:
470 return Standard_False;
472 myIndices->NbElements = 3 * (nedges / 3);
475 else if (nvertexs < 3
476 || nvertexs % 3 != 0 )
480 return Standard_False;
482 myAttribs->NbElements = 3 * (nvertexs / 3);
485 case Graphic3d_TOPA_QUADRANGLES:
493 return Standard_False;
495 myIndices->NbElements = 4 * (nedges / 4);
498 else if (nvertexs < 4
499 || nvertexs % 4 != 0)
503 return Standard_False;
505 myAttribs->NbElements = 4 * (nvertexs / 4);
508 case Graphic3d_TOPA_TRIANGLEFANS:
509 case Graphic3d_TOPA_TRIANGLESTRIPS:
512 return Standard_False;
515 case Graphic3d_TOPA_QUADRANGLESTRIPS:
518 return Standard_False;
521 case Graphic3d_TOPA_LINES_ADJACENCY:
522 case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
525 return Standard_False;
528 case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
529 case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
532 return Standard_False;
535 case Graphic3d_TOPA_UNDEFINED:
537 return Standard_False;
540 // total number of edges(vertices) in bounds should be the same as variable
541 // of total number of defined edges(vertices); if no edges - only vertices
542 // could be in bounds.
545 Standard_Integer n = 0;
546 for (Standard_Integer aBoundIter = 0; aBoundIter < nbounds; ++aBoundIter)
548 n += myBounds->Bounds[aBoundIter];
555 return Standard_False;
557 myIndices->NbElements = n;
564 return Standard_False;
566 myAttribs->NbElements = n;
570 // check that edges (indexes to an array of vertices) are in range.
573 for (Standard_Integer anEdgeIter = 0; anEdgeIter < nedges; ++anEdgeIter)
575 if (myIndices->Index (anEdgeIter) >= myAttribs->NbElements)
577 return Standard_False;
581 return Standard_True;