0030076: Visualization, TKV3d - API to update certain vertex attribute(s) without...
authorasl <asl@opencascade.com>
Tue, 16 Oct 2018 20:17:47 +0000 (23:17 +0300)
committerapn <apn@opencascade.com>
Wed, 17 Oct 2018 13:35:31 +0000 (16:35 +0300)
Graphic3d_Buffer can be now optionally initialized as non-interleaved array of vertex attributes
and provides an interface to invalidate buffer sub-range tracked by OpenGl_PrimitiveArray.

23 files changed:
src/Graphic3d/FILES
src/Graphic3d/Graphic3d_ArrayFlags.hxx
src/Graphic3d/Graphic3d_ArrayOfPrimitives.cxx
src/Graphic3d/Graphic3d_ArrayOfPrimitives.hxx
src/Graphic3d/Graphic3d_AttribBuffer.cxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_AttribBuffer.hxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_Buffer.cxx
src/Graphic3d/Graphic3d_Buffer.hxx
src/Graphic3d/Graphic3d_BufferRange.hxx [new file with mode: 0644]
src/Graphic3d/Graphic3d_Group.cxx
src/Graphic3d/Graphic3d_MutableIndexBuffer.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_PrimitiveArray.cxx
src/OpenGl/OpenGl_PrimitiveArray.hxx
src/OpenGl/OpenGl_VertexBuffer.hxx
src/OpenGl/OpenGl_VertexBufferCompat.hxx
src/OpenGl/OpenGl_View_Raytrace.cxx
src/Select3D/Select3D_SensitivePrimitiveArray.cxx
src/Select3D/Select3D_SensitivePrimitiveArray.hxx
src/ViewerTest/ViewerTest_ObjectCommands.cxx
tests/bugs/vis/bug23186
tests/bugs/vis/bug23226
tests/bugs/vis/bug23883
tests/bugs/vis/bug30076 [new file with mode: 0644]

index c0f5472..f9df238 100755 (executable)
@@ -20,6 +20,8 @@ Graphic3d_AspectMarker3d.hxx
 Graphic3d_AspectText3d.cxx
 Graphic3d_AspectText3d.hxx
 Graphic3d_AspectTextDefinitionError.hxx
+Graphic3d_AttribBuffer.cxx
+Graphic3d_AttribBuffer.hxx
 Graphic3d_BndBox3d.hxx
 Graphic3d_BndBox4d.hxx
 Graphic3d_BndBox4f.hxx
@@ -28,6 +30,7 @@ Graphic3d_BSDF.cxx
 Graphic3d_BSDF.hxx
 Graphic3d_Buffer.cxx
 Graphic3d_Buffer.hxx
+Graphic3d_BufferRange.hxx
 Graphic3d_BufferType.hxx
 Graphic3d_Camera.cxx
 Graphic3d_Camera.hxx
@@ -65,6 +68,7 @@ Graphic3d_PresentationAttributes.hxx
 Graphic3d_PresentationAttributes.cxx
 Graphic3d_HorizontalTextAlignment.hxx
 Graphic3d_IndexBuffer.hxx
+Graphic3d_MutableIndexBuffer.hxx
 Graphic3d_IndexedMapOfAddress.hxx
 Graphic3d_LevelOfTextureAnisotropy.hxx
 Graphic3d_LightSet.cxx
index f2e70b9..cb2da07 100644 (file)
@@ -25,6 +25,10 @@ enum
   Graphic3d_ArrayFlags_VertexColor   = 0x02,  //!< per-vertex color  attribute
   Graphic3d_ArrayFlags_VertexTexel   = 0x04,  //!< per-vertex texel coordinates (UV) attribute
   Graphic3d_ArrayFlags_BoundColor    = 0x10,
+  // advanced
+  Graphic3d_ArrayFlags_AttribsMutable       = 0x20,  //!< mutable array, which can be invalidated during lifetime without re-creation
+  Graphic3d_ArrayFlags_AttribsDeinterleaved = 0x40,  //!< non-interleaved vertex attributes packed into single array
+  Graphic3d_ArrayFlags_IndexesMutable       = 0x80,  //!< mutable index array, which can be invalidated during lifetime without re-creation
 };
 
 #endif // _Graphic3d_ArrayFlags_HeaderFile
index 4be1704..42c3574 100644 (file)
@@ -23,6 +23,8 @@
 #include <Graphic3d_ArrayOfQuadrangles.hxx>
 #include <Graphic3d_ArrayOfQuadrangleStrips.hxx>
 #include <Graphic3d_ArrayOfPolygons.hxx>
+#include <Graphic3d_AttribBuffer.hxx>
+#include <Graphic3d_MutableIndexBuffer.hxx>
 
 #include <NCollection_AlignedAllocator.hxx>
 #include <TCollection_AsciiString.hxx>
@@ -43,6 +45,47 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangleStrips, Graphic3d_ArrayOfP
 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfPolygons,         Graphic3d_ArrayOfPrimitives)
 
 // =======================================================================
