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