From a11395feece8669227d70e589caa845d0cf9b150 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 8 Aug 2003 00:21:30 +0000 Subject: [PATCH] Added missing copy ops in the copy constructor. Added computeInternalOptimziedGeometry() and associated methods to Geometry to support alternate versions of a geometry to be used to optimize rendering, such as flattening indexed attributes to straight attribute arrays. --- include/osg/Geometry | 20 +++- src/osg/Geometry.cpp | 235 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 251 insertions(+), 4 deletions(-) diff --git a/include/osg/Geometry b/include/osg/Geometry index 8fcdd0a7b..e22e64970 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -23,6 +23,7 @@ namespace osg { + class SG_EXPORT Geometry : public Drawable { public: @@ -260,6 +261,21 @@ class SG_EXPORT Geometry : public Drawable void computeCorrectBindingsAndArraySizes(); + bool suitableForOptimization() const; + + void copyToAndOptimize(Geometry& target); + + void computeInternalOptimizedGeometry(); + + void removeInternalOptimizedGeometry() { _internalOptimizedGeometry = 0; } + + void setInternalOptimizedGeometry(osg::Geometry* geometry) { _internalOptimizedGeometry = geometry; } + + osg::Geometry* getInternalOptimizedGeometry() { return _internalOptimizedGeometry.get(); } + + const osg::Geometry* getInternalOptimizedGeometry() const { return _internalOptimizedGeometry.get(); } + + /** draw Geometry directly ignoring an OpenGL display list which could be attached. * This is the internal draw method which does the drawing itself, * and is the method to override when deriving from Geometry for user-drawn objects. @@ -327,7 +343,8 @@ class SG_EXPORT Geometry : public Drawable mutable VertexAttribBindingList _vertexAttribBindingList; mutable bool _fastPath; - + + ref_ptr _internalOptimizedGeometry; }; /** Convenience function to be used for creating quad geometry with texture coords. @@ -335,7 +352,6 @@ class SG_EXPORT Geometry : public Drawable extern SG_EXPORT Geometry* createTexturedQuadGeometry(const Vec3& corner,const Vec3& widthVec,const Vec3& heightVec); - } #endif diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index 957c3c415..e89ad92b8 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -252,16 +252,22 @@ Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop): #ifdef COMPILE_POSSIBLE_NEW_ARRAY_METHODS _attributeList(geometry._attributeList), #endif - _vertexArray(dynamic_cast(copyop(geometry._vertexArray.get()))), + _vertexArray((copyop(geometry._vertexArray.get()))), + _vertexIndices(dynamic_cast(copyop(geometry._vertexIndices.get()))), _normalBinding(geometry._normalBinding), _normalArray(dynamic_cast(copyop(geometry._normalArray.get()))), + _normalIndices(dynamic_cast(copyop(geometry._normalIndices.get()))), _colorBinding(geometry._colorBinding), _colorArray(copyop(geometry._colorArray.get())), + _colorIndices(dynamic_cast(copyop(geometry._colorIndices.get()))), _secondaryColorBinding(geometry._secondaryColorBinding), _secondaryColorArray(copyop(geometry._secondaryColorArray.get())), + _secondaryColorIndices(dynamic_cast(copyop(geometry._secondaryColorIndices.get()))), _fogCoordBinding(geometry._fogCoordBinding), _fogCoordArray(dynamic_cast(copyop(geometry._fogCoordArray.get()))), - _fastPath(geometry._fastPath) + _fogCoordIndices(dynamic_cast(copyop(geometry._fogCoordIndices.get()))), + _fastPath(geometry._fastPath), + _internalOptimizedGeometry(geometry._internalOptimizedGeometry) { for(PrimitiveSetList::const_iterator pitr=geometry._primitives.begin(); pitr!=geometry._primitives.end(); @@ -728,6 +734,12 @@ bool Geometry::computeFastPathsUsed() void Geometry::drawImplementation(State& state) const { + if (_internalOptimizedGeometry.valid()) + { + _internalOptimizedGeometry->drawImplementation(state); + return; + } + const Extensions* extensions = getExtensions(state.getContextID(),true); if( !( ( _vertexArray.valid() && _vertexArray->getNumElements() != 0 ) || @@ -2132,6 +2144,225 @@ void Geometry::computeCorrectBindingsAndArraySizes() } +class ExpandIndexedArray : public osg::ConstArrayVisitor +{ + public: + ExpandIndexedArray(const osg::IndexArray& indices,Array* targetArray): + _indices(indices), + _targetArray(targetArray) {} + + template + T* create(const T& array,const I& indices) + { + T* newArray = 0; + + // if source array type and target array type are equal + if (_targetArray && _targetArray->getType()==array.getType()) + { + // reuse exisiting target array + newArray = static_cast(_targetArray); + if (newArray->size()!=indices.size()) + { + // make sure its the right size + newArray->resize(indices.size()); + } + } + else + { + // else create a new array. + newArray = new T(indices.size()); + } + + for(unsigned int i=0;i + T* create(const T& array) + { + switch(_indices.getType()) + { + case(osg::Array::ByteArrayType): return create(array,static_cast(_indices)); + case(osg::Array::ShortArrayType): return create(array,static_cast(_indices)); + case(osg::Array::IntArrayType): return create(array,static_cast(_indices)); + case(osg::Array::UByteArrayType): return create(array,static_cast(_indices)); + case(osg::Array::UShortArrayType): return create(array,static_cast(_indices)); + case(osg::Array::UIntArrayType): return create(array,static_cast(_indices)); + default: return 0; + } + + } + + virtual void apply(const osg::ByteArray& array) { _targetArray = create(array); } + virtual void apply(const osg::ShortArray& array) { _targetArray = create(array); } + virtual void apply(const osg::IntArray& array) { _targetArray = create(array); } + virtual void apply(const osg::UByteArray& array) { _targetArray = create(array); } + virtual void apply(const osg::UShortArray& array) { _targetArray = create(array); } + virtual void apply(const osg::UIntArray& array) { _targetArray = create(array); } + virtual void apply(const osg::UByte4Array& array) { _targetArray = create(array); } + virtual void apply(const osg::FloatArray& array) { _targetArray = create(array); } + virtual void apply(const osg::Vec2Array& array) { _targetArray = create(array); } + virtual void apply(const osg::Vec3Array& array) { _targetArray = create(array); } + virtual void apply(const osg::Vec4Array& array) { _targetArray = create(array); } + + const osg::IndexArray& _indices; + osg::Array* _targetArray; +}; + +bool Geometry::suitableForOptimization() const +{ + bool hasIndices = false; + + if (getVertexIndices()) hasIndices = true; + + if (getNormalIndices()) hasIndices = true; + + if (getColorIndices()) hasIndices = true; + + if (getSecondaryColorIndices()) hasIndices = true; + + if (getFogCoordIndices()) hasIndices = true; + + for(unsigned int ti=0;tiaccept(eia); + + target.setVertexArray(eia._targetArray); + target.setVertexIndices(0); + } + else if (getVertexArray()) + { + target.setVertexArray(getVertexArray()); + } + + target.setNormalBinding(getNormalBinding()); + if (getNormalIndices()) + { + ExpandIndexedArray eia(*(getNormalIndices()),target.getNormalArray()); + getNormalArray()->accept(eia); + + target.setNormalArray(dynamic_cast(eia._targetArray)); + target.setNormalIndices(0); + } + else if (getNormalArray()) + { + target.setNormalArray(getNormalArray()); + } + + target.setColorBinding(getColorBinding()); + if (getColorIndices()) + { + ExpandIndexedArray eia(*(getColorIndices()),target.getColorArray()); + getColorArray()->accept(eia); + + target.setColorArray(eia._targetArray); + target.setColorIndices(0); + } + else if (getColorArray()) + { + target.setColorArray(getColorArray()); + } + + target.setSecondaryColorBinding(getSecondaryColorBinding()); + if (getSecondaryColorIndices()) + { + ExpandIndexedArray eia(*(getSecondaryColorIndices()),target.getSecondaryColorArray()); + getSecondaryColorArray()->accept(eia); + + target.setSecondaryColorArray(eia._targetArray); + target.setSecondaryColorIndices(0); + } + else if (getSecondaryColorArray()) + { + target.setSecondaryColorArray(getSecondaryColorArray()); + } + + target.setFogCoordBinding(getFogCoordBinding()); + if (getFogCoordIndices()) + { + ExpandIndexedArray eia(*(getFogCoordIndices()),target.getFogCoordArray()); + getFogCoordArray()->accept(eia); + + target.setFogCoordArray(eia._targetArray); + target.setFogCoordIndices(0); + } + else if (getFogCoordArray()) + { + target.setFogCoordArray(getFogCoordArray()); + } + + for(unsigned int ti=0;tiaccept(eia); + + target.setTexCoordArray(ti,eia._targetArray); + target.setTexCoordIndices(ti,0); + } + else if (getTexCoordArray(ti)) + { + target.setTexCoordArray(ti,getTexCoordArray(ti)); + } + } + + for(unsigned int vi=0;viaccept(eia); + getVertexAttribNormalize(vi,normalize); + target.setVertexAttribArray(vi,normalize,eia._targetArray,vab); + target.setVertexAttribIndices(vi,0); + } + else if (getVertexAttribArray(vi)) + { + GLboolean normalize; + getVertexAttribNormalize(vi,normalize); + target.setVertexAttribArray(vi,normalize,getVertexAttribArray(vi),vab); + } + } +} + +void Geometry::computeInternalOptimizedGeometry() +{ + if (suitableForOptimization()) + { + if (!_internalOptimizedGeometry) _internalOptimizedGeometry = new Geometry; + + copyToAndOptimize(*_internalOptimizedGeometry); + } +} + Geometry* osg::createTexturedQuadGeometry(const osg::Vec3& corner,const osg::Vec3& widthVec,const osg::Vec3& heightVec) {