+// function : CreateArray
+// purpose  :
+// =======================================================================
+Handle(Graphic3d_ArrayOfPrimitives) Graphic3d_ArrayOfPrimitives::CreateArray (Graphic3d_TypeOfPrimitiveArray theType,
+                                                                              Standard_Integer theMaxVertexs,
+                                                                              Standard_Integer theMaxBounds,
+                                                                              Standard_Integer theMaxEdges,
+                                                                              Graphic3d_ArrayFlags theArrayFlags)
+{
+  switch (theType)
+  {
+    case Graphic3d_TOPA_UNDEFINED:
+      return Handle(Graphic3d_ArrayOfPrimitives)();
+    case Graphic3d_TOPA_POINTS:
+      return new Graphic3d_ArrayOfPoints (theMaxVertexs, theArrayFlags);
+    case Graphic3d_TOPA_SEGMENTS:
+      return new Graphic3d_ArrayOfSegments (theMaxVertexs, theMaxEdges, theArrayFlags);
+    case Graphic3d_TOPA_POLYLINES:
+      return new Graphic3d_ArrayOfPolylines (theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
+    case Graphic3d_TOPA_TRIANGLES:
+      return new Graphic3d_ArrayOfTriangles (theMaxVertexs, theMaxEdges, theArrayFlags);
+    case Graphic3d_TOPA_TRIANGLESTRIPS:
+      return new Graphic3d_ArrayOfTriangleStrips (theMaxVertexs, theMaxBounds, theArrayFlags);
+    case Graphic3d_TOPA_TRIANGLEFANS:
+      return new Graphic3d_ArrayOfTriangleFans (theMaxVertexs, theMaxBounds, theArrayFlags);
+    case Graphic3d_TOPA_LINES_ADJACENCY:
+    case Graphic3d_TOPA_LINE_STRIP_ADJACENCY:
+    case Graphic3d_TOPA_TRIANGLES_ADJACENCY:
+    case Graphic3d_TOPA_TRIANGLE_STRIP_ADJACENCY:
+      return new Graphic3d_ArrayOfPrimitives (theType, theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
+    case Graphic3d_TOPA_QUADRANGLES:
+      return new Graphic3d_ArrayOfQuadrangles (theMaxVertexs, theMaxEdges, theArrayFlags);
+    case Graphic3d_TOPA_QUADRANGLESTRIPS:
+      return new Graphic3d_ArrayOfQuadrangleStrips (theMaxVertexs, theMaxBounds, theArrayFlags);
+    case Graphic3d_TOPA_POLYGONS:
+      return new Graphic3d_ArrayOfPolygons (theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
+  }
+  return Handle(Graphic3d_ArrayOfPrimitives)();
+}
+
+// =======================================================================
 // function : init
 // purpose  :
 // =======================================================================
@@ -53,15 +96,26 @@ void Graphic3d_ArrayOfPrimitives::init (Graphic3d_TypeOfPrimitiveArray theType,
                                         Graphic3d_ArrayFlags theArrayOptions)
 {
   myType = theType;
-  myVNor = 0;
-  myVTex = 0;
-  myVCol = 0;
+  myNormData = NULL;
+  myTexData  = NULL;
+  myColData  = NULL;
   myAttribs.Nullify();
   myIndices.Nullify();
   myBounds.Nullify();
 
   Handle(NCollection_AlignedAllocator) anAlloc = new NCollection_AlignedAllocator (16);
-  myAttribs = new Graphic3d_Buffer (anAlloc);
+  if ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) != 0
+   || (theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) != 0)
+  {
+    Graphic3d_AttribBuffer* anAttribs = new Graphic3d_AttribBuffer (anAlloc);
+    anAttribs->SetMutable     ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) != 0);
+    anAttribs->SetInterleaved ((theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) == 0);
+    myAttribs = anAttribs;
+  }
+  else
+  {
+    myAttribs = new Graphic3d_Buffer (anAlloc);
+  }
   if (theMaxVertexs < 1)
   {
     return;
@@ -69,7 +123,14 @@ void Graphic3d_ArrayOfPrimitives::init (Graphic3d_TypeOfPrimitiveArray theType,
 
   if (theMaxEdges > 0)
   {
-    myIndices = new Graphic3d_IndexBuffer (anAlloc);
+    if ((theArrayOptions & Graphic3d_ArrayFlags_IndexesMutable) != 0)
+    {
+      myIndices = new Graphic3d_MutableIndexBuffer (anAlloc);
+    }
+    else
+    {
+      myIndices = new Graphic3d_IndexBuffer (anAlloc);
+    }
     if (theMaxVertexs < Standard_Integer(USHRT_MAX))
     {
       if (!myIndices->Init<unsigned short> (theMaxEdges))
@@ -119,8 +180,19 @@ void Graphic3d_ArrayOfPrimitives::init (Graphic3d_TypeOfPrimitiveArray theType,
     myIndices.Nullify();
     return;
   }
-  myAttribs->NbElements = 0;
-  memset (myAttribs->ChangeData (0), 0, size_t(myAttribs->Stride) * size_t(myAttribs->NbMaxElements()));
+
+  Standard_Integer anAttribDummy = 0;
+  myAttribs->ChangeAttributeData (Graphic3d_TOA_POS, anAttribDummy, myPosStride);
+  myNormData = myAttribs->ChangeAttributeData (Graphic3d_TOA_NORM,  anAttribDummy, myNormStride);
+  myTexData  = myAttribs->ChangeAttributeData (Graphic3d_TOA_UV,    anAttribDummy, myTexStride);
+  myColData  = myAttribs->ChangeAttributeData (Graphic3d_TOA_COLOR, anAttribDummy, myColStride);
+
+  memset (myAttribs->ChangeData(), 0, size_t(myAttribs->Stride) * size_t(myAttribs->NbMaxElements()));
+  if ((theArrayOptions & Graphic3d_ArrayFlags_AttribsMutable) == 0
+   && (theArrayOptions & Graphic3d_ArrayFlags_AttribsDeinterleaved) == 0)
+  {
+    myAttribs->NbElements = 0;
+  }
 
   if (theMaxBounds > 0)
   {
@@ -134,32 +206,6 @@ void Graphic3d_ArrayOfPrimitives::init (Graphic3d_TypeOfPrimitiveArray theType,
     }
     myBounds->NbBounds = 0;
   }
-
-  for (Standard_Integer anAttribIter = 0; anAttribIter < aNbAttribs; ++anAttribIter)
-  {
-    const Graphic3d_Attribute& anAttrib = anAttribs[anAttribIter];
-    switch (anAttrib.Id)
-    {
-      case Graphic3d_TOA_POS:
-      case Graphic3d_TOA_CUSTOM:
-        break;
-      case Graphic3d_TOA_NORM:
-      {
-        myVNor = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
-        break;
-      }
-      case Graphic3d_TOA_UV:
-      {
-        myVTex = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
-        break;
-      }
-      case Graphic3d_TOA_COLOR:
-      {
-        myVCol = static_cast<Standard_Byte>(myAttribs->AttributeOffset (anAttribIter));
-        break;
-      }
-    }
-  }
 }
 
 // =======================================================================
@@ -168,9 +214,6 @@ void Graphic3d_ArrayOfPrimitives::init (Graphic3d_TypeOfPrimitiveArray theType,
 // =======================================================================
 Graphic3d_ArrayOfPrimitives::~Graphic3d_ArrayOfPrimitives()
 {
-  myVNor = 0;
-  myVTex = 0;
-  myVCol = 0;
   myIndices.Nullify();
   myAttribs.Nullify();
   myBounds .Nullify();
index 86a79ae..7cc3d54 100644 (file)
@@ -64,6 +64,23 @@ class Graphic3d_ArrayOfPrimitives : public Standard_Transient
   DEFINE_STANDARD_RTTIEXT(Graphic3d_ArrayOfPrimitives, Standard_Transient)
 public:
 
+  //! Create an array of specified type.
+  static Handle(Graphic3d_ArrayOfPrimitives) CreateArray (Graphic3d_TypeOfPrimitiveArray theType,
+                                                          Standard_Integer theMaxVertexs,
+                                                          Standard_Integer theMaxEdges,
+                                                          Graphic3d_ArrayFlags theArrayFlags)
+  {
+    return CreateArray (theType, theMaxVertexs, 0, theMaxEdges, theArrayFlags);
+  }
+
+  //! Create an array of specified type.
+  static Standard_EXPORT Handle(Graphic3d_ArrayOfPrimitives) CreateArray (Graphic3d_TypeOfPrimitiveArray theType,
+                                                                          Standard_Integer theMaxVertexs,
+                                                                          Standard_Integer theMaxBounds,
+                                                                          Standard_Integer theMaxEdges,
+                                                                          Graphic3d_ArrayFlags theArrayFlags);
+public:
+
   //! Destructor.
   Standard_EXPORT virtual ~Graphic3d_ArrayOfPrimitives();
 
@@ -77,13 +94,13 @@ public:
   Standard_EXPORT Standard_CString StringType() const;
 
   //! Returns TRUE when vertex normals array is defined.
-  Standard_Boolean HasVertexNormals() const { return myVNor != 0; }
+  Standard_Boolean HasVertexNormals() const { return myNormData != NULL; }
 
   //! Returns TRUE when vertex colors array is defined.
-  Standard_Boolean HasVertexColors() const { return myVCol != 0; }
+  Standard_Boolean HasVertexColors() const { return myColData != NULL; }
 
   //! Returns TRUE when vertex texels array is defined.
-  Standard_Boolean HasVertexTexels() const { return myVTex != 0; }
+  Standard_Boolean HasVertexTexels() const { return myTexData != NULL; }
 
   //! Returns the number of defined vertex
   Standard_Integer VertexNumber() const { return myAttribs->NbElements; }
@@ -291,7 +308,7 @@ public:
   void SetVertice (const Standard_Integer theIndex, const Standard_ShortReal theX, const Standard_ShortReal theY, const Standard_ShortReal theZ)
   {
     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
-    Graphic3d_Vec3& aVec = myAttribs->ChangeValue<Graphic3d_Vec3> (theIndex - 1);
+    Graphic3d_Vec3& aVec = *reinterpret_cast<Graphic3d_Vec3*> (myAttribs->ChangeData() + myPosStride * (theIndex - 1));
     aVec.x() = theX;
     aVec.y() = theY;
     aVec.z() = theZ;
@@ -311,10 +328,9 @@ public:
   void SetVertexColor (const Standard_Integer theIndex, const Standard_Real theR, const Standard_Real theG, const Standard_Real theB)
   {
     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
-    if (myVCol != 0)
+    if (myColData != NULL)
     {
-      Graphic3d_Vec4ub *aColorPtr = 
-        reinterpret_cast<Graphic3d_Vec4ub* >(myAttribs->changeValue (theIndex - 1) + size_t(myVCol));
+      Graphic3d_Vec4ub* aColorPtr = reinterpret_cast<Graphic3d_Vec4ub* >(myColData + myColStride * (theIndex - 1));
       aColorPtr->SetValues (Standard_Byte(theR * 255.0),
                             Standard_Byte(theG * 255.0),
                             Standard_Byte(theB * 255.0), 255);
@@ -327,10 +343,9 @@ public:
                        const Graphic3d_Vec4ub& theColor)
   {
     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
-    if (myVCol != 0)
+    if (myColData != NULL)
     {
-      Graphic3d_Vec4ub *aColorPtr = 
-        reinterpret_cast<Graphic3d_Vec4ub* >(myAttribs->changeValue (theIndex - 1) + size_t(myVCol));
+      Graphic3d_Vec4ub* aColorPtr =  reinterpret_cast<Graphic3d_Vec4ub* >(myColData + myColStride * (theIndex - 1));
       (*aColorPtr) = theColor;
     }
     myAttribs->NbElements = Max (theIndex, myAttribs->NbElements);
@@ -343,9 +358,9 @@ public:
   void SetVertexColor (const Standard_Integer theIndex, const Standard_Integer theColor32)
   {
     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
-    if (myVCol != 0)
+    if (myColData != NULL)
     {
-      *reinterpret_cast<Standard_Integer* >(myAttribs->changeValue (theIndex - 1) + size_t(myVCol)) = theColor32;
+      *reinterpret_cast<Standard_Integer* >(myColData + myColStride * (theIndex - 1)) = theColor32;
     }
   }
 
@@ -359,9 +374,9 @@ public:
   void SetVertexNormal (const Standard_Integer theIndex, const Standard_Real theNX, const Standard_Real theNY, const Standard_Real theNZ)
   {
     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
-    if (myVNor != 0)
+    if (myNormData != NULL)
     {
-      Graphic3d_Vec3& aVec = *reinterpret_cast<Graphic3d_Vec3* >(myAttribs->changeValue (theIndex - 1) + size_t(myVNor));
+      Graphic3d_Vec3& aVec = *reinterpret_cast<Graphic3d_Vec3* >(myNormData + myNormStride * (theIndex - 1));
       aVec.x() = Standard_ShortReal (theNX);
       aVec.y() = Standard_ShortReal (theNY);
       aVec.z() = Standard_ShortReal (theNZ);
@@ -379,9 +394,9 @@ public:
   void SetVertexTexel (const Standard_Integer theIndex, const Standard_Real theTX, const Standard_Real theTY)
   {
     Standard_OutOfRange_Raise_if (theIndex < 1 || theIndex > myAttribs->NbMaxElements(), "BAD VERTEX index");
-    if (myVTex != 0)
+    if (myTexData != NULL)
     {
-      Graphic3d_Vec2& aVec = *reinterpret_cast<Graphic3d_Vec2* >(myAttribs->changeValue (theIndex - 1) + size_t(myVTex));
+      Graphic3d_Vec2& aVec = *reinterpret_cast<Graphic3d_Vec2* >(myTexData + myTexStride * (theIndex - 1));
       aVec.x() = Standard_ShortReal (theTX);
       aVec.y() = Standard_ShortReal (theTY);
     }
@@ -401,7 +416,7 @@ public:
   {
     theX = theY = theZ = 0.0;
     Standard_OutOfRange_Raise_if (theRank < 1 || theRank > myAttribs->NbElements, "BAD VERTEX index");
-    const Graphic3d_Vec3& aVec = myAttribs->Value<Graphic3d_Vec3> (theRank - 1);
+    const Graphic3d_Vec3& aVec = *reinterpret_cast<const Graphic3d_Vec3*> (myAttribs->Data() + myPosStride * (theRank - 1));
     theX = Standard_Real(aVec.x());
     theY = Standard_Real(aVec.y());
     theZ = Standard_Real(aVec.z());
@@ -419,8 +434,8 @@ public:
   void VertexColor (const Standard_Integer theIndex,
                     Graphic3d_Vec4ub&      theColor) const
   {
-    Standard_OutOfRange_Raise_if (myVCol == 0 || theIndex < 1 || theIndex > myAttribs->NbElements, "BAD VERTEX index");
-    theColor = *reinterpret_cast<const Graphic3d_Vec4ub* >(myAttribs->value (theIndex - 1) + size_t(myVCol));
+    Standard_OutOfRange_Raise_if (myColData == NULL || theIndex < 1 || theIndex > myAttribs->NbElements, "BAD VERTEX index");
+    theColor = *reinterpret_cast<const Graphic3d_Vec4ub* >(myColData + myColStride * (theIndex - 1));
   }
 
   //! Returns the vertex color values at rank theRank from the vertex table if defined.
@@ -428,11 +443,11 @@ public:
   {
     theR = theG = theB = 0.0;
     Standard_OutOfRange_Raise_if (theRank < 1 || theRank > myAttribs->NbElements, "BAD VERTEX index");
-    if (myVCol == 0)
+    if (myColData == NULL)
     {
       return;
     }
-    const Graphic3d_Vec4ub& aColor = *reinterpret_cast<const Graphic3d_Vec4ub* >(myAttribs->value (theRank - 1) + size_t(myVCol));
+    const Graphic3d_Vec4ub& aColor = *reinterpret_cast<const Graphic3d_Vec4ub* >(myColData + myColStride * (theRank - 1));
     theR = Standard_Real(aColor.r()) / 255.0;
     theG = Standard_Real(aColor.g()) / 255.0;
     theB = Standard_Real(aColor.b()) / 255.0;
@@ -442,9 +457,9 @@ public:
   void VertexColor (const Standard_Integer theRank, Standard_Integer& theColor) const
   {
     Standard_OutOfRange_Raise_if (theRank < 1 || theRank > myAttribs->NbElements, "BAD VERTEX index");
-    if (myVCol != 0)
+    if (myColData != NULL)
     {
-      theColor = *reinterpret_cast<const Standard_Integer* >(myAttribs->value (theRank - 1) + size_t(myVCol));
+      theColor = *reinterpret_cast<const Standard_Integer* >(myColData + myColStride * (theRank - 1));
     }
   }
 
@@ -461,9 +476,9 @@ public:
   {
     theNX = theNY = theNZ = 0.0;
     Standard_OutOfRange_Raise_if (theRank < 1 || theRank > myAttribs->NbElements, "BAD VERTEX index");
-    if (myVNor != 0)
+    if (myNormData != NULL)
     {
-      const Graphic3d_Vec3& aVec = *reinterpret_cast<const Graphic3d_Vec3* >(myAttribs->value (theRank - 1) + size_t(myVNor));
+      const Graphic3d_Vec3& aVec = *reinterpret_cast<const Graphic3d_Vec3* >(myNormData + myNormStride * (theRank - 1));
       theNX = Standard_Real(aVec.x());
       theNY = Standard_Real(aVec.y());
       theNZ = Standard_Real(aVec.z());
@@ -483,9 +498,9 @@ public:
   {
     theTX = theTY = 0.0;
     Standard_OutOfRange_Raise_if (theRank < 1 || theRank > myAttribs->NbElements, "BAD VERTEX index");
-    if (myVTex != 0)
+    if (myTexData != NULL)
     {
-      const Graphic3d_Vec2& aVec = *reinterpret_cast<const Graphic3d_Vec2* >(myAttribs->value (theRank - 1) + size_t(myVTex));
+      const Graphic3d_Vec2& aVec = *reinterpret_cast<const Graphic3d_Vec2* >(myTexData + myTexStride * (theRank - 1));
       theTX = Standard_Real(aVec.x());
       theTY = Standard_Real(aVec.y());
     }
@@ -637,7 +652,8 @@ protected: //! @name protected constructors
                                Standard_Integer theMaxBounds,
                                Standard_Integer theMaxEdges,
                                Graphic3d_ArrayFlags theArrayFlags)
-  : myType (Graphic3d_TOPA_UNDEFINED), myVNor (0), myVTex (0), myVCol (0)
+  : myNormData (NULL), myTexData (NULL), myColData (NULL), myPosStride (0), myNormStride (0), myTexStride (0), myColStride (0),
+    myType (Graphic3d_TOPA_UNDEFINED)
   {
     init (theType, theMaxVertexs, theMaxBounds, theMaxEdges, theArrayFlags);
   }
@@ -654,10 +670,14 @@ private: //! @name private fields
   Handle(Graphic3d_IndexBuffer)  myIndices;
   Handle(Graphic3d_Buffer)       myAttribs;
   Handle(Graphic3d_BoundBuffer)  myBounds;
+  Standard_Byte* myNormData;
+  Standard_Byte* myTexData;
+  Standard_Byte* myColData;
+  Standard_Size  myPosStride;
+  Standard_Size  myNormStride;
+  Standard_Size  myTexStride;
+  Standard_Size  myColStride;
   Graphic3d_TypeOfPrimitiveArray myType;
-  Standard_Byte myVNor;
-  Standard_Byte myVTex;
-  Standard_Byte myVCol;
 
 };
 
diff --git a/src/Graphic3d/Graphic3d_AttribBuffer.cxx b/src/Graphic3d/Graphic3d_AttribBuffer.cxx
new file mode 100644 (file)
index 0000000..b141e80
--- /dev/null
@@ -0,0 +1,194 @@
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <Graphic3d_AttribBuffer.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_AttribBuffer, Graphic3d_Buffer)
+
+// =======================================================================
+// function : Graphic3d_AttribBuffer
+// purpose  :
+// =======================================================================
+Graphic3d_AttribBuffer::Graphic3d_AttribBuffer(const Handle(NCollection_BaseAllocator)& theAlloc)
+: Graphic3d_Buffer (theAlloc),
+  myIsInterleaved (Standard_True),
+  myIsMutable (Standard_False)
+{
+}
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+bool Graphic3d_AttribBuffer::Init (const Standard_Integer     theNbElems,
+                                   const Graphic3d_Attribute* theAttribs,
+                                   const Standard_Integer     theNbAttribs)
+{
+  if (!Graphic3d_Buffer::Init (theNbElems, theAttribs, theNbAttribs))
+  {
+    return false;
+  }
+
+  if (mySize > (Standard_Size )IntegerLast()
+   && myIsMutable)
+  {
+    throw Standard_OutOfRange ("Graphic3d_AttribBuffer::Init(), Mutable flag cannot be used for buffer exceeding 32-bit address space");
+  }
+  return true;
+}
+
+// =======================================================================
+// function : SetMutable
+// purpose  :
+// =======================================================================
+void Graphic3d_AttribBuffer::SetMutable (Standard_Boolean theMutable)
+{
+  if (mySize > (Standard_Size )IntegerLast()
+   && theMutable)
+  {
+    throw Standard_OutOfRange ("Graphic3d_AttribBuffer::SetMutable(), Mutable flag cannot be used for buffer exceeding 32-bit address space");
+  }
+  myIsMutable = theMutable;
+}
+
+// =======================================================================
+// function : Invalidate
+// purpose  :
+// =======================================================================
+void Graphic3d_AttribBuffer::SetInterleaved (Standard_Boolean theIsInterleaved)
+{
+  if (NbMaxElements() != 0)
+  {
+    throw Standard_ProgramError ("Graphic3d_AttribBuffer::SetInterleaved() should not be called for allocated buffer");
+  }
+  myIsInterleaved = theIsInterleaved;
+}
+
+// =======================================================================
+// function : invalidate
+// purpose  :
+// =======================================================================
+void Graphic3d_AttribBuffer::invalidate (const Graphic3d_BufferRange& theRange)
+{
+  if (mySize > (Standard_Size )IntegerLast())
+  {
+    throw Standard_OutOfRange ("Graphic3d_Buffer::Invalidate() cannot be used for buffer exceeding 32-bit address space");
+  }
+
+  myInvalidatedRange.Unite (theRange);
+}
+
+// =======================================================================
+// function : Invalidate
+// purpose  :
+// =======================================================================
+void Graphic3d_AttribBuffer::Invalidate()
+{
+  if (mySize > (Standard_Size )IntegerLast())
+  {
+    throw Standard_OutOfRange ("Graphic3d_AttribBuffer::Invalidate() cannot be used for buffer exceeding 32-bit address space");
+  }
+
+  invalidate (Graphic3d_BufferRange (0, (Standard_Integer )mySize));
+}
+
+// =======================================================================
+// function : Invalidate
+// purpose  :
+// =======================================================================
+void Graphic3d_AttribBuffer::Invalidate (Standard_Integer theAttributeIndex)
+{
+  Standard_OutOfRange_Raise_if (theAttributeIndex < 0
+                             || theAttributeIndex >= NbAttributes, "Graphic3d_AttribBuffer::Invalidate()");
+  if (myIsInterleaved)
+  {
+    Invalidate();
+    return;
+  }
+
+  Graphic3d_BufferRange aRange;
+  const Standard_Integer aNbMaxVerts = NbMaxElements();
+  for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
+  {
+    const Graphic3d_Attribute& anAttrib = Attribute (anAttribIter);
+    const Standard_Integer anAttribStride = Graphic3d_Attribute::Stride (anAttrib.DataType);
+    if (anAttribIter == theAttributeIndex)
+    {
+      aRange.Length = anAttribStride * aNbMaxVerts;
+      invalidate (aRange);
+      return;
+    }
+
+    aRange.Start += anAttribStride * aNbMaxVerts;
+  }
+}
+
+// =======================================================================
+// function : Invalidate
+// purpose  :
+// =======================================================================
+void Graphic3d_AttribBuffer::Invalidate (Standard_Integer theAttributeIndex,
+                                         Standard_Integer theVertexLower,
+                                         Standard_Integer theVertexUpper)
+{
+  Standard_OutOfRange_Raise_if (theAttributeIndex < 0
+                             || theAttributeIndex >= NbAttributes
+                             || theVertexLower < 0
+                             || theVertexLower > theVertexUpper
+                             || theVertexUpper >= NbMaxElements(), "Graphic3d_AttribBuffer::Invalidate()");
+  if (myIsInterleaved)
+  {
+    Invalidate (theVertexLower, theVertexUpper);
+    return;
+  }
+
+  Graphic3d_BufferRange aRange;
+  const Standard_Integer aNbMaxVerts = NbMaxElements();
+  for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
+  {
+    const Graphic3d_Attribute& anAttrib = Attribute (anAttribIter);
+    const Standard_Integer anAttribStride = Graphic3d_Attribute::Stride (anAttrib.DataType);
+    if (anAttribIter == theAttributeIndex)
+    {
+      aRange.Start += anAttribStride * theVertexLower;
+      aRange.Length = anAttribStride * (theVertexUpper - theVertexLower + 1);
+      invalidate (aRange);
+      return;
+    }
+
+    aRange.Start += anAttribStride * aNbMaxVerts;
+  }
+}
+
+// =======================================================================
+// function : Invalidate
+// purpose  :
+// =======================================================================
+void Graphic3d_AttribBuffer::Invalidate (Standard_Integer theVertexLower,
+                                         Standard_Integer theVertexUpper)
+{
+  Standard_OutOfRange_Raise_if (theVertexLower < 0
+                             || theVertexLower > theVertexUpper
+                             || theVertexUpper >= NbMaxElements(), "Graphic3d_AttribBuffer::Invalidate()");
+  if (myIsInterleaved)
+  {
+    invalidate (Graphic3d_BufferRange (Stride * theVertexLower,
+                                       Stride * (theVertexUpper - theVertexLower + 1)));
+    return;
+  }
+
+  for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
+  {
+    Invalidate (anAttribIter, theVertexLower, theVertexUpper);
+  }
+}
diff --git a/src/Graphic3d/Graphic3d_AttribBuffer.hxx b/src/Graphic3d/Graphic3d_AttribBuffer.hxx
new file mode 100644 (file)
index 0000000..5705c9e
--- /dev/null
@@ -0,0 +1,84 @@
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Graphic3d_AttribBuffer_HeaderFile
+#define _Graphic3d_AttribBuffer_HeaderFile
+
+#include <Graphic3d_Buffer.hxx>
+
+//! Buffer of vertex attributes.
+//! This class is intended for advanced usage allowing invalidation of entire buffer content or its sub-part.
+class Graphic3d_AttribBuffer : public Graphic3d_Buffer
+{
+  DEFINE_STANDARD_RTTIEXT(Graphic3d_AttribBuffer, Graphic3d_Buffer)
+public:
+  //! Empty constructor.
+  Standard_EXPORT Graphic3d_AttribBuffer (const Handle(NCollection_BaseAllocator)& theAlloc);
+
+  //! Allocates new empty array
+  Standard_EXPORT bool Init (const Standard_Integer     theNbElems,
+                             const Graphic3d_Attribute* theAttribs,
+                             const Standard_Integer     theNbAttribs);
+
+  //! Allocates new empty array
+  bool Init (const Standard_Integer             theNbElems,
+             const Graphic3d_Array1OfAttribute& theAttribs)
+  {
+    return Init (theNbElems, &theAttribs.First(), theAttribs.Size());
+  }
+
+  //! Return TRUE if data can be invalidated; FALSE by default.
+  virtual Standard_Boolean IsMutable() const Standard_OVERRIDE { return myIsMutable; }
+
+  //! Set if data can be invalidated.
+  Standard_EXPORT void SetMutable (Standard_Boolean theMutable);
+
+  //! Return TRUE for interleaved array; TRUE by default.
+  virtual Standard_Boolean IsInterleaved() const Standard_OVERRIDE { return myIsInterleaved; }
+
+  //! Setup interleaved/non-interleaved array.
+  //! WARNING! Filling non-interleaved buffer should be implemented on user side
+  //!          without Graphic3d_Buffer auxiliary methods designed for interleaved data.
+  Standard_EXPORT void SetInterleaved (Standard_Boolean theIsInterleaved);
+
+  //! Return invalidated range.
+  virtual Graphic3d_BufferRange InvalidatedRange() const Standard_OVERRIDE { return myInvalidatedRange; }
+
+  //! Reset invalidated range.
+  virtual void Validate() Standard_OVERRIDE { myInvalidatedRange.Clear(); }
+
+  //! Invalidate the entire buffer data.
+  Standard_EXPORT virtual void Invalidate() Standard_OVERRIDE;
+
+  //! Invalidate the entire attribute data.
+  Standard_EXPORT void Invalidate (Standard_Integer theAttributeIndex);
+
+  //! Invalidate attribute data within specified sub-range (starting from 0).
+  Standard_EXPORT void Invalidate (Standard_Integer theAttributeIndex,
+                                   Standard_Integer theVertexLower,
+                                   Standard_Integer theVertexUpper);
+
+  //! Invalidate all attribute data within specified vertex sub-range (starting from 0).
+  Standard_EXPORT void Invalidate (Standard_Integer theVertexLower,
+                                   Standard_Integer theVertexUpper);
+
+  //! Invalidate specified sub-range of data (as byte offsets).
+  Standard_EXPORT void invalidate (const Graphic3d_BufferRange& theRange);
+
+protected:
+  Graphic3d_BufferRange myInvalidatedRange; //!< invalidated buffer data range (as byte offsets)
+  Standard_Boolean      myIsInterleaved;    //!< flag indicating the vertex attributes being interleaved
+  Standard_Boolean      myIsMutable;        //!< flag indicating that data can be invalidated
+};
+
+#endif // _Graphic3d_AttribBuffer_HeaderFile
index 6d76b84..2d46aef 100644 (file)
 // commercial license or contractual agreement.
 
 #include <Graphic3d_Buffer.hxx>
-#include <Graphic3d_IndexBuffer.hxx>
 #include <Graphic3d_BoundBuffer.hxx>
+#include <Graphic3d_MutableIndexBuffer.hxx>
 
 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Buffer,      NCollection_Buffer)
 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_IndexBuffer, Graphic3d_Buffer)
 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_BoundBuffer, NCollection_Buffer)
+IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_MutableIndexBuffer, Graphic3d_IndexBuffer)
index 455c8ff..103d185 100644 (file)
 #ifndef _Graphic3d_Buffer_HeaderFile
 #define _Graphic3d_Buffer_HeaderFile
 
+#include <Graphic3d_BufferRange.hxx>
 #include <Graphic3d_Vec.hxx>
 #include <NCollection_Array1.hxx>
 #include <NCollection_Buffer.hxx>
+#include <Standard_NotImplemented.hxx>
 
 //! Type of attribute in Vertex Buffer
 enum Graphic3d_TypeOfAttribute
@@ -86,7 +88,7 @@ public:
 
   //! Return number of initially allocated elements which can fit into this buffer,
   //! while NbElements can be overwritten to smaller value.
-  Standard_Integer NbMaxElements() const { return Standard_Integer(mySize / size_t(Stride)); }
+  Standard_Integer NbMaxElements() const { return Stride != 0 ? Standard_Integer(mySize / size_t(Stride)) : 0; }
 
   //! @return array of attributes definitions
   const Graphic3d_Attribute* AttributesArray() const
@@ -106,6 +108,25 @@ public:
     return *((Graphic3d_Attribute* )(myData + mySize) + theAttribIndex);
   }
 
+  //! Find attribute index.
+  //! @param theAttrib attribute to find
+  //! @return attribute index or -1 if not found
+  Standard_Integer FindAttribute (Graphic3d_TypeOfAttribute theAttrib) const
+  {
+    for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
+    {
+      const Graphic3d_Attribute& anAttrib = Attribute (anAttribIter);
+      if (anAttrib.Id == theAttrib)
+      {
+        return anAttribIter;
+      }
+    }
+    return -1;
+  }
+
+//! @name data accessors for interleaved array
+public:
+
   //! @return data offset to specified attribute
   Standard_Integer AttributeOffset (const Standard_Integer theAttribIndex) const
   {
@@ -117,9 +138,6 @@ public:
     return anOffset;
   }
 
-  using NCollection_Buffer::Data;
-  using NCollection_Buffer::ChangeData;
-
   //! @return data for specified attribute
   const Standard_Byte* Data (const Standard_Integer theAttribIndex) const
   {
@@ -158,6 +176,70 @@ public:
     return *reinterpret_cast<Type_t* >(changeValue (theElem));
   }
 
+//! @name general accessors
+public:
+
+  using NCollection_Buffer::Data;
+  using NCollection_Buffer::ChangeData;
+
+  //! Return the attribute data with stride size specific to this attribute.
+  //! @param theAttrib       attribute to find
+  //! @param theAttribIndex  index of found attribute
+  //! @param theAttribStride stride in bytes between values of this attribute within returned data pointer
+  Standard_Byte* ChangeAttributeData (Graphic3d_TypeOfAttribute theAttrib,
+                                      Standard_Integer& theAttribIndex,
+                                      Standard_Size& theAttribStride)
+  {
+    return (Standard_Byte* )AttributeData (theAttrib, theAttribIndex, theAttribStride);
+  }
+
+  //! Return the attribute data with stride size specific to this attribute.
+  //! @param theAttrib       attribute to find
+  //! @param theAttribIndex  index of found attribute
+  //! @param theAttribStride stride in bytes between values of this attribute within returned data pointer
+  const Standard_Byte* AttributeData (Graphic3d_TypeOfAttribute theAttrib,
+                                      Standard_Integer& theAttribIndex,
+                                      Standard_Size& theAttribStride) const
+  {
+    const Standard_Byte* aDataPtr = Data();
+    if (IsInterleaved())
+    {
+      for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
+      {
+        const Graphic3d_Attribute& anAttrib = Attribute (anAttribIter);
+        const Standard_Size anAttribStride = Graphic3d_Attribute::Stride (anAttrib.DataType);
+        if (anAttrib.Id == theAttrib)
+        {
+          theAttribIndex  = anAttribIter;
+          theAttribStride = Stride;
+          return aDataPtr;
+        }
+
+        aDataPtr += anAttribStride;
+      }
+    }
+    else
+    {
+      const Standard_Integer aNbMaxVerts = NbMaxElements();
+      for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
+      {
+        const Graphic3d_Attribute& anAttrib = Attribute (anAttribIter);
+        const Standard_Size anAttribStride = Graphic3d_Attribute::Stride (anAttrib.DataType);
+        if (anAttrib.Id == theAttrib)
+        {
+          theAttribIndex  = anAttribIter;
+          theAttribStride = anAttribStride;
+          return aDataPtr;
+        }
+
+        aDataPtr += anAttribStride * aNbMaxVerts;
+      }
+    }
+    return NULL;
+  }
+
+public:
+
   //! Release buffer.
   void release()
   {
@@ -214,6 +296,27 @@ public:
 
 public:
 
+  //! Flag indicating that attributes in the buffer are interleaved; TRUE by default.
+  //! Requires sub-classing for creating a non-interleaved buffer (advanced usage).
+  virtual Standard_Boolean IsInterleaved() const { return Standard_True; }
+
+  //! Return TRUE if data can be invalidated; FALSE by default.
+  //! Requires sub-classing for creating a mutable buffer (advanced usage).
+  virtual Standard_Boolean IsMutable() const { return Standard_False; }
+
+  //! Return invalidated range; EMPTY by default.
+  //! Requires sub-classing for creating a mutable buffer (advanced usage).
+  virtual Graphic3d_BufferRange InvalidatedRange() const { return Graphic3d_BufferRange(); }
+
+  //! Reset invalidated range.
+  //! Requires sub-classing for creating a mutable buffer (advanced usage).
+  virtual void Validate() {}
+
+  //! Invalidate entire buffer.
+  virtual void Invalidate() {}
+
+public:
+
   Standard_Integer Stride;       //!< the distance to the attributes of the next vertex within interleaved array
   Standard_Integer NbElements;   //!< number of the elements (@sa NbMaxElements() specifying the number of initially allocated number of elements)
   Standard_Integer NbAttributes; //!< number of vertex attributes
diff --git a/src/Graphic3d/Graphic3d_BufferRange.hxx b/src/Graphic3d/Graphic3d_BufferRange.hxx
new file mode 100644 (file)
index 0000000..3a90f7a
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Graphic3d_BufferRange_HeaderFile
+#define _Graphic3d_BufferRange_HeaderFile
+
+#include <Graphic3d_Vec.hxx>
+#include <Standard_Integer.hxx>
+
+//! Range of values defined as Start + Length pair.
+struct Graphic3d_BufferRange
+{
+  Standard_Integer Start;  //!< first element within the range
+  Standard_Integer Length; //!< number of elements within the range
+
+  //! Empty constructor.
+  Graphic3d_BufferRange() : Start (0), Length (0) {}
+
+  //! Constructor.
+  Graphic3d_BufferRange (Standard_Integer theStart, Standard_Integer theLength) : Start (theStart), Length (theLength) {}
+
+  //! Return TRUE if range is empty.
+  Standard_Boolean IsEmpty() const { return Length == 0; }
+
+  //! Return the Upper element within the range
+  Standard_Integer Upper() const { return Start + Length - 1; }
+
+  //! Clear the range.
+  void Clear()
+  {
+    Start  = 0;
+    Length = 0;
+  }
+
+  //! Add another range to this one.
+  void Unite (const Graphic3d_BufferRange& theRange)
+  {
+    if (IsEmpty())
+    {
+      *this = theRange;
+      return;
+    }
+    else if (theRange.IsEmpty())
+    {
+      return;
+    }
+
+    const Standard_Integer aStart = Min (Start,   theRange.Start);
+    const Standard_Integer aLast  = Max (Upper(), theRange.Upper());
+    Start  = aStart;
+    Length = aLast - aStart + 1;
+  }
+};
+
+#endif // _Graphic3d_BufferRange_HeaderFile
index f19c62c..42aba0d 100644 (file)
@@ -314,45 +314,45 @@ void Graphic3d_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray th
     myContainsFacet = true;
   }
 
-  if (theToEvalMinMax)
+  if (!theToEvalMinMax)
+  {
+    Update();
+    return;
+  }
+
+  const Standard_Integer aNbVerts = theAttribs->NbElements;
+  Standard_Integer anAttribIndex = 0;
+  Standard_Size anAttribStride = 0;
+  const Standard_Byte* aDataPtr = theAttribs->AttributeData (Graphic3d_TOA_POS, anAttribIndex, anAttribStride);
+  if (aDataPtr == NULL)
+  {
+    Update();
+    return;
+  }
+
+  switch (theAttribs->Attribute (anAttribIndex).DataType)
   {
-    const Standard_Integer aNbVerts = theAttribs->NbElements;
-    for (Standard_Integer anAttribIter = 0; anAttribIter < theAttribs->NbAttributes; ++anAttribIter)
+    case Graphic3d_TOD_VEC2:
     {
-      const Graphic3d_Attribute& anAttrib = theAttribs->Attribute (anAttribIter);
-      if (anAttrib.Id != Graphic3d_TOA_POS)
+      for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter)
       {
-        continue;
+        const Graphic3d_Vec2& aVert = *reinterpret_cast<const Graphic3d_Vec2* >(aDataPtr + anAttribStride * aVertIter);
+        myBounds.Add (Graphic3d_Vec4 (aVert.x(), aVert.y(), 0.0f, 1.0f));
       }
-
-      const size_t anOffset = theAttribs->AttributeOffset (anAttribIter);
-      switch (anAttrib.DataType)
+      break;
+    }
+    case Graphic3d_TOD_VEC3:
+    case Graphic3d_TOD_VEC4:
+    {
+      for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter)
       {
-        case Graphic3d_TOD_VEC2:
-        {
-          for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter)
-          {
-            const Graphic3d_Vec2& aVert = *reinterpret_cast<const Graphic3d_Vec2* >(theAttribs->value (aVertIter) + anOffset);
-            myBounds.Add (Graphic3d_Vec4 (aVert.x(), aVert.y(), 0.0f, 1.0f));
-          }
-          break;
-        }
-        case Graphic3d_TOD_VEC3:
-        case Graphic3d_TOD_VEC4:
-        {
-          for (Standard_Integer aVertIter = 0; aVertIter < aNbVerts; ++aVertIter)
-          {
-            const Graphic3d_Vec3& aVert = *reinterpret_cast<const Graphic3d_Vec3* >(theAttribs->value (aVertIter) + anOffset);
-            myBounds.Add (Graphic3d_Vec4 (aVert.x(), aVert.y(), aVert.z(), 1.0f));
-          }
-          break;
-        }
-        default: break;
+        const Graphic3d_Vec3& aVert = *reinterpret_cast<const Graphic3d_Vec3* >(aDataPtr + anAttribStride * aVertIter);
+        myBounds.Add (Graphic3d_Vec4 (aVert.x(), aVert.y(), aVert.z(), 1.0f));
       }
       break;
     }
+    default: break;
   }
-
   Update();
 }
 
diff --git a/src/Graphic3d/Graphic3d_MutableIndexBuffer.hxx b/src/Graphic3d/Graphic3d_MutableIndexBuffer.hxx
new file mode 100644 (file)
index 0000000..4bcfccd
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright (c) 2018 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Graphic3d_MutableIndexBuffer_HeaderFile
+#define _Graphic3d_MutableIndexBuffer_HeaderFile
+
+#include <Graphic3d_IndexBuffer.hxx>
+
+//! Mutable index buffer.
+class Graphic3d_MutableIndexBuffer : public Graphic3d_IndexBuffer
+{
+  DEFINE_STANDARD_RTTIEXT(Graphic3d_MutableIndexBuffer, Graphic3d_IndexBuffer)
+public:
+
+  //! Empty constructor.
+  Graphic3d_MutableIndexBuffer (const Handle(NCollection_BaseAllocator)& theAlloc) : Graphic3d_IndexBuffer (theAlloc) {}
+
+  //! Return TRUE if data can be invalidated.
+  virtual Standard_Boolean IsMutable() const Standard_OVERRIDE { return Standard_True; }
+
+  //! Return invalidated range.
+  virtual Graphic3d_BufferRange InvalidatedRange() const Standard_OVERRIDE { return myInvalidatedRange; }
+
+  //! Reset invalidated range.
+  virtual void Validate() Standard_OVERRIDE { myInvalidatedRange.Clear(); }
+
+  //! Invalidate the entire buffer data.
+  virtual void Invalidate() Standard_OVERRIDE
+  {
+    invalidate (Graphic3d_BufferRange (0, (Standard_Integer )mySize));
+  }
+
+  //! Invalidate the given indexes (starting from 0)
+  void Invalidate (Standard_Integer theIndexLower, Standard_Integer theIndexUpper)
+  {
+    Standard_OutOfRange_Raise_if (theIndexLower > theIndexUpper, "Graphic3d_MutableIndexBuffer::Invalidate()");
+    invalidate (Graphic3d_BufferRange (Stride * theIndexLower, Stride * (theIndexUpper - theIndexLower + 1)));
+  }
+
+  //! Invalidate specified sub-range of data (as byte offsets).
+  void invalidate (const Graphic3d_BufferRange& theRange) { myInvalidatedRange.Unite (theRange); }
+
+protected:
+
+  Graphic3d_BufferRange myInvalidatedRange; //!< invalidated buffer data range (as byte offsets)
+
+};
+
+#endif // _Graphic3d_MutableIndexBuffer_HeaderFile
index 09538a7..8986de7 100644 (file)
@@ -68,20 +68,11 @@ namespace
 template<class TheBaseClass, int NbAttributes>
 class OpenGl_VertexBufferT : public TheBaseClass
 {
-
 public:
 
   //! Create uninitialized VBO.
-  OpenGl_VertexBufferT (const Graphic3d_Attribute* theAttribs,
-                        const Standard_Integer     theStride)
-  : Stride (theStride)
-  {
-    memcpy (Attribs, theAttribs, sizeof(Graphic3d_Attribute) * NbAttributes);
-  }
-
-  //! Create uninitialized VBO.
   OpenGl_VertexBufferT (const Graphic3d_Buffer& theAttribs)
-  : Stride (theAttribs.Stride)
+  : Stride (theAttribs.IsInterleaved() ? theAttribs.Stride : 0)
   {
     memcpy (Attribs, theAttribs.AttributesArray(), sizeof(Graphic3d_Attribute) * NbAttributes);
   }
@@ -122,6 +113,7 @@ public:
     TheBaseClass::Bind (theGlCtx);
     GLint aNbComp;
     const GLubyte* anOffset = TheBaseClass::myOffset;
+    const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
     for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
     {
       const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
@@ -133,7 +125,7 @@ public:
         break;
       }
 
-      anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
+      anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
     }
   }
 
@@ -147,6 +139,7 @@ public:
     TheBaseClass::Bind (theGlCtx);
     GLint aNbComp;
     const GLubyte* anOffset = TheBaseClass::myOffset;
+    const Standard_Size aMuliplier = Stride != 0 ? 1 : TheBaseClass::myElemsNb;
     for (Standard_Integer anAttribIter = 0; anAttribIter < NbAttributes; ++anAttribIter)
     {
       const Graphic3d_Attribute& anAttrib = Attribs[anAttribIter];
@@ -155,7 +148,7 @@ public:
       {
         TheBaseClass::bindAttribute (theGlCtx, anAttrib.Id, aNbComp, aDataType, Stride, anOffset);
       }
-      anOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
+      anOffset += aMuliplier * Graphic3d_Attribute::Stride (anAttrib.DataType);
     }
   }
 
@@ -219,13 +212,20 @@ Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Conte
     case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
   }
 
+  const Standard_Boolean isAttribMutable     = myAttribs->IsMutable();
+  const Standard_Boolean isAttribInterleaved = myAttribs->IsInterleaved();
+  if (myAttribs->NbElements != myAttribs->NbMaxElements()
+   && myIndices.IsNull()
+   && (!isAttribInterleaved || isAttribMutable))
+  {
+    throw Standard_ProgramError ("OpenGl_PrimitiveArray::buildVBO() - vertex attribute data with reserved size is not supported");
+  }
+
   // specify data type as Byte and NbComponents as Stride, so that OpenGl_VertexBuffer::EstimatedDataSize() will return correct value
-  if (!myVboAttribs->init (theCtx, myAttribs->Stride, myAttribs->NbElements, myAttribs->Data(), GL_UNSIGNED_BYTE, myAttribs->Stride))
+  const Standard_Integer aNbVertexes = (isAttribMutable || !isAttribInterleaved) ? myAttribs->NbMaxElements() : myAttribs->NbElements;
+  if (!myVboAttribs->init (theCtx, myAttribs->Stride, aNbVertexes, myAttribs->Data(), GL_UNSIGNED_BYTE, myAttribs->Stride))
   {
-    TCollection_ExtendedString aMsg;
-    aMsg += "VBO creation for Primitive Array has failed for ";
-    aMsg += myAttribs->NbElements;
-    aMsg += " vertices. Out of memory?";
+    TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbVertexes + " vertices. Out of memory?";
     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
 
     clearMemoryGL (theCtx);
@@ -233,21 +233,32 @@ Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Conte
   }
   else if (myIndices.IsNull())
   {
+    if (isAttribMutable && isAttribInterleaved)
+    {
+      // for mutable interlaced array we can change dynamically number of vertexes (they will be just skipped at the end of buffer);
+      // this doesn't matter in case if we have indexed array
+      myVboAttribs->SetElemsNb (myAttribs->NbElements);
+    }
     return Standard_True;
   }
 
+  const Standard_Integer aNbIndexes = !myIndices->IsMutable() ? myIndices->NbElements : myIndices->NbMaxElements();
   myVboIndices = new OpenGl_IndexBuffer();
   bool isOk = false;
   switch (myIndices->Stride)
   {
     case 2:
     {
-      isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLushort*> (myIndices->Data()));
+      isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLushort*> (myIndices->Data()));
+      myVboIndices->SetElemsNb (myIndices->NbElements);
+      myIndices->Validate();
       break;
     }
     case 4:
     {
-      isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast<const GLuint*> (myIndices->Data()));
+      isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast<const GLuint*> (myIndices->Data()));
+      myVboIndices->SetElemsNb (myIndices->NbElements);
+      myIndices->Validate();
       break;
     }
     default:
