From 888d9e2a259641e51f7f3780382d960b28f9ed90 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 29 Jun 2004 15:04:38 +0000 Subject: [PATCH] From Pavel Moloshtan, added support for storing primitive sets in VBO's --- include/osg/PrimitiveSet | 21 +++-- include/osg/Quat | 186 ++++++++++++++++++++++----------------- src/osg/Geometry.cpp | 2 +- src/osg/PrimitiveSet.cpp | 82 +++++++++++++++-- 4 files changed, 196 insertions(+), 95 deletions(-) diff --git a/include/osg/PrimitiveSet b/include/osg/PrimitiveSet index 235c973ef..536b9159d 100644 --- a/include/osg/PrimitiveSet +++ b/include/osg/PrimitiveSet @@ -130,7 +130,7 @@ class PrimitiveSet : public Object void setMode(GLenum mode) { _mode = mode; } GLenum getMode() const { return _mode; } - virtual void draw() const = 0; + virtual void draw(State& state, bool useVertexBufferObjects) const = 0; virtual void accept(Drawable::PrimitiveFunctor& functor) const = 0; virtual void accept(Drawable::PrimitiveIndexFunctor& functor) const = 0; @@ -204,7 +204,7 @@ class SG_EXPORT DrawArrays : public PrimitiveSet void setCount(GLsizei count) { _count = count; } GLsizei getCount() const { return _count; } - virtual void draw() const; + virtual void draw(State& state, bool useVertexBufferObjects) const; virtual void accept(Drawable::PrimitiveFunctor& functor) const; virtual void accept(Drawable::PrimitiveIndexFunctor& functor) const; @@ -260,7 +260,7 @@ class SG_EXPORT DrawArrayLengths : public PrimitiveSet, public VectorSizei void setFirst(GLint first) { _first = first; } GLint getFirst() const { return _first; } - virtual void draw() const; + virtual void draw(State& state, bool useVertexBufferObjects) const; virtual void accept(Drawable::PrimitiveFunctor& functor) const; virtual void accept(Drawable::PrimitiveIndexFunctor& functor) const; @@ -319,7 +319,7 @@ class SG_EXPORT DrawElementsUByte : public PrimitiveSet, public VectorUByte virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "DrawElementsUByte"; } - virtual void draw() const ; + virtual void draw(State& state, bool useVertexBufferObjects) const ; virtual void accept(Drawable::PrimitiveFunctor& functor) const; virtual void accept(Drawable::PrimitiveIndexFunctor& functor) const; @@ -330,6 +330,9 @@ class SG_EXPORT DrawElementsUByte : public PrimitiveSet, public VectorUByte protected: + typedef osg::buffered_value GLObjectList; + mutable GLObjectList _vboList; + virtual ~DrawElementsUByte() {} }; @@ -364,7 +367,7 @@ class SG_EXPORT DrawElementsUShort : public PrimitiveSet, public VectorUShort virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "DrawElementsUShort"; } - virtual void draw() const; + virtual void draw(State& state, bool useVertexBufferObjects) const; virtual void accept(Drawable::PrimitiveFunctor& functor) const; virtual void accept(Drawable::PrimitiveIndexFunctor& functor) const; @@ -375,6 +378,9 @@ class SG_EXPORT DrawElementsUShort : public PrimitiveSet, public VectorUShort protected: + typedef osg::buffered_value GLObjectList; + mutable GLObjectList _vboList; + virtual ~DrawElementsUShort() {} }; @@ -408,7 +414,7 @@ class SG_EXPORT DrawElementsUInt : public PrimitiveSet, public VectorUInt virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "DrawElementsUInt"; } - virtual void draw() const; + virtual void draw(State& state, bool useVertexBufferObjects) const; virtual void accept(Drawable::PrimitiveFunctor& functor) const; virtual void accept(Drawable::PrimitiveIndexFunctor& functor) const; @@ -419,6 +425,9 @@ class SG_EXPORT DrawElementsUInt : public PrimitiveSet, public VectorUInt protected: + typedef osg::buffered_value GLObjectList; + mutable GLObjectList _vboList; + virtual ~DrawElementsUInt() {} }; diff --git a/include/osg/Quat b/include/osg/Quat index 93cde38d8..9219147ae 100644 --- a/include/osg/Quat +++ b/include/osg/Quat @@ -33,11 +33,11 @@ class SG_EXPORT Quat typedef double value_type; - value_type _v[4]; // a four-vector + value_type _v[4]; // a four-vector - inline Quat() { _v[0]=0.0; _v[1]=0.0; _v[2]=0.0; _v[3]=1.0; } + inline Quat() { _v[0]=0.0; _v[1]=0.0; _v[2]=0.0; _v[3]=1.0; } - inline Quat( value_type x, value_type y, value_type z, value_type w ) + inline Quat( value_type x, value_type y, value_type z, value_type w ) { _v[0]=x; _v[1]=y; @@ -45,7 +45,7 @@ class SG_EXPORT Quat _v[3]=w; } - inline Quat( const Vec4f& v ) + inline Quat( const Vec4f& v ) { _v[0]=v.x(); _v[1]=v.y(); @@ -53,7 +53,7 @@ class SG_EXPORT Quat _v[3]=v.w(); } - inline Quat( const Vec4d& v ) + inline Quat( const Vec4d& v ) { _v[0]=v.x(); _v[1]=v.y(); @@ -100,18 +100,18 @@ class SG_EXPORT Quat } /* ---------------------------------- - Methods to access data members - ---------------------------------- */ + Methods to access data members + ---------------------------------- */ - inline Vec4d asVec4() const - { - return Vec4d(_v[0], _v[1], _v[2], _v[3]); - } + inline Vec4d asVec4() const + { + return Vec4d(_v[0], _v[1], _v[2], _v[3]); + } - inline Vec3d asVec3() const - { - return Vec3d(_v[0], _v[1], _v[2]); - } + inline Vec3d asVec3() const + { + return Vec3d(_v[0], _v[1], _v[2]); + } inline void set(value_type x, value_type y, value_type z, value_type w) { @@ -159,65 +159,65 @@ class SG_EXPORT Quat inline value_type z() const { return _v[2]; } inline value_type w() const { return _v[3]; } - /** return true if the Quat represents a zero rotation, and therefore can be ignored in computations.*/ - bool zeroRotation() const { return _v[0]==0.0 && _v[1]==0.0 && _v[2]==0.0 && _v[3]==1.0; } + /** return true if the Quat represents a zero rotation, and therefore can be ignored in computations.*/ + bool zeroRotation() const { return _v[0]==0.0 && _v[1]==0.0 && _v[2]==0.0 && _v[3]==1.0; } /* ------------------------------------------------------------- - BASIC ARITHMETIC METHODS - Implemented in terms of Vec4s. Some Vec4 operators, e.g. - operator* are not appropriate for quaternions (as - mathematical objects) so they are implemented differently. - Also define methods for conjugate and the multiplicative inverse. - ------------------------------------------------------------- */ - /// Multiply by scalar + BASIC ARITHMETIC METHODS + Implemented in terms of Vec4s. Some Vec4 operators, e.g. + operator* are not appropriate for quaternions (as + mathematical objects) so they are implemented differently. + Also define methods for conjugate and the multiplicative inverse. + ------------------------------------------------------------- */ + /// Multiply by scalar inline const Quat operator * (value_type rhs) const { return Quat(_v[0]*rhs, _v[1]*rhs, _v[2]*rhs, _v[3]*rhs); } - /// Unary multiply by scalar + /// Unary multiply by scalar inline Quat& operator *= (value_type rhs) { _v[0]*=rhs; _v[1]*=rhs; _v[2]*=rhs; _v[3]*=rhs; - return *this; // enable nesting + return *this; // enable nesting } - /// Binary multiply - inline const Quat operator*(const Quat& rhs) const - { - return Quat( rhs._v[3]*_v[0] + rhs._v[0]*_v[3] + rhs._v[1]*_v[2] - rhs._v[2]*_v[1], - rhs._v[3]*_v[1] - rhs._v[0]*_v[2] + rhs._v[1]*_v[3] + rhs._v[2]*_v[0], - rhs._v[3]*_v[2] + rhs._v[0]*_v[1] - rhs._v[1]*_v[0] + rhs._v[2]*_v[3], - rhs._v[3]*_v[3] - rhs._v[0]*_v[0] - rhs._v[1]*_v[1] - rhs._v[2]*_v[2] ); - } + /// Binary multiply + inline const Quat operator*(const Quat& rhs) const + { + return Quat( rhs._v[3]*_v[0] + rhs._v[0]*_v[3] + rhs._v[1]*_v[2] - rhs._v[2]*_v[1], + rhs._v[3]*_v[1] - rhs._v[0]*_v[2] + rhs._v[1]*_v[3] + rhs._v[2]*_v[0], + rhs._v[3]*_v[2] + rhs._v[0]*_v[1] - rhs._v[1]*_v[0] + rhs._v[2]*_v[3], + rhs._v[3]*_v[3] - rhs._v[0]*_v[0] - rhs._v[1]*_v[1] - rhs._v[2]*_v[2] ); + } - /// Unary multiply - inline Quat& operator*=(const Quat& rhs) - { - value_type x = rhs._v[3]*_v[0] + rhs._v[0]*_v[3] + rhs._v[1]*_v[2] - rhs._v[2]*_v[1]; - value_type y = rhs._v[3]*_v[1] - rhs._v[0]*_v[2] + rhs._v[1]*_v[3] + rhs._v[2]*_v[0]; - value_type z = rhs._v[3]*_v[2] + rhs._v[0]*_v[1] - rhs._v[1]*_v[0] + rhs._v[2]*_v[3]; - _v[3] = rhs._v[3]*_v[3] - rhs._v[0]*_v[0] - rhs._v[1]*_v[1] - rhs._v[2]*_v[2]; + /// Unary multiply + inline Quat& operator*=(const Quat& rhs) + { + value_type x = rhs._v[3]*_v[0] + rhs._v[0]*_v[3] + rhs._v[1]*_v[2] - rhs._v[2]*_v[1]; + value_type y = rhs._v[3]*_v[1] - rhs._v[0]*_v[2] + rhs._v[1]*_v[3] + rhs._v[2]*_v[0]; + value_type z = rhs._v[3]*_v[2] + rhs._v[0]*_v[1] - rhs._v[1]*_v[0] + rhs._v[2]*_v[3]; + _v[3] = rhs._v[3]*_v[3] - rhs._v[0]*_v[0] - rhs._v[1]*_v[1] - rhs._v[2]*_v[2]; - _v[2] = z; - _v[1] = y; - _v[0] = x; + _v[2] = z; + _v[1] = y; + _v[0] = x; - return (*this); // enable nesting - } + return (*this); // enable nesting + } - /// Divide by scalar + /// Divide by scalar inline Quat operator / (value_type rhs) const { value_type div = 1.0/rhs; return Quat(_v[0]*div, _v[1]*div, _v[2]*div, _v[3]*div); } - /// Unary divide by scalar + /// Unary divide by scalar inline Quat& operator /= (value_type rhs) { value_type div = 1.0/rhs; @@ -228,41 +228,41 @@ class SG_EXPORT Quat return *this; } - /// Binary divide - inline const Quat operator/(const Quat& denom) const - { - return ( (*this) * denom.inverse() ); - } + /// Binary divide + inline const Quat operator/(const Quat& denom) const + { + return ( (*this) * denom.inverse() ); + } - /// Unary divide - inline Quat& operator/=(const Quat& denom) - { - (*this) = (*this) * denom.inverse(); - return (*this); // enable nesting - } + /// Unary divide + inline Quat& operator/=(const Quat& denom) + { + (*this) = (*this) * denom.inverse(); + return (*this); // enable nesting + } - /// Binary addition + /// Binary addition inline const Quat operator + (const Quat& rhs) const { return Quat(_v[0]+rhs._v[0], _v[1]+rhs._v[1], - _v[2]+rhs._v[2], _v[3]+rhs._v[3]); + _v[2]+rhs._v[2], _v[3]+rhs._v[3]); } - /// Unary addition + /// Unary addition inline Quat& operator += (const Quat& rhs) { _v[0] += rhs._v[0]; _v[1] += rhs._v[1]; _v[2] += rhs._v[2]; _v[3] += rhs._v[3]; - return *this; // enable nesting + return *this; // enable nesting } /// Binary subtraction inline const Quat operator - (const Quat& rhs) const { return Quat(_v[0]-rhs._v[0], _v[1]-rhs._v[1], - _v[2]-rhs._v[2], _v[3]-rhs._v[3] ); + _v[2]-rhs._v[2], _v[3]-rhs._v[3] ); } /// Unary subtraction @@ -272,11 +272,11 @@ class SG_EXPORT Quat _v[1]-=rhs._v[1]; _v[2]-=rhs._v[2]; _v[3]-=rhs._v[3]; - return *this; // enable nesting + return *this; // enable nesting } /** Negation operator - returns the negative of the quaternion. - Basically just calls operator - () on the Vec4 */ + Basically just calls operator - () on the Vec4 */ inline const Quat operator - () const { return Quat (-_v[0], -_v[1], -_v[2], -_v[3]); @@ -307,15 +307,15 @@ class SG_EXPORT Quat } /* -------------------------------------------------------- - METHODS RELATED TO ROTATIONS - Set a quaternion which will perform a rotation of an - angle around the axis given by the vector (x,y,z). - Should be written to also accept an angle and a Vec3? + METHODS RELATED TO ROTATIONS + Set a quaternion which will perform a rotation of an + angle around the axis given by the vector (x,y,z). + Should be written to also accept an angle and a Vec3? - Define Spherical Linear interpolation method also + Define Spherical Linear interpolation method also - Not inlined - see the Quat.cpp file for implementation - -------------------------------------------------------- */ + Not inlined - see the Quat.cpp file for implementation + -------------------------------------------------------- */ void makeRotate( value_type angle, value_type x, value_type y, value_type z ); void makeRotate ( value_type angle, const Vec3f& vec ); @@ -351,24 +351,50 @@ class SG_EXPORT Quat void getRotate ( value_type & angle, Vec3d& vec ) const; /** Spherical Linear Interpolation. - As t goes from 0 to 1, the Quat object goes from "from" to "to". */ + As t goes from 0 to 1, the Quat object goes from "from" to "to". */ void slerp ( value_type t, const Quat& from, const Quat& to); + /** Rotate a vector by this quaternion.*/ + Vec3f operator* (const Vec3f& v) const + { + // nVidia SDK implementation + Vec3f uv, uuv; + Vec3f qvec(_v[0], _v[1], _v[2]); + uv = qvec ^ v; + uuv = qvec ^ uv; + uv *= ( 2.0f * _v[3] ); + uuv *= 2.0f; + return v + uv + uuv; + } + + /** Rotate a vector by this quaternion.*/ + Vec3d operator* (const Vec3d& v) const + { + // nVidia SDK implementation + Vec3d uv, uuv; + Vec3d qvec(_v[0], _v[1], _v[2]); + uv = qvec ^ v; + uuv = qvec ^ uv; + uv *= ( 2.0f * _v[3] ); + uuv *= 2.0f; + return v + uv + uuv; + } + friend inline std::ostream& operator << (std::ostream& output, const Quat& vec); protected: -}; // end of class prototype +}; // end of class prototype inline std::ostream& operator << (std::ostream& output, const Quat& vec) { output << vec._v[0] << " " - << vec._v[1] << " " - << vec._v[2] << " " - << vec._v[3]; - return output; // to enable cascading + << vec._v[1] << " " + << vec._v[2] << " " + << vec._v[3]; + return output; // to enable cascading } -} // end of namespace +} // end of namespace #endif diff --git a/src/osg/Geometry.cpp b/src/osg/Geometry.cpp index 145e202ae..cac1c4bce 100644 --- a/src/osg/Geometry.cpp +++ b/src/osg/Geometry.cpp @@ -1148,7 +1148,7 @@ void Geometry::drawImplementation(State& state) const } } - (*itr)->draw(); + (*itr)->draw(state, usingVertexBufferObjects); } diff --git a/src/osg/PrimitiveSet.cpp b/src/osg/PrimitiveSet.cpp index 251e902c1..f125c8f82 100644 --- a/src/osg/PrimitiveSet.cpp +++ b/src/osg/PrimitiveSet.cpp @@ -14,7 +14,7 @@ using namespace osg; -void DrawArrays::draw() const +void DrawArrays::draw(State&, bool) const { glDrawArrays(_mode,_first,_count); } @@ -29,7 +29,7 @@ void DrawArrays::accept(Drawable::PrimitiveIndexFunctor& functor) const functor.drawArrays(_mode,_first,_count); } -void DrawArrayLengths::draw() const +void DrawArrayLengths::draw(State&, bool) const { GLint first = _first; for(VectorSizei::const_iterator itr=begin(); @@ -77,9 +77,31 @@ unsigned int DrawArrayLengths::getNumIndices() const return count; } -void DrawElementsUByte::draw() const +void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const { - glDrawElements(_mode,size(),GL_UNSIGNED_BYTE,&front()); + if (useVertexBufferObjects) + { + const Drawable::Extensions* extensions = Drawable::getExtensions(state.getContextID(), true); + + GLuint& buffer = _vboList[state.getContextID()]; + if (!buffer) + { + extensions->glGenBuffers(1, &buffer); + extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); + extensions->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, size() * sizeof(GL_UNSIGNED_BYTE), &front(), GL_STATIC_DRAW_ARB); + } + else + { + extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); + } + + glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, 0); + extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + } + else + { + glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, &front()); + } } void DrawElementsUByte::accept(Drawable::PrimitiveFunctor& functor) const @@ -103,9 +125,31 @@ void DrawElementsUByte::offsetIndices(int offset) } -void DrawElementsUShort::draw() const +void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const { - glDrawElements(_mode,size(),GL_UNSIGNED_SHORT,&front()); + if (useVertexBufferObjects) + { + const Drawable::Extensions* extensions = Drawable::getExtensions(state.getContextID(), true); + + GLuint& buffer = _vboList[state.getContextID()]; + if (!buffer) + { + extensions->glGenBuffers(1, &buffer); + extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); + extensions->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, size() * sizeof(GL_UNSIGNED_SHORT), &front(), GL_STATIC_DRAW_ARB); + } + else + { + extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); + } + + glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, 0); + extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + } + else + { + glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, &front()); + } } void DrawElementsUShort::accept(Drawable::PrimitiveFunctor& functor) const @@ -129,9 +173,31 @@ void DrawElementsUShort::offsetIndices(int offset) } -void DrawElementsUInt::draw() const +void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const { - glDrawElements(_mode,size(),GL_UNSIGNED_INT,&front()); + if (useVertexBufferObjects) + { + const Drawable::Extensions* extensions = Drawable::getExtensions(state.getContextID(), true); + + GLuint& buffer = _vboList[state.getContextID()]; + if (!buffer) + { + extensions->glGenBuffers(1, &buffer); + extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); + extensions->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, size() * sizeof(GL_UNSIGNED_INT), &front(), GL_STATIC_DRAW_ARB); + } + else + { + extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); + } + + glDrawElements(_mode, size(), GL_UNSIGNED_INT, 0); + extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + } + else + { + glDrawElements(_mode, size(), GL_UNSIGNED_INT, &front()); + } } void DrawElementsUInt::accept(Drawable::PrimitiveFunctor& functor) const