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