0030854: Visualization, AIS_ViewCube - pack triangulations into common array(s)
[occt.git] / src / Graphic3d / Graphic3d_ArrayOfPrimitives.hxx
1 // Created on: 2000-06-16
2 // Copyright (c) 2000-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
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.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #ifndef _Graphic3d_ArrayOfPrimitives_HeaderFile
16 #define _Graphic3d_ArrayOfPrimitives_HeaderFile
17
18 #include <Graphic3d_BoundBuffer.hxx>
19 #include <Graphic3d_ArrayFlags.hxx>
20 #include <Graphic3d_Buffer.hxx>
21 #include <Graphic3d_IndexBuffer.hxx>
22 #include <Graphic3d_TypeOfPrimitiveArray.hxx>
23 #include <gp_Dir.hxx>
24 #include <gp_Pnt.hxx>
25 #include <Standard_OutOfRange.hxx>
26 #include <Standard_TypeMismatch.hxx>
27 #include <Quantity_Color.hxx>
28
29 class Graphic3d_ArrayOfPrimitives;
30 DEFINE_STANDARD_HANDLE(Graphic3d_ArrayOfPrimitives, Standard_Transient)
31
32 //! This class furnish services to defined and fill an array of primitives
33 //! which can be passed directly to graphics rendering API.
34 //!
35 //! The basic interface consists of the following parts:
36 //! 1) Specifying primitive type.
37 //!    WARNING! Particular primitive types might be unsupported by specific hardware/graphics API (like quads and polygons).
38 //!             It is always preferred using one of basic types having maximum compatibility:
39 //!             Point, Triangle (or Triangle strip), Segment aka Lines (or Polyline aka Line Strip).
40 //!    Primitive strip types can be used to reduce memory usage as alternative to Indexed arrays.
41 //! 2) Vertex array.
42 //!    - Specifying the (maximum) number of vertexes within array.
43 //!    - Specifying the vertex attributes, complementary to mandatory vertex Position (normal, color, UV texture coordinates).
44 //!    - Defining vertex values by using various versions of AddVertex() or SetVertex*() methods.
45 //! 3) Index array (optional).
46 //!    - Specifying the (maximum) number of indexes (edges).
47 //!    - Defining index values by using AddEdge() method; the index value should be within number of defined Vertexes.
48 //!
49 //!    Indexed array allows sharing vertex data across Primitives and thus reducing memory usage,
50 //!    since index size is much smaller then size of vertex with all its attributes.
51 //!    It is a preferred way for defining primitive array and main alternative to Primitive Strips for optimal memory usage,
52 //!    although it is also possible (but unusual) defining Indexed Primitive Strip.
53 //!    Note that it is NOT possible sharing Vertex Attributes partially (e.g. share Position, but have different Normals);
54 //!    in such cases Vertex should be entirely duplicated with all Attributes.
55 //! 4) Bounds array (optional).
56 //!    - Specifying the (maximum) number of bounds.
57 //!    - Defining bounds using AddBound() methods.
58 //!
59 //!    Bounds allow splitting Primitive Array into sub-groups.
60 //!    This is useful only in two cases - for specifying per-group color and for restarting Primitive Strips.
61 //!    WARNING! Bounds within Primitive Array break rendering batches into parts (additional for loops),
62 //!             affecting rendering performance negatively (increasing CPU load).
63 class Graphic3d_ArrayOfPrimitives : public Standard_Transient
64 {
65   DEFINE_STANDARD_RTTIEXT(Graphic3d_ArrayOfPrimitives, Standard_Transient)
66 public:
67
68   //! Create an array of specified type.
69   static Handle(Graphic3d_ArrayOfPrimitives) CreateArray (Graphic3d_TypeOfPrimitiveArray theType,
70                                                           Standard_Integer theMaxVertexs,
71                                                           Standard_Integer theMaxEdges,
72                                                           Graphic3d_ArrayFlags theArrayFlags)
73   {
74     return CreateArray (theType, theMaxVertexs, 0, theMaxEdges, theArrayFlags);
75   }
76
77   //! Create an array of specified type.
78   static Standard_EXPORT Handle(Graphic3d_ArrayOfPrimitives) CreateArray (Graphic3d_TypeOfPrimitiveArray theType,
79                                                                           Standard_Integer theMaxVertexs,
80                                                                           Standard_Integer theMaxBounds,
81                                                                           Standard_Integer theMaxEdges,
82                                                                           Graphic3d_ArrayFlags theArrayFlags);
83 public:
84
85   //! Destructor.
86   Standard_EXPORT virtual ~Graphic3d_ArrayOfPrimitives();
87
88   //! Returns vertex attributes buffer (colors, normals, texture coordinates).
89   const Handle(Graphic3d_Buffer)& Attributes() const { return myAttribs; }
90
91   //! Returns the type of this primitive
92   Graphic3d_TypeOfPrimitiveArray Type() const { return myType; }
93
94   //! Returns the string type of this primitive
95   Standard_EXPORT Standard_CString StringType() const;
96
97   //! Returns TRUE when vertex normals array is defined.
98   Standard_Boolean HasVertexNormals() const { return myNormData != NULL; }
99
100   //! Returns TRUE when vertex colors array is defined.
101   Standard_Boolean HasVertexColors() const { return myColData != NULL; }
102
103   //! Returns TRUE when vertex texels array is defined.
104   Standard_Boolean HasVertexTexels() const { return myTexData != NULL; }
105
106   //! Returns the number of defined vertex
107   Standard_Integer VertexNumber() const { return myAttribs->NbElements; }
108
109   //! Returns the number of allocated vertex
110   Standard_Integer VertexNumberAllocated() const { return myAttribs->NbMaxElements(); }
111
112   //! Returns the number of total items according to the array type.
113   Standard_EXPORT Standard_Integer ItemNumber() const;
114
115   //! Returns TRUE only when the contains of this array is available.
116   Standard_EXPORT Standard_Boolean IsValid();
117
118   //! Adds a vertice in the array.
119   //! @return the actual vertex number
120   Standard_Integer AddVertex (const gp_Pnt& theVertex) { return AddVertex (theVertex.X(), theVertex.Y(), theVertex.Z()); }
121
122   //! Adds a vertice in the array.
123   //! @return the actual vertex number
124   Standard_Integer AddVertex (const Graphic3d_Vec3& theVertex) { return AddVertex (theVertex.x(), theVertex.y(), theVertex.z()); }
125
126   //! Adds a vertice in the array.
127   //! @return the actual vertex number
128   Standard_Integer AddVertex (const Standard_Real theX, const Standard_Real theY, const Standard_Real theZ)
129   {
130     return AddVertex (RealToShortReal (theX), RealToShortReal (theY), RealToShortReal (theZ));
131   }
132
133   //! Adds a vertice in the array.
134   //! @return the actual vertex number.
135   Standard_Integer AddVertex (const Standard_ShortReal theX, const Standard_ShortReal theY, const Standard_ShortReal theZ)
136   {
137     const Standard_Integer anIndex = myAttribs->NbElements + 1;
138     SetVertice (anIndex, theX, theY, theZ);
139     return anIndex;
140   }
141
142   //! Adds a vertice and vertex color in the vertex array.
143   //! Warning: theColor is ignored when the hasVColors constructor parameter is FALSE
144   //! @return the actual vertex number
145   Standard_Integer AddVertex (const gp_Pnt& theVertex, const Quantity_Color& theColor)
146   {
147     const Standard_Integer anIndex = AddVertex (theVertex);
148     SetVertexColor (anIndex, theColor.Red(), theColor.Green(), theColor.Blue());
149     return anIndex;
150   }
151
152   //! Adds a vertice and vertex color in the vertex array.
153   //! Warning: theColor is ignored when the hasVColors constructor parameter is FALSE
154   //! @code
155   //!   theColor32 = Alpha << 24 + Blue << 16 + Green << 8 + Red
156   //! @endcode
157   //! @return the actual vertex number
158   Standard_Integer AddVertex (const gp_Pnt& theVertex, const Standard_Integer theColor32)
159   {
160     const Standard_Integer anIndex = AddVertex (theVertex);
161     SetVertexColor (anIndex, theColor32);
162     return anIndex;
163   }
164
165   //! Adds a vertice and vertex color in the vertex array.
166   //! Warning: theColor is ignored when the hasVColors constructor parameter is FALSE
167   //! @return the actual vertex number
168   Standard_Integer AddVertex (const gp_Pnt&           theVertex,
169                               const Graphic3d_Vec4ub& theColor)
170   {
171     const Standard_Integer anIndex = AddVertex (theVertex);
172     SetVertexColor (anIndex, theColor);
173     return anIndex;
174   }
175
176   //! Adds a vertice and vertex normal in the vertex array.
177   //! Warning: theNormal is ignored when the hasVNormals constructor parameter is FALSE.
178   //! @return the actual vertex number
179   Standard_Integer AddVertex (const gp_Pnt& theVertex, const gp_Dir& theNormal)
180   {
181     return AddVertex (theVertex.X(), theVertex.Y(), theVertex.Z(),
182                       theNormal.X(), theNormal.Y(), theNormal.Z());
183   }
184
185   //! Adds a vertice and vertex normal in the vertex array.
186   //! Warning: Normal is ignored when the hasVNormals constructor parameter is FALSE.
187   //! @return the actual vertex number
188   Standard_Integer AddVertex (const Standard_Real theX,  const Standard_Real theY,  const Standard_Real theZ,
189                               const Standard_Real theNX, const Standard_Real theNY, const Standard_Real theNZ)
190   {
191     return AddVertex (RealToShortReal (theX),  RealToShortReal (theY),  RealToShortReal (theZ),
192                       Standard_ShortReal (theNX), Standard_ShortReal (theNY), Standard_ShortReal (theNZ));
193   }
194
195   //! Adds a vertice and vertex normal in the vertex array.
196   //! Warning: Normal is ignored when the hasVNormals constructor parameter is FALSE.
197   //! @return the actual vertex number
198   Standard_Integer AddVertex (const Standard_ShortReal theX,  const Standard_ShortReal theY,  const Standard_ShortReal theZ,
199                               const Standard_ShortReal theNX, const Standard_ShortReal theNY, const Standard_ShortReal theNZ)
200   {
201     const Standard_Integer anIndex = myAttribs->NbElements + 1;
202     SetVertice      (anIndex, theX,  theY,  theZ);
203     SetVertexNormal (anIndex, theNX, theNY, theNZ);
204     return anIndex;
205   }
206
207   //! Adds a vertice,vertex normal and color in the vertex array.
208   //! Warning: theNormal is ignored when the hasVNormals constructor parameter is FALSE
209   //! and      theColor  is ignored when the hasVColors  constructor parameter is FALSE.
210   //! @return the actual vertex number
211   Standard_Integer AddVertex (const gp_Pnt& theVertex, const gp_Dir& theNormal, const Quantity_Color& theColor)
212   {
213     const Standard_Integer anIndex = AddVertex (theVertex, theNormal);
214     SetVertexColor (anIndex, theColor.Red(), theColor.Green(), theColor.Blue());
215     return anIndex;
216   }
217
218   //! Adds a vertice,vertex normal and color in the vertex array.
219   //! Warning: theNormal is ignored when the hasVNormals constructor parameter is FALSE
220   //! and      theColor  is ignored when the hasVColors  constructor parameter is FALSE.
221   //! @code
222   //!   theColor32 = Alpha << 24 + Blue << 16 + Green << 8 + Red
223   //! @endcode
224   //! @return the actual vertex number
225   Standard_Integer AddVertex (const gp_Pnt& theVertex, const gp_Dir& theNormal, const Standard_Integer theColor32)
226   {
227     const Standard_Integer anIndex = AddVertex (theVertex, theNormal);
228     SetVertexColor (anIndex, theColor32);
229     return anIndex;
230   }
231
232   //! Adds a vertice and vertex texture in the vertex array.
233   //! theTexel is ignored when the hasVTexels constructor parameter is FALSE.
234   //! @return the actual vertex number
235   Standard_Integer AddVertex (const gp_Pnt& theVertex, const gp_Pnt2d& theTexel)
236   {
237     return AddVertex (theVertex.X(), theVertex.Y(), theVertex.Z(),
238                       theTexel.X(), theTexel.Y());
239   }
240
241   //! Adds a vertice and vertex texture coordinates in the vertex array.
242   //! Texel is ignored when the hasVTexels constructor parameter is FALSE.
243   //! @return the actual vertex number
244   Standard_Integer AddVertex (const Standard_Real theX, const Standard_Real theY, const Standard_Real theZ,
245                               const Standard_Real theTX, const Standard_Real theTY)
246   {
247     return AddVertex (RealToShortReal (theX),  RealToShortReal (theY),  RealToShortReal (theZ),
248                       Standard_ShortReal (theTX), Standard_ShortReal (theTY));
249   }
250
251   //! Adds a vertice and vertex texture coordinates in the vertex array.
252   //! Texel is ignored when the hasVTexels constructor parameter is FALSE.
253   //! @return the actual vertex number
254   Standard_Integer AddVertex (const Standard_ShortReal theX, const Standard_ShortReal theY, const Standard_ShortReal theZ,
255                               const Standard_ShortReal theTX, const Standard_ShortReal theTY)
256   {
257     const Standard_Integer anIndex = myAttribs->NbElements + 1;
258     SetVertice     (anIndex, theX, theY, theZ);
259     SetVertexTexel (anIndex, theTX, theTY);
260     return anIndex;
261   }
262
263   //! Adds a vertice,vertex normal and texture in the vertex array.
264   //! Warning: theNormal is ignored when the hasVNormals constructor parameter is FALSE
265   //! and      theTexel  is ignored when the hasVTexels  constructor parameter is FALSE.
266   //! @return the actual vertex number
267   Standard_Integer AddVertex (const gp_Pnt& theVertex, const gp_Dir& theNormal, const gp_Pnt2d& theTexel)
268   {
269     return AddVertex (theVertex.X(), theVertex.Y(), theVertex.Z(),
270                       theNormal.X(), theNormal.Y(), theNormal.Z(),
271                       theTexel.X(),  theTexel.Y());
272   }
273
274   //! Adds a vertice,vertex normal and texture in the vertex array.
275   //! Warning: Normal is ignored when the hasVNormals constructor parameter is FALSE
276   //! and      Texel  is ignored when the hasVTexels  constructor parameter is FALSE.
277   //! @return the actual vertex number
278   Standard_Integer AddVertex (const Standard_Real theX,  const Standard_Real theY,  const Standard_Real theZ,
279                               const Standard_Real theNX, const Standard_Real theNY, const Standard_Real theNZ,
280                               const Standard_Real theTX, const Standard_Real theTY)
281   {
282     return AddVertex (RealToShortReal (theX), RealToShortReal (theY), RealToShortReal (theZ),
283                       Standard_ShortReal (theNX), Standard_ShortReal (theNY), Standard_ShortReal (theNZ),
284                       Standard_ShortReal (theTX), Standard_ShortReal (theTY));
285   }
286
287   //! Adds a vertice,vertex normal and texture in the vertex array.
288   //! Warning: Normal is ignored when the hasVNormals constructor parameter is FALSE
289   //!     and  Texel  is ignored when the hasVTexels  constructor parameter is FALSE.
290   //! @return the actual vertex number
291   Standard_Integer AddVertex (const Standard_ShortReal theX,  const Standard_ShortReal theY,  const Standard_ShortReal theZ,
292                               const Standard_ShortReal theNX, const Standard_ShortReal theNY, const Standard_ShortReal theNZ,
293                               const Standard_ShortReal theTX, const Standard_ShortReal theTY)
294   {
295     const Standard_Integer anIndex = myAttribs->NbElements + 1;
296     SetVertice     (anIndex, theX,  theY,  theZ);
297     SetVertexNormal(anIndex, theNX, theNY, theNZ);
298     SetVertexTexel (anIndex, theTX, theTY);
299     return anIndex;
300   }
301
302   //! Change the vertice of rank theIndex in the array.
303   void SetVertice (const Standard_Integer theIndex, const gp_Pnt& theVertex)
304   {
305     SetVertice (theIndex, Standard_ShortReal (theVertex.X()), Standard_ShortReal (theVertex.Y()), Standard_ShortReal (theVertex.Z()));
306   }
307
308   //! Change the vertice of rank theIndex in the array.
309   void SetVertice (const Standard_Integer theIndex, const Standard_ShortReal theX, const Standard_ShortReal theY, const Standard_ShortReal theZ)
310   {
311     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
312     Graphic3d_Vec3& aVec = *reinterpret_cast<Graphic3d_Vec3*> (myAttribs->ChangeData() + myPosStride * (theIndex - 1));
313     aVec.x() = theX;
314     aVec.y() = theY;
315     aVec.z() = theZ;
316     if (myAttribs->NbElements < theIndex)
317     {
318       myAttribs->NbElements = theIndex;
319     }
320   }
321
322   //! Change the vertex color of rank theIndex in the array.
323   void SetVertexColor (const Standard_Integer theIndex, const Quantity_Color& theColor)
324   {
325     SetVertexColor (theIndex, theColor.Red(), theColor.Green(), theColor.Blue());
326   }
327
328   //! Change the vertex color of rank theIndex in the array.
329   void SetVertexColor (const Standard_Integer theIndex, const Standard_Real theR, const Standard_Real theG, const Standard_Real theB)
330   {
331     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
332     if (myColData != NULL)
333     {
334       Graphic3d_Vec4ub* aColorPtr = reinterpret_cast<Graphic3d_Vec4ub* >(myColData + myColStride * (theIndex - 1));
335       aColorPtr->SetValues (Standard_Byte(theR * 255.0),
336                             Standard_Byte(theG * 255.0),
337                             Standard_Byte(theB * 255.0), 255);
338     }
339     myAttribs->NbElements = Max (theIndex, myAttribs->NbElements);
340   }
341
342   //! Change the vertex color of rank theIndex in the array.
343   void SetVertexColor (const Standard_Integer  theIndex,
344                        const Graphic3d_Vec4ub& theColor)
345   {
346     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
347     if (myColData != NULL)
348     {
349       Graphic3d_Vec4ub* aColorPtr =  reinterpret_cast<Graphic3d_Vec4ub* >(myColData + myColStride * (theIndex - 1));
350       (*aColorPtr) = theColor;
351     }
352     myAttribs->NbElements = Max (theIndex, myAttribs->NbElements);
353   }
354
355   //! Change the vertex color of rank theIndex> in the array.
356   //! @code
357   //!   theColor32 = Alpha << 24 + Blue << 16 + Green << 8 + Red
358   //! @endcode
359   void SetVertexColor (const Standard_Integer theIndex, const Standard_Integer theColor32)
360   {
361     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
362     if (myColData != NULL)
363     {
364       *reinterpret_cast<Standard_Integer* >(myColData + myColStride * (theIndex - 1)) = theColor32;
365     }
366   }
367
368   //! Change the vertex normal of rank theIndex in the array.
369   void SetVertexNormal (const Standard_Integer theIndex, const gp_Dir& theNormal)
370   {
371     SetVertexNormal (theIndex, theNormal.X(), theNormal.Y(), theNormal.Z());
372   }
373
374   //! Change the vertex normal of rank theIndex in the array.
375   void SetVertexNormal (const Standard_Integer theIndex, const Standard_Real theNX, const Standard_Real theNY, const Standard_Real theNZ)
376   {
377     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
378     if (myNormData != NULL)
379     {
380       Graphic3d_Vec3& aVec = *reinterpret_cast<Graphic3d_Vec3* >(myNormData + myNormStride * (theIndex - 1));
381       aVec.x() = Standard_ShortReal (theNX);
382       aVec.y() = Standard_ShortReal (theNY);
383       aVec.z() = Standard_ShortReal (theNZ);
384     }
385     myAttribs->NbElements = Max (theIndex, myAttribs->NbElements);
386   }
387
388   //! Change the vertex texel of rank theIndex in the array.
389   void SetVertexTexel (const Standard_Integer theIndex, const gp_Pnt2d& theTexel)
390   {
391     SetVertexTexel (theIndex, theTexel.X(), theTexel.Y());
392   }
393
394   //! Change the vertex texel of rank theIndex in the array.
395   void SetVertexTexel (const Standard_Integer theIndex, const Standard_Real theTX, const Standard_Real theTY)
396   {
397     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
398     if (myTexData != NULL)
399     {
400       Graphic3d_Vec2& aVec = *reinterpret_cast<Graphic3d_Vec2* >(myTexData + myTexStride * (theIndex - 1));
401       aVec.x() = Standard_ShortReal (theTX);
402       aVec.y() = Standard_ShortReal (theTY);
403     }
404     myAttribs->NbElements = Max (theIndex, myAttribs->NbElements);
405   }
406
407   //! Returns the vertice at rank theRank from the vertex table if defined.
408   gp_Pnt Vertice (const Standard_Integer theRank) const
409   {
410     Standard_Real anXYZ[3];
411     Vertice (theRank, anXYZ[0], anXYZ[1], anXYZ[2]);
412     return gp_Pnt (anXYZ[0], anXYZ[1], anXYZ[2]);
413   }
414
415   //! Returns the vertice coordinates at rank theRank from the vertex table if defined.
416   void Vertice (const Standard_Integer theRank, Standard_Real& theX, Standard_Real& theY, Standard_Real& theZ) const
417   {
418     theX = theY = theZ = 0.0;
419     Standard_OutOfRange_Raise_if (theRank < 1 || theRank > myAttribs->NbElements, "BAD VERTEX index");
420     const Graphic3d_Vec3& aVec = *reinterpret_cast<const Graphic3d_Vec3*> (myAttribs->Data() + myPosStride * (theRank - 1));
421     theX = Standard_Real(aVec.x());
422     theY = Standard_Real(aVec.y());
423     theZ = Standard_Real(aVec.z());
424   }
425
426   //! Returns the vertex color at rank theRank from the vertex table if defined.
427   Quantity_Color VertexColor (const Standard_Integer theRank) const
428   {
429     Standard_Real anRGB[3];
430     VertexColor (theRank, anRGB[0], anRGB[1], anRGB[2]);
431     return Quantity_Color (anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB);
432   }
433
434   //! Returns the vertex color at rank theIndex from the vertex table if defined.
435   void VertexColor (const Standard_Integer theIndex,
436                     Graphic3d_Vec4ub&      theColor) const
437   {
438     Standard_OutOfRange_Raise_if (myColData == NULL || theIndex < 1 || theIndex > myAttribs->NbElements, "BAD VERTEX index");
439     theColor = *reinterpret_cast<const Graphic3d_Vec4ub* >(myColData + myColStride * (theIndex - 1));
440   }
441
442   //! Returns the vertex color values at rank theRank from the vertex table if defined.
443   void VertexColor (const Standard_Integer theRank, Standard_Real& theR, Standard_Real& theG, Standard_Real& theB) const
444   {
445     theR = theG = theB = 0.0;
446     Standard_OutOfRange_Raise_if (theRank < 1 || theRank > myAttribs->NbElements, "BAD VERTEX index");
447     if (myColData == NULL)
448     {
449       return;
450     }
451     const Graphic3d_Vec4ub& aColor = *reinterpret_cast<const Graphic3d_Vec4ub* >(myColData + myColStride * (theRank - 1));
452     theR = Standard_Real(aColor.r()) / 255.0;
453     theG = Standard_Real(aColor.g()) / 255.0;
454     theB = Standard_Real(aColor.b()) / 255.0;
455   }
456
457   //! Returns the vertex color values at rank theRank from the vertex table if defined.
458   void VertexColor (const Standard_Integer theRank, Standard_Integer& theColor) const
459   {
460     Standard_OutOfRange_Raise_if (theRank < 1 || theRank > myAttribs->NbElements, "BAD VERTEX index");
461     if (myColData != NULL)
462     {
463       theColor = *reinterpret_cast<const Standard_Integer* >(myColData + myColStride * (theRank - 1));
464     }
465   }
466
467   //! Returns the vertex normal at rank theRank from the vertex table if defined.
468   gp_Dir VertexNormal (const Standard_Integer theRank) const
469   {
470     Standard_Real anXYZ[3];
471     VertexNormal (theRank, anXYZ[0], anXYZ[1], anXYZ[2]);
472     return gp_Dir (anXYZ[0], anXYZ[1], anXYZ[2]);
473   }
474
475   //! Returns the vertex normal coordinates at rank theRank from the vertex table if defined.
476   void VertexNormal (const Standard_Integer theRank, Standard_Real& theNX, Standard_Real& theNY, Standard_Real& theNZ) const
477   {
478     theNX = theNY = theNZ = 0.0;
479     Standard_OutOfRange_Raise_if (theRank < 1 || theRank > myAttribs->NbElements, "BAD VERTEX index");
480     if (myNormData != NULL)
481     {
482       const Graphic3d_Vec3& aVec = *reinterpret_cast<const Graphic3d_Vec3* >(myNormData + myNormStride * (theRank - 1));
483       theNX = Standard_Real(aVec.x());
484       theNY = Standard_Real(aVec.y());
485       theNZ = Standard_Real(aVec.z());
486     }
487   }
488
489   //! Returns the vertex texture at rank theRank from the vertex table if defined.
490   gp_Pnt2d VertexTexel (const Standard_Integer theRank) const
491   {
492     Standard_Real anXY[2];
493     VertexTexel (theRank, anXY[0], anXY[1]);
494     return gp_Pnt2d (anXY[0], anXY[1]);
495   }
496
497   //! Returns the vertex texture coordinates at rank theRank from the vertex table if defined.
498   void VertexTexel (const Standard_Integer theRank, Standard_Real& theTX, Standard_Real& theTY) const
499   {
500     theTX = theTY = 0.0;
501     Standard_OutOfRange_Raise_if (theRank < 1 || theRank > myAttribs->NbElements, "BAD VERTEX index");
502     if (myTexData != NULL)
503     {
504       const Graphic3d_Vec2& aVec = *reinterpret_cast<const Graphic3d_Vec2* >(myTexData + myTexStride * (theRank - 1));
505       theTX = Standard_Real(aVec.x());
506       theTY = Standard_Real(aVec.y());
507     }
508   }
509
510 public: //! @name optional array of Indices/Edges for using shared Vertex data
511
512   //! Returns optional index buffer.
513   const Handle(Graphic3d_IndexBuffer)& Indices() const { return myIndices; }
514
515   //! Returns the number of defined edges
516   Standard_Integer EdgeNumber() const { return !myIndices.IsNull() ? myIndices->NbElements : -1; }
517
518   //! Returns the number of allocated edges
519   Standard_Integer EdgeNumberAllocated() const { return !myIndices.IsNull() ? myIndices->NbMaxElements() : 0; }
520
521   //! Returns the vertex index at rank theRank in the range [1,EdgeNumber()]
522   Standard_Integer Edge (const Standard_Integer theRank) const
523   {
524     Standard_OutOfRange_Raise_if (myIndices.IsNull() || theRank < 1 || theRank > myIndices->NbElements, "BAD EDGE index");
525     return Standard_Integer(myIndices->Index (theRank - 1) + 1);
526   }
527
528   //! Adds an edge in the range [1,VertexNumber()] in the array.
529   //! @return the actual edges number
530   Standard_EXPORT Standard_Integer AddEdge (const Standard_Integer theVertexIndex);
531
532   //! Convenience method, adds two vertex indices (a segment) in the range [1,VertexNumber()] in the array.
533   //! @return the actual edges number
534   Standard_Integer AddEdges (Standard_Integer theVertexIndex1,
535                              Standard_Integer theVertexIndex2)
536   {
537     AddEdge (theVertexIndex1);
538     return AddEdge (theVertexIndex2);
539   }
540
541   //! Convenience method, adds two vertex indices (a segment) in the range [1,VertexNumber()] in the array of segments (Graphic3d_TOPA_SEGMENTS).
542   //! Raises exception if array is not of type Graphic3d_TOPA_SEGMENTS.
543   //! @return the actual edges number
544   Standard_Integer AddSegmentEdges (Standard_Integer theVertexIndex1,
545                                     Standard_Integer theVertexIndex2)
546   {
547     Standard_TypeMismatch_Raise_if (myType != Graphic3d_TOPA_SEGMENTS, "Not array of segments");
548     return AddEdges (theVertexIndex1, theVertexIndex2);
549   }
550
551   //! Convenience method, adds three vertex indices (a triangle) in the range [1,VertexNumber()] in the array.
552   //! @return the actual edges number
553   Standard_Integer AddEdges (Standard_Integer theVertexIndex1,
554                              Standard_Integer theVertexIndex2,
555                              Standard_Integer theVertexIndex3)
556   {
557     AddEdge (theVertexIndex1);
558     AddEdge (theVertexIndex2);
559     return AddEdge (theVertexIndex3);
560   }
561
562   //! Convenience method, adds three vertex indices of triangle in the range [1,VertexNumber()] in the array of triangles.
563   //! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
564   //! @return the actual edges number
565   Standard_Integer AddTriangleEdges (Standard_Integer theVertexIndex1,
566                                      Standard_Integer theVertexIndex2,
567                                      Standard_Integer theVertexIndex3)
568   {
569     Standard_TypeMismatch_Raise_if (myType != Graphic3d_TOPA_TRIANGLES, "Not array of triangles");
570     return AddEdges (theVertexIndex1, theVertexIndex2, theVertexIndex3);
571   }
572
573   //! Convenience method, adds three vertex indices of triangle in the range [1,VertexNumber()] in the array of triangles.
574   //! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
575   //! @return the actual edges number
576   Standard_Integer AddTriangleEdges (const Graphic3d_Vec3i& theIndexes)
577   {
578     Standard_TypeMismatch_Raise_if (myType != Graphic3d_TOPA_TRIANGLES, "Not array of triangles");
579     return AddEdges (theIndexes[0], theIndexes[1], theIndexes[2]);
580   }
581
582   //! Convenience method, adds three vertex indices (4th component is ignored) of triangle in the range [1,VertexNumber()] in the array of triangles.
583   //! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
584   //! @return the actual edges number
585   Standard_Integer AddTriangleEdges (const Graphic3d_Vec4i& theIndexes)
586   {
587     Standard_TypeMismatch_Raise_if (myType != Graphic3d_TOPA_TRIANGLES, "Not array of triangles");
588     return AddEdges (theIndexes[0], theIndexes[1], theIndexes[2]);
589   }
590
591   //! Convenience method, adds four vertex indices (a quad) in the range [1,VertexNumber()] in the array.
592   //! @return the actual edges number
593   Standard_Integer AddEdges (Standard_Integer theVertexIndex1,
594                              Standard_Integer theVertexIndex2,
595                              Standard_Integer theVertexIndex3,
596                              Standard_Integer theVertexIndex4)
597   {
598     AddEdge (theVertexIndex1);
599     AddEdge (theVertexIndex2);
600     AddEdge (theVertexIndex3);
601     return AddEdge (theVertexIndex4);
602   }
603
604   //! Convenience method, adds four vertex indices (a quad) in the range [1,VertexNumber()] in the array of quads.
605   //! Raises exception if array is not of type Graphic3d_TOPA_QUADRANGLES.
606   //! @return the actual edges number
607   Standard_Integer AddQuadEdges (Standard_Integer theVertexIndex1,
608                                  Standard_Integer theVertexIndex2,
609                                  Standard_Integer theVertexIndex3,
610                                  Standard_Integer theVertexIndex4)
611   {
612     Standard_TypeMismatch_Raise_if (myType != Graphic3d_TOPA_QUADRANGLES, "Not array of quads");
613     return AddEdges (theVertexIndex1, theVertexIndex2, theVertexIndex3, theVertexIndex4);
614   }
615
616   //! Convenience method, adds quad indices in the range [1,VertexNumber()] into array or triangles as two triangles.
617   //! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
618   //! @return the actual edges number
619   Standard_Integer AddQuadTriangleEdges (Standard_Integer theVertexIndex1,
620                                          Standard_Integer theVertexIndex2,
621                                          Standard_Integer theVertexIndex3,
622                                          Standard_Integer theVertexIndex4)
623   {
624     AddTriangleEdges (theVertexIndex3, theVertexIndex1, theVertexIndex2);
625     return AddTriangleEdges (theVertexIndex1, theVertexIndex3, theVertexIndex4);
626   }
627
628   //! Convenience method, adds quad indices in the range [1,VertexNumber()] into array or triangles as two triangles.
629   //! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
630   //! @return the actual edges number
631   Standard_Integer AddQuadTriangleEdges (const Graphic3d_Vec4i& theIndexes)
632   {
633     return AddQuadTriangleEdges (theIndexes[0], theIndexes[1], theIndexes[2], theIndexes[3]);
634   }
635
636   //! Add triangle strip into indexed triangulation array.
637   //! N-2 triangles are added from N input nodes.
638   //! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
639   //! @param theVertexLower [in] index of first node defining triangle strip
640   //! @param theVertexUpper [in] index of last  node defining triangle strip
641   Standard_EXPORT void AddTriangleStripEdges (Standard_Integer theVertexLower,
642                                               Standard_Integer theVertexUpper);
643
644   //! Add triangle fan into indexed triangulation array.
645   //! N-2 triangles are added from N input nodes (or N-1 with closed flag).
646   //! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
647   //! @param theVertexLower [in] index of first node defining triangle fun (center)
648   //! @param theVertexUpper [in] index of last  node defining triangle fun
649   //! @param theToClose [in] close triangle fan (connect first and last points)
650   Standard_EXPORT void AddTriangleFanEdges (Standard_Integer theVertexLower,
651                                             Standard_Integer theVertexUpper,
652                                             Standard_Boolean theToClose);
653
654   //! Add line strip (polyline) into indexed segments array.
655   //! N-1 segments are added from N input nodes (or N with closed flag).
656   //! Raises exception if array is not of type Graphic3d_TOPA_SEGMENTS.
657   //! @param theVertexLower [in] index of first node defining line strip fun (center)
658   //! @param theVertexUpper [in] index of last  node defining triangle fun
659   //! @param theToClose [in] close triangle fan (connect first and last points)
660   Standard_EXPORT void AddPolylineEdges (Standard_Integer theVertexLower,
661                                          Standard_Integer theVertexUpper,
662                                          Standard_Boolean theToClose);
663
664 public: //! @name optional array of Bounds/Subgroups within primitive array (e.g. restarting primitives / assigning colors)
665
666   //! Returns optional bounds buffer.
667   const Handle(Graphic3d_BoundBuffer)& Bounds() const { return myBounds; }
668
669   //! Returns TRUE when bound colors array is defined.
670   Standard_Boolean HasBoundColors() const { return !myBounds.IsNull() && myBounds->Colors != NULL; }
671
672   //! Returns the number of defined bounds
673   Standard_Integer BoundNumber() const { return !myBounds.IsNull() ? myBounds->NbBounds : -1; }
674
675   //! Returns the number of allocated bounds
676   Standard_Integer BoundNumberAllocated() const { return !myBounds.IsNull() ? myBounds->NbMaxBounds : 0; }
677
678   //! Returns the edge number at rank theRank.
679   Standard_Integer Bound (const Standard_Integer theRank) const
680   {
681     Standard_OutOfRange_Raise_if (myBounds.IsNull() || theRank < 1 || theRank > myBounds->NbBounds, "BAD BOUND index");
682     return myBounds->Bounds[theRank - 1];
683   }
684
685   //! Returns the bound color at rank theRank from the bound table if defined.
686   Quantity_Color BoundColor (const Standard_Integer theRank) const
687   {
688     Standard_Real anRGB[3] = {0.0, 0.0, 0.0};
689     BoundColor (theRank, anRGB[0], anRGB[1], anRGB[2]);
690     return Quantity_Color (anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB);
691   }
692
693   //! Returns the bound color values at rank theRank from the bound table if defined.
694   void BoundColor (const Standard_Integer theRank, Standard_Real& theR, Standard_Real& theG, Standard_Real& theB) const
695   {
696     Standard_OutOfRange_Raise_if (myBounds.IsNull() || myBounds->Colors == NULL || theRank < 1 || theRank > myBounds->NbBounds, "BAD BOUND index");
697     const Graphic3d_Vec4& aVec = myBounds->Colors[theRank - 1];
698     theR = Standard_Real(aVec.r());
699     theG = Standard_Real(aVec.g());
700     theB = Standard_Real(aVec.b());
701   }
702
703   //! Adds a bound of length theEdgeNumber in the bound array
704   //! @return the actual bounds number
705   Standard_EXPORT Standard_Integer AddBound (const Standard_Integer theEdgeNumber);
706
707   //! Adds a bound of length theEdgeNumber and bound color theBColor in the bound array.
708   //! Warning: theBColor is ignored when the hasBColors constructor parameter is FALSE
709   //! @return the actual bounds number
710   Standard_Integer AddBound (const Standard_Integer theEdgeNumber, const Quantity_Color& theBColor)
711   {
712     return AddBound (theEdgeNumber, theBColor.Red(), theBColor.Green(), theBColor.Blue());
713   }
714
715   //! Adds a bound of length theEdgeNumber and bound color coordinates in the bound array.
716   //! Warning: <theR,theG,theB> are ignored when the hasBColors constructor parameter is FALSE
717   //! @return the actual bounds number
718   Standard_EXPORT Standard_Integer AddBound (const Standard_Integer theEdgeNumber, const Standard_Real theR, const Standard_Real theG, const Standard_Real theB);
719
720   //! Change the bound color of rank theIndex in the array.
721   void SetBoundColor (const Standard_Integer theIndex, const Quantity_Color& theColor)
722   {
723     SetBoundColor (theIndex, theColor.Red(), theColor.Green(), theColor.Blue());
724   }
725
726   //! Change the bound color of rank theIndex in the array.
727   void SetBoundColor (const Standard_Integer theIndex, const Standard_Real theR, const Standard_Real theG, const Standard_Real theB)
728   {
729     if (myBounds.IsNull())
730     {
731       return;
732     }
733     Standard_OutOfRange_Raise_if (myBounds.IsNull() || myBounds->Colors == NULL || theIndex < 1 || theIndex > myBounds->NbMaxBounds, "BAD BOUND index");
734     Graphic3d_Vec4& aVec = myBounds->Colors[theIndex - 1];
735     aVec.r() = Standard_ShortReal (theR);
736     aVec.g() = Standard_ShortReal (theG);
737     aVec.b() = Standard_ShortReal (theB);
738     aVec.a() = 1.0f;
739     myBounds->NbBounds = Max (theIndex, myBounds->NbBounds);
740   }
741
742 protected: //! @name protected constructors
743
744   //! Main constructor.
745   //! @param theType       type of primitive
746   //! @param theMaxVertexs length of vertex attributes buffer to be allocated (maximum number of vertexes, @sa ::AddVertex())
747   //! @param theMaxBounds  length of bounds buffer to be allocated (maximum number of bounds, @sa ::AddBound())
748   //! @param theMaxEdges   length of edges (index) buffer to be allocated (maximum number of indexes @sa ::AddEdge())
749   //! @param theArrayFlags array flags
750   Graphic3d_ArrayOfPrimitives (Graphic3d_TypeOfPrimitiveArray theType,
751                                Standard_Integer theMaxVertexs,
752                                Standard_Integer theMaxBounds,
753                                Standard_Integer theMaxEdges,
754                                Graphic3d_ArrayFlags theArrayFlags)
755   : myNormData (NULL), myTexData (NULL), myColData (NULL), myPosStride (0), myNormStride (0), myTexStride (0), myColStride (0),
756     myType (Graphic3d_TOPA_UNDEFINED)
757   {
758     init (theType, theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
759   }
760
761   //! Array constructor.
762   Standard_EXPORT void init (Graphic3d_TypeOfPrimitiveArray theType,
763                              Standard_Integer theMaxVertexs,
764                              Standard_Integer theMaxBounds,
765                              Standard_Integer theMaxEdges,
766                              Graphic3d_ArrayFlags theArrayFlags);
767
768 private: //! @name private fields
769
770   Handle(Graphic3d_IndexBuffer)  myIndices;
771   Handle(Graphic3d_Buffer)       myAttribs;
772   Handle(Graphic3d_BoundBuffer)  myBounds;
773   Standard_Byte* myNormData;
774   Standard_Byte* myTexData;
775   Standard_Byte* myColData;
776   Standard_Size  myPosStride;
777   Standard_Size  myNormStride;
778   Standard_Size  myTexStride;
779   Standard_Size  myColStride;
780   Graphic3d_TypeOfPrimitiveArray myType;
781
782 };
783
784 #endif // _Graphic3d_ArrayOfPrimitives_HeaderFile