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.ixx>
16 #include <Standard.hxx>
17 #include <TCollection_AsciiString.hxx>
18 #include <OSD_Environment.hxx>
19 #include <NCollection_AlignedAllocator.hxx>
24 Graphic3d_ArrayOfPrimitives::Graphic3d_ArrayOfPrimitives (const Graphic3d_TypeOfPrimitiveArray theType,
25 const Standard_Integer theMaxVertexs,
26 const Standard_Integer theMaxBounds,
27 const Standard_Integer theMaxEdges,
28 const Standard_Boolean theHasVNormals,
29 const Standard_Boolean theHasVColors,
30 const Standard_Boolean theHasFColors,
31 const Standard_Boolean theHasVTexels)
40 Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
41 myAttribs = new Graphic3d_Buffer (anAlloc);
42 if (theMaxVertexs < 1)
49 myIndices = new Graphic3d_IndexBuffer (anAlloc);
50 if (theMaxEdges < Standard_Integer(USHRT_MAX))
52 if (!myIndices->Init<unsigned short> (theMaxEdges))
60 if (!myIndices->Init<unsigned int> (theMaxEdges))
66 myIndices->NbElements = 0;
69 Graphic3d_Attribute anAttribs[4];
70 Standard_Integer aNbAttribs = 0;
71 anAttribs[aNbAttribs].Id = Graphic3d_TOA_POS;
72 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
76 anAttribs[aNbAttribs].Id = Graphic3d_TOA_NORM;
77 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC3;
82 anAttribs[aNbAttribs].Id = Graphic3d_TOA_UV;
83 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC2;
88 anAttribs[aNbAttribs].Id = Graphic3d_TOA_COLOR;
89 anAttribs[aNbAttribs].DataType = Graphic3d_TOD_VEC4UB;
93 if (!myAttribs->Init (theMaxVertexs, anAttribs, aNbAttribs))
99 memset (myAttribs->ChangeData (0), 0, myAttribs->Stride * myAttribs->NbElements);
101 if (theMaxBounds > 0)
103 myBounds = new Graphic3d_BoundBuffer (anAlloc);
104 if (!myBounds->Init (theMaxBounds, theHasFColors))
111 myBounds->NbBounds = 0;
114 for (Standard_Integer anAttribIter = 0; anAttribIter < aNbAttribs; ++anAttribIter)
116 const Graphic3d_Attribute& anAttrib = anAttribs[anAttribIter];
119 case Graphic3d_TOA_POS:
120 case Graphic3d_TOA_CUSTOM:
122 case Graphic3d_TOA_NORM:
124 myVNor = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
127 case Graphic3d_TOA_UV:
129 myVTex = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
132 case Graphic3d_TOA_COLOR:
134 myVCol = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
140 myAttribs->NbElements = 0;
141 myMaxVertexs = theMaxVertexs;
142 myMaxBounds = theMaxBounds;
143 myMaxEdges = theMaxEdges;
146 void Graphic3d_ArrayOfPrimitives::Destroy()
156 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const Standard_ShortReal theX,
157 const Standard_ShortReal theY,
158 const Standard_ShortReal theZ)
160 if (myAttribs.IsNull())
165 const Standard_Integer anIndex = myAttribs->NbElements + 1;
166 SetVertice (anIndex, theX, theY, theZ);
170 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const gp_Pnt& theVertex,
171 const Quantity_Color& theColor)
173 const Standard_Integer anIndex = AddVertex (theVertex);
174 SetVertexColor (anIndex, theColor.Red(), theColor.Green(), theColor.Blue());
178 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const gp_Pnt& theVertex,
179 const Standard_Integer theColor32)
181 const Standard_Integer anIndex = AddVertex (theVertex);
182 SetVertexColor (anIndex, theColor32);
186 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const Standard_ShortReal theX, const Standard_ShortReal theY, const Standard_ShortReal theZ,
187 const Standard_ShortReal theNX, const Standard_ShortReal theNY, const Standard_ShortReal theNZ)
189 if (myAttribs.IsNull())
194 const Standard_Integer anIndex = myAttribs->NbElements + 1;
195 SetVertice (anIndex, theX, theY, theZ);
196 SetVertexNormal (anIndex, theNX, theNY, theNZ);
200 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const gp_Pnt& theVertex,
201 const gp_Dir& theNormal,
202 const Quantity_Color& theColor)
204 const Standard_Integer anIndex = AddVertex (theVertex, theNormal);
205 SetVertexColor (anIndex, theColor.Red(), theColor.Green(), theColor.Blue());
209 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const gp_Pnt& theVertex,
210 const gp_Dir& theNormal,
211 const Standard_Integer theColor32)
213 const Standard_Integer anIndex = AddVertex (theVertex, theNormal);
214 SetVertexColor (anIndex, theColor32);
218 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const Standard_ShortReal theX, const Standard_ShortReal theY, const Standard_ShortReal theZ,
219 const Standard_ShortReal theTX, const Standard_ShortReal theTY)
221 if (myAttribs.IsNull())
226 const Standard_Integer anIndex = myAttribs->NbElements + 1;
227 SetVertice (anIndex, theX, theY, theZ);
228 SetVertexTexel (anIndex, theTX, theTY);
232 Standard_Integer Graphic3d_ArrayOfPrimitives::AddVertex (const Standard_ShortReal theX, const Standard_ShortReal theY, const Standard_ShortReal theZ,
233 const Standard_ShortReal theNX, const Standard_ShortReal theNY, const Standard_ShortReal theNZ,
234 const Standard_ShortReal theTX, const Standard_ShortReal theTY)
236 if (myAttribs.IsNull())
241 const Standard_Integer anIndex = myAttribs->NbElements + 1;
242 SetVertice (anIndex, theX, theY, theZ);
243 SetVertexNormal (anIndex, theNX, theNY, theNZ);
244 SetVertexTexel (anIndex, theTX, theTY);
248 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber)
250 if (myBounds.IsNull())
254 Standard_Integer anIndex = myBounds->NbBounds;
255 if (anIndex >= myMaxBounds)
257 Standard_OutOfRange::Raise ("TOO many BOUNDS");
260 myBounds->Bounds[anIndex] = theEdgeNumber;
261 myBounds->NbBounds = ++anIndex;
265 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber,
266 const Quantity_Color& theColor)
268 return AddBound (theEdgeNumber, theColor.Red(), theColor.Green(), theColor.Blue());
271 Standard_Integer Graphic3d_ArrayOfPrimitives::AddBound (const Standard_Integer theEdgeNumber,
272 const Standard_Real theR,
273 const Standard_Real theG,
274 const Standard_Real theB)
276 if (myBounds.IsNull())
280 Standard_Integer anIndex = myBounds->NbBounds;
281 if (anIndex >= myMaxBounds)
283 Standard_OutOfRange::Raise ("TOO many BOUND");
286 myBounds->Bounds[anIndex] = theEdgeNumber;
287 myBounds->NbBounds = ++anIndex;
288 SetBoundColor (anIndex, theR, theG, theB);
292 Standard_Integer Graphic3d_ArrayOfPrimitives::AddEdge (const Standard_Integer theVertexIndex)
294 if (myIndices.IsNull())
299 Standard_Integer anIndex = myIndices->NbElements;
300 if (anIndex >= myMaxEdges)
302 Standard_OutOfRange::Raise ("TOO many EDGE");
305 Standard_Integer aVertIndex = theVertexIndex - 1;
306 if (theVertexIndex <= 0
307 || aVertIndex >= myMaxVertexs)
309 Standard_OutOfRange::Raise ("BAD EDGE vertex index");
312 myIndices->SetIndex (anIndex, aVertIndex);
313 myIndices->NbElements = ++anIndex;
317 void Graphic3d_ArrayOfPrimitives::SetVertice (const Standard_Integer theIndex,
318 const gp_Pnt& theVertex)
320 SetVertice (theIndex,
321 Standard_ShortReal (theVertex.X()),
322 Standard_ShortReal (theVertex.Y()),
323 Standard_ShortReal (theVertex.Z()));
326 void Graphic3d_ArrayOfPrimitives::SetVertexColor (const Standard_Integer theIndex,
327 const Quantity_Color& theColor)
329 SetVertexColor (theIndex, theColor.Red(), theColor.Green(), theColor.Blue());
332 void Graphic3d_ArrayOfPrimitives::SetVertexColor (const Standard_Integer theIndex,
333 const Standard_Integer theColor)
335 if (myAttribs.IsNull())
341 || theIndex > myMaxVertexs)
343 Standard_OutOfRange::Raise ("BAD VERTEX index");
348 *reinterpret_cast<Standard_Integer* >(myAttribs->changeValue (theIndex - 1) + size_t(myVCol)) = theColor;
352 void Graphic3d_ArrayOfPrimitives::SetVertexNormal (const Standard_Integer theIndex,
353 const gp_Dir& theNormal)
355 SetVertexNormal (theIndex, theNormal.X(), theNormal.Y(), theNormal.Z());
358 void Graphic3d_ArrayOfPrimitives::SetVertexTexel (const Standard_Integer theIndex,
359 const gp_Pnt2d& theTexel)
361 SetVertexTexel (theIndex, theTexel.X(), theTexel.Y());
364 void Graphic3d_ArrayOfPrimitives::SetBoundColor (const Standard_Integer theIndex,
365 const Quantity_Color& theColor)
367 SetBoundColor (theIndex, theColor.Red(), theColor.Green(), theColor.Blue());
370 Standard_CString Graphic3d_ArrayOfPrimitives::StringType() const
374 case Graphic3d_TOPA_POINTS: return "ArrayOfPoints";
375 case Graphic3d_TOPA_POLYLINES: return "ArrayOfPolylines";
376 case Graphic3d_TOPA_SEGMENTS: return "ArrayOfSegments";
377 case Graphic3d_TOPA_POLYGONS: return "ArrayOfPolygons";
378 case Graphic3d_TOPA_TRIANGLES: return "ArrayOfTriangles";
379 case Graphic3d_TOPA_QUADRANGLES: return "ArrayOfQuadrangles";
380 case Graphic3d_TOPA_TRIANGLESTRIPS: return "ArrayOfTriangleStrips";
381 case Graphic3d_TOPA_QUADRANGLESTRIPS: return "ArrayOfQuadrangleStrips";
382 case Graphic3d_TOPA_TRIANGLEFANS: return "ArrayOfTriangleFans";
383 case Graphic3d_TOPA_UNDEFINED: return "UndefinedArray";
385 return "UndefinedArray";
388 gp_Pnt Graphic3d_ArrayOfPrimitives::Vertice (const Standard_Integer theRank) const
390 Standard_Real anXYZ[3];
391 Vertice (theRank, anXYZ[0], anXYZ[1], anXYZ[2]);
392 return gp_Pnt (anXYZ[0], anXYZ[1], anXYZ[2]);
395 Quantity_Color Graphic3d_ArrayOfPrimitives::VertexColor (const Standard_Integer theRank) const
397 Standard_Real anRGB[3];
398 VertexColor (theRank, anRGB[0], anRGB[1], anRGB[2]);
399 return Quantity_Color (anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB);
402 gp_Dir Graphic3d_ArrayOfPrimitives::VertexNormal (const Standard_Integer theRank) const
404 Standard_Real anXYZ[3];
405 VertexNormal (theRank, anXYZ[0], anXYZ[1], anXYZ[2]);
406 return gp_Dir (anXYZ[0], anXYZ[1], anXYZ[2]);
409 gp_Pnt2d Graphic3d_ArrayOfPrimitives::VertexTexel (const Standard_Integer theRank) const
411 Standard_Real anXY[2];
412 VertexTexel (theRank, anXY[0], anXY[1]);
413 return gp_Pnt2d (anXY[0], anXY[1]);
416 Quantity_Color Graphic3d_ArrayOfPrimitives::BoundColor (const Standard_Integer theRank) const
418 Standard_Real anRGB[3] = {0.0, 0.0, 0.0};
419 BoundColor (theRank, anRGB[0], anRGB[1], anRGB[2]);
420 return Quantity_Color (anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB);
423 Standard_Integer Graphic3d_ArrayOfPrimitives::ItemNumber() const
425 if (myAttribs.IsNull())
432 case Graphic3d_TOPA_POINTS: return myAttribs->NbElements;
433 case Graphic3d_TOPA_POLYLINES:
434 case Graphic3d_TOPA_POLYGONS: return !myBounds.IsNull() ? myBounds->NbBounds : 1;
435 case Graphic3d_TOPA_SEGMENTS: return myIndices.IsNull() || myIndices->NbElements < 1
436 ? myAttribs->NbElements / 2
437 : myIndices->NbElements / 2;
438 case Graphic3d_TOPA_TRIANGLES: return myIndices.IsNull() || myIndices->NbElements < 1
439 ? myAttribs->NbElements / 3
440 : myIndices->NbElements / 3;
441 case Graphic3d_TOPA_QUADRANGLES: return myIndices.IsNull() || myIndices->NbElements < 1
442 ? myAttribs->NbElements / 4
443 : myIndices->NbElements / 4;
444 case Graphic3d_TOPA_TRIANGLESTRIPS: return !myBounds.IsNull()
445 ? myAttribs->NbElements - 2 * myBounds->NbBounds
446 : myAttribs->NbElements - 2;
447 case Graphic3d_TOPA_QUADRANGLESTRIPS: return !myBounds.IsNull()
448 ? myAttribs->NbElements / 2 - myBounds->NbBounds
449 : myAttribs->NbElements / 2 - 1;
450 case Graphic3d_TOPA_TRIANGLEFANS: return !myBounds.IsNull()
451 ? myAttribs->NbElements - 2 * myBounds->NbBounds
452 : myAttribs->NbElements - 2;
453 case Graphic3d_TOPA_UNDEFINED: return -1;
458 void Graphic3d_ArrayOfPrimitives::ComputeVNormals (const Standard_Integer theFrom,
459 const Standard_Integer theTo)
461 Standard_Integer aNext = theFrom + 1;
462 Standard_Integer aLast = theTo + 1;
466 aTri[0] = Vertice (Edge (aNext++));
467 aTri[1] = Vertice (Edge (aNext++));
471 aTri[0] = Vertice (aNext++);
472 aTri[1] = Vertice (aNext++);
476 while (aNext <= aLast)
480 aTri[2] = Vertice (Edge (aNext));
484 aTri[2] = Vertice (aNext);
486 gp_Vec v21 (aTri[1], aTri[0]);
487 gp_Vec v31 (aTri[2], aTri[0]);
489 if (vn.SquareMagnitude() > 0.0)
504 for (int i = theFrom + 1; i <= theTo + 1; i++)
506 SetVertexNormal (Edge (i), vn);
511 for (int i = theFrom + 1; i <= theTo + 1; i++)
513 SetVertexNormal (i, vn);
518 Standard_Boolean Graphic3d_ArrayOfPrimitives::IsValid()
520 if (myAttribs.IsNull())
522 return Standard_False;
525 Standard_Integer nvertexs = myAttribs->NbElements;
526 Standard_Integer nbounds = myBounds.IsNull() ? 0 : myBounds->NbBounds;
527 Standard_Integer nedges = myIndices.IsNull() ? 0 : myIndices->NbElements;
530 case Graphic3d_TOPA_POINTS:
533 return Standard_False;
536 case Graphic3d_TOPA_POLYLINES:
540 return Standard_False;
544 return Standard_False;
547 case Graphic3d_TOPA_SEGMENTS:
550 return Standard_False;
553 case Graphic3d_TOPA_POLYGONS:
557 return Standard_False;
561 return Standard_False;
564 case Graphic3d_TOPA_TRIANGLES:
572 return Standard_False;
574 myIndices->NbElements = 3 * (nedges / 3);
577 else if (nvertexs < 3
578 || nvertexs % 3 != 0 )
582 return Standard_False;
584 myAttribs->NbElements = 3 * (nvertexs / 3);
587 case Graphic3d_TOPA_QUADRANGLES:
595 return Standard_False;
597 myIndices->NbElements = 4 * (nedges / 4);
600 else if (nvertexs < 4
601 || nvertexs % 4 != 0)
605 return Standard_False;
607 myAttribs->NbElements = 4 * (nvertexs / 4);
610 case Graphic3d_TOPA_TRIANGLEFANS:
611 case Graphic3d_TOPA_TRIANGLESTRIPS:
614 return Standard_False;
617 case Graphic3d_TOPA_QUADRANGLESTRIPS:
620 return Standard_False;
623 case Graphic3d_TOPA_UNDEFINED:
625 return Standard_False;
628 // total number of edges(vertices) in bounds should be the same as variable
629 // of total number of defined edges(vertices); if no edges - only vertices
630 // could be in bounds.
633 Standard_Integer n = 0;
634 for (Standard_Integer aBoundIter = 0; aBoundIter < nbounds; ++aBoundIter)
636 n += myBounds->Bounds[aBoundIter];
643 return Standard_False;
645 myIndices->NbElements = n;
652 return Standard_False;
654 myAttribs->NbElements = n;
658 // check that edges (indexes to an array of vertices) are in range.
661 for (Standard_Integer anEdgeIter = 0; anEdgeIter < nedges; ++anEdgeIter)
663 if (myIndices->Index (anEdgeIter) >= myAttribs->NbElements)
665 return Standard_False;
669 return Standard_True;