@@ -258,10 +269,7 @@ Standard_Boolean OpenGl_PrimitiveArray::initNormalVbo (const Handle(OpenGl_Conte
   }
   if (!isOk)
   {
-    TCollection_ExtendedString aMsg;
-    aMsg += "VBO creation for Primitive Array has failed for ";
-    aMsg += myIndices->NbElements;
-    aMsg += " indices. Out of memory?";
+    TCollection_ExtendedString aMsg = TCollection_ExtendedString("VBO creation for Primitive Array has failed for ") + aNbIndexes + " indices. Out of memory?";
     theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PERFORMANCE, 0, GL_DEBUG_SEVERITY_LOW, aMsg);
     clearMemoryGL (theCtx);
     return Standard_False;
@@ -292,11 +300,16 @@ Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)&
    && initNormalVbo (theCtx))
   {
     if (!theCtx->caps->keepArrayData
-     && !theToKeepData)
+     && !theToKeepData
+     && !myAttribs->IsMutable())
     {
       myIndices.Nullify();
       myAttribs.Nullify();
     }
+    else
+    {
+      myAttribs->Validate();
+    }
     return Standard_True;
   }
 
@@ -350,6 +363,51 @@ Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)&
 }
 
 // =======================================================================
+// function : updateVBO
+// purpose  :
+// =======================================================================
+void OpenGl_PrimitiveArray::updateVBO (const Handle(OpenGl_Context)& theCtx) const
+{
+  if (!myAttribs.IsNull())
+  {
+    Graphic3d_BufferRange aRange = myAttribs->InvalidatedRange();
+    if (!aRange.IsEmpty()
+     &&  myVboAttribs->IsValid()
+     && !myVboAttribs->IsVirtual())
+    {
+      myVboAttribs->Bind (theCtx);
+      theCtx->core15fwd->glBufferSubData (myVboAttribs->GetTarget(),
+                                          aRange.Start,
+                                          aRange.Length,
+                                          myAttribs->Data() + aRange.Start);
+      myVboAttribs->Unbind (theCtx);
+      if (myAttribs->IsInterleaved())
+      {
+        myVboAttribs->SetElemsNb (myAttribs->NbElements);
+      }
+    }
+    myAttribs->Validate();
+  }
+  if (!myIndices.IsNull())
+  {
+    Graphic3d_BufferRange aRange = myIndices->InvalidatedRange();
+    if (!aRange.IsEmpty()
+     &&  myVboIndices->IsValid()
+     && !myVboIndices->IsVirtual())
+    {
+      myVboIndices->Bind (theCtx);
+      theCtx->core15fwd->glBufferSubData (myVboIndices->GetTarget(),
+                                          aRange.Start,
+                                          aRange.Length,
+                                          myIndices->Data() + aRange.Start);
+      myVboIndices->Unbind (theCtx);
+      myVboIndices->SetElemsNb (myIndices->NbElements);
+    }
+    myIndices->Validate();
+  }
+}
+
+// =======================================================================
 // function : drawArray
 // purpose  :
 // =======================================================================
