diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index c0f5472815..f9df238ce0 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -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 diff --git a/src/Graphic3d/Graphic3d_ArrayFlags.hxx b/src/Graphic3d/Graphic3d_ArrayFlags.hxx index f2e70b9921..cb2da070ae 100644 --- a/src/Graphic3d/Graphic3d_ArrayFlags.hxx +++ b/src/Graphic3d/Graphic3d_ArrayFlags.hxx @@ -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 diff --git a/src/Graphic3d/Graphic3d_ArrayOfPrimitives.cxx b/src/Graphic3d/Graphic3d_ArrayOfPrimitives.cxx index 4be17047b7..42c3574890 100644 --- a/src/Graphic3d/Graphic3d_ArrayOfPrimitives.cxx +++ b/src/Graphic3d/Graphic3d_ArrayOfPrimitives.cxx @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include @@ -42,6 +44,47 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangles, Graphic3d_ArrayOfP IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ArrayOfQuadrangleStrips, Graphic3d_ArrayOfPrimitives) 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 (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(myAttribs->AttributeOffset (anAttribIter)); - break; - } - case Graphic3d_TOA_UV: - { - myVTex = static_cast(myAttribs->AttributeOffset (anAttribIter)); - break; - } - case Graphic3d_TOA_COLOR: - { - myVCol = static_cast(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(); diff --git a/src/Graphic3d/Graphic3d_ArrayOfPrimitives.hxx b/src/Graphic3d/Graphic3d_ArrayOfPrimitives.hxx index 86a79ae8c0..7cc3d5424d 100644 --- a/src/Graphic3d/Graphic3d_ArrayOfPrimitives.hxx +++ b/src/Graphic3d/Graphic3d_ArrayOfPrimitives.hxx @@ -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 (theIndex - 1); + Graphic3d_Vec3& aVec = *reinterpret_cast (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(myAttribs->changeValue (theIndex - 1) + size_t(myVCol)); + Graphic3d_Vec4ub* aColorPtr = reinterpret_cast(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(myAttribs->changeValue (theIndex - 1) + size_t(myVCol)); + Graphic3d_Vec4ub* aColorPtr = reinterpret_cast(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(myAttribs->changeValue (theIndex - 1) + size_t(myVCol)) = theColor32; + *reinterpret_cast(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(myAttribs->changeValue (theIndex - 1) + size_t(myVNor)); + Graphic3d_Vec3& aVec = *reinterpret_cast(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(myAttribs->changeValue (theIndex - 1) + size_t(myVTex)); + Graphic3d_Vec2& aVec = *reinterpret_cast(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 (theRank - 1); + const Graphic3d_Vec3& aVec = *reinterpret_cast (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(myAttribs->value (theIndex - 1) + size_t(myVCol)); + Standard_OutOfRange_Raise_if (myColData == NULL || theIndex < 1 || theIndex > myAttribs->NbElements, "BAD VERTEX index"); + theColor = *reinterpret_cast(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(myAttribs->value (theRank - 1) + size_t(myVCol)); + const Graphic3d_Vec4ub& aColor = *reinterpret_cast(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(myAttribs->value (theRank - 1) + size_t(myVCol)); + theColor = *reinterpret_cast(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(myAttribs->value (theRank - 1) + size_t(myVNor)); + const Graphic3d_Vec3& aVec = *reinterpret_cast(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(myAttribs->value (theRank - 1) + size_t(myVTex)); + const Graphic3d_Vec2& aVec = *reinterpret_cast(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 index 0000000000..b141e808dc --- /dev/null +++ b/src/Graphic3d/Graphic3d_AttribBuffer.cxx @@ -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 + +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 index 0000000000..5705c9ea26 --- /dev/null +++ b/src/Graphic3d/Graphic3d_AttribBuffer.hxx @@ -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 + +//! 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 diff --git a/src/Graphic3d/Graphic3d_Buffer.cxx b/src/Graphic3d/Graphic3d_Buffer.cxx index 6d76b84778..2d46aef4f4 100644 --- a/src/Graphic3d/Graphic3d_Buffer.cxx +++ b/src/Graphic3d/Graphic3d_Buffer.cxx @@ -12,9 +12,10 @@ // commercial license or contractual agreement. #include -#include #include +#include 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) diff --git a/src/Graphic3d/Graphic3d_Buffer.hxx b/src/Graphic3d/Graphic3d_Buffer.hxx index 455c8ff85a..103d185298 100644 --- a/src/Graphic3d/Graphic3d_Buffer.hxx +++ b/src/Graphic3d/Graphic3d_Buffer.hxx @@ -14,9 +14,11 @@ #ifndef _Graphic3d_Buffer_HeaderFile #define _Graphic3d_Buffer_HeaderFile +#include #include #include #include +#include //! 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(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() { @@ -212,6 +294,27 @@ public: return Init (theNbElems, &theAttribs.First(), theAttribs.Size()); } +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 diff --git a/src/Graphic3d/Graphic3d_BufferRange.hxx b/src/Graphic3d/Graphic3d_BufferRange.hxx new file mode 100644 index 0000000000..3a90f7ac5e --- /dev/null +++ b/src/Graphic3d/Graphic3d_BufferRange.hxx @@ -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 +#include + +//! 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 diff --git a/src/Graphic3d/Graphic3d_Group.cxx b/src/Graphic3d/Graphic3d_Group.cxx index f19c62c647..42aba0dc8e 100644 --- a/src/Graphic3d/Graphic3d_Group.cxx +++ b/src/Graphic3d/Graphic3d_Group.cxx @@ -314,45 +314,45 @@ void Graphic3d_Group::AddPrimitiveArray (const Graphic3d_TypeOfPrimitiveArray th myContainsFacet = true; } - if (theToEvalMinMax) + if (!theToEvalMinMax) { - const Standard_Integer aNbVerts = theAttribs->NbElements; - for (Standard_Integer anAttribIter = 0; anAttribIter < theAttribs->NbAttributes; ++anAttribIter) - { - const Graphic3d_Attribute& anAttrib = theAttribs->Attribute (anAttribIter); - if (anAttrib.Id != Graphic3d_TOA_POS) - { - continue; - } + Update(); + return; + } - const size_t anOffset = theAttribs->AttributeOffset (anAttribIter); - switch (anAttrib.DataType) + 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) + { + case Graphic3d_TOD_VEC2: + { + 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(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(theAttribs->value (aVertIter) + anOffset); - myBounds.Add (Graphic3d_Vec4 (aVert.x(), aVert.y(), aVert.z(), 1.0f)); - } - break; - } - default: break; + const Graphic3d_Vec2& aVert = *reinterpret_cast(aDataPtr + anAttribStride * aVertIter); + 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(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 index 0000000000..4bcfccd2fe --- /dev/null +++ b/src/Graphic3d/Graphic3d_MutableIndexBuffer.hxx @@ -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 + +//! 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 diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index 09538a76e8..8986de7bb6 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -68,20 +68,11 @@ namespace template 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(*myAttribs); break; } - // 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_Boolean isAttribMutable = myAttribs->IsMutable(); + const Standard_Boolean isAttribInterleaved = myAttribs->IsInterleaved(); + if (myAttribs->NbElements != myAttribs->NbMaxElements() + && myIndices.IsNull() + && (!isAttribInterleaved || isAttribMutable)) { - TCollection_ExtendedString aMsg; - aMsg += "VBO creation for Primitive Array has failed for "; - aMsg += myAttribs->NbElements; - aMsg += " vertices. Out of memory?"; + 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 + 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 = 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 (myIndices->Data())); + isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast (myIndices->Data())); + myVboIndices->SetElemsNb (myIndices->NbElements); + myIndices->Validate(); break; } case 4: { - isOk = myVboIndices->Init (theCtx, 1, myIndices->NbElements, reinterpret_cast (myIndices->Data())); + isOk = myVboIndices->Init (theCtx, 1, aNbIndexes, reinterpret_cast (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; } @@ -349,6 +362,51 @@ Standard_Boolean OpenGl_PrimitiveArray::buildVBO (const Handle(OpenGl_Context)& return Standard_True; } +// ======================================================================= +// 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; diff --git a/src/OpenGl/OpenGl_PrimitiveArray.hxx b/src/OpenGl/OpenGl_PrimitiveArray.hxx index 978af7409b..811b222071 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.hxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.hxx @@ -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; diff --git a/src/OpenGl/OpenGl_VertexBuffer.hxx b/src/OpenGl/OpenGl_VertexBuffer.hxx index 2558a0c3ae..5f259ef7c0 100644 --- a/src/OpenGl/OpenGl_VertexBuffer.hxx +++ b/src/OpenGl/OpenGl_VertexBuffer.hxx @@ -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 { diff --git a/src/OpenGl/OpenGl_VertexBufferCompat.hxx b/src/OpenGl/OpenGl_VertexBufferCompat.hxx index 7106929c27..331dbe6ebb 100644 --- a/src/OpenGl/OpenGl_VertexBufferCompat.hxx +++ b/src/OpenGl/OpenGl_VertexBufferCompat.hxx @@ -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; diff --git a/src/OpenGl/OpenGl_View_Raytrace.cxx b/src/OpenGl/OpenGl_View_Raytrace.cxx index adaeb09ce1..60322e1059 100644 --- a/src/OpenGl/OpenGl_View_Raytrace.cxx +++ b/src/OpenGl/OpenGl_View_Raytrace.cxx @@ -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) - { - const Graphic3d_Attribute& anAttrib = anAttribs->Attribute (anAttribIter); - const size_t anOffset = anAttribs->AttributeOffset (anAttribIter); - if (anAttrib.Id == Graphic3d_TOA_POS) - { - 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 (anAttribs->value (aVertIter) + anOffset)); - } - } - else if (anAttrib.DataType == Graphic3d_TOD_VEC2) - { - for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter) - { - const Standard_ShortReal* aCoords = - reinterpret_cast (anAttribs->value (aVertIter) + anOffset); - aSet->Vertices.push_back (BVH_Vec3f (aCoords[0], aCoords[1], 0.0f)); - } + 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 (anAttribIndex); + if (anAttrib.DataType == Graphic3d_TOD_VEC2 + || anAttrib.DataType == Graphic3d_TOD_VEC3 + || anAttrib.DataType == Graphic3d_TOD_VEC4) + { + for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter) + { + const float* aCoords = reinterpret_cast (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 (anAttribs->value (aVertIter) + anOffset)); - } + aSet->Normals.push_back (*reinterpret_cast (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 (anAttribs->value (aVertIter) + anOffset)); - } + aSet->TexCrds.push_back (*reinterpret_cast (aTexData + anAttribStride * aVertIter)); } } } diff --git a/src/Select3D/Select3D_SensitivePrimitiveArray.cxx b/src/Select3D/Select3D_SensitivePrimitiveArray.cxx index fc0c6ce432..494f2eef98 100644 --- a/src/Select3D/Select3D_SensitivePrimitiveArray.cxx +++ b/src/Select3D/Select3D_SensitivePrimitiveArray.cxx @@ -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; } diff --git a/src/Select3D/Select3D_SensitivePrimitiveArray.hxx b/src/Select3D/Select3D_SensitivePrimitiveArray.hxx index 50e767bf04..851b16304f 100644 --- a/src/Select3D/Select3D_SensitivePrimitiveArray.hxx +++ b/src/Select3D/Select3D_SensitivePrimitiveArray.hxx @@ -268,13 +268,13 @@ protected: //! Auxiliary getter. const Graphic3d_Vec3& getPosVec3 (const Standard_Integer theIndex) const { - return *reinterpret_cast(myVerts->value (theIndex) + myPosOffset); + return *reinterpret_cast(myPosData + myPosStride * theIndex); } //! Auxiliary getter. const Graphic3d_Vec2& getPosVec2 (const Standard_Integer theIndex) const { - return *reinterpret_cast(myVerts->value (theIndex) + myPosOffset); + return *reinterpret_cast(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 diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx index 37e0f34738..68cb3b7082 100644 --- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx +++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx @@ -104,6 +104,7 @@ #include #include #include +#include #include #include #include @@ -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 (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) + else { - aCommand = myArrayDescription->Value (anArgIndex); - aCommand.LowerCase(); - if (!aCommand.IsAscii()) - break; - - // vertex command - if (CheckInputCommand ("v", myArrayDescription, anArgIndex, 3, anArgsCount)) + if (myPArray->Type() != thePrimType + || aVertexNum > myPArray->VertexNumberAllocated() + || aEdgeNum > myPArray->EdgeNumberAllocated() + || aBoundNum > myPArray->BoundNumberAllocated() + || !myPArray->Attributes()->IsMutable() + || (!myPArray->Indices().IsNull() && !myPArray->Indices()->IsMutable())) { - anArray->AddVertex (myArrayDescription->Value (anArgIndex - 3).RealValue(), - myArrayDescription->Value (anArgIndex - 2).RealValue(), - myArrayDescription->Value (anArgIndex - 1).RealValue()); - const Standard_Integer aVertIndex = anArray->VertexNumber(); + 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; + } + } + + Standard_Integer aVertIndex = 0; + for (Standard_Integer anArgIndex = theDesc->Lower(); anArgIndex <= theDesc->Upper(); ) + { + aCommand = theDesc->Value (anArgIndex); + aCommand.LowerCase(); + 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 + else if (CheckInputCommand ("v", theDesc, anArgIndex, 3, anArgsCount)) + { + 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 ("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 ("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 ("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(); + } + + 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; + } + } Standard_Boolean hasVertex = Standard_False; - Handle(TColStd_HArray1OfAsciiString) anArgsArray = new TColStd_HArray1OfAsciiString (0, argc - 2); - anArgsArray->SetValue (0, anArrayType); - - 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") { - di << "Unexpected type of primitives array\n"; + 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") + { + 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); diff --git a/tests/bugs/vis/bug23186 b/tests/bugs/vis/bug23186 index b386a01511..fe851c4e89 100755 --- a/tests/bugs/vis/bug23186 +++ b/tests/bugs/vis/bug23186 @@ -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 diff --git a/tests/bugs/vis/bug23226 b/tests/bugs/vis/bug23226 index fdf76f443d..5e0216b343 100755 --- a/tests/bugs/vis/bug23226 +++ b/tests/bugs/vis/bug23226 @@ -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 - } + global limit_x limit_y view_width view_height + # show only primitive that we interested in to test + vdonly $name1 $args + vtop + vfit - # 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] - } + # move cursor not to select shape + vmoveto 0 0 + vmoveto 0 0 - # show all primitives - vdisplayall - vtop - vfit - - # return a result - if { ${TestPassed} == 4 } { + # 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 + 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 + # 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_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: 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_ArrayOfSegments ****************************** # + puts "Graphic3d_ArrayOfSegments: TEST" - # ****************************** 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 )) + # 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 - # ****************************** 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 + # 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_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_ArrayOfPolylines ****************************** # + puts "Graphic3d_ArrayOfPolylines: TEST" - # ****************************** 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 )) + # 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 - # ****************************** 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 + # 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 - # ****************************** 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 )) + # 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 )) - # ****************************** 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 - # + # 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 )) - 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 } + # ****************************** 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 - - diff --git a/tests/bugs/vis/bug23883 b/tests/bugs/vis/bug23883 index 8f0b3cc382..0e5e32492d 100644 --- a/tests/bugs/vis/bug23883 +++ b/tests/bugs/vis/bug23883 @@ -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 index 0000000000..8575bd8f05 --- /dev/null +++ b/tests/bugs/vis/bug30076 @@ -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