Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-12 09:17:26

0001 // Created on: 2000-06-16
0002 // Copyright (c) 2000-2014 OPEN CASCADE SAS
0003 //
0004 // This file is part of Open CASCADE Technology software library.
0005 //
0006 // This library is free software; you can redistribute it and/or modify it under
0007 // the terms of the GNU Lesser General Public License version 2.1 as published
0008 // by the Free Software Foundation, with special exception defined in the file
0009 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0010 // distribution for complete text of the license and disclaimer of any warranty.
0011 //
0012 // Alternatively, this file may be used under the terms of Open CASCADE
0013 // commercial license or contractual agreement.
0014 
0015 #ifndef _Graphic3d_ArrayOfPrimitives_HeaderFile
0016 #define _Graphic3d_ArrayOfPrimitives_HeaderFile
0017 
0018 #include <Graphic3d_BoundBuffer.hxx>
0019 #include <Graphic3d_ArrayFlags.hxx>
0020 #include <Graphic3d_Buffer.hxx>
0021 #include <Graphic3d_IndexBuffer.hxx>
0022 #include <Graphic3d_TypeOfPrimitiveArray.hxx>
0023 #include <gp_Dir.hxx>
0024 #include <gp_Pnt.hxx>
0025 #include <Standard_OutOfRange.hxx>
0026 #include <Standard_TypeMismatch.hxx>
0027 #include <Quantity_Color.hxx>
0028 
0029 //! This class furnish services to defined and fill an array of primitives
0030 //! which can be passed directly to graphics rendering API.
0031 //!
0032 //! The basic interface consists of the following parts:
0033 //! 1) Specifying primitive type.
0034 //!    WARNING! Particular primitive types might be unsupported by specific hardware/graphics API
0035 //!    (like quads and polygons).
0036 //!             It is always preferred using one of basic types having maximum compatibility:
0037 //!             Point, Triangle (or Triangle strip), Segment aka Lines (or Polyline aka Line Strip).
0038 //!    Primitive strip types can be used to reduce memory usage as alternative to Indexed arrays.
0039 //! 2) Vertex array.
0040 //!    - Specifying the (maximum) number of vertexes within array.
0041 //!    - Specifying the vertex attributes, complementary to mandatory vertex Position (normal,
0042 //!    color, UV texture coordinates).
0043 //!    - Defining vertex values by using various versions of AddVertex() or SetVertex*() methods.
0044 //! 3) Index array (optional).
0045 //!    - Specifying the (maximum) number of indexes (edges).
0046 //!    - Defining index values by using AddEdge() method; the index value should be within number of
0047 //!    defined Vertexes.
0048 //!
0049 //!    Indexed array allows sharing vertex data across Primitives and thus reducing memory usage,
0050 //!    since index size is much smaller then size of vertex with all its attributes.
0051 //!    It is a preferred way for defining primitive array and main alternative to Primitive Strips
0052 //!    for optimal memory usage, although it is also possible (but unusual) defining Indexed
0053 //!    Primitive Strip. Note that it is NOT possible sharing Vertex Attributes partially (e.g. share
0054 //!    Position, but have different Normals); in such cases Vertex should be entirely duplicated
0055 //!    with all Attributes.
0056 //! 4) Bounds array (optional).
0057 //!    - Specifying the (maximum) number of bounds.
0058 //!    - Defining bounds using AddBound() methods.
0059 //!
0060 //!    Bounds allow splitting Primitive Array into sub-groups.
0061 //!    This is useful only in two cases - for specifying per-group color and for restarting
0062 //!    Primitive Strips. WARNING! Bounds within Primitive Array break rendering batches into parts
0063 //!    (additional for loops),
0064 //!             affecting rendering performance negatively (increasing CPU load).
0065 class Graphic3d_ArrayOfPrimitives : public Standard_Transient
0066 {
0067   DEFINE_STANDARD_RTTIEXT(Graphic3d_ArrayOfPrimitives, Standard_Transient)
0068 public:
0069   //! Create an array of specified type.
0070   static occ::handle<Graphic3d_ArrayOfPrimitives> CreateArray(
0071     Graphic3d_TypeOfPrimitiveArray theType,
0072     int                            theMaxVertexs,
0073     int                            theMaxEdges,
0074     Graphic3d_ArrayFlags           theArrayFlags)
0075   {
0076     return CreateArray(theType, theMaxVertexs, 0, theMaxEdges, theArrayFlags);
0077   }
0078 
0079   //! Create an array of specified type.
0080   static Standard_EXPORT occ::handle<Graphic3d_ArrayOfPrimitives> CreateArray(
0081     Graphic3d_TypeOfPrimitiveArray theType,
0082     int                            theMaxVertexs,
0083     int                            theMaxBounds,
0084     int                            theMaxEdges,
0085     Graphic3d_ArrayFlags           theArrayFlags);
0086 
0087 public:
0088   //! Destructor.
0089   Standard_EXPORT ~Graphic3d_ArrayOfPrimitives() override;
0090 
0091   //! Returns vertex attributes buffer (colors, normals, texture coordinates).
0092   const occ::handle<Graphic3d_Buffer>& Attributes() const { return myAttribs; }
0093 
0094   //! Returns the type of this primitive
0095   Graphic3d_TypeOfPrimitiveArray Type() const { return myType; }
0096 
0097   //! Returns the string type of this primitive
0098   Standard_EXPORT const char* StringType() const;
0099 
0100   //! Returns TRUE when vertex normals array is defined.
0101   bool HasVertexNormals() const { return myNormData != nullptr; }
0102 
0103   //! Returns TRUE when vertex colors array is defined.
0104   bool HasVertexColors() const { return myColData != nullptr; }
0105 
0106   //! Returns TRUE when vertex texels array is defined.
0107   bool HasVertexTexels() const { return myTexData != nullptr; }
0108 
0109   //! Returns the number of defined vertex
0110   int VertexNumber() const { return myAttribs->NbElements; }
0111 
0112   //! Returns the number of allocated vertex
0113   int VertexNumberAllocated() const { return myAttribs->NbMaxElements(); }
0114 
0115   //! Returns the number of total items according to the array type.
0116   Standard_EXPORT int ItemNumber() const;
0117 
0118   //! Returns TRUE only when the contains of this array is available.
0119   Standard_EXPORT bool IsValid();
0120 
0121   //! Adds a vertice in the array.
0122   //! @return the actual vertex number
0123   int AddVertex(const gp_Pnt& theVertex)
0124   {
0125     return AddVertex(theVertex.X(), theVertex.Y(), theVertex.Z());
0126   }
0127 
0128   //! Adds a vertice in the array.
0129   //! @return the actual vertex number
0130   int AddVertex(const NCollection_Vec3<float>& theVertex)
0131   {
0132     return AddVertex(theVertex.x(), theVertex.y(), theVertex.z());
0133   }
0134 
0135   //! Adds a vertice in the array.
0136   //! @return the actual vertex number
0137   int AddVertex(const double theX, const double theY, const double theZ)
0138   {
0139     return AddVertex(RealToShortReal(theX), RealToShortReal(theY), RealToShortReal(theZ));
0140   }
0141 
0142   //! Adds a vertice in the array.
0143   //! @return the actual vertex number.
0144   int AddVertex(const float theX, const float theY, const float theZ)
0145   {
0146     const int anIndex = myAttribs->NbElements + 1;
0147     SetVertice(anIndex, theX, theY, theZ);
0148     return anIndex;
0149   }
0150 
0151   //! Adds a vertice and vertex color in the vertex array.
0152   //! Warning: theColor is ignored when the hasVColors constructor parameter is FALSE
0153   //! @return the actual vertex number
0154   int AddVertex(const gp_Pnt& theVertex, const Quantity_Color& theColor)
0155   {
0156     const int anIndex = AddVertex(theVertex);
0157     SetVertexColor(anIndex, theColor.Red(), theColor.Green(), theColor.Blue());
0158     return anIndex;
0159   }
0160 
0161   //! Adds a vertice and vertex color in the vertex array.
0162   //! Warning: theColor is ignored when the hasVColors constructor parameter is FALSE
0163   //! @code
0164   //!   theColor32 = Alpha << 24 + Blue << 16 + Green << 8 + Red
0165   //! @endcode
0166   //! @return the actual vertex number
0167   int AddVertex(const gp_Pnt& theVertex, const int theColor32)
0168   {
0169     const int anIndex = AddVertex(theVertex);
0170     SetVertexColor(anIndex, theColor32);
0171     return anIndex;
0172   }
0173 
0174   //! Adds a vertice and vertex color in the vertex array.
0175   //! Warning: theColor is ignored when the hasVColors constructor parameter is FALSE
0176   //! @return the actual vertex number
0177   int AddVertex(const gp_Pnt& theVertex, const NCollection_Vec4<uint8_t>& theColor)
0178   {
0179     const int anIndex = AddVertex(theVertex);
0180     SetVertexColor(anIndex, theColor);
0181     return anIndex;
0182   }
0183 
0184   //! Adds a vertice and vertex normal in the vertex array.
0185   //! Warning: theNormal is ignored when the hasVNormals constructor parameter is FALSE.
0186   //! @return the actual vertex number
0187   int AddVertex(const gp_Pnt& theVertex, const gp_Dir& theNormal)
0188   {
0189     return AddVertex(theVertex.X(),
0190                      theVertex.Y(),
0191                      theVertex.Z(),
0192                      theNormal.X(),
0193                      theNormal.Y(),
0194                      theNormal.Z());
0195   }
0196 
0197   //! Adds a vertice and vertex normal in the vertex array.
0198   //! Warning: Normal is ignored when the hasVNormals constructor parameter is FALSE.
0199   //! @return the actual vertex number
0200   int AddVertex(const double theX,
0201                 const double theY,
0202                 const double theZ,
0203                 const double theNX,
0204                 const double theNY,
0205                 const double theNZ)
0206   {
0207     return AddVertex(RealToShortReal(theX),
0208                      RealToShortReal(theY),
0209                      RealToShortReal(theZ),
0210                      float(theNX),
0211                      float(theNY),
0212                      float(theNZ));
0213   }
0214 
0215   //! Adds a vertice and vertex normal in the vertex array.
0216   //! Warning: Normal is ignored when the hasVNormals constructor parameter is FALSE.
0217   //! @return the actual vertex number
0218   int AddVertex(const float theX,
0219                 const float theY,
0220                 const float theZ,
0221                 const float theNX,
0222                 const float theNY,
0223                 const float theNZ)
0224   {
0225     const int anIndex = myAttribs->NbElements + 1;
0226     SetVertice(anIndex, theX, theY, theZ);
0227     SetVertexNormal(anIndex, theNX, theNY, theNZ);
0228     return anIndex;
0229   }
0230 
0231   //! Adds a vertice,vertex normal and color in the vertex array.
0232   //! Warning: theNormal is ignored when the hasVNormals constructor parameter is FALSE
0233   //! and      theColor  is ignored when the hasVColors  constructor parameter is FALSE.
0234   //! @return the actual vertex number
0235   int AddVertex(const gp_Pnt& theVertex, const gp_Dir& theNormal, const Quantity_Color& theColor)
0236   {
0237     const int anIndex = AddVertex(theVertex, theNormal);
0238     SetVertexColor(anIndex, theColor.Red(), theColor.Green(), theColor.Blue());
0239     return anIndex;
0240   }
0241 
0242   //! Adds a vertice,vertex normal and color in the vertex array.
0243   //! Warning: theNormal is ignored when the hasVNormals constructor parameter is FALSE
0244   //! and      theColor  is ignored when the hasVColors  constructor parameter is FALSE.
0245   //! @code
0246   //!   theColor32 = Alpha << 24 + Blue << 16 + Green << 8 + Red
0247   //! @endcode
0248   //! @return the actual vertex number
0249   int AddVertex(const gp_Pnt& theVertex, const gp_Dir& theNormal, const int theColor32)
0250   {
0251     const int anIndex = AddVertex(theVertex, theNormal);
0252     SetVertexColor(anIndex, theColor32);
0253     return anIndex;
0254   }
0255 
0256   //! Adds a vertice and vertex texture in the vertex array.
0257   //! theTexel is ignored when the hasVTexels constructor parameter is FALSE.
0258   //! @return the actual vertex number
0259   int AddVertex(const gp_Pnt& theVertex, const gp_Pnt2d& theTexel)
0260   {
0261     return AddVertex(theVertex.X(), theVertex.Y(), theVertex.Z(), theTexel.X(), theTexel.Y());
0262   }
0263 
0264   //! Adds a vertice and vertex texture coordinates in the vertex array.
0265   //! Texel is ignored when the hasVTexels constructor parameter is FALSE.
0266   //! @return the actual vertex number
0267   int AddVertex(const double theX,
0268                 const double theY,
0269                 const double theZ,
0270                 const double theTX,
0271                 const double theTY)
0272   {
0273     return AddVertex(RealToShortReal(theX),
0274                      RealToShortReal(theY),
0275                      RealToShortReal(theZ),
0276                      float(theTX),
0277                      float(theTY));
0278   }
0279 
0280   //! Adds a vertice and vertex texture coordinates in the vertex array.
0281   //! Texel is ignored when the hasVTexels constructor parameter is FALSE.
0282   //! @return the actual vertex number
0283   int AddVertex(const float theX,
0284                 const float theY,
0285                 const float theZ,
0286                 const float theTX,
0287                 const float theTY)
0288   {
0289     const int anIndex = myAttribs->NbElements + 1;
0290     SetVertice(anIndex, theX, theY, theZ);
0291     SetVertexTexel(anIndex, theTX, theTY);
0292     return anIndex;
0293   }
0294 
0295   //! Adds a vertice,vertex normal and texture in the vertex array.
0296   //! Warning: theNormal is ignored when the hasVNormals constructor parameter is FALSE
0297   //! and      theTexel  is ignored when the hasVTexels  constructor parameter is FALSE.
0298   //! @return the actual vertex number
0299   int AddVertex(const gp_Pnt& theVertex, const gp_Dir& theNormal, const gp_Pnt2d& theTexel)
0300   {
0301     return AddVertex(theVertex.X(),
0302                      theVertex.Y(),
0303                      theVertex.Z(),
0304                      theNormal.X(),
0305                      theNormal.Y(),
0306                      theNormal.Z(),
0307                      theTexel.X(),
0308                      theTexel.Y());
0309   }
0310 
0311   //! Adds a vertice,vertex normal and texture in the vertex array.
0312   //! Warning: Normal is ignored when the hasVNormals constructor parameter is FALSE
0313   //! and      Texel  is ignored when the hasVTexels  constructor parameter is FALSE.
0314   //! @return the actual vertex number
0315   int AddVertex(const double theX,
0316                 const double theY,
0317                 const double theZ,
0318                 const double theNX,
0319                 const double theNY,
0320                 const double theNZ,
0321                 const double theTX,
0322                 const double theTY)
0323   {
0324     return AddVertex(RealToShortReal(theX),
0325                      RealToShortReal(theY),
0326                      RealToShortReal(theZ),
0327                      float(theNX),
0328                      float(theNY),
0329                      float(theNZ),
0330                      float(theTX),
0331                      float(theTY));
0332   }
0333 
0334   //! Adds a vertice,vertex normal and texture in the vertex array.
0335   //! Warning: Normal is ignored when the hasVNormals constructor parameter is FALSE
0336   //!     and  Texel  is ignored when the hasVTexels  constructor parameter is FALSE.
0337   //! @return the actual vertex number
0338   int AddVertex(const float theX,
0339                 const float theY,
0340                 const float theZ,
0341                 const float theNX,
0342                 const float theNY,
0343                 const float theNZ,
0344                 const float theTX,
0345                 const float theTY)
0346   {
0347     const int anIndex = myAttribs->NbElements + 1;
0348     SetVertice(anIndex, theX, theY, theZ);
0349     SetVertexNormal(anIndex, theNX, theNY, theNZ);
0350     SetVertexTexel(anIndex, theTX, theTY);
0351     return anIndex;
0352   }
0353 
0354   //! Change the vertice of rank theIndex in the array.
0355   //! @param[in] theIndex  node index within [1, VertexNumberAllocated()] range
0356   //! @param[in] theVertex 3D coordinates
0357   void SetVertice(const int theIndex, const gp_Pnt& theVertex)
0358   {
0359     SetVertice(theIndex, float(theVertex.X()), float(theVertex.Y()), float(theVertex.Z()));
0360   }
0361 
0362   //! Change the vertice in the array.
0363   //! @param[in] theIndex node index within [1, VertexNumberAllocated()] range
0364   //! @param[in] theX coordinate X
0365   //! @param[in] theY coordinate Y
0366   //! @param[in] theZ coordinate Z
0367   void SetVertice(const int theIndex, const float theX, const float theY, const float theZ)
0368   {
0369     Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > myAttribs->NbMaxElements(),
0370                                  "BAD VERTEX index");
0371     NCollection_Vec3<float>& aVec = *reinterpret_cast<NCollection_Vec3<float>*>(
0372       myAttribs->ChangeData() + myPosStride * ((size_t)theIndex - 1));
0373     aVec.x() = theX;
0374     aVec.y() = theY;
0375     aVec.z() = theZ;
0376     if (myAttribs->NbElements < theIndex)
0377     {
0378       myAttribs->NbElements = theIndex;
0379     }
0380   }
0381 
0382   //! Change the vertex color in the array.
0383   //! @param[in] theIndex node index within [1, VertexNumberAllocated()] range
0384   //! @param[in] theColor node color
0385   void SetVertexColor(const int theIndex, const Quantity_Color& theColor)
0386   {
0387     SetVertexColor(theIndex, theColor.Red(), theColor.Green(), theColor.Blue());
0388   }
0389 
0390   //! Change the vertex color in the array.
0391   //! @param[in] theIndex node index within [1, VertexNumberAllocated()] range
0392   //! @param[in] theR red   color value within [0, 1] range
0393   //! @param[in] theG green color value within [0, 1] range
0394   //! @param[in] theB blue  color value within [0, 1] range
0395   void SetVertexColor(const int theIndex, const double theR, const double theG, const double theB)
0396   {
0397     Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > myAttribs->NbMaxElements(),
0398                                  "BAD VERTEX index");
0399     if (myColData != nullptr)
0400     {
0401       NCollection_Vec4<uint8_t>* aColorPtr = reinterpret_cast<NCollection_Vec4<uint8_t>*>(
0402         myColData + myColStride * ((size_t)theIndex - 1));
0403       aColorPtr->SetValues(static_cast<uint8_t>(theR * 255.0),
0404                            static_cast<uint8_t>(theG * 255.0),
0405                            static_cast<uint8_t>(theB * 255.0),
0406                            255);
0407     }
0408     myAttribs->NbElements = (std::max)(theIndex, myAttribs->NbElements);
0409   }
0410 
0411   //! Change the vertex color in the array.
0412   //! @param[in] theIndex node index within [1, VertexNumberAllocated()] range
0413   //! @param[in] theColor node RGBA color values within [0, 255] range
0414   void SetVertexColor(const int theIndex, const NCollection_Vec4<uint8_t>& theColor)
0415   {
0416     Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > myAttribs->NbMaxElements(),
0417                                  "BAD VERTEX index");
0418     if (myColData != nullptr)
0419     {
0420       NCollection_Vec4<uint8_t>* aColorPtr = reinterpret_cast<NCollection_Vec4<uint8_t>*>(
0421         myColData + myColStride * ((size_t)theIndex - 1));
0422       (*aColorPtr) = theColor;
0423     }
0424     myAttribs->NbElements = (std::max)(theIndex, myAttribs->NbElements);
0425   }
0426 
0427   //! Change the vertex color in the array.
0428   //! @code
0429   //!   theColor32 = Alpha << 24 + Blue << 16 + Green << 8 + Red
0430   //! @endcode
0431   //! @param[in] theIndex   node index within [1, VertexNumberAllocated()] range
0432   //! @param[in] theColor32 packed RGBA color values
0433   void SetVertexColor(const int theIndex, const int theColor32)
0434   {
0435     Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > myAttribs->NbMaxElements(),
0436                                  "BAD VERTEX index");
0437     if (myColData != nullptr)
0438     {
0439       *reinterpret_cast<int*>(myColData + myColStride * ((size_t)theIndex - 1)) = theColor32;
0440     }
0441   }
0442 
0443   //! Change the vertex normal in the array.
0444   //! @param[in] theIndex  node index within [1, VertexNumberAllocated()] range
0445   //! @param[in] theNormal normalized surface normal
0446   void SetVertexNormal(const int theIndex, const gp_Dir& theNormal)
0447   {
0448     SetVertexNormal(theIndex, theNormal.X(), theNormal.Y(), theNormal.Z());
0449   }
0450 
0451   //! Change the vertex normal in the array.
0452   //! @param[in] theIndex node index within [1, VertexNumberAllocated()] range
0453   //! @param[in] theNX surface normal X component
0454   //! @param[in] theNY surface normal Y component
0455   //! @param[in] theNZ surface normal Z component
0456   void SetVertexNormal(const int    theIndex,
0457                        const double theNX,
0458                        const double theNY,
0459                        const double theNZ)
0460   {
0461     Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > myAttribs->NbMaxElements(),
0462                                  "BAD VERTEX index");
0463     if (myNormData != nullptr)
0464     {
0465       NCollection_Vec3<float>& aVec = *reinterpret_cast<NCollection_Vec3<float>*>(
0466         myNormData + myNormStride * ((size_t)theIndex - 1));
0467       aVec.x() = float(theNX);
0468       aVec.y() = float(theNY);
0469       aVec.z() = float(theNZ);
0470     }
0471     myAttribs->NbElements = (std::max)(theIndex, myAttribs->NbElements);
0472   }
0473 
0474   //! Change the vertex texel in the array.
0475   //! @param[in] theIndex node index within [1, VertexNumberAllocated()] range
0476   //! @param[in] theTexel node UV coordinates
0477   void SetVertexTexel(const int theIndex, const gp_Pnt2d& theTexel)
0478   {
0479     SetVertexTexel(theIndex, theTexel.X(), theTexel.Y());
0480   }
0481 
0482   //! Change the vertex texel in the array.
0483   //! @param[in] theIndex node index within [1, VertexNumberAllocated()] range
0484   //! @param[in] theTX node U coordinate
0485   //! @param[in] theTY node V coordinate
0486   void SetVertexTexel(const int theIndex, const double theTX, const double theTY)
0487   {
0488     Standard_OutOfRange_Raise_if(theIndex < 1 || theIndex > myAttribs->NbMaxElements(),
0489                                  "BAD VERTEX index");
0490     if (myTexData != nullptr)
0491     {
0492       NCollection_Vec2<float>& aVec = *reinterpret_cast<NCollection_Vec2<float>*>(
0493         myTexData + myTexStride * ((size_t)theIndex - 1));
0494       aVec.x() = float(theTX);
0495       aVec.y() = float(theTY);
0496     }
0497     myAttribs->NbElements = (std::max)(theIndex, myAttribs->NbElements);
0498   }
0499 
0500   //! Returns the vertice from the vertex table if defined.
0501   //! @param[in] theRank node index within [1, VertexNumber()] range
0502   //! @return node 3D coordinates
0503   gp_Pnt Vertice(const int theRank) const
0504   {
0505     double anXYZ[3];
0506     Vertice(theRank, anXYZ[0], anXYZ[1], anXYZ[2]);
0507     return gp_Pnt(anXYZ[0], anXYZ[1], anXYZ[2]);
0508   }
0509 
0510   //! Returns the vertice coordinates at rank theRank from the vertex table if defined.
0511   //! @param[in]  theRank node index within [1, VertexNumber()] range
0512   //! @param[out] theX node X coordinate value
0513   //! @param[out] theY node Y coordinate value
0514   //! @param[out] theZ node Z coordinate value
0515   void Vertice(const int theRank, double& theX, double& theY, double& theZ) const
0516   {
0517     theX = theY = theZ = 0.0;
0518     Standard_OutOfRange_Raise_if(theRank < 1 || theRank > myAttribs->NbElements,
0519                                  "BAD VERTEX index");
0520     const NCollection_Vec3<float>& aVec = *reinterpret_cast<const NCollection_Vec3<float>*>(
0521       myAttribs->Data() + myPosStride * ((size_t)theRank - 1));
0522     theX = double(aVec.x());
0523     theY = double(aVec.y());
0524     theZ = double(aVec.z());
0525   }
0526 
0527   //! Returns the vertex color at rank theRank from the vertex table if defined.
0528   //! @param[in] theRank node index within [1, VertexNumber()] range
0529   //! @return node color RGB value
0530   Quantity_Color VertexColor(const int theRank) const
0531   {
0532     double anRGB[3];
0533     VertexColor(theRank, anRGB[0], anRGB[1], anRGB[2]);
0534     return Quantity_Color(anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB);
0535   }
0536 
0537   //! Returns the vertex color from the vertex table if defined.
0538   //! @param[in]  theIndex node index within [1, VertexNumber()] range
0539   //! @param[out] theColor node RGBA color values within [0, 255] range
0540   void VertexColor(const int theIndex, NCollection_Vec4<uint8_t>& theColor) const
0541   {
0542     Standard_OutOfRange_Raise_if(myColData == nullptr || theIndex < 1
0543                                    || theIndex > myAttribs->NbElements,
0544                                  "BAD VERTEX index");
0545     theColor = *reinterpret_cast<const NCollection_Vec4<uint8_t>*>(
0546       myColData + myColStride * ((size_t)theIndex - 1));
0547   }
0548 
0549   //! Returns the vertex color values from the vertex table if defined.
0550   //! @param[in]  theRank node index within [1, VertexNumber()] range
0551   //! @param[out] theR node red   color component value within [0, 1] range
0552   //! @param[out] theG node green color component value within [0, 1] range
0553   //! @param[out] theB node blue  color component value within [0, 1] range
0554   void VertexColor(const int theRank, double& theR, double& theG, double& theB) const
0555   {
0556     theR = theG = theB = 0.0;
0557     Standard_OutOfRange_Raise_if(theRank < 1 || theRank > myAttribs->NbElements,
0558                                  "BAD VERTEX index");
0559     if (myColData == nullptr)
0560     {
0561       return;
0562     }
0563     const NCollection_Vec4<uint8_t>& aColor = *reinterpret_cast<const NCollection_Vec4<uint8_t>*>(
0564       myColData + myColStride * ((size_t)theRank - 1));
0565     theR = double(aColor.r()) / 255.0;
0566     theG = double(aColor.g()) / 255.0;
0567     theB = double(aColor.b()) / 255.0;
0568   }
0569 
0570   //! Returns the vertex color values from the vertex table if defined.
0571   //! @param[in]  theRank  node index within [1, VertexNumber()] range
0572   //! @param[out] theColor node RGBA color packed into 32-bit integer
0573   void VertexColor(const int theRank, int& theColor) const
0574   {
0575     Standard_OutOfRange_Raise_if(theRank < 1 || theRank > myAttribs->NbElements,
0576                                  "BAD VERTEX index");
0577     if (myColData != nullptr)
0578     {
0579       theColor = *reinterpret_cast<const int*>(myColData + myColStride * ((size_t)theRank - 1));
0580     }
0581   }
0582 
0583   //! Returns the vertex normal from the vertex table if defined.
0584   //! @param[in] theRank node index within [1, VertexNumber()] range
0585   //! @return normalized 3D vector defining surface normal
0586   gp_Dir VertexNormal(const int theRank) const
0587   {
0588     double anXYZ[3];
0589     VertexNormal(theRank, anXYZ[0], anXYZ[1], anXYZ[2]);
0590     return gp_Dir(anXYZ[0], anXYZ[1], anXYZ[2]);
0591   }
0592 
0593   //! Returns the vertex normal coordinates at rank theRank from the vertex table if defined.
0594   //! @param[in]  theRank node index within [1, VertexNumber()] range
0595   //! @param[out] theNX   normal X coordinate
0596   //! @param[out] theNY   normal Y coordinate
0597   //! @param[out] theNZ   normal Z coordinate
0598   void VertexNormal(const int theRank, double& theNX, double& theNY, double& theNZ) const
0599   {
0600     theNX = theNY = theNZ = 0.0;
0601     Standard_OutOfRange_Raise_if(theRank < 1 || theRank > myAttribs->NbElements,
0602                                  "BAD VERTEX index");
0603     if (myNormData != nullptr)
0604     {
0605       const NCollection_Vec3<float>& aVec = *reinterpret_cast<const NCollection_Vec3<float>*>(
0606         myNormData + myNormStride * ((size_t)theRank - 1));
0607       theNX = double(aVec.x());
0608       theNY = double(aVec.y());
0609       theNZ = double(aVec.z());
0610     }
0611   }
0612 
0613   //! Returns the vertex texture at rank theRank from the vertex table if defined.
0614   //! @param[in] theRank node index within [1, VertexNumber()] range
0615   //! @return UV coordinates
0616   gp_Pnt2d VertexTexel(const int theRank) const
0617   {
0618     double anXY[2];
0619     VertexTexel(theRank, anXY[0], anXY[1]);
0620     return gp_Pnt2d(anXY[0], anXY[1]);
0621   }
0622 
0623   //! Returns the vertex texture coordinates at rank theRank from the vertex table if defined.
0624   //! @param[in]  theRank node index within [1, VertexNumber()] range
0625   //! @param[out] theTX texel U coordinate value
0626   //! @param[out] theTY texel V coordinate value
0627   void VertexTexel(const int theRank, double& theTX, double& theTY) const
0628   {
0629     theTX = theTY = 0.0;
0630     Standard_OutOfRange_Raise_if(theRank < 1 || theRank > myAttribs->NbElements,
0631                                  "BAD VERTEX index");
0632     if (myTexData != nullptr)
0633     {
0634       const NCollection_Vec2<float>& aVec = *reinterpret_cast<const NCollection_Vec2<float>*>(
0635         myTexData + myTexStride * ((size_t)theRank - 1));
0636       theTX = double(aVec.x());
0637       theTY = double(aVec.y());
0638     }
0639   }
0640 
0641 public: //! @name optional array of Indices/Edges for using shared Vertex data
0642   //! Returns optional index buffer.
0643   const occ::handle<Graphic3d_IndexBuffer>& Indices() const { return myIndices; }
0644 
0645   //! Returns the number of defined edges
0646   int EdgeNumber() const { return !myIndices.IsNull() ? myIndices->NbElements : -1; }
0647 
0648   //! Returns the number of allocated edges
0649   int EdgeNumberAllocated() const { return !myIndices.IsNull() ? myIndices->NbMaxElements() : 0; }
0650 
0651   //! Returns the vertex index at rank theRank in the range [1,EdgeNumber()]
0652   int Edge(const int theRank) const
0653   {
0654     Standard_OutOfRange_Raise_if(myIndices.IsNull() || theRank < 1
0655                                    || theRank > myIndices->NbElements,
0656                                  "BAD EDGE index");
0657     return int(myIndices->Index(theRank - 1) + 1);
0658   }
0659 
0660   //! Adds an edge in the range [1,VertexNumber()] in the array.
0661   //! @return the actual edges number
0662   Standard_EXPORT int AddEdge(const int theVertexIndex);
0663 
0664   //! Convenience method, adds two vertex indices (a segment) in the range [1,VertexNumber()] in the
0665   //! array.
0666   //! @return the actual edges number
0667   int AddEdges(int theVertexIndex1, int theVertexIndex2)
0668   {
0669     AddEdge(theVertexIndex1);
0670     return AddEdge(theVertexIndex2);
0671   }
0672 
0673   //! Convenience method, adds two vertex indices (a segment) in the range [1,VertexNumber()] in the
0674   //! array of segments (Graphic3d_TOPA_SEGMENTS). Raises exception if array is not of type
0675   //! Graphic3d_TOPA_SEGMENTS.
0676   //! @return the actual edges number
0677   int AddSegmentEdges(int theVertexIndex1, int theVertexIndex2)
0678   {
0679     Standard_TypeMismatch_Raise_if(myType != Graphic3d_TOPA_SEGMENTS, "Not array of segments");
0680     return AddEdges(theVertexIndex1, theVertexIndex2);
0681   }
0682 
0683   //! Convenience method, adds three vertex indices (a triangle) in the range [1,VertexNumber()] in
0684   //! the array.
0685   //! @return the actual edges number
0686   int AddEdges(int theVertexIndex1, int theVertexIndex2, int theVertexIndex3)
0687   {
0688     AddEdge(theVertexIndex1);
0689     AddEdge(theVertexIndex2);
0690     return AddEdge(theVertexIndex3);
0691   }
0692 
0693   //! Convenience method, adds three vertex indices of triangle in the range [1,VertexNumber()] in
0694   //! the array of triangles. Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
0695   //! @return the actual edges number
0696   int AddTriangleEdges(int theVertexIndex1, int theVertexIndex2, int theVertexIndex3)
0697   {
0698     Standard_TypeMismatch_Raise_if(myType != Graphic3d_TOPA_TRIANGLES, "Not array of triangles");
0699     return AddEdges(theVertexIndex1, theVertexIndex2, theVertexIndex3);
0700   }
0701 
0702   //! Convenience method, adds three vertex indices of triangle in the range [1,VertexNumber()] in
0703   //! the array of triangles. Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
0704   //! @return the actual edges number
0705   int AddTriangleEdges(const NCollection_Vec3<int>& theIndexes)
0706   {
0707     Standard_TypeMismatch_Raise_if(myType != Graphic3d_TOPA_TRIANGLES, "Not array of triangles");
0708     return AddEdges(theIndexes[0], theIndexes[1], theIndexes[2]);
0709   }
0710 
0711   //! Convenience method, adds three vertex indices (4th component is ignored) of triangle in the
0712   //! range [1,VertexNumber()] in the array of triangles. Raises exception if array is not of type
0713   //! Graphic3d_TOPA_TRIANGLES.
0714   //! @return the actual edges number
0715   int AddTriangleEdges(const NCollection_Vec4<int>& theIndexes)
0716   {
0717     Standard_TypeMismatch_Raise_if(myType != Graphic3d_TOPA_TRIANGLES, "Not array of triangles");
0718     return AddEdges(theIndexes[0], theIndexes[1], theIndexes[2]);
0719   }
0720 
0721   //! Convenience method, adds four vertex indices (a quad) in the range [1,VertexNumber()] in the
0722   //! array.
0723   //! @return the actual edges number
0724   int AddEdges(int theVertexIndex1, int theVertexIndex2, int theVertexIndex3, int theVertexIndex4)
0725   {
0726     AddEdge(theVertexIndex1);
0727     AddEdge(theVertexIndex2);
0728     AddEdge(theVertexIndex3);
0729     return AddEdge(theVertexIndex4);
0730   }
0731 
0732   //! Convenience method, adds four vertex indices (a quad) in the range [1,VertexNumber()] in the
0733   //! array of quads. Raises exception if array is not of type Graphic3d_TOPA_QUADRANGLES.
0734   //! @return the actual edges number
0735   int AddQuadEdges(int theVertexIndex1,
0736                    int theVertexIndex2,
0737                    int theVertexIndex3,
0738                    int theVertexIndex4)
0739   {
0740     Standard_TypeMismatch_Raise_if(myType != Graphic3d_TOPA_QUADRANGLES, "Not array of quads");
0741     return AddEdges(theVertexIndex1, theVertexIndex2, theVertexIndex3, theVertexIndex4);
0742   }
0743 
0744   //! Convenience method, adds quad indices in the range [1,VertexNumber()] into array or triangles
0745   //! as two triangles. Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
0746   //! @return the actual edges number
0747   int AddQuadTriangleEdges(int theVertexIndex1,
0748                            int theVertexIndex2,
0749                            int theVertexIndex3,
0750                            int theVertexIndex4)
0751   {
0752     AddTriangleEdges(theVertexIndex3, theVertexIndex1, theVertexIndex2);
0753     return AddTriangleEdges(theVertexIndex1, theVertexIndex3, theVertexIndex4);
0754   }
0755 
0756   //! Convenience method, adds quad indices in the range [1,VertexNumber()] into array or triangles
0757   //! as two triangles. Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
0758   //! @return the actual edges number
0759   int AddQuadTriangleEdges(const NCollection_Vec4<int>& theIndexes)
0760   {
0761     return AddQuadTriangleEdges(theIndexes[0], theIndexes[1], theIndexes[2], theIndexes[3]);
0762   }
0763 
0764   //! Add triangle strip into indexed triangulation array.
0765   //! N-2 triangles are added from N input nodes.
0766   //! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
0767   //! @param[in] theVertexLower  index of first node defining triangle strip
0768   //! @param[in] theVertexUpper  index of last  node defining triangle strip
0769   Standard_EXPORT void AddTriangleStripEdges(int theVertexLower, int theVertexUpper);
0770 
0771   //! Add triangle fan into indexed triangulation array.
0772   //! N-2 triangles are added from N input nodes (or N-1 with closed flag).
0773   //! Raises exception if array is not of type Graphic3d_TOPA_TRIANGLES.
0774   //! @param[in] theVertexLower  index of first node defining triangle fun (center)
0775   //! @param[in] theVertexUpper  index of last  node defining triangle fun
0776   //! @param[in] theToClose  close triangle fan (connect first and last points)
0777   Standard_EXPORT void AddTriangleFanEdges(int theVertexLower, int theVertexUpper, bool theToClose);
0778 
0779   //! Add line strip (polyline) into indexed segments array.
0780   //! N-1 segments are added from N input nodes (or N with closed flag).
0781   //! Raises exception if array is not of type Graphic3d_TOPA_SEGMENTS.
0782   //! @param[in] theVertexLower  index of first node defining line strip fun (center)
0783   //! @param[in] theVertexUpper  index of last  node defining triangle fun
0784   //! @param[in] theToClose  close triangle fan (connect first and last points)
0785   Standard_EXPORT void AddPolylineEdges(int theVertexLower, int theVertexUpper, bool theToClose);
0786 
0787 public: //! @name optional array of Bounds/Subgroups within primitive array (e.g. restarting
0788         //! primitives / assigning colors)
0789   //! Returns optional bounds buffer.
0790   const occ::handle<Graphic3d_BoundBuffer>& Bounds() const { return myBounds; }
0791 
0792   //! Returns TRUE when bound colors array is defined.
0793   bool HasBoundColors() const { return !myBounds.IsNull() && myBounds->Colors != nullptr; }
0794 
0795   //! Returns the number of defined bounds
0796   int BoundNumber() const { return !myBounds.IsNull() ? myBounds->NbBounds : -1; }
0797 
0798   //! Returns the number of allocated bounds
0799   int BoundNumberAllocated() const { return !myBounds.IsNull() ? myBounds->NbMaxBounds : 0; }
0800 
0801   //! Returns the edge number at rank theRank.
0802   int Bound(const int theRank) const
0803   {
0804     Standard_OutOfRange_Raise_if(myBounds.IsNull() || theRank < 1 || theRank > myBounds->NbBounds,
0805                                  "BAD BOUND index");
0806     return myBounds->Bounds[theRank - 1];
0807   }
0808 
0809   //! Returns the bound color at rank theRank from the bound table if defined.
0810   Quantity_Color BoundColor(const int theRank) const
0811   {
0812     double anRGB[3] = {0.0, 0.0, 0.0};
0813     BoundColor(theRank, anRGB[0], anRGB[1], anRGB[2]);
0814     return Quantity_Color(anRGB[0], anRGB[1], anRGB[2], Quantity_TOC_RGB);
0815   }
0816 
0817   //! Returns the bound color values at rank theRank from the bound table if defined.
0818   void BoundColor(const int theRank, double& theR, double& theG, double& theB) const
0819   {
0820     Standard_OutOfRange_Raise_if(myBounds.IsNull() || myBounds->Colors == nullptr || theRank < 1
0821                                    || theRank > myBounds->NbBounds,
0822                                  "BAD BOUND index");
0823     const NCollection_Vec4<float>& aVec = myBounds->Colors[theRank - 1];
0824     theR                                = double(aVec.r());
0825     theG                                = double(aVec.g());
0826     theB                                = double(aVec.b());
0827   }
0828 
0829   //! Adds a bound of length theEdgeNumber in the bound array
0830   //! @return the actual bounds number
0831   Standard_EXPORT int AddBound(const int theEdgeNumber);
0832 
0833   //! Adds a bound of length theEdgeNumber and bound color theBColor in the bound array.
0834   //! Warning: theBColor is ignored when the hasBColors constructor parameter is FALSE
0835   //! @return the actual bounds number
0836   int AddBound(const int theEdgeNumber, const Quantity_Color& theBColor)
0837   {
0838     return AddBound(theEdgeNumber, theBColor.Red(), theBColor.Green(), theBColor.Blue());
0839   }
0840 
0841   //! Adds a bound of length theEdgeNumber and bound color coordinates in the bound array.
0842   //! Warning: <theR,theG,theB> are ignored when the hasBColors constructor parameter is FALSE
0843   //! @return the actual bounds number
0844   Standard_EXPORT int AddBound(const int    theEdgeNumber,
0845                                const double theR,
0846                                const double theG,
0847                                const double theB);
0848 
0849   //! Change the bound color of rank theIndex in the array.
0850   void SetBoundColor(const int theIndex, const Quantity_Color& theColor)
0851   {
0852     SetBoundColor(theIndex, theColor.Red(), theColor.Green(), theColor.Blue());
0853   }
0854 
0855   //! Change the bound color of rank theIndex in the array.
0856   void SetBoundColor(const int theIndex, const double theR, const double theG, const double theB)
0857   {
0858     if (myBounds.IsNull())
0859     {
0860       return;
0861     }
0862     Standard_OutOfRange_Raise_if(myBounds.IsNull() || myBounds->Colors == nullptr || theIndex < 1
0863                                    || theIndex > myBounds->NbMaxBounds,
0864                                  "BAD BOUND index");
0865     NCollection_Vec4<float>& aVec = myBounds->Colors[theIndex - 1];
0866     aVec.r()                      = float(theR);
0867     aVec.g()                      = float(theG);
0868     aVec.b()                      = float(theB);
0869     aVec.a()                      = 1.0f;
0870     myBounds->NbBounds            = (std::max)(theIndex, myBounds->NbBounds);
0871   }
0872 
0873 protected: //! @name protected constructors
0874   //! Main constructor.
0875   //! @param theType       type of primitive
0876   //! @param theMaxVertexs length of vertex attributes buffer to be allocated (maximum number of
0877   //! vertexes, @sa ::AddVertex())
0878   //! @param theMaxBounds  length of bounds buffer to be allocated (maximum number of bounds, @sa
0879   //! ::AddBound())
0880   //! @param theMaxEdges   length of edges (index) buffer to be allocated (maximum number of indexes
0881   //! @sa ::AddEdge())
0882   //! @param theArrayFlags array flags
0883   Graphic3d_ArrayOfPrimitives(Graphic3d_TypeOfPrimitiveArray theType,
0884                               int                            theMaxVertexs,
0885                               int                            theMaxBounds,
0886                               int                            theMaxEdges,
0887                               Graphic3d_ArrayFlags           theArrayFlags)
0888       : myNormData(nullptr),
0889         myTexData(nullptr),
0890         myColData(nullptr),
0891         myPosStride(0),
0892         myNormStride(0),
0893         myTexStride(0),
0894         myColStride(0),
0895         myType(Graphic3d_TOPA_UNDEFINED)
0896   {
0897     init(theType, theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
0898   }
0899 
0900   //! Array constructor.
0901   Standard_EXPORT void init(Graphic3d_TypeOfPrimitiveArray theType,
0902                             int                            theMaxVertexs,
0903                             int                            theMaxBounds,
0904                             int                            theMaxEdges,
0905                             Graphic3d_ArrayFlags           theArrayFlags);
0906 
0907 private: //! @name private fields
0908   occ::handle<Graphic3d_IndexBuffer> myIndices;
0909   occ::handle<Graphic3d_Buffer>      myAttribs;
0910   occ::handle<Graphic3d_BoundBuffer> myBounds;
0911   uint8_t*                           myNormData;
0912   uint8_t*                           myTexData;
0913   uint8_t*                           myColData;
0914   size_t                             myPosStride;
0915   size_t                             myNormStride;
0916   size_t                             myTexStride;
0917   size_t                             myColStride;
0918   Graphic3d_TypeOfPrimitiveArray     myType;
0919 };
0920 
0921 #endif // _Graphic3d_ArrayOfPrimitives_HeaderFile