@@ -732,6 +790,13 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace
     buildVBO (aCtx, toKeepData);
     myIsVboInit = Standard_True;
   }
+  else if ((!myAttribs.IsNull()
+         &&  myAttribs->IsMutable())
+        || (!myIndices.IsNull()
+         &&  myIndices->IsMutable()))
+  {
+    updateVBO (aCtx);
+  }
 
   // Temporarily disable environment mapping
   Handle(OpenGl_TextureSet) aTextureBack;
index 978af74..811b222 100644 (file)
@@ -107,6 +107,9 @@ protected:
   Standard_EXPORT Standard_Boolean buildVBO (const Handle(OpenGl_Context)& theCtx,
                                              const Standard_Boolean        theToKeepData) const;
 
+  //! Patch VBO sub-date within invalidated range.
+  Standard_EXPORT void updateVBO (const Handle(OpenGl_Context)& theCtx) const;
+
   //! Release GL memory.
   Standard_EXPORT void clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const;
 
index 2558a0c..5f259ef 100644 (file)
@@ -42,6 +42,9 @@ public:
 
   Standard_EXPORT virtual GLenum GetTarget() const;
 
+  //! Return TRUE if this is a virtual (for backward compatibility) VBO object.
+  virtual bool IsVirtual() const { return false; }
+
   //! @return true if current object was initialized
   inline bool IsValid() const
   {
@@ -54,12 +57,16 @@ public:
     return myComponentsNb;
   }
 
-  //! @return number of vertex attributes / number of vertices.
+  //! @return number of vertex attributes / number of vertices specified within ::Init()
   inline GLsizei GetElemsNb() const
   {
     return myElemsNb;
   }
 
