Moved the Array::AttribDivisor into the Array::Binding enum to avoid conflicts in settings between Binding and AttribDivisor.

Removed the vertify bindings/shared arrays handling from GeometryNew
This commit is contained in:
Robert Osfield 2013-06-05 07:27:35 +00:00
parent eb693f6a92
commit 4f1e6b28e8
3 changed files with 15 additions and 525 deletions

View File

@ -78,11 +78,19 @@ class OSG_EXPORT Array : public BufferData
enum Binding enum Binding
{ {
BIND_UNDEFINED=-1,
BIND_OFF=0, BIND_OFF=0,
BIND_OVERALL=1, BIND_OVERALL=1,
BIND_PER_PRIMITIVE_SET=2, BIND_PER_PRIMITIVE_SET=2,
BIND_PER_VERTEX=4, BIND_PER_VERTEX=4,
BIND_AUTO=5 BIND_INSTANCE_DIVISOR_0=6,
BIND_INSTANCE_DIVISOR_1=BIND_INSTANCE_DIVISOR_0+1,
BIND_INSTANCE_DIVISOR_2=BIND_INSTANCE_DIVISOR_0+2,
BIND_INSTANCE_DIVISOR_3=BIND_INSTANCE_DIVISOR_0+3,
BIND_INSTANCE_DIVISOR_4=BIND_INSTANCE_DIVISOR_0+4,
BIND_INSTANCE_DIVISOR_5=BIND_INSTANCE_DIVISOR_0+5,
BIND_INSTANCE_DIVISOR_6=BIND_INSTANCE_DIVISOR_0+6,
BIND_INSTANCE_DIVISOR_7=BIND_INSTANCE_DIVISOR_0+7
}; };
Array(Type arrayType=ArrayType,GLint dataSize=0,GLenum dataType=0): Array(Type arrayType=ArrayType,GLint dataSize=0,GLenum dataType=0):
@ -91,8 +99,7 @@ class OSG_EXPORT Array : public BufferData
_dataType(dataType), _dataType(dataType),
_normalize(false), _normalize(false),
_preserveDataType(false), _preserveDataType(false),
_attribDivisor(false), _binding(BIND_UNDEFINED) {}
_binding(BIND_AUTO) {}
Array(const Array& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY): Array(const Array& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
BufferData(array,copyop), BufferData(array,copyop),
@ -101,7 +108,6 @@ class OSG_EXPORT Array : public BufferData
_dataType(array._dataType), _dataType(array._dataType),
_normalize(array._normalize), _normalize(array._normalize),
_preserveDataType(array._preserveDataType), _preserveDataType(array._preserveDataType),
_attribDivisor(array._attribDivisor),
_binding(array._binding) {} _binding(array._binding) {}
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Array*>(obj)!=NULL; } virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Array*>(obj)!=NULL; }
@ -140,16 +146,12 @@ class OSG_EXPORT Array : public BufferData
/** Get hint to ask that the array data is passed via integer or double, or normal setVertexAttribPointer function.*/ /** Get hint to ask that the array data is passed via integer or double, or normal setVertexAttribPointer function.*/
bool getPreserveDataType() const { return _preserveDataType; } bool getPreserveDataType() const { return _preserveDataType; }
/** Set the rate at which generic vertex attributes advance during instanced rendering. Uses the glVertexAttribDivisor feature of OpenGL 4.0*/
void setAttribDivisor(GLuint divisor) { _attribDivisor = divisor; }
/** Get the rate at which generic vertex attributes advance during instanced rendering.*/
GLuint getAttribDivisor() const { return _attribDivisor; }
/** Specify how this array should be passed to OpenGL.*/ /** Specify how this array should be passed to OpenGL.*/
void setBinding(Binding binding) { _binding = binding; } void setBinding(int binding) { _binding = binding; }
/** Get how this array should be passed to OpenGL.*/ /** Get how this array should be passed to OpenGL.*/
Binding getBinding() const { return _binding; } int getBinding() const { return _binding; }
/** Frees unused space on this vector - i.e. the difference between size() and max_size() of the underlying vector.*/ /** Frees unused space on this vector - i.e. the difference between size() and max_size() of the underlying vector.*/
@ -173,8 +175,7 @@ class OSG_EXPORT Array : public BufferData
GLenum _dataType; GLenum _dataType;
bool _normalize; bool _normalize;
bool _preserveDataType; bool _preserveDataType;
GLuint _attribDivisor; int _binding;
Binding _binding;
}; };
template<typename T, Array::Type ARRAYTYPE, int DataSize, int DataType> template<typename T, Array::Type ARRAYTYPE, int DataSize, int DataType>

