diff --git a/include/osg/Geometry b/include/osg/Geometry index 611080c2e..59bb9676c 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -127,6 +127,29 @@ class SG_EXPORT Geometry : public Drawable const TexCoordArrayList& getTexCoordArrayList() const { return _texCoordList; } + + typedef std::pair< ref_ptr, ref_ptr > VertexAttribArrayPair; + typedef std::pair< GLboolean, VertexAttribArrayPair > VertexAttribNormArrayPair; + typedef std::vector< VertexAttribNormArrayPair > VertexAttribArrayList; + typedef std::vector< AttributeBinding > VertexAttribBindingList; + + void setVertexAttribArray(unsigned int index,bool normalize,Array* array,AttributeBinding ab=BIND_OFF); + Array *getVertexAttribArray(unsigned int index); + const Array *getVertexAttribArray(unsigned int index) const; + + bool getVertexAttribNormalize(unsigned int index, GLboolean &ret) const; + bool getVertexAttribBinding(unsigned int index, AttributeBinding& ab) const; + + void setVertexAttribIndices(unsigned int index,IndexArray* array); + IndexArray* getVertexAttribIndices(unsigned int index); + const IndexArray* getVertexAttribIndices(unsigned int index) const; + + unsigned int getNumVertexAttribArrays() const { return _vertexAttribList.size(); } + VertexAttribArrayList& getVertexAttribArrayList() { return _vertexAttribList; } + const VertexAttribArrayList& getVertexAttribArrayList() const { return _vertexAttribList; } + + + typedef std::vector< ref_ptr > PrimitiveSetList; void setPrimitiveSetList(const PrimitiveSetList& primitives) { _primitives = primitives; dirtyDisplayList(); dirtyBound(); } @@ -190,38 +213,139 @@ class SG_EXPORT Geometry : public Drawable /** accept a PrimitiveFunctor and call its methods to tell it about the interal primitives that this Drawable has.*/ virtual void accept(PrimitiveFunctor& pf) const; + /** Extensions class which encapsulates the querring of extensions and + * associated function pointers, and provide convinience wrappers to + * check for the extensions or use the associated functions.*/ + class SG_EXPORT Extensions : public osg::Referenced + { + public: + Extensions(); + + Extensions(const Extensions& rhs); + + void lowestCommonDenominator(const Extensions& rhs); + + void setupGLExtenions(); + + void setVertexProgramSupported(bool flag) { _isVertexProgramSupported=flag; } + bool isVertexProgramSupported() const { return _isVertexProgramSupported; } + + void setSecondaryColorSupported(bool flag) { _isSecondaryColorSupported=flag; } + bool isSecondaryColorSupported() const { return _isSecondaryColorSupported; } + + void setFogCoordSupported(bool flag) { _isFogCoordSupported=flag; } + bool isFogCoordSupported() const { return _isFogCoordSupported; } + + void setMultiTexSupported(bool flag) { _isMultiTexSupported=flag; } + bool isMultiTexSupported() const { return _isMultiTexSupported; } + + void glSecondaryColor3ubv(const GLubyte* coord) const; + void glSecondaryColor3fv(const GLfloat* coord) const; + + void glFogCoordfv(const GLfloat* coord) const; + + void glMultiTexCoord1f(GLenum target,GLfloat coord) const; + void glMultiTexCoord2fv(GLenum target,const GLfloat* coord) const; + void glMultiTexCoord3fv(GLenum target,const GLfloat* coord) const; + void glMultiTexCoord4fv(GLenum target,const GLfloat* coord) const; + + void glVertexAttrib1s(unsigned int index, GLshort s) const; + void glVertexAttrib1f(unsigned int index, GLfloat f) const; + void glVertexAttrib2fv(unsigned int index, const GLfloat * v) const; + void glVertexAttrib3fv(unsigned int index, const GLfloat * v) const; + void glVertexAttrib4fv(unsigned int index, const GLfloat * v) const; + void glVertexAttrib4ubv(unsigned int index, const GLubyte * v) const; + void glVertexAttrib4Nubv(unsigned int index, const GLubyte * v) const; + + protected: + + typedef void (APIENTRY * FogCoordProc) (const GLfloat* coord); + + typedef void (APIENTRY * VertexAttrib1sProc) (unsigned int index, GLshort s); + typedef void (APIENTRY * VertexAttrib1fProc) (unsigned int index, GLfloat f); + typedef void (APIENTRY * VertexAttribfvProc) (unsigned int index, const GLfloat * v); + typedef void (APIENTRY * VertexAttribubvProc) (unsigned int index, const GLubyte * v); + + typedef void (APIENTRY * SecondaryColor3ubvProc) (const GLubyte* coord); + typedef void (APIENTRY * SecondaryColor3fvProc) (const GLfloat* coord); + + typedef void (APIENTRY * MultiTexCoord1fProc) (GLenum target,GLfloat coord); + typedef void (APIENTRY * MultiTexCoordfvProc) (GLenum target,const GLfloat* coord); + + ~Extensions() {} + + bool _isVertexProgramSupported; + bool _isSecondaryColorSupported; + bool _isFogCoordSupported; + bool _isMultiTexSupported; + + FogCoordProc _glFogCoordfv; + + SecondaryColor3ubvProc _glSecondaryColor3ubv; + SecondaryColor3fvProc _glSecondaryColor3fv; + + VertexAttrib1sProc _glVertexAttrib1s; + VertexAttrib1fProc _glVertexAttrib1f; + VertexAttribfvProc _glVertexAttrib2fv; + VertexAttribfvProc _glVertexAttrib3fv; + VertexAttribfvProc _glVertexAttrib4fv; + VertexAttribubvProc _glVertexAttrib4ubv; + VertexAttribubvProc _glVertexAttrib4Nubv; + + MultiTexCoord1fProc _glMultiTexCoord1f; + MultiTexCoordfvProc _glMultiTexCoord2fv; + MultiTexCoordfvProc _glMultiTexCoord3fv; + MultiTexCoordfvProc _glMultiTexCoord4fv; + }; + + /** Function to call to get the extension of a specified context. + * If the Exentsion object for that context has not yet been created then + * and the 'createIfNotInitalized' flag been set to false then returns NULL. + * If 'createIfNotInitalized' is true then the Extensions object is + * automatically created. However, in this case the extension object + * only be created with the graphics context associated with ContextID..*/ + static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized); + + /** setExtensions allows users to override the extensions across graphics contexts. + * typically used when you have different extensions supported across graphics pipes + * but need to ensure that they all use the same low common denominator extensions.*/ + static void setExtensions(unsigned int contextID,Extensions* extensions); + + protected: Geometry& operator = (const Geometry&) { return *this;} virtual ~Geometry(); - PrimitiveSetList _primitives; + PrimitiveSetList _primitives; - ref_ptr _vertexArray; - ref_ptr _vertexIndices; + ref_ptr _vertexArray; + ref_ptr _vertexIndices; - mutable AttributeBinding _normalBinding; - ref_ptr _normalArray; - ref_ptr _normalIndices; + mutable AttributeBinding _normalBinding; + ref_ptr _normalArray; + ref_ptr _normalIndices; - mutable AttributeBinding _colorBinding; - ref_ptr _colorArray; - ref_ptr _colorIndices; + mutable AttributeBinding _colorBinding; + ref_ptr _colorArray; + ref_ptr _colorIndices; - mutable AttributeBinding _secondaryColorBinding; - ref_ptr _secondaryColorArray; - ref_ptr _secondaryColorIndices; + mutable AttributeBinding _secondaryColorBinding; + ref_ptr _secondaryColorArray; + ref_ptr _secondaryColorIndices; - mutable AttributeBinding _fogCoordBinding; - ref_ptr _fogCoordArray; - ref_ptr _fogCoordIndices; + mutable AttributeBinding _fogCoordBinding; + ref_ptr _fogCoordArray; + ref_ptr _fogCoordIndices; - TexCoordArrayList _texCoordList; + TexCoordArrayList _texCoordList; - mutable bool _fastPathComputed; - mutable bool _fastPath; + VertexAttribArrayList _vertexAttribList; + mutable VertexAttribBindingList _vertexAttribBindingList; + mutable bool _fastPathComputed; + mutable bool _fastPath; }; diff --git a/include/osg/State b/include/osg/State index 2d22f4101..c10b9bb77 100644 --- a/include/osg/State +++ b/include/osg/State @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,7 @@ namespace osg { #ifdef GL_FOG_COORDINATE_ARRAY_EXT #define GL_FOG_COORDINATE_ARRAY GL_FOG_COORDINATE_ARRAY_EXT #else - #define GL_FOG_COORDINATE_ARRAY 0x8457 + #define GL_FOG_COORDINATE_ARRAY 0x8457 #endif #endif @@ -43,7 +44,7 @@ namespace osg { #ifdef GL_SECONDARY_COLOR_ARRAY_EXT #define GL_SECONDARY_COLOR_ARRAY GL_SECONDARY_COLOR_ARRAY_EXT #else - #define GL_SECONDARY_COLOR_ARRAY 0x845E + #define GL_SECONDARY_COLOR_ARRAY 0x845E #endif #endif @@ -449,8 +450,8 @@ class SG_EXPORT State : public Referenced /** wrapper around glEnableClientState(GL_TEXTURE_COORD_ARRAY);glTexCoordPointer(..); * note, only updates values that change.*/ inline void setTexCoordPointer( unsigned int unit, - GLint size, GLenum type, - GLsizei stride, const GLvoid *ptr ) + GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr ) { if (setClientActiveTextureUnit(unit)) { @@ -470,7 +471,7 @@ class SG_EXPORT State : public Referenced eap._dirty = false; } } - + /** wrapper around glDisableClientState(GL_TEXTURE_COORD_ARRAY); * note, only updates values that change.*/ inline void disableTexCoordPointer( unsigned int unit ) @@ -537,6 +538,96 @@ class SG_EXPORT State : public Referenced bool setActiveTextureUnit( unsigned int unit ); + typedef void (APIENTRY * VertexAttribPointerProc) (unsigned int, GLint, GLenum, GLboolean normalized, GLsizei stride, const GLvoid *pointer); + typedef void (APIENTRY * EnableVertexAttribProc) (unsigned int); + typedef void (APIENTRY * DisableVertexAttribProc) (unsigned int); + + /** wrapper around glEnableVertexAttribArrayARB(index);glVertexAttribPointerARB(..); + * note, only updates values that change.*/ + inline void setVertexAttribPointer( unsigned int index, + GLint size, GLenum type, GLboolean normalized, + GLsizei stride, const GLvoid *ptr ) + { + static VertexAttribPointerProc s_glVertexAttribPointer = + (VertexAttribPointerProc) osg::getGLExtensionFuncPtr("glVertexAttribPointer","glVertexAttribPointerARB"); + + static EnableVertexAttribProc s_glEnableVertexAttribArray = + (EnableVertexAttribProc) osg::getGLExtensionFuncPtr("glEnableVertexAttribArray","glEnableVertexAttribArrayARB"); + + if( s_glVertexAttribPointer ) + { + if ( index >= _vertexAttribArrayList.size()) _vertexAttribArrayList.resize(index+1); + EnabledArrayPair& eap = _vertexAttribArrayList[index]; + + if (!eap._enabled || eap._dirty) + { + eap._enabled = true; + s_glEnableVertexAttribArray( index ); + } + if (eap._pointer != ptr || eap._normalized!=normalized || eap._dirty) + { + s_glVertexAttribPointer( index, size, type, normalized, stride, ptr ); + eap._pointer = ptr; + eap._normalized = normalized; + } + eap._dirty = false; + } + } + + /** wrapper around DisableVertexAttribArrayARB(index); + * note, only updates values that change.*/ + inline void disableVertexAttribPointer( unsigned int index ) + { + static DisableVertexAttribProc s_glDisableVertexAttribArray = + (DisableVertexAttribProc) osg::getGLExtensionFuncPtr("glDisableVertexAttribArray","glDisableVertexAttribArrayARB"); + + if (s_glDisableVertexAttribArray) + { + if ( index >= _vertexAttribArrayList.size()) _vertexAttribArrayList.resize(index+1); + EnabledArrayPair& eap = _vertexAttribArrayList[index]; + + if (eap._enabled || eap._dirty) + { + eap._enabled = false; + eap._dirty = false; + s_glDisableVertexAttribArray( index ); + } + } + } + + inline void disableVertexAttribPointersAboveAndIncluding( unsigned int index ) + { + static DisableVertexAttribProc s_glDisableVertexAttribArray = + (DisableVertexAttribProc) osg::getGLExtensionFuncPtr("glDisableVertexAttribArray","glDisableVertexAttribArrayARB"); + + if (s_glDisableVertexAttribArray) + { + while (index<_vertexAttribArrayList.size()) + { + EnabledArrayPair& eap = _vertexAttribArrayList[index]; + if (eap._enabled || eap._dirty) + { + eap._enabled = false; + eap._dirty = false; + s_glDisableVertexAttribArray( index ); + } + ++index; + } + } + } + + inline void dirtyVertexAttribPointersAboveAndIncluding( unsigned int index ) + { + while (index<_vertexAttribArrayList.size()) + { + EnabledArrayPair& eap = _vertexAttribArrayList[index]; + eap._pointer = 0; + eap._dirty = true; + ++index; + } + } + + /** Set the current OpenGL context uniqueID. Note, it is the application developers responsibility to set up unique ID for each OpenGL context. This value is @@ -712,27 +803,30 @@ class SG_EXPORT State : public Referenced struct EnabledArrayPair { - EnabledArrayPair():_dirty(true),_enabled(false),_pointer(0) {} - EnabledArrayPair(const EnabledArrayPair& eap):_dirty(eap._dirty), _enabled(eap._enabled),_pointer(eap._pointer) {} - EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _dirty=eap._dirty; _enabled=eap._enabled; _pointer=eap._pointer; return *this; } + EnabledArrayPair():_dirty(true),_enabled(false),_normalized(0),_pointer(0) {} + EnabledArrayPair(const EnabledArrayPair& eap):_dirty(eap._dirty), _enabled(eap._enabled),_normalized(eap._normalized),_pointer(eap._pointer) {} + EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _dirty=eap._dirty; _enabled=eap._enabled; _normalized=eap._normalized;_pointer=eap._pointer; return *this; } bool _dirty; bool _enabled; + GLboolean _normalized; const GLvoid* _pointer; }; typedef std::vector EnabledTexCoordArrayList; + typedef std::vector EnabledVertexAttribArrayList; - EnabledArrayPair _vertexArray; - EnabledArrayPair _normalArray; - EnabledArrayPair _colorArray; - EnabledArrayPair _secondaryColorArray; - EnabledArrayPair _indexArray; - EnabledArrayPair _fogArray; - EnabledTexCoordArrayList _texCoordArrayList; - - unsigned int _currentActiveTextureUnit; - unsigned int _currentClientActiveTextureUnit; + EnabledArrayPair _vertexArray; + EnabledArrayPair _normalArray; + EnabledArrayPair _colorArray; + EnabledArrayPair _secondaryColorArray; + EnabledArrayPair _indexArray; + EnabledArrayPair _fogArray; + EnabledTexCoordArrayList _texCoordArrayList; + EnabledVertexAttribArrayList _vertexAttribArrayList; + + unsigned int _currentActiveTextureUnit; + unsigned int _currentClientActiveTextureUnit; inline ModeMap& getOrCreateTextureModeMap(unsigned int unit) { diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index b5bb8df00..3d2eca10d 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -74,6 +74,62 @@ class DrawColor : public osg::ConstValueVisitor const IndexArray* _indices; }; +class DrawVertexAttrib : public osg::Referenced, public osg::ConstValueVisitor +{ +public: + + DrawVertexAttrib(const Geometry::Extensions * extensions,unsigned int index,GLboolean normalized,const Array* attribcoords,const IndexArray* indices): + _index(index), + _normalized(normalized), + _extensions(extensions), + _attribcoords(attribcoords), + _indices(indices) {} + + void operator () (unsigned int pos) + { + if (_indices) _attribcoords->accept(_indices->index(pos),*this); + else _attribcoords->accept(pos,*this); + } + + virtual void apply(const GLshort& s) + { + _extensions->glVertexAttrib1s( _index, s ); + } + virtual void apply(const GLfloat& f) + { + _extensions->glVertexAttrib1f( _index, f ); + } + virtual void apply(const UByte4& v) + { + if( _normalized ) + { + _extensions->glVertexAttrib4Nubv( _index, v.ptr() ); + } + else + { + _extensions->glVertexAttrib4ubv( _index, v.ptr() ); + } + } + virtual void apply(const Vec2& v) + { + _extensions->glVertexAttrib2fv( _index, v.ptr() ); + } + virtual void apply(const Vec3& v) + { + _extensions->glVertexAttrib3fv( _index, v.ptr() ); + } + virtual void apply(const Vec4& v) + { + _extensions->glVertexAttrib4fv( _index, v.ptr() ); + } + + unsigned int _index; + GLboolean _normalized; + const Geometry::Extensions* _extensions; + const Array* _attribcoords; + const IndexArray* _indices; +}; + class DrawTexCoord : public osg::Referenced, public osg::ConstValueVisitor { public: @@ -97,24 +153,16 @@ class DrawTexCoord : public osg::Referenced, public osg::ConstValueVisitor const IndexArray* _indices; }; -typedef void (APIENTRY * MultiTexCoord1fProc) (GLenum target,GLfloat coord); -typedef void (APIENTRY * MultiTexCoordfvProc) (GLenum target,const GLfloat* coord); class DrawMultiTexCoord : public osg::Referenced, public osg::ConstValueVisitor { public: DrawMultiTexCoord(GLenum target,const Array* texcoords,const IndexArray* indices, - MultiTexCoord1fProc glMultiTexCoord1f, - MultiTexCoordfvProc glMultiTexCoord2fv, - MultiTexCoordfvProc glMultiTexCoord3fv, - MultiTexCoordfvProc glMultiTexCoord4fv): + const Geometry::Extensions * extensions): _target(target), _texcoords(texcoords), _indices(indices), - _glMultiTexCoord1f(glMultiTexCoord1f), - _glMultiTexCoord2fv(glMultiTexCoord2fv), - _glMultiTexCoord3fv(glMultiTexCoord3fv), - _glMultiTexCoord4fv(glMultiTexCoord4fv) {} + _extensions(extensions) {} void operator () (unsigned int pos) { @@ -122,33 +170,29 @@ class DrawMultiTexCoord : public osg::Referenced, public osg::ConstValueVisitor else _texcoords->accept(pos,*this); } - virtual void apply(const GLfloat& v){ _glMultiTexCoord1f(_target,v); } - virtual void apply(const Vec2& v) { _glMultiTexCoord2fv(_target,v.ptr()); } - virtual void apply(const Vec3& v) { _glMultiTexCoord3fv(_target,v.ptr()); } - virtual void apply(const Vec4& v) { _glMultiTexCoord4fv(_target,v.ptr()); } + virtual void apply(const GLfloat& v){ _extensions->glMultiTexCoord1f(_target,v); } + virtual void apply(const Vec2& v) { _extensions->glMultiTexCoord2fv(_target,v.ptr()); } + virtual void apply(const Vec3& v) { _extensions->glMultiTexCoord3fv(_target,v.ptr()); } + virtual void apply(const Vec4& v) { _extensions->glMultiTexCoord4fv(_target,v.ptr()); } GLenum _target; const Array* _texcoords; const IndexArray* _indices; - MultiTexCoord1fProc _glMultiTexCoord1f; - MultiTexCoordfvProc _glMultiTexCoord2fv; - MultiTexCoordfvProc _glMultiTexCoord3fv; - MultiTexCoordfvProc _glMultiTexCoord4fv; + + const Geometry::Extensions * _extensions; }; -typedef void (APIENTRY * SecondaryColor3ubvProc) (const GLubyte* coord); -typedef void (APIENTRY * SecondaryColor3fvProc) (const GLfloat* coord); class DrawSecondaryColor : public osg::ConstValueVisitor { public: DrawSecondaryColor(const Array* colors,const IndexArray* indices, - SecondaryColor3ubvProc sc3ubv,SecondaryColor3fvProc sc3fv): + const Geometry::Extensions * extensions): _colors(colors), _indices(indices), - _glSecondaryColor3ubv(sc3ubv), - _glSecondaryColor3fv(sc3fv) {} + _extensions(extensions) + {} void operator () (unsigned int pos) { @@ -156,26 +200,24 @@ class DrawSecondaryColor : public osg::ConstValueVisitor else _colors->accept(pos,*this); } - virtual void apply(const UByte4& v) { _glSecondaryColor3ubv(v.ptr()); } - virtual void apply(const Vec3& v) { _glSecondaryColor3fv(v.ptr()); } - virtual void apply(const Vec4& v) { _glSecondaryColor3fv(v.ptr()); } + virtual void apply(const UByte4& v) { _extensions->glSecondaryColor3ubv(v.ptr()); } + virtual void apply(const Vec3& v) { _extensions->glSecondaryColor3fv(v.ptr()); } + virtual void apply(const Vec4& v) { _extensions->glSecondaryColor3fv(v.ptr()); } const Array* _colors; const IndexArray* _indices; - SecondaryColor3ubvProc _glSecondaryColor3ubv; - SecondaryColor3fvProc _glSecondaryColor3fv; + const Geometry::Extensions * _extensions; }; -typedef void (APIENTRY * FogCoordProc) (const GLfloat* coord); class DrawFogCoord : public osg::ConstValueVisitor { public: - DrawFogCoord(const Array* fogcoords,const IndexArray* indices,FogCoordProc fogCoordProc): + DrawFogCoord(const Array* fogcoords,const IndexArray* indices,const Geometry::Extensions * extensions): _fogcoords(fogcoords), _indices(indices), - _glFogCoord1fv(fogCoordProc) {} + _extensions(extensions) {} void operator () (unsigned int pos) { @@ -183,12 +225,12 @@ class DrawFogCoord : public osg::ConstValueVisitor else _fogcoords->accept(pos,*this); } - virtual void apply(const GLfloat& v) { _glFogCoord1fv(&v); } + virtual void apply(const GLfloat& v) { _extensions->glFogCoordfv(&v); } const Array* _fogcoords; const IndexArray* _indices; - FogCoordProc _glFogCoord1fv; + const Geometry::Extensions * _extensions; }; @@ -231,6 +273,13 @@ Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop): { _texCoordList.push_back(*titr); } + + for(VertexAttribArrayList::const_iterator vitr=geometry._vertexAttribList.begin(); + vitr!=geometry._vertexAttribList.end(); + ++vitr) + { + _vertexAttribList.push_back(*vitr); + } } Geometry::~Geometry() @@ -282,6 +331,89 @@ const IndexArray* Geometry::getTexCoordIndices(unsigned int unit) const else return 0; } +void Geometry::setVertexAttribArray(unsigned int index,bool normalize,Array* array,AttributeBinding ab) +{ + if (_vertexAttribList.size()<=index) + { + _vertexAttribList.resize(index+1); + _vertexAttribBindingList.resize(index+1); + } + + _vertexAttribList[index].first = normalize; + _vertexAttribList[index].second.first = array; + + _vertexAttribBindingList[index] = ab; + + _fastPathComputed = false; + dirtyDisplayList(); +} + +Array *Geometry::getVertexAttribArray(unsigned int index) +{ + if (index<_vertexAttribList.size()) return _vertexAttribList[index].second.first.get(); + else return 0; +} + +const Array *Geometry::getVertexAttribArray(unsigned int index) const +{ + if (index<_vertexAttribList.size()) return _vertexAttribList[index].second.first.get(); + else return 0; +} + +bool Geometry::getVertexAttribBinding(unsigned int index, AttributeBinding& ab) const +{ + // AttributeBinding value goes in ab + // return true if index is valid, false otherwise + + if (index<_vertexAttribBindingList.size()) + { + ab = _vertexAttribBindingList[index]; + return true; + } + else + { + return false; + } +} + +bool Geometry::getVertexAttribNormalize(unsigned int index, GLboolean &ret) const +{ + // normalized value goes in ret + // return true if index is valid, false otherwise + + if (index<_vertexAttribList.size()) + { + ret = _vertexAttribList[index].first; + return true; + } + else + { + return false; + } +} + +void Geometry::setVertexAttribIndices(unsigned int index,IndexArray* array) +{ + if (_vertexAttribList.size()<=index) + _vertexAttribList.resize(index+1); + + _vertexAttribList[index].second.second = array; + + dirtyDisplayList(); +} + +IndexArray* Geometry::getVertexAttribIndices(unsigned int index) +{ + if (index<_vertexAttribList.size()) return _vertexAttribList[index].second.second.get(); + else return 0; +} + +const IndexArray* Geometry::getVertexAttribIndices(unsigned int index) const +{ + if (index<_vertexAttribList.size()) return _vertexAttribList[index].second.second.get(); + else return 0; +} + bool Geometry::addPrimitiveSet(PrimitiveSet* primitiveset) { if (primitiveset) @@ -418,6 +550,23 @@ bool Geometry::areFastPathsUsed() const _fogCoordBinding = BIND_OFF; } + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Set up vertex attrib if required. + // + for( unsigned int va = 0; va < _vertexAttribList.size(); ++va ) + { + const Array * array = _vertexAttribList[va].second.first.get(); + const IndexArray * idxArray = _vertexAttribList[va].second.second.get(); + + if (!array || + array->getNumElements()==0 || + (idxArray && idxArray->getNumElements()==0) ) + { + // switch off if not supported or have a valid data. + _vertexAttribBindingList[va] = BIND_OFF; + } + } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -428,6 +577,30 @@ bool Geometry::areFastPathsUsed() const else if (_colorBinding==BIND_PER_PRIMITIVE || (_colorBinding==BIND_PER_VERTEX && _colorIndices.valid())) _fastPath = false; else if (_secondaryColorBinding==BIND_PER_PRIMITIVE || (_secondaryColorBinding==BIND_PER_VERTEX && _secondaryColorIndices.valid())) _fastPath = false; else if (_fogCoordBinding==BIND_PER_PRIMITIVE || (_fogCoordBinding==BIND_PER_VERTEX && _fogCoordIndices.valid())) _fastPath = false; + else + { + for( unsigned int va = 0; va < _vertexAttribBindingList.size(); ++va ) + { + if (_vertexAttribBindingList[va]==BIND_PER_PRIMITIVE) + { + _fastPath = false; + break; + } + else + { + const Array * array = _vertexAttribList[va].second.first.get(); + const IndexArray * idxArray = _vertexAttribList[va].second.second.get(); + + if( _vertexAttribBindingList[va]==BIND_PER_VERTEX && + array && array->getNumElements()>0 && + idxArray && idxArray->getNumElements()>0 ) + { + _fastPath = false; + break; + } + } + } + } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -442,7 +615,8 @@ bool Geometry::areFastPathsUsed() const { if (texcoordPair.second->getNumElements()>0) { - _fastPath = false; + _fastPath = false; + break; } } } @@ -455,34 +629,37 @@ bool Geometry::areFastPathsUsed() const void Geometry::drawImplementation(State& state) const { - if (!_vertexArray.valid() || _vertexArray->getNumElements()==0) return; - if (_vertexIndices.valid() && _vertexIndices->getNumElements()==0) return; - - // set up extensions. - static SecondaryColor3ubvProc s_glSecondaryColor3ubv = - (SecondaryColor3ubvProc) osg::getGLExtensionFuncPtr("glSecondaryColor3ubv","glSecondaryColor3ubvEXT"); - static SecondaryColor3fvProc s_glSecondaryColor3fv = - (SecondaryColor3fvProc) osg::getGLExtensionFuncPtr("glSecondaryColor3fv","glSecondaryColor3fvEXT"); + const Extensions* extensions = getExtensions(state.getContextID(),true); - static FogCoordProc s_glFogCoordfv = - (FogCoordProc) osg::getGLExtensionFuncPtr("glFogCoordfv","glFogCoordfvEXT"); + if( !( ( _vertexArray.valid() && _vertexArray->getNumElements() != 0 ) || + ( _vertexAttribList.size() > 0 && + _vertexAttribList[0].second.first.valid() && + _vertexAttribList[0].second.first->getNumElements() != 0 ) ) ) + { + return; + } + + if( ( _vertexIndices.valid() && _vertexIndices->getNumElements() == 0 ) || + ( _vertexAttribList.size() > 0 && + _vertexAttribList[0].second.second.valid() && + _vertexAttribList[0].second.second->getNumElements() == 0 ) ) + { + return; + } DrawNormal drawNormal(_normalArray.get(),_normalIndices.get()); DrawColor drawColor(_colorArray.get(),_colorIndices.get()); - DrawSecondaryColor drawSecondaryColor(_secondaryColorArray.get(),_secondaryColorIndices.get(), - s_glSecondaryColor3ubv,s_glSecondaryColor3fv); - DrawFogCoord drawFogCoord(_fogCoordArray.get(),_fogCoordIndices.get(), - s_glFogCoordfv); + DrawSecondaryColor drawSecondaryColor(_secondaryColorArray.get(),_secondaryColorIndices.get(),extensions); + DrawFogCoord drawFogCoord(_fogCoordArray.get(),_fogCoordIndices.get(),extensions); - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Set up secondary color if required. // AttributeBinding secondaryColorBinding = _secondaryColorBinding; - if (secondaryColorBinding!=BIND_OFF && (!s_glSecondaryColor3ubv || !s_glSecondaryColor3fv)) + if (secondaryColorBinding!=BIND_OFF && !extensions->isSecondaryColorSupported()) { // switch off if not supported or have a valid data. secondaryColorBinding = BIND_OFF; @@ -494,16 +671,34 @@ void Geometry::drawImplementation(State& state) const // Set up fog coord if required. // AttributeBinding fogCoordBinding = _fogCoordBinding; - if (fogCoordBinding!=BIND_OFF && !s_glFogCoordfv) + if (fogCoordBinding!=BIND_OFF && !extensions->isFogCoordSupported()) { // switch off if not supported or have a valid data. fogCoordBinding = BIND_OFF; } + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Set up vertex attrib if required. + // + if(!extensions->isVertexProgramSupported()) + { + notify(WARN) << "Error: VertexProgram not supported by OpenGL driver" << std::endl; + + for( unsigned int va = 0; va < _vertexAttribBindingList.size(); ++va ) + { + if (_vertexAttribBindingList[va]!=BIND_OFF) + { + _vertexAttribBindingList[va] = BIND_OFF; + } + } + } + unsigned int normalIndex = 0; unsigned int colorIndex = 0; unsigned int secondaryColorIndex = 0; unsigned int fogCoordIndex = 0; + unsigned int vertexAttribIndex = 0; #if USE_DEFAULT_NORMAL // if no values are defined for normal and color provide some defaults... @@ -514,9 +709,12 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_OFF) glColor4f(1.0f,1.0f,1.0f,1.0f); #endif + typedef std::vector< ref_ptr > DrawVertexAttribList; + typedef std::map< Geometry::AttributeBinding, DrawVertexAttribList> DrawVertexAttribMap; + DrawVertexAttribMap drawVertexAttribMap; + if (areFastPathsUsed()) { - /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // fast path. @@ -555,6 +753,47 @@ void Geometry::drawImplementation(State& state) const } state.disableTexCoordPointersAboveAndIncluding(unit); + if( extensions->isVertexProgramSupported() ) + { + unsigned int index; + for( index = 0; index < _vertexAttribList.size(); ++index ) + { + const Array* array = _vertexAttribList[index].second.first.get(); + const IndexArray* indexArray = _vertexAttribList[index].second.second.get(); + + if( _vertexAttribBindingList[index] == BIND_PER_VERTEX ) + { + if( array ) + { + state.setVertexAttribPointer( index, array->getDataSize(), array->getDataType(), + _vertexAttribList[index].first, 0, array->getDataPointer() ); + } + else + { + state.disableVertexAttribPointer( index ); + } + } + else + { + if( indexArray ) + { + if( indexArray->getNumElements() > 0 ) + { + drawVertexAttribMap[_vertexAttribBindingList[index]].push_back( + new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,indexArray) ); + } + } + else + { + drawVertexAttribMap[_vertexAttribBindingList[index]].push_back( + new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,0) ); + } + + state.disableVertexAttribPointer( index ); + } + } + state.disableVertexAttribPointersAboveAndIncluding( index ); + } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -564,7 +803,15 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_OVERALL) drawColor(colorIndex++); if (secondaryColorBinding==BIND_OVERALL) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_OVERALL) drawFogCoord(fogCoordIndex++); + if( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL]; + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // @@ -579,6 +826,15 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE_SET) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE_SET) drawFogCoord(fogCoordIndex++); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } (*itr)->draw(); @@ -594,17 +850,6 @@ void Geometry::drawImplementation(State& state) const // - // Set up tex coords if required. - static MultiTexCoord1fProc s_glMultiTexCoord1f = - (MultiTexCoord1fProc) osg::getGLExtensionFuncPtr("glMultiTexCoord1f","glMultiTexCoord1fARB"); - static MultiTexCoordfvProc s_glMultiTexCoord2fv = - (MultiTexCoordfvProc) osg::getGLExtensionFuncPtr("glMultiTexCoord2fv","glMultiTexCoord2fvARB"); - static MultiTexCoordfvProc s_glMultiTexCoord3fv = - (MultiTexCoordfvProc) osg::getGLExtensionFuncPtr("glMultiTexCoord3fv","glMultiTexCoord3fvARB"); - static MultiTexCoordfvProc s_glMultiTexCoord4fv = - (MultiTexCoordfvProc) osg::getGLExtensionFuncPtr("glMultiTexCoord4fv","glMultiTexCoord4fvARB"); - - typedef std::vector< ref_ptr > DrawTexCoordList; DrawTexCoordList drawTexCoordList; drawTexCoordList.reserve(_texCoordList.size()); @@ -612,7 +857,7 @@ void Geometry::drawImplementation(State& state) const // fallback if multitexturing not supported. ref_ptr drawTextCoord; - if (s_glMultiTexCoord2fv) + if (extensions->isMultiTexSupported()) { // multitexture supported.. for(unsigned int unit=0;unit!=_texCoordList.size();++unit) @@ -625,20 +870,14 @@ void Geometry::drawImplementation(State& state) const if (texcoordPair.second->getNumElements()>0) { drawTexCoordList.push_back(new DrawMultiTexCoord(GL_TEXTURE0+unit,texcoordPair.first.get(),texcoordPair.second.get(), - s_glMultiTexCoord1f, - s_glMultiTexCoord2fv, - s_glMultiTexCoord3fv, - s_glMultiTexCoord4fv)); + extensions)); } } else { drawTexCoordList.push_back(new DrawMultiTexCoord(GL_TEXTURE0+unit,texcoordPair.first.get(),0, - s_glMultiTexCoord1f, - s_glMultiTexCoord2fv, - s_glMultiTexCoord3fv, - s_glMultiTexCoord4fv)); + extensions)); } } } @@ -666,6 +905,30 @@ void Geometry::drawImplementation(State& state) const } } + if( extensions->isVertexProgramSupported() ) + { + unsigned int index; + for( index = 0; index < _vertexAttribList.size(); ++index ) + { + const Array* array = _vertexAttribList[index].second.first.get(); + const IndexArray* indexArray = _vertexAttribList[index].second.second.get(); + + if( indexArray ) + { + if( indexArray->getNumElements() > 0 ) + { + drawVertexAttribMap[_vertexAttribBindingList[index]].push_back( + new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,indexArray) ); + } + } + else + { + drawVertexAttribMap[_vertexAttribBindingList[index]].push_back( + new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,0) ); + } + } + } + // disable all the vertex arrays in the slow path as we are // sending everything using glVertex etc. state.disableAllVertexArrays(); @@ -679,7 +942,15 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_OVERALL) drawColor(colorIndex++); if (secondaryColorBinding==BIND_OVERALL) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_OVERALL) drawFogCoord(fogCoordIndex++); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL]; + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } // set up vertex functor. DrawVertex drawVertex(_vertexArray.get(),_vertexIndices.get()); @@ -696,7 +967,16 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE_SET) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE_SET) drawFogCoord(fogCoordIndex++); - + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } + const PrimitiveSet* primitiveset = itr->get(); GLenum mode=primitiveset->getMode(); @@ -735,12 +1015,30 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } } if (_normalBinding==BIND_PER_VERTEX) drawNormal(vindex); if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); texItr!=drawTexCoordList.end(); @@ -779,13 +1077,30 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } } if (_normalBinding==BIND_PER_VERTEX) drawNormal(vindex); if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); texItr!=drawTexCoordList.end(); ++texItr) @@ -823,6 +1138,15 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } } unsigned int vindex=*primItr; @@ -831,6 +1155,15 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); texItr!=drawTexCoordList.end(); @@ -865,6 +1198,15 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } } unsigned int vindex=*primItr; @@ -873,6 +1215,15 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); texItr!=drawTexCoordList.end(); @@ -907,6 +1258,15 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } } unsigned int vindex=*primItr; @@ -915,6 +1275,15 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); + if ( extensions->isVertexProgramSupported() ) + { + DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; + + for( unsigned int i = 0; i < list.size(); ++i ) + { + ( *( list[i] ) )(vertexAttribIndex++); + } + } for(DrawTexCoordList::iterator texItr=drawTexCoordList.begin(); texItr!=drawTexCoordList.end(); @@ -1310,3 +1679,261 @@ void Geometry::computeCorrectBindingsAndArraySizes() // TODO colours and tex coords. } + +typedef buffered_value< ref_ptr > BufferedExtensions; +static BufferedExtensions s_extensions; + +Geometry::Extensions* Geometry::getExtensions(unsigned int contextID,bool createIfNotInitalized) +{ + if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Geometry::Extensions; + return s_extensions[contextID].get(); +} + +void Geometry::setExtensions(unsigned int contextID,Extensions* extensions) +{ + s_extensions[contextID] = extensions; +} + +Geometry::Extensions::Extensions() +{ + setupGLExtenions(); +} + +Geometry::Extensions::Extensions(const Extensions& rhs): + Referenced() +{ + _isVertexProgramSupported = rhs._isVertexProgramSupported; + _isSecondaryColorSupported = rhs._isSecondaryColorSupported; + _isFogCoordSupported = rhs._isFogCoordSupported; + _isMultiTexSupported = rhs._isMultiTexSupported; + _glFogCoordfv = rhs._glFogCoordfv; + _glSecondaryColor3ubv = rhs._glSecondaryColor3ubv; + _glSecondaryColor3fv = rhs._glSecondaryColor3fv; + _glMultiTexCoord1f = rhs._glMultiTexCoord1f; + _glMultiTexCoord2fv = rhs._glMultiTexCoord2fv; + _glMultiTexCoord3fv = rhs._glMultiTexCoord3fv; + _glMultiTexCoord4fv = rhs._glMultiTexCoord4fv; + _glVertexAttrib1s = rhs._glVertexAttrib1s; + _glVertexAttrib1f = rhs._glVertexAttrib1f; + _glVertexAttrib2fv = rhs._glVertexAttrib2fv; + _glVertexAttrib3fv = rhs._glVertexAttrib3fv; + _glVertexAttrib4fv = rhs._glVertexAttrib4fv; + _glVertexAttrib4ubv = rhs._glVertexAttrib4ubv; + _glVertexAttrib4Nubv = rhs._glVertexAttrib4Nubv; +} + + +void Geometry::Extensions::lowestCommonDenominator(const Extensions& rhs) +{ + if (!rhs._isVertexProgramSupported) _isVertexProgramSupported = false; + if (!rhs._isSecondaryColorSupported) _isSecondaryColorSupported = false; + if (!rhs._isFogCoordSupported) _isFogCoordSupported = false; + if (!rhs._isMultiTexSupported) _isMultiTexSupported = false; + + if (!rhs._glFogCoordfv) _glFogCoordfv = 0; + if (!rhs._glSecondaryColor3ubv) _glSecondaryColor3ubv = 0; + if (!rhs._glSecondaryColor3fv) _glSecondaryColor3fv = 0; + if (!rhs._glMultiTexCoord1f) _glMultiTexCoord1f = 0; + if (!rhs._glMultiTexCoord2fv) _glMultiTexCoord2fv = 0; + if (!rhs._glMultiTexCoord3fv) _glMultiTexCoord3fv = 0; + if (!rhs._glMultiTexCoord4fv) _glMultiTexCoord4fv = 0; + + if (!rhs._glVertexAttrib1s) _glVertexAttrib1s = 0; + if (!rhs._glVertexAttrib1f) _glVertexAttrib1f = 0; + if (!rhs._glVertexAttrib2fv) _glVertexAttrib2fv = 0; + if (!rhs._glVertexAttrib3fv) _glVertexAttrib3fv = 0; + if (!rhs._glVertexAttrib4fv) _glVertexAttrib4fv = 0; + if (!rhs._glVertexAttrib4ubv) _glVertexAttrib4ubv = 0; + if (!rhs._glVertexAttrib4Nubv) _glVertexAttrib4Nubv = 0; +} + +void Geometry::Extensions::setupGLExtenions() +{ + _isVertexProgramSupported = isGLExtensionSupported("GL_ARB_vertex_program"); + _isSecondaryColorSupported = isGLExtensionSupported("GL_EXT_secondary_color"); + _isFogCoordSupported = isGLExtensionSupported("GL_EXT_fog_coord"); + _isMultiTexSupported = isGLExtensionSupported("GL_ARB_multitexture"); + + _glFogCoordfv = ((FogCoordProc)osg::getGLExtensionFuncPtr("glFogCoordfv","glFogCoordfvEXT")); + _glSecondaryColor3ubv = ((SecondaryColor3ubvProc)osg::getGLExtensionFuncPtr("glSecondaryColor3ubv","glSecondaryColor3ubvEXT")); + _glSecondaryColor3fv = ((SecondaryColor3fvProc)osg::getGLExtensionFuncPtr("glSecondaryColor3fv","glSecondaryColor3fvEXT")); + _glMultiTexCoord1f = ((MultiTexCoord1fProc)osg::getGLExtensionFuncPtr("glMultiTexCoord1f","glMultiTexCoord1fARB")); + _glMultiTexCoord2fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord2fv","glMultiTexCoord2fvARB")); + _glMultiTexCoord3fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord3fv","glMultiTexCoord3fvARB")); + _glMultiTexCoord4fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord4fv","glMultiTexCoord4fvARB")); + + _glVertexAttrib1s = ((VertexAttrib1sProc)osg::getGLExtensionFuncPtr("glVertexAttrib1s","glVertexAttrib1sARB")); + _glVertexAttrib1f = ((VertexAttrib1fProc)osg::getGLExtensionFuncPtr("glVertexAttrib1f","glVertexAttrib1fARB")); + _glVertexAttrib2fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib2fv","glVertexAttrib2fvARB")); + _glVertexAttrib3fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib3fv","glVertexAttrib3fvARB")); + _glVertexAttrib4fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4fv","glVertexAttrib4fvARB")); + _glVertexAttrib4ubv = ((VertexAttribubvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4ubv","glVertexAttrib4ubvARB")); + _glVertexAttrib4Nubv = ((VertexAttribubvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4Nubv","glVertexAttrib4NubvARB")); +} +void Geometry::Extensions::glFogCoordfv(const GLfloat* coord) const +{ + if (_glFogCoordfv) + { + _glFogCoordfv(coord); + } + else + { + notify(WARN)<<"Error: glFogCoordfv not supported by OpenGL driver"< #include #include #include @@ -202,7 +201,7 @@ void State::captureCurrentState(StateSet& stateset) const // template // T mymax(const T& a,const T& b) // { -// return (((a) > (b)) ? (a) : (b)); +// return (((a) > (b)) ? (a) : (b)); // } void State::apply(const StateSet* dstate) @@ -491,6 +490,7 @@ void State::disableAllVertexArrays() { disableVertexPointer(); disableTexCoordPointersAboveAndIncluding(0); + disableVertexAttribPointersAboveAndIncluding(0); disableColorPointer(); disableFogCoordPointer(); disableIndexPointer(); @@ -502,6 +502,7 @@ void State::dirtyAllVertexArrays() { dirtyVertexPointer(); dirtyTexCoordPointersAboveAndIncluding(0); + dirtyVertexAttribPointersAboveAndIncluding(0); dirtyColorPointer(); dirtyFogCoordPointer(); dirtyIndexPointer(); diff --git a/src/osg/VertexProgram.cpp b/src/osg/VertexProgram.cpp index e90676763..72da1d9f6 100644 --- a/src/osg/VertexProgram.cpp +++ b/src/osg/VertexProgram.cpp @@ -119,7 +119,7 @@ void VertexProgram::apply(State& state) const } else if (!_vertexProgram.empty()) { - ::glGetError(); // Reset Error flags. + glGetError(); // Reset Error flags. extensions->glGenPrograms( 1, &vertexProgramId ); extensions->glBindProgram( GL_VERTEX_PROGRAM_ARB, vertexProgramId ); extensions->glProgramString( GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, @@ -127,10 +127,10 @@ void VertexProgram::apply(State& state) const // Check for errors GLint errorposition; - ::glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorposition); + glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorposition); if (errorposition != -1) { - notify(osg::FATAL) << "VertexProgram: " << ::glGetString(GL_PROGRAM_ERROR_STRING_ARB) << std::endl; + notify(osg::FATAL) << "VertexProgram: " << glGetString(GL_PROGRAM_ERROR_STRING_ARB) << std::endl; std::string::size_type start = _vertexProgram.rfind('\n', errorposition); std::string::size_type stop = _vertexProgram.find('\n', errorposition); @@ -161,10 +161,10 @@ void VertexProgram::apply(State& state) const itr!=_matrixList.end(); ++itr) { - ::glMatrixMode((*itr).first); - ::glLoadMatrixf((*itr).second.ptr()); + glMatrixMode((*itr).first); + glLoadMatrixf((*itr).second.ptr()); } - ::glMatrixMode(GL_MODELVIEW); // restore matrix mode + glMatrixMode(GL_MODELVIEW); // restore matrix mode } }