Added osg::Geometry::verifyArray(std::ostream&) method to enable checks to be done on osg::Geometry to see if the arrays

are big enough to handle the primitives used in the geometry.

Added usage of verifyArray into osgfilecache so that it reports any problems on reading files in paged database.
This commit is contained in:
Robert Osfield
2011-01-03 19:41:06 +00:00
parent 25ef1a9e58
commit d644a6dfe3
3 changed files with 302 additions and 6 deletions

View File

@@ -997,6 +997,14 @@ void Geometry::compileGLObjects(RenderInfo& renderInfo) const
void Geometry::drawImplementation(RenderInfo& renderInfo) const
{
#if 0
if (!validGeometry())
{
OSG_NOTICE<<"Error, osg::Geometry has invalid array/primitive set usage"<<std::endl;
return;
}
#endif
if (_internalOptimizedGeometry.valid())
{
_internalOptimizedGeometry->drawImplementation(renderInfo);
@@ -2483,6 +2491,245 @@ void Geometry::computeInternalOptimizedGeometry()
}
}
class CheckArrayValidity
{
public:
CheckArrayValidity(const osg::Geometry* 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::Geometry::ArrayData& arrayData, const char* arrayName)
{
unsigned int numRequired = 0;
switch(arrayData.binding)
{
case(osg::Geometry::BIND_OFF): numRequired = 0; break;
case(osg::Geometry::BIND_OVERALL): numRequired = 1; break;
case(osg::Geometry::BIND_PER_PRIMITIVE): numRequired = primitiveNum; break;
case(osg::Geometry::BIND_PER_PRIMITIVE_SET): numRequired = numPrimitiveSets; break;
case(osg::Geometry::BIND_PER_VERTEX): numRequired = maxVertexNumber+1; break;
}
if (arrayData.indices.valid())
{
unsigned int numIndices= arrayData.indices.valid() ? arrayData.indices->getNumElements() : 0;
if (numIndices<numRequired)
{
out<<"Not enough "<<arrayName<<" indices, numRequired="<<numRequired<<std::endl;
return false;
}
unsigned int numNormals = arrayData.array.valid() ? arrayData.array->getNumElements() : 0;
for(unsigned int i=0; i<numIndices; ++i)
{
if (arrayData.indices->index(i)>=numNormals)
{
out<<arrayName<<" index out of bounds of normal array"<<std::endl;
return false;
}
}
}
else
{
unsigned int numElements = arrayData.array.valid() ? arrayData.array->getNumElements() : 0;
if (numElements<numRequired)
{
out<<"Not enough "<<arrayName<<"s, numRequired="<<numRequired<<", but number in array="<<numElements<<std::endl;
return false;
}
}
return true;
}
unsigned int numPrimitiveSets;
unsigned int primitiveNum;
unsigned int maxVertexNumber;
};
bool Geometry::verifyArrays(std::ostream& out) const
{
CheckArrayValidity cav(this);
bool result = true;
// check _vertexData
if (_vertexData.indices.valid())
{
unsigned int numIndices= _vertexData.indices.valid() ? _vertexData.indices->getNumElements() : 0;
if (numIndices<=cav.maxVertexNumber)
{
out<<"Not enough vertex indices"<<std::endl;
result = false;
}
unsigned int numVertices = _vertexData.array.valid() ? _vertexData.array->getNumElements() : 0;
for(unsigned int i=0; i<numIndices; ++i)
{
if (_vertexData.indices->index(i)>=numVertices)
{
out<<"Vertex indice out of bounds of vertex array"<<std::endl;
result = false;
}
}
}
else
{
unsigned int numVertices = _vertexData.array.valid() ? _vertexData.array->getNumElements() : 0;
if (numVertices<cav.maxVertexNumber)
{
out<<"Not enough vertices"<<std::endl;
result = false;
}
}
// check _normalData
if (!cav.validArray(out, _normalData, "Normal")) result = false;
if (!cav.validArray(out, _colorData, "Color")) result = false;
if (!cav.validArray(out, _secondaryColorData, "SecondaryColor")) result = false;
return result;
}
Geometry* osg::createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec, float l, float b, float r, float t)
{