View File

@ -83,7 +83,7 @@ class OSG_EXPORT GeometryNew : public Drawable
void setSecondaryColorArray(Array* array); void setSecondaryColorArray(Array* array);
Array* getSecondaryColorArray() { return _secondaryColorArray.get(); } Array* getSecondaryColorArray() { return _secondaryColorArray.get(); }
const Array* getSecondaryColorArray() const; const Array* getSecondaryColorArray() const { return _secondaryColorArray.get(); }
void setFogCoordBinding(AttributeBinding ab); void setFogCoordBinding(AttributeBinding ab);
@ -177,19 +177,6 @@ class OSG_EXPORT GeometryNew : public Drawable
osg::ElementBufferObject* getOrCreateElementBufferObject(); osg::ElementBufferObject* getOrCreateElementBufferObject();
bool verifyBindings() const;
void computeCorrectBindingsAndArraySizes();
/** check whether the arrays, indices, bindings and primitives all match correctly, return false is .*/
bool verifyArrays(std::ostream& out) const;
bool containsSharedArrays() const;
void duplicateSharedArrays();
/** Return the estimated size of GLObjects (display lists/vertex buffer objects) that are associated with this drawable. /** Return the estimated size of GLObjects (display lists/vertex buffer objects) that are associated with this drawable.
* This size is used a hint for reuse of deleted display lists/vertex buffer objects. */ * This size is used a hint for reuse of deleted display lists/vertex buffer objects. */
@ -237,9 +224,6 @@ class OSG_EXPORT GeometryNew : public Drawable
virtual ~GeometryNew(); virtual ~GeometryNew();
bool verifyBindings(const osg::ref_ptr<Array>& array) const;
void computeCorrectBindingsAndArraySizes(osg::ref_ptr<Array>& ,const char* arrayName);
void addVertexBufferObjectIfRequired(osg::Array* array); void addVertexBufferObjectIfRequired(osg::Array* array);
void addElementBufferObjectIfRequired(osg::PrimitiveSet* primitiveSet); void addElementBufferObjectIfRequired(osg::PrimitiveSet* primitiveSet);

View File