+  //! Overrides the number of vertex attributes / number of vertexes.
+  //! It is up to user specifying this number correct (e.g. below initial value)!
+  void SetElemsNb (GLsizei theNbElems) { myElemsNb = theNbElems; }
+
   //! @return data type of each component in the array.
   inline GLenum GetDataType() const
   {
index 7106929..331dbe6 100644 (file)
@@ -42,6 +42,9 @@ public:
   //! Destroy object.
   Standard_EXPORT virtual ~OpenGl_VertexBufferCompat();
 
+  //! Return TRUE.
+  virtual bool IsVirtual() const Standard_OVERRIDE { return true; }
+
   //! Creates VBO name (id) if not yet generated.
   //! Data should be initialized by another method.
   Standard_EXPORT bool Create (const Handle(OpenGl_Context)& theGlCtx) Standard_OVERRIDE;
index adaeb09..60322e1 100644 (file)
@@ -620,53 +620,43 @@ Handle(OpenGl_TriangleSet) OpenGl_View::addRaytracePrimitiveArray (const OpenGl_
     aSet->TexCrds.reserve  (anAttribs->NbElements);
 
     const size_t aVertFrom = aSet->Vertices.size();
-    for (Standard_Integer anAttribIter = 0; anAttribIter < anAttribs->NbAttributes; ++anAttribIter)
+
+    Standard_Integer anAttribIndex = 0;
+    Standard_Size anAttribStride = 0;
+    if (const Standard_Byte* aPosData = anAttribs->AttributeData (Graphic3d_TOA_POS, anAttribIndex, anAttribStride))
     {
-      const Graphic3d_Attribute& anAttrib = anAttribs->Attribute       (anAttribIter);
-      const size_t               anOffset = anAttribs->AttributeOffset (anAttribIter);
-      if (anAttrib.Id == Graphic3d_TOA_POS)
+      const Graphic3d_Attribute& anAttrib = anAttribs->Attribute (anAttribIndex);
+      if (anAttrib.DataType == Graphic3d_TOD_VEC2
+       || anAttrib.DataType == Graphic3d_TOD_VEC3
+       || anAttrib.DataType == Graphic3d_TOD_VEC4)
       {
-        if (anAttrib.DataType == Graphic3d_TOD_VEC3
-         || anAttrib.DataType == Graphic3d_TOD_VEC4)
-        {
-          for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
-          {
-            aSet->Vertices.push_back (
-              *reinterpret_cast<const Graphic3d_Vec3*> (anAttribs->value (aVertIter) + anOffset));
-          }
-        }
-        else if (anAttrib.DataType == Graphic3d_TOD_VEC2)
+        for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
         {
-          for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
-          {
-            const Standard_ShortReal* aCoords =
-              reinterpret_cast<const Standard_ShortReal*> (anAttribs->value (aVertIter) + anOffset);
-
-            aSet->Vertices.push_back (BVH_Vec3f (aCoords[0], aCoords[1], 0.0f));
-          }
+          const float* aCoords = reinterpret_cast<const float*> (aPosData + anAttribStride * aVertIter);
+          aSet->Vertices.push_back (BVH_Vec3f (aCoords[0], aCoords[1], anAttrib.DataType != Graphic3d_TOD_VEC2 ? aCoords[2] : 0.0f));
         }
       }
-      else if (anAttrib.Id == Graphic3d_TOA_NORM)
+    }
+    if (const Standard_Byte* aNormData = anAttribs->AttributeData (Graphic3d_TOA_NORM, anAttribIndex, anAttribStride))
+    {
+      const Graphic3d_Attribute& anAttrib = anAttribs->Attribute (anAttribIndex);
+      if (anAttrib.DataType == Graphic3d_TOD_VEC3
+       || anAttrib.DataType == Graphic3d_TOD_VEC4)
       {
-        if (anAttrib.DataType == Graphic3d_TOD_VEC3
-         || anAttrib.DataType == Graphic3d_TOD_VEC4)
+        for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
         {
-          for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
-          {
-            aSet->Normals.push_back (
-              *reinterpret_cast<const Graphic3d_Vec3*> (anAttribs->value (aVertIter) + anOffset));
-          }
+          aSet->Normals.push_back (*reinterpret_cast<const Graphic3d_Vec3*> (aNormData + anAttribStride * aVertIter));
         }
       }
-      else if (anAttrib.Id == Graphic3d_TOA_UV)
+    }
+    if (const Standard_Byte* aTexData = anAttribs->AttributeData (Graphic3d_TOA_UV, anAttribIndex, anAttribStride))
+    {
+      const Graphic3d_Attribute& anAttrib = anAttribs->Attribute (anAttribIndex);
+      if (anAttrib.DataType == Graphic3d_TOD_VEC2)
       {
-        if (anAttrib.DataType == Graphic3d_TOD_VEC2)
+        for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
         {
-          for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
-          {
-            aSet->TexCrds.push_back (
-              *reinterpret_cast<const Graphic3d_Vec2*> (anAttribs->value (aVertIter) + anOffset));
-          }
+          aSet->TexCrds.push_back (*reinterpret_cast<const Graphic3d_Vec2*> (aTexData + anAttribStride * aVertIter));
         }
       }
     }
index fc0c6ce..494f2ee 100644 (file)
@@ -157,10 +157,11 @@ private:
 // =======================================================================
 Select3D_SensitivePrimitiveArray::Select3D_SensitivePrimitiveArray (const Handle(SelectBasics_EntityOwner)& theOwnerId)
 : Select3D_SensitiveSet (theOwnerId),
+  myPosData (NULL),
+  myPosStride (Standard_Size(-1)),
   myPrimType (Graphic3d_TOPA_UNDEFINED),
   myIndexLower (0),
   myIndexUpper (0),
-  myPosOffset (Standard_Size(-1)),
   myPatchSizeMax (1),
   myPatchDistance (ShortRealLast()),
   myIs3d (false),
@@ -243,7 +244,8 @@ bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d
   myIndices.Nullify();
   myIndexLower = 0;
   myIndexUpper = 0;
-  myPosOffset = Standard_Size(-1);
+  myPosData = NULL;
+  myPosStride = Standard_Size(-1);
   myBvhIndices.release();
   myIs3d = false;
   myInitLocation = theInitLoc;
@@ -254,27 +256,19 @@ bool Select3D_SensitivePrimitiveArray::InitTriangulation (const Handle(Graphic3d
     return false;
   }
 
-  for (Standard_Integer anAttribIter = 0; anAttribIter < theVerts->NbAttributes; ++anAttribIter)
+  Standard_Integer aPosAttribIndex = 0;
+  myPosData = theVerts->AttributeData (Graphic3d_TOA_POS, aPosAttribIndex, myPosStride);
+  if (myPosData == NULL)
   {
-    const Graphic3d_Attribute& anAttrib = theVerts->Attribute (anAttribIter);
-    if (anAttrib.Id == Graphic3d_TOA_POS)
-    {
-      if (anAttrib.DataType == Graphic3d_TOD_VEC3
-       || anAttrib.DataType == Graphic3d_TOD_VEC4)
-      {
-        myIs3d = true;
-      }
-      else if (anAttrib.DataType != Graphic3d_TOD_VEC2)
-      {
-        return false;
-      }
-
-      myPosOffset = theVerts->AttributeOffset (anAttribIter);
-      break;
-    }
+    return false;
   }
-  if (myPosOffset == Standard_Size(-1))
+
+  const Graphic3d_Attribute& anAttrib = theVerts->Attribute (aPosAttribIndex);
+  myIs3d = anAttrib.DataType == Graphic3d_TOD_VEC3
+        || anAttrib.DataType == Graphic3d_TOD_VEC4;
+  if (!myIs3d && anAttrib.DataType != Graphic3d_TOD_VEC2)
   {
+    myPosData = NULL;
     return false;
   }
 
@@ -422,7 +416,8 @@ bool Select3D_SensitivePrimitiveArray::InitPoints (const Handle(Graphic3d_Buffer
   myIndices.Nullify();
   myIndexLower = 0;
   myIndexUpper = 0;
-  myPosOffset = Standard_Size(-1);
+  myPosData = NULL;
+  myPosStride = Standard_Size(-1);
   myBvhIndices.release();
   myIs3d = false;
   myInitLocation = theInitLoc;
@@ -432,27 +427,19 @@ bool Select3D_SensitivePrimitiveArray::InitPoints (const Handle(Graphic3d_Buffer
     return false;
   }
 
-  for (Standard_Integer anAttribIter = 0; anAttribIter < theVerts->NbAttributes; ++anAttribIter)
+  Standard_Integer aPosAttribIndex = 0;
+  myPosData = theVerts->AttributeData (Graphic3d_TOA_POS, aPosAttribIndex, myPosStride);
+  if (myPosData == NULL)
   {
-    const Graphic3d_Attribute& anAttrib = theVerts->Attribute (anAttribIter);
-    if (anAttrib.Id == Graphic3d_TOA_POS)
-    {
-      if (anAttrib.DataType == Graphic3d_TOD_VEC3
-       || anAttrib.DataType == Graphic3d_TOD_VEC4)
-      {
-        myIs3d = true;
-      }
-      else if (anAttrib.DataType != Graphic3d_TOD_VEC2)
-      {
-        return false;
-      }
-
-      myPosOffset = theVerts->AttributeOffset (anAttribIter);
-      break;
-    }
+    return false;
   }
-  if (myPosOffset == Standard_Size(-1))
+
+  const Graphic3d_Attribute& anAttrib = theVerts->Attribute (aPosAttribIndex);
+  myIs3d = anAttrib.DataType == Graphic3d_TOD_VEC3
+        || anAttrib.DataType == Graphic3d_TOD_VEC4;
+  if (!myIs3d && anAttrib.DataType != Graphic3d_TOD_VEC2)
   {
+    myPosData = NULL;
     return false;
   }
 
index 50e767b..851b163 100644 (file)
@@ -268,13 +268,13 @@ protected:
   //! Auxiliary getter.
   const Graphic3d_Vec3& getPosVec3 (const Standard_Integer theIndex) const
   {
-    return *reinterpret_cast<const Graphic3d_Vec3* >(myVerts->value (theIndex) + myPosOffset);
+    return *reinterpret_cast<const Graphic3d_Vec3* >(myPosData + myPosStride * theIndex);
   }
 
   //! Auxiliary getter.
   const Graphic3d_Vec2& getPosVec2 (const Standard_Integer theIndex) const
   {
-    return *reinterpret_cast<const Graphic3d_Vec2* >(myVerts->value (theIndex) + myPosOffset);
+    return *reinterpret_cast<const Graphic3d_Vec2* >(myPosData + myPosStride * theIndex);
   }
 
   //! Checks whether the element with index theIdx overlaps the current selecting volume
@@ -303,10 +303,11 @@ private:
 
   Handle(Graphic3d_Buffer)            myVerts;              //!< source data - nodes position
   Handle(Graphic3d_IndexBuffer)       myIndices;            //!< source data - primitive indexes
+  const Standard_Byte*                myPosData;            //!< position vertex attribute data
+  Standard_Size                       myPosStride;          //!< position vertex attribute stride in bytes
   Graphic3d_TypeOfPrimitiveArray      myPrimType;           //!< primitives type
   Standard_Integer                    myIndexLower;         //!< index range - first index in myIndices (inclusive)
   Standard_Integer                    myIndexUpper;         //!< index range - last  index in myIndices (inclusive)
-  Standard_Size                       myPosOffset;          //!< offset to the position vertex attribute
   Standard_Integer                    myPatchSizeMax;       //!< patch size limit (1 by default)
   float                               myPatchDistance;      //!< distance between elements in patch
   bool                                myIs3d;               //!< flag indicating that position attribute has 3 components
index 37e0f34..68cb3b7 100644 (file)
 #include <Graphic3d_ArrayOfQuadrangles.hxx>
 #include <Graphic3d_ArrayOfQuadrangleStrips.hxx>
 #include <Graphic3d_ArrayOfPolygons.hxx>
+#include <Graphic3d_AttribBuffer.hxx>
 #include <Graphic3d_AspectMarker3d.hxx>
 #include <Graphic3d_Group.hxx>
 #include <Standard_Real.hxx>
@@ -3281,8 +3282,18 @@ public:
 
   MyPArrayObject (const Handle(Graphic3d_ArrayOfPrimitives)& thePArray) : myPArray (thePArray) {}
 
-  MyPArrayObject (Handle(TColStd_HArray1OfAsciiString) theArrayDescription,
-                  Handle(Graphic3d_AspectMarker3d) theMarkerAspect = NULL);
+  MyPArrayObject (Graphic3d_TypeOfPrimitiveArray thePrimType,
+                  const Handle(TColStd_HArray1OfAsciiString)& theDesc,
+                  const Handle(Graphic3d_AspectMarker3d)& theMarkerAspect)
+  {
+    Init (thePrimType, theDesc, theMarkerAspect, Standard_False);
+  }
+
+  //! Initialize the array from specified description.
+  Standard_Boolean Init (Graphic3d_TypeOfPrimitiveArray thePrimType,
+                         const Handle(TColStd_HArray1OfAsciiString)& theDesc,
+                         const Handle(Graphic3d_AspectMarker3d)& theMarkerAspect,
+                         Standard_Boolean theToPatch);
 
   DEFINE_STANDARD_RTTI_INLINE(MyPArrayObject,AIS_InteractiveObject);
 
@@ -3298,14 +3309,13 @@ private:
                          const Standard_Integer /*theMode*/) Standard_OVERRIDE;
 
   bool CheckInputCommand (const TCollection_AsciiString theCommand,
-                          const Handle(TColStd_HArray1OfAsciiString) theArgsArray,
+                          const Handle(TColStd_HArray1OfAsciiString)& theArgsArray,
                           Standard_Integer &theArgIndex,
                           Standard_Integer theArgCount,
                           Standard_Integer theMaxArgs);
 
 protected:
 
-  Handle(TColStd_HArray1OfAsciiString) myArrayDescription;
   Handle(Graphic3d_AspectMarker3d) myMarkerAspect;
   Handle(Graphic3d_ArrayOfPrimitives) myPArray;
 
@@ -3330,43 +3340,54 @@ void MyPArrayObject::Compute (const Handle(PrsMgr_PresentationManager3d)& /*aPre
   aGroup->AddPrimitiveArray (myPArray);
 }
 
-MyPArrayObject::MyPArrayObject (Handle(TColStd_HArray1OfAsciiString) theArrayDescription,
-                                Handle(Graphic3d_AspectMarker3d) theMarkerAspect)
+Standard_Boolean MyPArrayObject::Init (Graphic3d_TypeOfPrimitiveArray thePrimType,
+                                       const Handle(TColStd_HArray1OfAsciiString)& theDesc,
+                                       const Handle(Graphic3d_AspectMarker3d)& theMarkerAspect,
+                                       Standard_Boolean theToPatch)
 {
-  myArrayDescription = theArrayDescription;
   myMarkerAspect = theMarkerAspect;
+  if (!theToPatch)
+  {
+    myPArray.Nullify();
+  }
 
   // Parsing array description
   Standard_Integer aVertexNum = 0, aBoundNum = 0, aEdgeNum = 0;
   Graphic3d_ArrayFlags anArrayFlags = Graphic3d_ArrayFlags_None;
 
-  Standard_Integer anArgIndex = 0;
-  Standard_Integer anArgsCount = myArrayDescription->Length();
-  TCollection_AsciiString anArrayType = myArrayDescription->Value (anArgIndex++);
-
+  const Standard_Integer anArgsCount = theDesc->Length();
   TCollection_AsciiString aCommand;
-  while (anArgIndex < anArgsCount)
+  for (Standard_Integer anArgIndex = theDesc->Lower(); anArgIndex <= theDesc->Upper(); )
   {
-    aCommand = myArrayDescription->Value (anArgIndex);
+    aCommand = theDesc->Value (anArgIndex);
     aCommand.LowerCase();
 
+    if (CheckInputCommand ("-deinterleaved", theDesc, anArgIndex, 0, anArgsCount))
+    {
+      anArrayFlags |= Graphic3d_ArrayFlags_AttribsDeinterleaved;
+    }
+    else if (CheckInputCommand ("-mutable", theDesc, anArgIndex, 0, anArgsCount))
+    {
+      anArrayFlags |= Graphic3d_ArrayFlags_AttribsMutable;
+      anArrayFlags |= Graphic3d_ArrayFlags_IndexesMutable;
+    }
     // vertex command
-    if (CheckInputCommand ("v", myArrayDescription, anArgIndex, 3, anArgsCount))
+    else if (CheckInputCommand ("v", theDesc, anArgIndex, 3, anArgsCount))
     {
       // vertex has a normal or normal with color or texel
-      if (CheckInputCommand ("n", myArrayDescription, anArgIndex, 3, anArgsCount))
+      if (CheckInputCommand ("n", theDesc, anArgIndex, 3, anArgsCount))
       {
         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_VertexNormal;
       }
 
       // vertex has a color
-      if (CheckInputCommand ("c", myArrayDescription, anArgIndex, 3, anArgsCount))
+      if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
       {
         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_VertexColor;
       }
 
       // vertex has a texel
-      if (CheckInputCommand ("t", myArrayDescription, anArgIndex, 2, anArgsCount))
+      if (CheckInputCommand ("t", theDesc, anArgIndex, 2, anArgsCount))
       {
         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_VertexTexel;
       }
@@ -3374,10 +3395,10 @@ MyPArrayObject::MyPArrayObject (Handle(TColStd_HArray1OfAsciiString) theArrayDes
       aVertexNum++;
     }
     // bound command
-    else if (CheckInputCommand ("b", myArrayDescription, anArgIndex, 1, anArgsCount))
+    else if (CheckInputCommand ("b", theDesc, anArgIndex, 1, anArgsCount))
     {
       // bound has color
-      if (CheckInputCommand ("c", myArrayDescription, anArgIndex, 3, anArgsCount))
+      if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
       {
         anArrayFlags = anArrayFlags | Graphic3d_ArrayFlags_BoundColor;
       }
@@ -3385,7 +3406,7 @@ MyPArrayObject::MyPArrayObject (Handle(TColStd_HArray1OfAsciiString) theArrayDes
       aBoundNum++;
     }
     // edge command
-    else if (CheckInputCommand ("e", myArrayDescription, anArgIndex, 1, anArgsCount))
+    else if (CheckInputCommand ("e", theDesc, anArgIndex, 1, anArgsCount))
     {
       aEdgeNum++;
     }
@@ -3394,87 +3415,126 @@ MyPArrayObject::MyPArrayObject (Handle(TColStd_HArray1OfAsciiString) theArrayDes
       anArgIndex++;
   }
 
-  Handle(Graphic3d_ArrayOfPrimitives) anArray;
-  if (anArrayType == "points")
+  if (myPArray.IsNull())
   {
-    anArray = new Graphic3d_ArrayOfPoints (aVertexNum);
+    myPArray = Graphic3d_ArrayOfPrimitives::CreateArray (thePrimType, aVertexNum, aBoundNum, aEdgeNum, anArrayFlags);
+  }
+  else
+  {
+    if (myPArray->Type() != thePrimType
+    ||  aVertexNum > myPArray->VertexNumberAllocated()
+    ||  aEdgeNum   > myPArray->EdgeNumberAllocated()
+    ||  aBoundNum  > myPArray->BoundNumberAllocated()
+    || !myPArray->Attributes()->IsMutable()
+    || (!myPArray->Indices().IsNull() && !myPArray->Indices()->IsMutable()))
+    {
+      std::cout << "Syntax error: array cannot be patched\n";
+      return Standard_False;
+    }
+
+    myPArray->Attributes()->NbElements = aVertexNum;
+    if (Handle(Graphic3d_AttribBuffer) anAttribs = Handle(Graphic3d_AttribBuffer)::DownCast (myPArray->Attributes()))
+    {
+      anAttribs->Invalidate (0, aVertexNum - 1);
+    }
+    if (!myPArray->Indices().IsNull())
+    {
+      myPArray->Indices()->NbElements = aEdgeNum;
+    }
+    if (!myPArray->Bounds().IsNull())
+    {
+      myPArray->Bounds()->NbBounds = aBoundNum;
+    }
   }
-  else if (anArrayType == "segments")
-    anArray = new Graphic3d_ArrayOfSegments (aVertexNum, aEdgeNum, anArrayFlags);
-  else if (anArrayType == "polylines")
-    anArray = new Graphic3d_ArrayOfPolylines (aVertexNum, aBoundNum, aEdgeNum, anArrayFlags);
-  else if (anArrayType == "triangles")
-    anArray = new Graphic3d_ArrayOfTriangles (aVertexNum, aEdgeNum, anArrayFlags);
-  else if (anArrayType == "trianglefans")
-    anArray = new Graphic3d_ArrayOfTriangleFans (aVertexNum, aBoundNum, anArrayFlags);
-  else if (anArrayType == "trianglestrips")
-    anArray = new Graphic3d_ArrayOfTriangleStrips (aVertexNum, aBoundNum, anArrayFlags);
-  else if (anArrayType == "quads")
-    anArray = new Graphic3d_ArrayOfQuadrangles (aVertexNum, aEdgeNum, anArrayFlags);
-  else if (anArrayType == "quadstrips")
-    anArray = new Graphic3d_ArrayOfQuadrangleStrips (aVertexNum, aBoundNum, anArrayFlags);
-  else if (anArrayType == "polygons")
-    anArray = new Graphic3d_ArrayOfPolygons (aVertexNum, aBoundNum, aEdgeNum, anArrayFlags);
 
-  anArgIndex = 1;
-  while (anArgIndex < anArgsCount)
+  Standard_Integer aVertIndex = 0;
+  for (Standard_Integer anArgIndex = theDesc->Lower(); anArgIndex <= theDesc->Upper(); )
   {
-    aCommand = myArrayDescription->Value (anArgIndex);
+    aCommand = theDesc->Value (anArgIndex);
     aCommand.LowerCase();
-    if (!aCommand.IsAscii())
+    if (!aCommand.IsAscii()
+      || aCommand.IsEmpty())
+    {
       break;
+    }
 
+    // skip beautifiers (syntax is not actually validated)
+    if (aCommand == "-deinterleaved"
+     || aCommand == "-mutable"
+     || aCommand.Value (1) == '('
+     || aCommand.Value (1) == ')'
+     || aCommand.Value (1) == ',')
+    {
+      ++anArgIndex;
+    }
     // vertex command
-    if (CheckInputCommand ("v", myArrayDescription, anArgIndex, 3, anArgsCount))
+    else if (CheckInputCommand ("v", theDesc, anArgIndex, 3, anArgsCount))
     {
-      anArray->AddVertex (myArrayDescription->Value (anArgIndex - 3).RealValue(),
-                          myArrayDescription->Value (anArgIndex - 2).RealValue(),
-                          myArrayDescription->Value (anArgIndex - 1).RealValue());
-      const Standard_Integer aVertIndex = anArray->VertexNumber();
+      const Graphic3d_Vec3 aVert ((float )theDesc->Value (anArgIndex - 3).RealValue(),
+                                  (float )theDesc->Value (anArgIndex - 2).RealValue(),
+                                  (float )theDesc->Value (anArgIndex - 1).RealValue());
+      if ((anArrayFlags & Graphic3d_ArrayFlags_AttribsDeinterleaved) != 0
+       || (anArrayFlags & Graphic3d_ArrayFlags_AttribsMutable) != 0)
+      {
+        ++aVertIndex;
+        myPArray->SetVertice (aVertIndex, aVert.x(), aVert.y(), aVert.z());
+      }
+      else
+      {
+        aVertIndex = myPArray->AddVertex (aVert);
+      }
 
       // vertex has a normal or normal with color or texel
-      if (CheckInputCommand ("n", myArrayDescription, anArgIndex, 3, anArgsCount))
-        anArray->SetVertexNormal (aVertIndex,
-                                  myArrayDescription->Value (anArgIndex - 3).RealValue(),
-                                  myArrayDescription->Value (anArgIndex - 2).RealValue(),
-                                  myArrayDescription->Value (anArgIndex - 1).RealValue());
-      
-      if (CheckInputCommand ("c", myArrayDescription, anArgIndex, 3, anArgsCount))
-        anArray->SetVertexColor (aVertIndex,
-                                 myArrayDescription->Value (anArgIndex - 3).RealValue(),
-                                 myArrayDescription->Value (anArgIndex - 2).RealValue(),
-                                 myArrayDescription->Value (anArgIndex - 1).RealValue());
+      if (CheckInputCommand ("n", theDesc, anArgIndex, 3, anArgsCount))
+      {
+        const Graphic3d_Vec3 aNorm ((float )theDesc->Value (anArgIndex - 3).RealValue(),
+                                    (float )theDesc->Value (anArgIndex - 2).RealValue(),
+                                    (float )theDesc->Value (anArgIndex - 1).RealValue());
+        myPArray->SetVertexNormal (aVertIndex, aNorm.x(), aNorm.y(), aNorm.z());
+      }
       
-      if (CheckInputCommand ("t", myArrayDescription, anArgIndex, 2, anArgsCount))
-        anArray->SetVertexTexel (aVertIndex,
-                                 myArrayDescription->Value (anArgIndex - 2).RealValue(),
-                                 myArrayDescription->Value (anArgIndex - 1).RealValue());
+      if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
+      {
+        const Graphic3d_Vec3d aCol (theDesc->Value (anArgIndex - 3).RealValue(),
+                                    theDesc->Value (anArgIndex - 2).RealValue(),
+                                    theDesc->Value (anArgIndex - 1).RealValue());
+        myPArray->SetVertexColor (aVertIndex, aCol.r(), aCol.g(), aCol.b());
+      }
+      if (CheckInputCommand ("t", theDesc, anArgIndex, 2, anArgsCount))
+      {
+        const Graphic3d_Vec2 aTex ((float )theDesc->Value (anArgIndex - 2).RealValue(),
+                                   (float )theDesc->Value (anArgIndex - 1).RealValue());
+        myPArray->SetVertexTexel (aVertIndex, aTex.x(), aTex.y());
+      }
     }
     // bounds command
-    else if (CheckInputCommand ("b", myArrayDescription, anArgIndex, 1, anArgsCount))
+    else if (CheckInputCommand ("b", theDesc, anArgIndex, 1, anArgsCount))
     {
-      Standard_Integer aVertCount = myArrayDescription->Value (anArgIndex - 1).IntegerValue();
+      Standard_Integer aVertCount = theDesc->Value (anArgIndex - 1).IntegerValue();
 
-      if (CheckInputCommand ("c", myArrayDescription, anArgIndex, 3, anArgsCount))
-        anArray->AddBound (aVertCount,
-                           myArrayDescription->Value (anArgIndex - 3).RealValue(),
-                           myArrayDescription->Value (anArgIndex - 2).RealValue(),
-                           myArrayDescription->Value (anArgIndex - 1).RealValue());
+      if (CheckInputCommand ("c", theDesc, anArgIndex, 3, anArgsCount))
+        myPArray->AddBound (aVertCount,
+                            theDesc->Value (anArgIndex - 3).RealValue(),
+                            theDesc->Value (anArgIndex - 2).RealValue(),
+                            theDesc->Value (anArgIndex - 1).RealValue());
 
       else
-        anArray->AddBound (aVertCount);
+        myPArray->AddBound (aVertCount);
     }
     // edge command
-    else if (CheckInputCommand ("e", myArrayDescription, anArgIndex, 1, anArgsCount))
+    else if (CheckInputCommand ("e", theDesc, anArgIndex, 1, anArgsCount))
     {
-      const Standard_Integer aVertIndex = myArrayDescription->Value (anArgIndex - 1).IntegerValue();
-      anArray->AddEdge (aVertIndex);
+      const Standard_Integer anEdge = theDesc->Value (anArgIndex - 1).IntegerValue();
+      myPArray->AddEdge (anEdge);
     }
     // unknown command
     else
-      anArgIndex++;
+    {
+      std::cout << "Syntax error: unknown argument '" << theDesc->Value(anArgIndex) << "'\n";
+      return Standard_False;
+    }
   }
-  myPArray = anArray;
+  return Standard_True;
 }
 
 void MyPArrayObject::ComputeSelection (const Handle(SelectMgr_Selection)& theSelection,
@@ -3524,7 +3584,7 @@ void MyPArrayObject::ComputeSelection (const Handle(SelectMgr_Selection)& theSel
 }
 
 bool MyPArrayObject::CheckInputCommand (const TCollection_AsciiString theCommand,
-                                       const Handle(TColStd_HArray1OfAsciiString) theArgsArray,
+                                       const Handle(TColStd_HArray1OfAsciiString)& theArgsArray,
                                        Standard_Integer &theArgIndex,
                                        Standard_Integer theArgCount,
                                        Standard_Integer theMaxArgs)
@@ -3573,12 +3633,14 @@ static int VDrawPArray (Draw_Interpretor& di, Standard_Integer argc, const char*
   }
 
   // read the arguments
-  Standard_Integer aArgIndex = 1;
-  TCollection_AsciiString aName (argv[aArgIndex++]);
-  TCollection_AsciiString anArrayType (argv[aArgIndex++]);
+  Standard_Integer anArgIndex = 1;
+  TCollection_AsciiString aName (argv[anArgIndex++]);
+  TCollection_AsciiString anArrayType (argv[anArgIndex++]);
+  anArrayType.LowerCase();
+  Handle(MyPArrayObject) aPObject;
   if (anArrayType == "-shape")
   {
-    Standard_CString aShapeName = argv[aArgIndex++];
+    Standard_CString aShapeName = argv[anArgIndex++];
     TopoDS_Shape aShape = DBRep::Get (aShapeName);
     Handle(Graphic3d_ArrayOfPrimitives) aTris = StdPrs_ShadedShape::FillTriangles (aShape);
     if (aShape.IsNull())
@@ -3592,38 +3654,85 @@ static int VDrawPArray (Draw_Interpretor& di, Standard_Integer argc, const char*
       return 1;
     }
 
-    Handle(MyPArrayObject) aPObject = new MyPArrayObject (aTris);
+    aPObject = new MyPArrayObject (aTris);
     ViewerTest::Display (aName, aPObject);
     return 0;
   }
+  else if (anArrayType == "-patch"
+        || anArrayType == "-modify"
+        || anArrayType == "-edit")
+  {
+    if (argc >= 3)
+    {
+      anArrayType = argv[anArgIndex++];
+      anArrayType.LowerCase();
+    }
 
-  Standard_Boolean hasVertex = Standard_False;
+    if (GetMapOfAIS().IsBound2 (aName))
+    {
+      aPObject = Handle(MyPArrayObject)::DownCast (GetMapOfAIS().Find2 (aName));
+    }
+    if (aPObject.IsNull())
+    {
+      std::cout << "Syntax error: object '" << aName << "' cannot be found\n";
+      return 1;
+    }
+  }
 
-  Handle(TColStd_HArray1OfAsciiString) anArgsArray = new TColStd_HArray1OfAsciiString (0, argc - 2);
-  anArgsArray->SetValue (0, anArrayType);
+  Standard_Boolean hasVertex = Standard_False;
 
-  if (anArrayType != "points"         &&
-      anArrayType != "segments"       &&
-      anArrayType != "polylines"      &&
-      anArrayType != "triangles"      &&
-      anArrayType != "trianglefans"   &&
-      anArrayType != "trianglestrips" &&
-      anArrayType != "quads"          &&
-      anArrayType != "quadstrips"     &&
-      anArrayType != "polygons")
+  Graphic3d_TypeOfPrimitiveArray aPrimType = Graphic3d_TOPA_UNDEFINED;
+  if (anArrayType == "points")
+  {
+    aPrimType = Graphic3d_TOPA_POINTS;
+  }
+  else if (anArrayType == "segments")
+  {
+    aPrimType = Graphic3d_TOPA_SEGMENTS;
+  }
+  else if (anArrayType == "polylines")
+  {
+    aPrimType = Graphic3d_TOPA_POLYLINES;
+  }
+  else if (anArrayType == "triangles")
+  {
+    aPrimType = Graphic3d_TOPA_TRIANGLES;
+  }
+  else if (anArrayType == "trianglefans")
   {
-    di << "Unexpected type of primitives array\n";
+    aPrimType = Graphic3d_TOPA_TRIANGLEFANS;
+  }
+  else if (anArrayType == "trianglestrips")
+  {
+    aPrimType = Graphic3d_TOPA_TRIANGLESTRIPS;
+  }
+  else if (anArrayType == "quads")
+  {
+    aPrimType = Graphic3d_TOPA_QUADRANGLES;
+  }
+  else if (anArrayType == "quadstrips")
+  {
+    aPrimType = Graphic3d_TOPA_QUADRANGLESTRIPS;
+  }
+  else if (anArrayType == "polygons")
+  {
+    aPrimType = Graphic3d_TOPA_POLYGONS;
+  }
+  if (aPrimType == Graphic3d_TOPA_UNDEFINED)
+  {
+    std::cout << "Syntax error: unexpected type of primitives array\n";
     return 1;
   }
 
-  TCollection_AsciiString aCommand;
-  for (Standard_Integer anArgIndex = 3; anArgIndex < argc; anArgIndex++)
+  Standard_Integer aLowerArg = anArgIndex;
+  Handle(TColStd_HArray1OfAsciiString) anArgsArray = new TColStd_HArray1OfAsciiString (0, argc - 3);
+  for (; anArgIndex < argc; ++anArgIndex)
   {
-    aCommand = argv[anArgIndex];
+    TCollection_AsciiString aCommand (argv[anArgIndex]);
     aCommand.LowerCase();
     if (!aCommand.IsAscii())
     {
-      di << "Unexpected argument: #" << aArgIndex - 1 << " , "
+      di << "Unexpected argument: #" << anArgIndex - 1 << " , "
          << "should be an array element: 'v', 'b', 'e' \n";
       break;
     }
@@ -3633,7 +3742,7 @@ static int VDrawPArray (Draw_Interpretor& di, Standard_Integer argc, const char*
       hasVertex = Standard_True;
     }
 
-    anArgsArray->SetValue (anArgIndex - 2, aCommand);
+    anArgsArray->SetValue (anArgIndex - aLowerArg, aCommand);
   }
 
   if (!hasVertex)
@@ -3643,17 +3752,23 @@ static int VDrawPArray (Draw_Interpretor& di, Standard_Integer argc, const char*
   }
 
   Handle(Graphic3d_AspectMarker3d)    anAspPoints;
-  if (anArrayType == "points")
+  if (aPrimType == Graphic3d_TOPA_POINTS)
   {
     anAspPoints = new Graphic3d_AspectMarker3d (Aspect_TOM_POINT, Quantity_NOC_YELLOW, 1.0f);
   }
 
   // create primitives array object
-  Handle(MyPArrayObject) aPObject = new MyPArrayObject (anArgsArray, anAspPoints);
-
-  // register the object in map
-  VDisplayAISObject (aName, aPObject);
-
+  if (aPObject.IsNull())
+  {
+    // register the object in map
+    aPObject = new MyPArrayObject (aPrimType, anArgsArray, anAspPoints);
+    VDisplayAISObject (aName, aPObject);
+  }
+  else
+  {
+    aPObject->Init (aPrimType, anArgsArray, anAspPoints, Standard_True);
+    ViewerTest::CurrentView()->Redraw();
+  }
   return 0;
 }
 
@@ -6449,10 +6564,11 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
   theCommands.Add("vdrawparray",
                 "vdrawparray name TypeOfArray={points|segments|polylines|triangles"
       "\n\t\t:                                |trianglefans|trianglestrips|quads|quadstrips|polygons}"
+      "\n\t\t:              [-deinterleaved|-mutable]"
       "\n\t\t:              [vertex={'v' x y z [normal={'n' nx ny nz}] [color={'c' r g b}] [texel={'t' tx ty}]]"
       "\n\t\t:              [bound= {'b' nbVertices [bound_color={'c' r g b}]]"
       "\n\t\t:              [edge=  {'e' vertexId]"
-      "\n\t\t:              [-shape shapeName]"
+      "\n\t\t:              [-shape shapeName] [-patch]"
       "\n\t\t: Commands create an Interactive Object for specified Primitive Array definition (Graphic3d_ArrayOfPrimitives)"
       "\n\t\t: with the main purpose is covering various combinations by tests",
     __FILE__,VDrawPArray,group);
index b386a01..fe851c4 100755 (executable)
@@ -9,7 +9,7 @@ puts ""
 set BugNumber OCC23186
 
 vinit
-vdrawparray a points 0 v 0 0 0 v 0 0 10 v 0 10 10 v 0 10 0
+vdrawparray a points v 0 0 0 v 0 0 10 v 0 10 10 v 0 10 0
 vfit
 
 checkcolor 321 2 1 1 0
index fdf76f4..5e0216b 100755 (executable)
@@ -56,108 +56,110 @@ set limit_y 3
 # this procedure is internal and will be removed at the end of the script
 # generate points for primitive
 proc generate_points {x y z r g b} {
-       # define top plane points
-       global pts01 pts02 pts03 pts04 pts05 pts06
-       set pts01 "v [expr "$x-5"] [expr "$y+5"] [expr "$z"]  n 0 0 -1 c $r $g $b"
-       set pts02 "v [expr "$x  "] [expr "$y+5"] [expr "$z"]  n 0 0 -1 c $r $g $b"
-       set pts03 "v [expr "$x  "] [expr "$y "] [expr "$z"]  n 0 0 -1 c $r $g $b"
-       set pts04 "v [expr "$x+5"] [expr "$y "] [expr "$z"]  n 0 0 -1 c $r $g $b"
-       set pts05 "v [expr "$x-5"] [expr "$y-5"] [expr "$z"]  n 0 0 -1 c $r $g $b"
-       set pts06 "v [expr "$x  "] [expr "$y-5"] [expr "$z"]  n 0 0 -1 c $r $g $b"
+  # define top plane points
+  global pts01 pts02 pts03 pts04 pts05 pts06
+  set pts01 "v [expr "$x-5"] [expr "$y+5"] [expr "$z"]  n 0 0 -1 c $r $g $b"
+  set pts02 "v [expr "$x  "] [expr "$y+5"] [expr "$z"]  n 0 0 -1 c $r $g $b"
+  set pts03 "v [expr "$x  "] [expr "$y "] [expr "$z"]  n 0 0 -1 c $r $g $b"
+  set pts04 "v [expr "$x+5"] [expr "$y "] [expr "$z"]  n 0 0 -1 c $r $g $b"
+  set pts05 "v [expr "$x-5"] [expr "$y-5"] [expr "$z"]  n 0 0 -1 c $r $g $b"
+  set pts06 "v [expr "$x  "] [expr "$y-5"] [expr "$z"]  n 0 0 -1 c $r $g $b"
 }
 
 # this procedure is internal and will be removed at the end of the script
 # check pixels of primitive
 proc check_primitive {name1 r g b args} {
-       global limit_x limit_y view_width view_height
-       # show only primitive that we interested in to test
-       vdonly $name1 $args
-       vtop
-       vfit
-       
-       # move cursor not to select shape
-       vmoveto 0 0
-       vmoveto 0 0
-       
-       # test pixels in a top left corner
-       set TestPassed 0
-       set HasPixel 0
-       for {set i 0} {$i < $limit_x} {incr i} {
-               for {set j 0} {$j < $limit_y} {incr j} {
-                       if { "[vreadpixel $i $j rgb]" == "$r $g $b" } {
-                               set HasPixel 1
-                       }
-               }
-       }
-       if { $HasPixel == 1 } { 
-               set TestPassed [expr $TestPassed + 1]
-       } else {
-               set TestPassed 0
-       }
-
-       # test pixels in bottom left corner
-       set HasPixel 1
-       for {set i 0} {$i < $limit_x} {incr i} {
-               for {set j 0} {$j < $limit_y} {incr j} {
-                       set coord_y [expr $view_height-$j]
-                       if { "[vreadpixel $i $coord_y rgb]" == "$r $g $b" } {
-                               set HasPixel 1
-                       }
-               }
-       }
-       if { $HasPixel == 1 } { 
-               set TestPassed [expr $TestPassed + 1]
-       } else {
-               set TestPassed 0
-       }
-       
-       # test pixels in center right corner
-       set HasPixel 1
-       for {set i 0} {$i < $limit_x} {incr i} {
-               for {set j 0} {$j < $limit_y} {incr j} {
-                       set coord_x [expr ($view_width-$limit_y) + $i]
-                       set coord_y [expr ($view_height-$limit_y)/2 + $j]
-                       if { "[vreadpixel $coord_x $coord_y rgb]" == "$r $g $b" } {
-                               set HasPixel 1
-                       }
-               }
-       }
-       if { $HasPixel == 1 } { 
-               set TestPassed [expr $TestPassed + 1]
-       } else {
-               set TestPassed 0
-       }
-       
-       # test pixels in center left corner (shouldn't be anything)
-       set HasPixel 0
-       for {set i 0} {$i < $limit_x} {incr i} {
-               for {set j 0} {$j < $limit_y} {incr j} {
-                       set coord_x [expr $view_width/4 + $i]
-                       set coord_y [expr ($view_height-$limit_y)/2 + $j]
-                       if { "[vreadpixel $coord_x $coord_y rgb]" == "$r $g $b" } {
-                               set HasPixel 1
-                       }
-               }
-       }
-       if { $HasPixel == 1 } { 
-               set TestPassed 0
-       } else {
-               set TestPassed [expr $TestPassed + 1]
-       }
-
-       # show all primitives
-       vdisplayall
-       vtop
-       vfit
-       
-       # return a result
-       if { ${TestPassed} == 4 } {
+  global limit_x limit_y view_width view_height
+  # show only primitive that we interested in to test
+  vdonly $name1 $args
+  vtop
+  vfit
+
+  # move cursor not to select shape
+  vmoveto 0 0
+  vmoveto 0 0
+
+  # test pixels in a top left corner
+  set TestPassed 0
+  set HasPixel 0
+  for {set i 0} {$i < $limit_x} {incr i} {
+    for {set j 0} {$j < $limit_y} {incr j} {
+      if { "[vreadpixel $i $j rgb]" == "$r $g $b" } {
+        set HasPixel 1
+      }
+    }
+  }
+  if { $HasPixel == 1 } {
+    set TestPassed [expr $TestPassed + 1]
+  } else {
+    set TestPassed 0
+  }
+
+  # test pixels in bottom left corner
+  set HasPixel 1
+  for {set i 0} {$i < $limit_x} {incr i} {
+    for {set j 0} {$j < $limit_y} {incr j} {
+      set coord_y [expr $view_height-$j]
+      if { "[vreadpixel $i $coord_y rgb]" == "$r $g $b" } {
+        set HasPixel 1
+      }
+    }
+  }
+  if { $HasPixel == 1 } {
+    set TestPassed [expr $TestPassed + 1]
+  } else {
+    set TestPassed 0
+  }
+
+  # test pixels in center right corner
+  set HasPixel 1
+  for {set i 0} {$i < $limit_x} {incr i} {
+    for {set j 0} {$j < $limit_y} {incr j} {
+      set coord_x [expr ($view_width-$limit_y) + $i]
+      set coord_y [expr ($view_height-$limit_y)/2 + $j]
+      if { "[vreadpixel $coord_x $coord_y rgb]" == "$r $g $b" } {
+        set HasPixel 1
+      }
+    }
+  }
+  if { $HasPixel == 1 } {
+    set TestPassed [expr $TestPassed + 1]
+  } else {
+    set TestPassed 0
+  }
+
+  # test pixels in center left corner (shouldn't be anything)
+  set HasPixel 0
+  for {set i 0} {$i < $limit_x} {incr i} {
+    for {set j 0} {$j < $limit_y} {incr j} {
+      set coord_x [expr $view_width/4 + $i]
+      set coord_y [expr ($view_height-$limit_y)/2 + $j]
+      if { "[vreadpixel $coord_x $coord_y rgb]" == "$r $g $b" } {
+        set HasPixel 1
+      }
+    }
+  }
+  if { $HasPixel == 1 } {
+    set TestPassed 0
+  } else {
+    set TestPassed [expr $TestPassed + 1]
+  }
+
+  # show all primitives
+  vdisplayall
+  vtop
+  vfit
+
+  # return a result
+  if { ${TestPassed} == 4 } {
       return 1
-       } else {
+  } else {
       return 0
-       }
+  }
 }
 
+vclose ALL
+
 # ### THIS IS THE HEAD LOOP OF THE TEST ####################
 # During this test primitives are created and displayed
 # with commands vdrawparray, and verified for consistency
@@ -167,170 +169,144 @@ proc check_primitive {name1 r g b args} {
 # The iteration loop is intended to check primitives with
 # "vertex buffer objects" turned off (vbo_enable = 0) and
 # turned on (vbo_enable = 1)
-
 for {set vbo_enable 0} {$vbo_enable < 2} {incr vbo_enable} {
-       vinit
-       if { $vbo_enable == 0 } { 
-           vvbo 0
-           puts "TEST WITH VBO is OFF"
-       }
-       if { $vbo_enable == 1 } {
-           vvbo 1
-           puts "TEST WITH VBO is ON"
-       }
-       
-##     vinit
-       veraseall
-       vclear
-
-       # this points are only to simplify visiual check of dumped image
-       vpoint point1   65 0 0
-       vpoint point2 -145 0 0
-
-       # ****************************** Graphic3d_ArrayOfPoints ****************************** #
-       puts "Graphic3d_ArrayOfPoints: TEST"
-       # 
-       # 1: verticies
-       #
-       generate_points 60 0 0   $colorY_R $colorY_G $colorY_B
-       eval vdrawparray pt01 points $vbo_enable $pts01 $pts02 $pts03 $pts04 $pts05 $pts06
-
-       # ****************************** Graphic3d_ArrayOfSegments ****************************** #
-       puts "Graphic3d_ArrayOfSegments: TEST"
-       #
-       # 1: verticies
-       #
-       generate_points 50 0 0   $colorY_R $colorY_G $colorY_B
-       eval vdrawparray seg01 segments $vbo_enable $pts02 $pts01 $pts01 $pts03 $pts03 $pts05 $pts05 $pts06 $pts06 $pts04 $pts04 $pts02
-       #
-       # 2: edges
-       #
-       generate_points 40 0 0   $colorR_R $colorR_G $colorR_B
-       eval vdrawparray seg02 segments $vbo_enable $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 e 1 e 2 e 2 e 4 e 4 e 6 e 6 e 5 e 5 e 3 e 3 e 1
-
-       # ****************************** Graphic3d_ArrayOfPolylines ****************************** #
-       puts "Graphic3d_ArrayOfPolylines: TEST"
-       #
-       # 1: verticies
-       #
-       generate_points 30 0 0   $colorY_R $colorY_G $colorY_B
-       eval vdrawparray pline01 polylines $vbo_enable $pts02 $pts01 $pts03 $pts05 $pts06 $pts04 $pts02
-       #
-       # 2: edges
-       #
-       generate_points 20 0 0   $colorR_R $colorR_G $colorR_B
-       eval vdrawparray pline02 polylines $vbo_enable $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 e 2 e 4 e 6 e 5 e 3 e 1 e 2
-       #
-       # 3: bounds
-       #
-       generate_points 10 0 0   $colorY_R $colorY_G $colorY_B
-       eval vdrawparray pline03 polylines $vbo_enable ( b 3 ( $pts02 $pts01 $pts03 )), ( b 4 ( $pts03 $pts05 $pts06 $pts04 )), ( b 2 ( $pts04 $pts02 ))
-       #
-       # 4: verticies, bounds and edges
-       #
-       generate_points 0 0 0   $colorR_R $colorR_G $colorR_B
-       eval vdrawparray pline04 polylines $vbo_enable $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 ( b 4 ( e 2 e 1 e 3 e 5 )), ( b 4 ( e 5 e 6 e 4 e 2 ))
-
-       # ****************************** Graphic3d_ArrayOfTriangles ****************************** #
-       puts "Graphic3d_ArrayOfTriangles: TEST"
-       #
-       # 1: verticies 
-       #
-       generate_points   -10 0 0   $colorB_R $colorB_G $colorB_B
-       eval vdrawparray t01 triangles $vbo_enable ( $pts03 $pts02 $pts01 ) , ( $pts03 $pts04 $pts02 ) , ( $pts04 $pts03 $pts06 ) , ( $pts06 $pts03 $pts05 )
-       #
-       # 2: by edges
-       #
-       generate_points -20 0 0   $colorG_R $colorG_G $colorG_B
-       eval vdrawparray t02 triangles $vbo_enable $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 e 6 e 3 e 5 e 6 e 4 e 3 e 1 e 3 e 2 e 2 e 3 e 4
-
-       # ****************************** Graphic3d_ArrayOfTriangleFans ****************************** #
-       puts "Graphic3d_ArrayOfTriangleFans: TEST"
-       #
-       # 1: verticies
-       #
-       generate_points -30 0 0    $colorB_R $colorB_G $colorB_B
-       eval vdrawparray tfan01 trianglefans $vbo_enable ( $pts02 $pts01 $pts03 $pts04 )
-       eval vdrawparray tfan02 trianglefans $vbo_enable ( $pts03 $pts05 $pts06 $pts04 )
-       #
-       # 2: bounds and verticies
-       #
-       generate_points -40 0 0   $colorG_R $colorG_G $colorG_B
-       eval vdrawparray tfan03 trianglefans $vbo_enable ( b 4 ( $pts02 $pts01 $pts03 $pts04 )), ( b 4 ( $pts03 $pts05 $pts06 $pts04 ))
-
-       # ****************************** Graphic3d_ArrayOfTriangleStrips ****************************** #
-       puts "Graphic3d_ArrayOfTriangleStrips: TEST"
-       #
-       # 1: verticies
-       #
-       generate_points -50 0 0    $colorB_R $colorB_G $colorB_B
-       eval vdrawparray tstrip01 trianglestrips $vbo_enable ( $pts06 $pts04 $pts03 $pts02 $pts01 )
-       eval vdrawparray tstrip02 trianglestrips $vbo_enable ( $pts03 $pts05 $pts06 )
-       #
-       # 2: bounds and verticies
-       #
-       generate_points -60 0 0    $colorG_R $colorG_G $colorG_B
-       eval vdrawparray tstrip03 trianglestrips $vbo_enable ( b 5 ( $pts06 $pts04 $pts03 $pts02 $pts01 )) , ( b 3 ( $pts03 $pts05 $pts06 ))
-
-       # ****************************** Graphic3d_ArrayOfQuadrangles ****************************** #
-       puts "Graphic3d_ArrayOfQuadrangles: TEST"
-       #
-       # 1: verticies
-       #
-       generate_points -70 0 0    $colorB_R $colorB_G $colorB_B
-       eval vdrawparray q01 quads $vbo_enable ( $pts01 $pts03 $pts04 $pts02 )
-       eval vdrawparray q02 quads $vbo_enable ( $pts03 $pts05 $pts06 $pts04 )
-       #
-       # 2: verticies and edges
-       #
-       generate_points -80 0 0    $colorG_R $colorG_G $colorG_B
-       eval vdrawparray q03 quads $vbo_enable $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 e 1 e 3 e 4 e 2 e 3 e 5 e 6 e 4
-
-       # ****************************** Graphic3d_ArrayOfQuadrangleStrips ****************************** #
-       puts "Graphic3d_ArrayOfQuadrangleStrips: TEST"
-       #
-       # 1: verticies
-       #
-       generate_points -90 0 0    $colorB_R $colorB_G $colorB_B
-       eval vdrawparray qstrips01 quadstrips $vbo_enable ( $pts02 $pts01 $pts04 $pts03 $pts06 $pts05 )
-       #
-       # 2: verticies and edges
-       #
-       generate_points -100 0 0    $colorG_R $colorG_G $colorG_B
-       eval vdrawparray qstrips02 quadstrips $vbo_enable ( b 4 ( $pts02 $pts01 $pts04 $pts03 )) , ( b 4 ( $pts04 $pts03 $pts06 $pts05 ))
-
-       # ****************************** Graphic3d_ArrayOfPolygons ****************************** #
-       puts "Graphic3d_ArrayOfPolygons: TEST"
-       #
-       # 1: verticies
-       #
-       generate_points -110 0 0    $colorB_R $colorB_G $colorB_B
-       eval vdrawparray poly01 polygons $vbo_enable ( $pts04 $pts02 $pts01 $pts03 $pts05 $pts06 )
-       #
-       # 2: verticies and bounds
-       #
-       generate_points -120 0 0   $colorG_R $colorG_G $colorG_B
-       eval vdrawparray poly02 polygons $vbo_enable ( b 5 ( $pts04 $pts02 $pts01 $pts03 $pts06 )) , ( b 3 ( $pts06 $pts03 $pts05 ))
-       #
-       # 3: verticies and edges
-       #
-       generate_points -130 0 0   $colorB_R $colorB_G $colorB_B
-       eval vdrawparray poly03 polygons $vbo_enable $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 e 4 e 2 e 1 e 3 e 5 e 6
-       #
-       # 4: vertices, bounds and edges
-       #
-
-       generate_points -140 0 0   $colorG_R $colorG_G $colorG_B
-       eval vdrawparray poly04 polygons $vbo_enable $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 ( b 5 ( e 4 e 2 e 1 e 3 e 6 )), ( b 3 ( e 6 e 3 e 5 ))
-       
-       vtop
-       vfit
-       
-       # dump resulted image
-#        vfeedback ;# fails on Intel HD 4600 with FPE signals armed
-       if { $vbo_enable == 0 } { vdump ${imagedir}/$ImageName1 }
-       if { $vbo_enable == 1 } { vdump ${imagedir}/$ImageName2 }
+  for {set isNonInterleaved 0} {$isNonInterleaved < 2} {incr isNonInterleaved} {
+    vclear
+    vinit View1
+    vtop
+    vvbo $vbo_enable
+    if { $vbo_enable == 0 } {
+      puts "TEST WITH VBO is OFF"
+    } else {
+      puts "TEST WITH VBO is ON"
+    }
+    set aParams ""
+    if { $isNonInterleaved == 1 } { set aParams "-deinterleaved" }
+
+    # this points are only to simplify visiual check of dumped image
+    vpoint point1   65 0 0
+    vpoint point2 -145 0 0
+
+    # ****************************** Graphic3d_ArrayOfPoints ****************************** #
+    puts "Graphic3d_ArrayOfPoints: TEST"
+    generate_points 60 0 0   $colorY_R $colorY_G $colorY_B
+    eval vdrawparray pt01 points {*}$aParams $pts01 $pts02 $pts03 $pts04 $pts05 $pts06
+
+    # ****************************** Graphic3d_ArrayOfSegments ****************************** #
+    puts "Graphic3d_ArrayOfSegments: TEST"
+
+    # 1: no indexes
+    generate_points 50 0 0   $colorY_R $colorY_G $colorY_B
+    eval vdrawparray seg01 segments {*}$aParams $pts02 $pts01 $pts01 $pts03 $pts03 $pts05 $pts05 $pts06 $pts06 $pts04 $pts04 $pts02
+
+    # 2: indexes
+    generate_points 40 0 0   $colorR_R $colorR_G $colorR_B
+    eval vdrawparray seg02 segments {*}$aParams $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 e 1 e 2 e 2 e 4 e 4 e 6 e 6 e 5 e 5 e 3 e 3 e 1
+
+    # ****************************** Graphic3d_ArrayOfPolylines ****************************** #
+    puts "Graphic3d_ArrayOfPolylines: TEST"
+
+    # 1: no indexes
+    generate_points 30 0 0   $colorY_R $colorY_G $colorY_B
+    eval vdrawparray pline01 polylines {*}$aParams $pts02 $pts01 $pts03 $pts05 $pts06 $pts04 $pts02
+
+    # 2: indexes
+    generate_points 20 0 0   $colorR_R $colorR_G $colorR_B
+    eval vdrawparray pline02 polylines {*}$aParams $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 e 2 e 4 e 6 e 5 e 3 e 1 e 2
+
+    # 3: bounds
+    generate_points 10 0 0   $colorY_R $colorY_G $colorY_B
+    eval vdrawparray pline03 polylines {*}$aParams ( b 3 ( $pts02 $pts01 $pts03 )), ( b 4 ( $pts03 $pts05 $pts06 $pts04 )), ( b 2 ( $pts04 $pts02 ))
+
+    # 4: bounds and indexes
+    generate_points 0 0 0   $colorR_R $colorR_G $colorR_B
+    eval vdrawparray pline04 polylines {*}$aParams $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 ( b 4 ( e 2 e 1 e 3 e 5 )), ( b 4 ( e 5 e 6 e 4 e 2 ))
+
+    # ****************************** Graphic3d_ArrayOfTriangles ****************************** #
+    puts "Graphic3d_ArrayOfTriangles: TEST"
+
+    # 1: no indexes
+    generate_points -10 0 0   $colorB_R $colorB_G $colorB_B
+    eval vdrawparray t01 triangles {*}$aParams ( $pts03 $pts02 $pts01 ) , ( $pts03 $pts04 $pts02 ) , ( $pts04 $pts03 $pts06 ) , ( $pts06 $pts03 $pts05 )
+
+    # 2: indexes
+    generate_points -20 0 0   $colorG_R $colorG_G $colorG_B
+    eval vdrawparray t02 triangles {*}$aParams $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 e 6 e 3 e 5 e 6 e 4 e 3 e 1 e 3 e 2 e 2 e 3 e 4
+
+    # ****************************** Graphic3d_ArrayOfTriangleFans ****************************** #
+    puts "Graphic3d_ArrayOfTriangleFans: TEST"
+
+    # 1: no bounds
+    generate_points -30 0 0    $colorB_R $colorB_G $colorB_B
+    eval vdrawparray tfan01 trianglefans {*}$aParams ( $pts02 $pts01 $pts03 $pts04 )
+    eval vdrawparray tfan02 trianglefans {*}$aParams ( $pts03 $pts05 $pts06 $pts04 )
+
+    # 2: bounds
+    generate_points -40 0 0   $colorG_R $colorG_G $colorG_B
+    eval vdrawparray tfan03 trianglefans {*}$aParams ( b 4 ( $pts02 $pts01 $pts03 $pts04 )), ( b 4 ( $pts03 $pts05 $pts06 $pts04 ))
+
+    # ****************************** Graphic3d_ArrayOfTriangleStrips ****************************** #
+    puts "Graphic3d_ArrayOfTriangleStrips: TEST"
+
+    # 1: no bounds
+    generate_points -50 0 0    $colorB_R $colorB_G $colorB_B
+    eval vdrawparray tstrip01 trianglestrips {*}$aParams ( $pts06 $pts04 $pts03 $pts02 $pts01 )
+    eval vdrawparray tstrip02 trianglestrips {*}$aParams ( $pts03 $pts05 $pts06 )
+
+    # 2: bounds
+    generate_points -60 0 0    $colorG_R $colorG_G $colorG_B
+    eval vdrawparray tstrip03 trianglestrips {*}$aParams ( b 5 ( $pts06 $pts04 $pts03 $pts02 $pts01 )) , ( b 3 ( $pts03 $pts05 $pts06 ))
+
+    # ****************************** Graphic3d_ArrayOfQuadrangles ****************************** #
+    puts "Graphic3d_ArrayOfQuadrangles: TEST"
+
+    # 1: no indexes
+    generate_points -70 0 0    $colorB_R $colorB_G $colorB_B
+    eval vdrawparray q01 quads {*}$aParams ( $pts01 $pts03 $pts04 $pts02 )
+    eval vdrawparray q02 quads {*}$aParams ( $pts03 $pts05 $pts06 $pts04 )
+
+    # 2: indexes
+    generate_points -80 0 0    $colorG_R $colorG_G $colorG_B
+    eval vdrawparray q03 quads {*}$aParams $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 e 1 e 3 e 4 e 2 e 3 e 5 e 6 e 4
+
+    # ****************************** Graphic3d_ArrayOfQuadrangleStrips ****************************** #
+    puts "Graphic3d_ArrayOfQuadrangleStrips: TEST"
+
+    # 1: no bounds
+    generate_points -90 0 0    $colorB_R $colorB_G $colorB_B
+    eval vdrawparray qstrips01 quadstrips {*}$aParams ( $pts02 $pts01 $pts04 $pts03 $pts06 $pts05 )
+
+    # 2: bounds
+    generate_points -100 0 0    $colorG_R $colorG_G $colorG_B
+    eval vdrawparray qstrips02 quadstrips {*}$aParams ( b 4 ( $pts02 $pts01 $pts04 $pts03 )) , ( b 4 ( $pts04 $pts03 $pts06 $pts05 ))
+
+    # ****************************** Graphic3d_ArrayOfPolygons ****************************** #
+    puts "Graphic3d_ArrayOfPolygons: TEST"
+
+    # 1: no indexes
+    generate_points -110 0 0    $colorB_R $colorB_G $colorB_B
+    eval vdrawparray poly01 polygons {*}$aParams ( $pts04 $pts02 $pts01 $pts03 $pts05 $pts06 )
+
+    # 2: bounds
+    generate_points -120 0 0   $colorG_R $colorG_G $colorG_B
+    eval vdrawparray poly02 polygons {*}$aParams ( b 5 ( $pts04 $pts02 $pts01 $pts03 $pts06 )) , ( b 3 ( $pts06 $pts03 $pts05 ))
+
+    # 3: indexes
+    generate_points -130 0 0   $colorB_R $colorB_G $colorB_B
+    eval vdrawparray poly03 polygons {*}$aParams $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 e 4 e 2 e 1 e 3 e 5 e 6
 
+    # 4: bounds and indexes
+    generate_points -140 0 0   $colorG_R $colorG_G $colorG_B
+    eval vdrawparray poly04 polygons {*}$aParams $pts01 $pts02 $pts03 $pts04 $pts05 $pts06 ( b 5 ( e 4 e 2 e 1 e 3 e 6 )), ( b 3 ( e 6 e 3 e 5 ))
+
+    # dump resulted image
+    set anImgName "${casename}"
+    if { $vbo_enable == 0 } { set anImgName "${anImgName}_vbooff" }
+    if { $vbo_enable == 1 } { set anImgName "${anImgName}_vboon" }
+    if { $isNonInterleaved == 1 } { set anImgName "${anImgName}_noninter" }
+    vfit
+    vdump ${imagedir}/${anImgName}.png
+  }
 }
 
 # delete internal procedures
@@ -340,11 +316,7 @@ rename check_primitive ""
 checkcolor 200 200 $colorG_R $colorG_G $colorG_B
 checkcolor 220 200 $colorB_R $colorB_G $colorB_B
 if { $stat == 1 } {
-    puts "BUG OK ${BUGNUMBER}"
+  puts "BUG OK ${BUGNUMBER}"
 } else {
-    puts "BUG FAULTY ${BUGNUMBER}"
+  puts "BUG FAULTY ${BUGNUMBER}"
 }
-
-checkview -screenshot -3d -path ${imagedir}/${test_image}.png
-
-
index 8f0b3cc..0e5e324 100644 (file)
@@ -7,15 +7,16 @@ puts "Bound color in the primitive array do not work when displayed using VBO"
 set x_coord 321
 set y_coord 200
 
-vinit
+vclear
+vinit View1
 vvbo 0
-vdrawparray pl01 polylines 0 v 0 0 0 v 0 10 0 v 0 10 10 v 0 0 0 b 4 c 1 0 0
+vdrawparray pl01 polylines v 0 0 0 v 0 10 0 v 0 10 10 v 0 0 0 b 4 c 1 0 0
 vfit
 checkcolor $x_coord $y_coord 1 0 0
 
 vclear
 vvbo 1
-vdrawparray pl01 polylines 0 v 0 0 0 v 0 10 0 v 0 10 10 v 0 0 0 b 4 c 1 0 0
+vdrawparray pl01 polylines v 0 0 0 v 0 10 0 v 0 10 10 v 0 0 0 b 4 c 1 0 0
 checkcolor $x_coord $y_coord 1 0 0
 
 checkview -screenshot -3d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/vis/bug30076 b/tests/bugs/vis/bug30076
new file mode 100644 (file)
index 0000000..8575bd8
--- /dev/null
@@ -0,0 +1,18 @@
+puts "============="
+puts "0030076: Visualization, TKV3d - API to update certain vertex attribute(s) without recomputing a presentation"
+puts "============="
+
+set c1 {c 1 0 0}
+set c2 {c 0 0 1}
+
+pload VISUALIZATION
+
+vclear
+vinit View1
+vdrawparray a        triangles -deinterleaved -mutable v 10 0 0 {*}$c1 v 11 0 0 {*}$c1 v 11 1 0 {*}$c1 v 11 1 0 {*}$c2 v 10 1 0 {*}$c2 v 10 0 0 {*}$c2
+vfit
+vdump $imagedir/${casename}_1.png
+vdrawparray a -patch triangles -deinterleaved -mutable v 10 0 0 {*}$c2 v 11 0 0 {*}$c2 v 11 1 0 {*}$c2 v 11 1 0 {*}$c1 v 10 1 0 {*}$c1 v 10 0 0 {*}$c1
+if { [vreadpixel 200 150 rgb name] != "RED"   } { puts "Error: array was not updated" }
+if { [vreadpixel 200 250 rgb name] != "BLUE1" } { puts "Error: array was not updated" }
+vdump $imagedir/${casename}_2.png