@ -769,14 +769,6 @@ void GeometryNew::compileGLObjects(RenderInfo& renderInfo) const
void GeometryNew::drawImplementation(RenderInfo& renderInfo) const void GeometryNew::drawImplementation(RenderInfo& renderInfo) const
{ {
#if 0
if (!validGeometryNew())
{
OSG_NOTICE<<"Error, osg::Geometry has invalid array/primitive set usage"<<std::endl;
return;
}
#endif
State& state = *renderInfo.getState(); State& state = *renderInfo.getState();
bool checkForGLErrors = state.getCheckForGLErrors()==osg::State::ONCE_PER_ATTRIBUTE; bool checkForGLErrors = state.getCheckForGLErrors()==osg::State::ONCE_PER_ATTRIBUTE;
@ -1107,493 +1099,6 @@ void GeometryNew::accept(PrimitiveIndexFunctor& functor) const
} }
} }
unsigned int _computeNumberOfPrimitives(const osg::GeometryNew& geom)
{
unsigned int totalNumberOfPrimitives = 0;
for(GeometryNew::PrimitiveSetList::const_iterator itr=geom.getPrimitiveSetList().begin();
itr!=geom.getPrimitiveSetList().end();
++itr)
{
const PrimitiveSet* primitiveset = itr->get();
GLenum mode=primitiveset->getMode();
unsigned int primLength;
switch(mode)
{
case(GL_POINTS): primLength=1; OSG_INFO<<"prim=GL_POINTS"<<std::endl; break;
case(GL_LINES): primLength=2; OSG_INFO<<"prim=GL_LINES"<<std::endl; break;
case(GL_TRIANGLES): primLength=3; OSG_INFO<<"prim=GL_TRIANGLES"<<std::endl; break;
case(GL_QUADS): primLength=4; OSG_INFO<<"prim=GL_QUADS"<<std::endl; break;
default: primLength=0; OSG_INFO<<"prim="<<std::hex<<mode<<std::dec<<std::endl; break; // compute later when =0.
}
// draw primitives by the more flexible "slow" path,
// sending OpenGL Begin/glVertex.../End().
switch(primitiveset->getType())
{
case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
{
const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
primItr!=drawArrayLengths->end();
++primItr)
{
if (primLength==0) totalNumberOfPrimitives += 1;
else totalNumberOfPrimitives += *primItr/primLength;
}
break;
}
default:
{
if (primLength==0) { totalNumberOfPrimitives += 1; OSG_INFO<<" totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl;}
else { totalNumberOfPrimitives += primitiveset->getNumIndices()/primLength; OSG_INFO<<" primitiveset->getNumIndices()="<<primitiveset->getNumIndices()<<" totalNumberOfPrimitives="<<totalNumberOfPrimitives<<std::endl; }
}
}
}
return totalNumberOfPrimitives;
}
template<class A>
bool _verifyBindings(const osg::GeometryNew& geom, const A& array)
{
unsigned int numElements = array.valid()?array->getNumElements():0;
switch(array->getBinding())
{
case(osg::Array::BIND_OFF):
if (numElements>0) return false;
break;
case(osg::Array::BIND_OVERALL):
if (numElements!=1) return false;
break;
case(osg::Array::BIND_PER_PRIMITIVE_SET):
if (numElements!=geom.getPrimitiveSetList().size()) return false;
break;
case(osg::Array::BIND_PER_VERTEX):
{
unsigned int numVertices = geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
if (numElements!=numVertices) return false;
break;
}
case(osg::Array::BIND_AUTO):
{
return true;
}
}
return true;
}
template<class A>
void _computeCorrectBindingsAndArraySizes(std::ostream& out, const osg::GeometryNew& geom, A& array, const char* arrayName)
{
unsigned int numElements = array.valid()?array->getNumElements():0;
// check to see if binding matches 0 elements required.
if (numElements==0)
{
// correct binding if not correct.
if (array->getBinding()!=osg::Array::BIND_OFF)
{
out<<"Warning: in osg::GeometryNew::computeCorrectBindingsAndArraySizes() "<<std::endl
<<" "<<arrayName<<" binding has been reset to BIND_OFF"<<std::endl;
array->setBinding(osg::Array::BIND_OFF);
}
return;
}
// check to see if binding matches 1 elements required.
if (numElements==1)
{
// correct binding if not correct.
if (array->getBinding()!=osg::Array::BIND_OVERALL)
{
out<<"Warning: in osg::GeometryNew::computeCorrectBindingsAndArraySizes() "<<std::endl
<<" "<<arrayName<<" binding has been reset to BIND_OVERALL"<<std::endl;
array->setBinding(osg::Array::BIND_OVERALL);
}
return;
}
unsigned int numVertices = geom.getVertexArray()?geom.getVertexArray()->getNumElements():0;
if ( numVertices==0 )
{
if (array->getBinding()!=osg::Array::BIND_OFF)
{
array = 0;
out<<"Warning: in osg::GeometryNew::computeCorrectBindingsAndArraySizes() vertex array is empty but "<<std::endl
<<" vertex array is empty but"<<arrayName<<" is set"<<std::endl
<<" reseting "<<arrayName<< " binding to BIND_OFF and array & 0."<<std::endl;
}
}
if (numElements==numVertices)
{
// correct the binding to per vertex.
if (array->getBinding()!=osg::Array::BIND_PER_VERTEX)
{
out<<"Warning: in osg::GeometryNew::computeCorrectBindingsAndArraySizes() "<<std::endl
<<" "<<arrayName<<" binding has been reset to BIND_PER_VERTEX"<<std::endl;
array->setBinding(osg::Array::BIND_PER_VERTEX);
}
return;
}
// check to see if binding might be per primitive set
unsigned int numPrimitiveSets = geom.getPrimitiveSetList().size();
if (numElements==numPrimitiveSets)
{
if (array->getBinding() != osg::Array::BIND_PER_PRIMITIVE_SET)
{
out<<"Warning: in osg::GeometryNew::computeCorrectBindingsAndArraySizes() "<<std::endl
<<" "<<arrayName<<" binding has been reset to BIND_PER_PRIMITIVE_SET"<<std::endl;
array->setBinding(osg::Array::BIND_PER_PRIMITIVE_SET);
}
return;
}
if (numElements>=numVertices)
{
array->setBinding(osg::Array::BIND_PER_VERTEX);
return;
}
if (numElements>=numPrimitiveSets)
{
array->setBinding(osg::Array::BIND_PER_PRIMITIVE_SET);
return;
}
if (numElements>=1)
{
array->setBinding(osg::Array::BIND_OVERALL);
return;
}
array = 0;
}
bool GeometryNew::verifyBindings(const osg::ref_ptr<Array>& array) const
{
return _verifyBindings(*this, array);
}
bool GeometryNew::verifyBindings() const
{
if (!verifyBindings(_normalArray)) return false;
if (!verifyBindings(_colorArray)) return false;
if (!verifyBindings(_secondaryColorArray)) return false;
if (!verifyBindings(_fogCoordArray)) return false;
for(ArrayList::const_iterator titr=_texCoordList.begin();
titr!=_texCoordList.end();
++titr)
{
if (!verifyBindings(*titr)) return false;
}
for(ArrayList::const_iterator vitr=_vertexAttribList.begin();
vitr!=_vertexAttribList.end();
++vitr)
{
if (!verifyBindings(*vitr)) return false;
}
return true;
}
void GeometryNew::computeCorrectBindingsAndArraySizes(osg::ref_ptr<Array>& array,const char* arrayName)
{
return _computeCorrectBindingsAndArraySizes(osg::notify(osg::INFO), *this, array, arrayName);
}
void GeometryNew::computeCorrectBindingsAndArraySizes()
{
// if (verifyBindings()) return;
computeCorrectBindingsAndArraySizes(_normalArray,"_normalArray");
computeCorrectBindingsAndArraySizes(_colorArray,"_colorArray");
computeCorrectBindingsAndArraySizes(_secondaryColorArray,"_secondaryColorArray");
computeCorrectBindingsAndArraySizes(_fogCoordArray,"_fogCoordArray");
for(ArrayList::iterator titr=_texCoordList.begin();
titr!=_texCoordList.end();
++titr)
{
computeCorrectBindingsAndArraySizes(*titr,"_texCoordList[]");
}
for(ArrayList::iterator vitr=_vertexAttribList.begin();
vitr!=_vertexAttribList.end();
++vitr)
{
computeCorrectBindingsAndArraySizes(*vitr,"_vertAttribList[]");
}
}
bool GeometryNew::containsSharedArrays() const
{
unsigned int numSharedArrays = 0;
if (getVertexArray() && getVertexArray()->referenceCount()>1) ++numSharedArrays;
if (getNormalArray() && getNormalArray()->referenceCount()>1) ++numSharedArrays;
if (getColorArray() && getColorArray()->referenceCount()>1) ++numSharedArrays;
if (getSecondaryColorArray() && getSecondaryColorArray()->referenceCount()>1) ++numSharedArrays;
if (getFogCoordArray() && getFogCoordArray()->referenceCount()>1) ++numSharedArrays;
for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
{
if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1) ++numSharedArrays;
}
for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
{
const Array* array = _vertexAttribList[vi].get();
if (array && array->referenceCount()>1) ++numSharedArrays;
}
return numSharedArrays!=0;
}
void GeometryNew::duplicateSharedArrays()
{
#define DUPLICATE_IF_REQUIRED(A) \
if (get##A() && get##A()->referenceCount()>1) \
{ \
set##A(osg::clone(get##A(), osg::CopyOp::DEEP_COPY_ARRAYS)); \
}
DUPLICATE_IF_REQUIRED(VertexArray)
DUPLICATE_IF_REQUIRED(NormalArray)
DUPLICATE_IF_REQUIRED(ColorArray)
DUPLICATE_IF_REQUIRED(SecondaryColorArray)
DUPLICATE_IF_REQUIRED(FogCoordArray)
for(unsigned int ti=0;ti<getNumTexCoordArrays();++ti)
{
if (getTexCoordArray(ti) && getTexCoordArray(ti)->referenceCount()>1)
{
setTexCoordArray(ti, osg::clone(getTexCoordArray(ti),osg::CopyOp::DEEP_COPY_ARRAYS));
}
}
for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
{
Array* array = _vertexAttribList[vi].get();
if (array && array->referenceCount()>1)
{
_vertexAttribList[vi] = osg::clone(array, osg::CopyOp::DEEP_COPY_ARRAYS);
}
}
}
class CheckArrayValidity
{
public:
CheckArrayValidity(const osg::GeometryNew* geometry)
{
numPrimitiveSets = geometry->getNumPrimitiveSets();
primitiveNum = 0;
maxVertexNumber = 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// draw the primitives themselves.
//
for(unsigned int primitiveSetNum=0; primitiveSetNum != numPrimitiveSets; ++primitiveSetNum)
{
const PrimitiveSet* primitiveset = geometry->getPrimitiveSet(primitiveSetNum);
GLenum mode=primitiveset->getMode();
unsigned int primLength;
switch(mode)
{
case(GL_POINTS): primLength=1; break;
case(GL_LINES): primLength=2; break;
case(GL_TRIANGLES): primLength=3; break;
case(GL_QUADS): primLength=4; break;
default: primLength=0; break; // compute later when =0.
}
// draw primitives by the more flexible "slow" path,
// sending OpenGL glBegin/glVertex.../glEnd().
switch(primitiveset->getType())
{
case(PrimitiveSet::DrawArraysPrimitiveType):
{
if (primLength==0) primLength=primitiveset->getNumIndices();
const DrawArrays* drawArray = static_cast<const DrawArrays*>(primitiveset);
unsigned int primCount=0;
unsigned int indexEnd = drawArray->getFirst()+drawArray->getCount();
for(unsigned int vindex=drawArray->getFirst();
vindex<indexEnd;
++vindex,++primCount)
{
if ((primCount%primLength)==0)
{
primitiveNum++;
}
}
if ((indexEnd-1) > maxVertexNumber) maxVertexNumber = (indexEnd-1);
break;
}
case(PrimitiveSet::DrawArrayLengthsPrimitiveType):
{
const DrawArrayLengths* drawArrayLengths = static_cast<const DrawArrayLengths*>(primitiveset);
unsigned int vindex=drawArrayLengths->getFirst();
for(DrawArrayLengths::const_iterator primItr=drawArrayLengths->begin();
primItr!=drawArrayLengths->end();
++primItr)
{
unsigned int localPrimLength;
if (primLength==0) localPrimLength=*primItr;
else localPrimLength=primLength;
for(GLsizei primCount=0;
primCount<*primItr;
++vindex,++primCount)
{
if ((primCount%localPrimLength)==0)
{
primitiveNum++;
}
}
}
if ((vindex-1) > maxVertexNumber) maxVertexNumber = (vindex-1);
break;
}
case(PrimitiveSet::DrawElementsUBytePrimitiveType):
{
if (primLength==0) primLength=primitiveset->getNumIndices();
const DrawElementsUByte* drawElements = static_cast<const DrawElementsUByte*>(primitiveset);
unsigned int primCount=0;
for(DrawElementsUByte::const_iterator primItr=drawElements->begin();
primItr!=drawElements->end();
++primCount,++primItr)
{
if ((primCount%primLength)==0)
{
primitiveNum++;
}
unsigned int vindex = *primItr;
if (vindex > maxVertexNumber) maxVertexNumber = vindex;
}
break;
}
case(PrimitiveSet::DrawElementsUShortPrimitiveType):
{
if (primLength==0) primLength=primitiveset->getNumIndices();
const DrawElementsUShort* drawElements = static_cast<const DrawElementsUShort*>(primitiveset);
unsigned int primCount=0;
for(DrawElementsUShort::const_iterator primItr=drawElements->begin();
primItr!=drawElements->end();
++primCount,++primItr)
{
if ((primCount%primLength)==0)
{
primitiveNum++;
}
unsigned int vindex = *primItr;
if (vindex > maxVertexNumber) maxVertexNumber = vindex;
}
break;
}
case(PrimitiveSet::DrawElementsUIntPrimitiveType):
{
if (primLength==0) primLength=primitiveset->getNumIndices();
const DrawElementsUInt* drawElements = static_cast<const DrawElementsUInt*>(primitiveset);
unsigned int primCount=0;
for(DrawElementsUInt::const_iterator primItr=drawElements->begin();
primItr!=drawElements->end();
++primCount,++primItr)
{
if ((primCount%primLength)==0)
{
primitiveNum++;
}
unsigned int vindex = *primItr;
if (vindex > maxVertexNumber) maxVertexNumber = vindex;
}
break;
}
default:
{
break;
}
}
}
}
bool validArray(std::ostream& out, const osg::Array* array, const char* arrayName)
{
unsigned int numRequired = 0;
switch(array->getBinding())
{
case(osg::Array::BIND_OFF): numRequired = 0; break;
case(osg::Array::BIND_OVERALL): numRequired = 1; break;
case(osg::Array::BIND_PER_PRIMITIVE_SET): numRequired = numPrimitiveSets; break;
case(osg::Array::BIND_PER_VERTEX): numRequired = maxVertexNumber+1; break;
case(osg::Array::BIND_AUTO): numRequired = maxVertexNumber+1; break;
}
{
unsigned int numElements = array ? array->getNumElements() : 0;
if (numElements<numRequired)
{
out<<"Not enough "<<arrayName<<", numRequired="<<numRequired<<", but number in array="<<numElements<<std::endl;
return false;
}
}
return true;
}
unsigned int numPrimitiveSets;
unsigned int primitiveNum;
unsigned int maxVertexNumber;
};
bool GeometryNew::verifyArrays(std::ostream& out) const
{
CheckArrayValidity cav(this);
bool result = true;
if (!cav.validArray(out, _vertexArray.get(), "Vertex")) result = false;
if (!cav.validArray(out, _normalArray.get(), "Normal")) result = false;
if (!cav.validArray(out, _colorArray.get(), "Color")) result = false;
if (!cav.validArray(out, _secondaryColorArray.get(), "SecondaryColor")) result = false;
if (!cav.validArray(out, _fogCoordArray.get(), "FogCoord")) result = false;
for(unsigned int ti=0;ti<_texCoordList.size();++ti)
{
if (!cav.validArray(out, _texCoordList[ti].get(), "TexCoord")) result = false;
}
for(unsigned int vi=0;vi<_vertexAttribList.size();++vi)
{
if (!cav.validArray(out, _vertexAttribList[vi].get(), "TexCoord")) result = false;
}
return result;
}
GeometryNew* osg::createTexturedQuadGeometryNew(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t) GeometryNew* osg::createTexturedQuadGeometryNew(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t)
{ {
GeometryNew* geom = new GeometryNew; GeometryNew* geom = new GeometryNew;