/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #ifndef OSG_PRIMITIVESET #define OSG_PRIMITIVESET 1 #include #include #include #include #include #include #include #include #include #include #include #include #define OSG_HAS_MULTIDRAWARRAYS namespace osg { typedef MixinVector VectorGLsizei; typedef MixinVector VectorGLubyte; typedef MixinVector VectorGLushort; typedef MixinVector VectorGLuint; class State; /** A \c PrimitiveFunctor is used (in conjunction with * osg::Drawable::accept (PrimitiveFunctor&)) to get access to the * primitives that compose the things drawn by OSG. *

If \c osg::Drawable::accept() is called with a \c PrimitiveFunctor * parameter, the \c Drawable will "pretend" it is drawing itself, but instead * of calling real OpenGL functions, it will call PrimitiveFunctor's * member functions that "mimic" the OpenGL calls. *

Concrete subclasses of \c PrimitiveFunctor must implement these methods * so that they performs whatever they want. */ class PrimitiveFunctor { public: virtual ~PrimitiveFunctor() {} /** Sets the array of vertices used to describe the primitives. Somehow * mimics the OpenGL \c glVertexPointer() function. */ virtual void setVertexArray(unsigned int count,const Vec2* vertices) = 0; /** Sets the array of vertices used to describe the primitives. Somehow * mimics the OpenGL \c glVertexPointer() function. */ virtual void setVertexArray(unsigned int count,const Vec3* vertices) = 0; /** Sets the array of vertices used to describe the primitives. Somehow * mimics the OpenGL \c glVertexPointer() function. */ virtual void setVertexArray(unsigned int count,const Vec4* vertices) = 0; /** Sets the array of vertices used to describe the primitives. Somehow * mimics the OpenGL \c glVertexPointer() function. */ virtual void setVertexArray(unsigned int count,const Vec2d* vertices) = 0; /** Sets the array of vertices used to describe the primitives. Somehow * mimics the OpenGL \c glVertexPointer() function. */ virtual void setVertexArray(unsigned int count,const Vec3d* vertices) = 0; /** Sets the array of vertices used to describe the primitives. Somehow * mimics the OpenGL \c glVertexPointer() function. */ virtual void setVertexArray(unsigned int count,const Vec4d* vertices) = 0; /// Mimics the OpenGL \c glDrawArrays() function. virtual void drawArrays(GLenum mode,GLint first,GLsizei count) = 0; /// Mimics the OpenGL \c glDrawElements() function. virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices) = 0; /// Mimics the OpenGL \c glDrawElements() function. virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices) = 0; /// Mimics the OpenGL \c glDrawElements() function. virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices) = 0; /// Mimics the OpenGL \c glBegin() function. virtual void begin(GLenum mode) = 0; /// Mimics the OpenGL \c glVertex() "family of functions". virtual void vertex(const Vec2& vert) = 0; /// Mimics the OpenGL \c glVertex() "family of functions". virtual void vertex(const Vec3& vert) = 0; /// Mimics the OpenGL \c glVertex() "family of functions". virtual void vertex(const Vec4& vert) = 0; /// Mimics the OpenGL \c glVertex() "family of functions". virtual void vertex(float x,float y) = 0; /// Mimics the OpenGL \c glVertex() "family of functions". virtual void vertex(float x,float y,float z) = 0; /// Mimics the OpenGL \c glVertex() "family of functions". virtual void vertex(float x,float y,float z,float w) = 0; /// Mimics the OpenGL \c glEnd() function. virtual void end() = 0; void useVertexCacheAsVertexArray() { setVertexArray(_vertexCache.size(),&_vertexCache.front()); } std::vector _vertexCache; bool _treatVertexDataAsTemporary; }; class PrimitiveIndexFunctor { public: virtual ~PrimitiveIndexFunctor() {} virtual void setVertexArray(unsigned int count,const Vec2* vertices) = 0; virtual void setVertexArray(unsigned int count,const Vec3* vertices) = 0; virtual void setVertexArray(unsigned int count,const Vec4* vertices) = 0; virtual void setVertexArray(unsigned int count,const Vec2d* vertices) = 0; virtual void setVertexArray(unsigned int count,const Vec3d* vertices) = 0; virtual void setVertexArray(unsigned int count,const Vec4d* vertices) = 0; virtual void drawArrays(GLenum mode,GLint first,GLsizei count) = 0; virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices) = 0; virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices) = 0; virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices) = 0; virtual void begin(GLenum mode) = 0; virtual void vertex(unsigned int pos) = 0; virtual void end() = 0; void useVertexCacheAsVertexArray() { setVertexArray(_vertexCache.size(),&_vertexCache.front()); } std::vector _vertexCache; bool _treatVertexDataAsTemporary; }; class DrawElements; class OSG_EXPORT PrimitiveSet : public BufferData { public: enum Type { PrimitiveType, DrawArraysPrimitiveType, DrawArrayLengthsPrimitiveType, DrawElementsUBytePrimitiveType, DrawElementsUShortPrimitiveType, DrawElementsUIntPrimitiveType, MultiDrawArraysPrimitiveType }; enum Mode { POINTS = GL_POINTS, LINES = GL_LINES, LINE_STRIP = GL_LINE_STRIP, LINE_LOOP = GL_LINE_LOOP, TRIANGLES = GL_TRIANGLES, TRIANGLE_STRIP = GL_TRIANGLE_STRIP, TRIANGLE_FAN = GL_TRIANGLE_FAN, QUADS = GL_QUADS, QUAD_STRIP = GL_QUAD_STRIP, POLYGON = GL_POLYGON, LINES_ADJACENCY = GL_LINES_ADJACENCY, LINE_STRIP_ADJACENCY = GL_LINE_STRIP_ADJACENCY, TRIANGLES_ADJACENCY = GL_TRIANGLES_ADJACENCY, TRIANGLE_STRIP_ADJACENCY = GL_TRIANGLE_STRIP_ADJACENCY, PATCHES = GL_PATCHES }; PrimitiveSet(Type primType=PrimitiveType,GLenum mode=0, int numInstances=0): _primitiveType(primType), _numInstances(numInstances), _mode(mode) {} PrimitiveSet(const PrimitiveSet& prim,const CopyOp& copyop=CopyOp::SHALLOW_COPY): BufferData(prim,copyop), _primitiveType(prim._primitiveType), _numInstances(prim._numInstances), _mode(prim._mode) {} virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "PrimitiveSet"; } Type getType() const { return _primitiveType; } virtual osg::PrimitiveSet* asPrimitiveSet() { return this; } virtual const osg::PrimitiveSet* asPrimitiveSet() const { return this; } virtual const GLvoid* getDataPointer() const { return 0; } virtual unsigned int getTotalDataSize() const { return 0; } virtual bool supportsBufferObject() const { return false; } virtual DrawElements* getDrawElements() { return 0; } virtual const DrawElements* getDrawElements() const { return 0; } void setNumInstances(int n) { _numInstances = n; } int getNumInstances() const { return _numInstances; } void setMode(GLenum mode) { _mode = mode; } GLenum getMode() const { return _mode; } virtual void draw(State& state, bool useVertexBufferObjects) const = 0; virtual void accept(PrimitiveFunctor& functor) const = 0; virtual void accept(PrimitiveIndexFunctor& functor) const = 0; virtual unsigned int index(unsigned int pos) const = 0; virtual unsigned int getNumIndices() const = 0; virtual void offsetIndices(int offset) = 0; virtual unsigned int getNumPrimitives() const; virtual void computeRange() const {} protected: virtual ~PrimitiveSet() {} Type _primitiveType; int _numInstances; GLenum _mode; }; class OSG_EXPORT DrawArrays : public PrimitiveSet { public: DrawArrays(GLenum mode=0): PrimitiveSet(DrawArraysPrimitiveType,mode), _first(0), _count(0) {} DrawArrays(GLenum mode, GLint first, GLsizei count, int numInstances=0): PrimitiveSet(DrawArraysPrimitiveType, mode, numInstances), _first(first), _count(count) {} DrawArrays(const DrawArrays& da,const CopyOp& copyop=CopyOp::SHALLOW_COPY): PrimitiveSet(da,copyop), _first(da._first), _count(da._count) {} virtual Object* cloneType() const { return new DrawArrays(); } virtual Object* clone(const CopyOp& copyop) const { return new DrawArrays(*this,copyop); } virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "DrawArrays"; } void set(GLenum mode,GLint first, GLsizei count) { _mode = mode; _first = first; _count = count; } void setFirst(GLint first) { _first = first; } GLint getFirst() const { return _first; } void setCount(GLsizei count) { _count = count; } GLsizei getCount() const { return _count; } virtual void draw(State& state, bool useVertexBufferObjects) const; virtual void accept(PrimitiveFunctor& functor) const; virtual void accept(PrimitiveIndexFunctor& functor) const; virtual unsigned int getNumIndices() const { return static_cast(_count); } virtual unsigned int index(unsigned int pos) const { return static_cast(_first)+pos; } virtual void offsetIndices(int offset) { _first += offset; } protected: virtual ~DrawArrays() {} GLint _first; GLsizei _count; }; class OSG_EXPORT DrawArrayLengths : public PrimitiveSet, public VectorGLsizei { public: typedef VectorGLsizei vector_type; DrawArrayLengths(GLenum mode=0): PrimitiveSet(DrawArrayLengthsPrimitiveType,mode), _first(0) {} DrawArrayLengths(const DrawArrayLengths& dal,const CopyOp& copyop=CopyOp::SHALLOW_COPY): PrimitiveSet(dal,copyop), vector_type(dal), _first(dal._first) {} DrawArrayLengths(GLenum mode, GLint first, unsigned int no, GLsizei* ptr) : PrimitiveSet(DrawArrayLengthsPrimitiveType,mode), vector_type(ptr,ptr+no), _first(first) {} DrawArrayLengths(GLenum mode,GLint first, unsigned int no) : PrimitiveSet(DrawArrayLengthsPrimitiveType,mode), vector_type(no), _first(first) {} DrawArrayLengths(GLenum mode,GLint first) : PrimitiveSet(DrawArrayLengthsPrimitiveType,mode), vector_type(), _first(first) {} virtual Object* cloneType() const { return new DrawArrayLengths(); } virtual Object* clone(const CopyOp& copyop) const { return new DrawArrayLengths(*this,copyop); } virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "DrawArrayLengths"; } void setFirst(GLint first) { _first = first; } GLint getFirst() const { return _first; } virtual void draw(State& state, bool useVertexBufferObjects) const; virtual void accept(PrimitiveFunctor& functor) const; virtual void accept(PrimitiveIndexFunctor& functor) const; virtual unsigned int getNumIndices() const; virtual unsigned int index(unsigned int pos) const { return _first+pos; } virtual void offsetIndices(int offset) { _first += offset; } virtual unsigned int getNumPrimitives() const; protected: virtual ~DrawArrayLengths() {} GLint _first; }; class DrawElements : public PrimitiveSet { public: DrawElements(Type primType=PrimitiveType, GLenum mode=0, int numInstances=0): PrimitiveSet(primType,mode, numInstances) {} DrawElements(const DrawElements& copy,const CopyOp& copyop=CopyOp::SHALLOW_COPY): PrimitiveSet(copy,copyop) {} virtual DrawElements* getDrawElements() { return this; } virtual const DrawElements* getDrawElements() const { return this; } /** Set the ElementBufferObject.*/ inline void setElementBufferObject(osg::ElementBufferObject* ebo) { setBufferObject(ebo); } /** Get the ElementBufferObject. If no EBO is assigned returns NULL*/ inline osg::ElementBufferObject* getElementBufferObject() { return dynamic_cast(_bufferObject.get()); } /** Get the const ElementBufferObject. If no EBO is assigned returns NULL*/ inline const osg::ElementBufferObject* getElementBufferObject() const { return dynamic_cast(_bufferObject.get()); } virtual GLenum getDataType() = 0; virtual void resizeElements(unsigned int numIndices) = 0; virtual void reserveElements(unsigned int numIndices) = 0; virtual void setElement(unsigned int, unsigned int) = 0; virtual unsigned int getElement(unsigned int) = 0; virtual void addElement(unsigned int) = 0; protected: virtual ~DrawElements() {} }; class OSG_EXPORT DrawElementsUByte : public DrawElements, public VectorGLubyte { public: typedef VectorGLubyte vector_type; DrawElementsUByte(GLenum mode=0): DrawElements(DrawElementsUBytePrimitiveType,mode) {} DrawElementsUByte(const DrawElementsUByte& array, const CopyOp& copyop=CopyOp::SHALLOW_COPY): DrawElements(array,copyop), vector_type(array) {} /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. * \param ptr Pointer to a GLubyte to copy index data from. * \param numInstances When non zero passed as the number of draw instances to use re. */ DrawElementsUByte(GLenum mode, unsigned int no, const GLubyte* ptr, int numInstances=0) : DrawElements(DrawElementsUBytePrimitiveType,mode,numInstances), vector_type(ptr,ptr+no) {} /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. */ DrawElementsUByte(GLenum mode, unsigned int no) : DrawElements(DrawElementsUBytePrimitiveType,mode), vector_type(no) {} virtual Object* cloneType() const { return new DrawElementsUByte(); } virtual Object* clone(const CopyOp& copyop) const { return new DrawElementsUByte(*this,copyop); } virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "DrawElementsUByte"; } virtual const GLvoid* getDataPointer() const { return empty()?0:&front(); } virtual unsigned int getTotalDataSize() const { return static_cast(size()); } virtual bool supportsBufferObject() const { return false; } virtual void draw(State& state, bool useVertexBufferObjects) const ; virtual void accept(PrimitiveFunctor& functor) const; virtual void accept(PrimitiveIndexFunctor& functor) const; virtual unsigned int getNumIndices() const { return static_cast(size()); } virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; } virtual void offsetIndices(int offset); virtual GLenum getDataType() { return GL_UNSIGNED_BYTE; } virtual void resizeElements(unsigned int numIndices) { resize(numIndices); } virtual void reserveElements(unsigned int numIndices) { reserve(numIndices); } virtual void setElement(unsigned int i, unsigned int v) { (*this)[i] = v; } virtual unsigned int getElement(unsigned int i) { return (*this)[i]; } virtual void addElement(unsigned int v) { push_back(GLubyte(v)); } protected: virtual ~DrawElementsUByte(); }; class OSG_EXPORT DrawElementsUShort : public DrawElements, public VectorGLushort { public: typedef VectorGLushort vector_type; DrawElementsUShort(GLenum mode=0): DrawElements(DrawElementsUShortPrimitiveType,mode) {} DrawElementsUShort(const DrawElementsUShort& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY): DrawElements(array,copyop), vector_type(array) {} /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. * \param ptr Pointer to a GLushort to copy index data from. * \param numInstances When non zero passed as the number of draw instances to use re. */ DrawElementsUShort(GLenum mode, unsigned int no, const GLushort* ptr, int numInstances=0) : DrawElements(DrawElementsUShortPrimitiveType,mode,numInstances), vector_type(ptr,ptr+no) {} /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. */ DrawElementsUShort(GLenum mode, unsigned int no) : DrawElements(DrawElementsUShortPrimitiveType,mode), vector_type(no) {} template DrawElementsUShort(GLenum mode, InputIterator first,InputIterator last) : DrawElements(DrawElementsUShortPrimitiveType,mode), vector_type(first,last) {} virtual Object* cloneType() const { return new DrawElementsUShort(); } virtual Object* clone(const CopyOp& copyop) const { return new DrawElementsUShort(*this,copyop); } virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "DrawElementsUShort"; } virtual const GLvoid* getDataPointer() const { return empty()?0:&front(); } virtual unsigned int getTotalDataSize() const { return 2u*static_cast(size()); } virtual bool supportsBufferObject() const { return false; } virtual void draw(State& state, bool useVertexBufferObjects) const; virtual void accept(PrimitiveFunctor& functor) const; virtual void accept(PrimitiveIndexFunctor& functor) const; virtual unsigned int getNumIndices() const { return static_cast(size()); } virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; } virtual void offsetIndices(int offset); virtual GLenum getDataType() { return GL_UNSIGNED_SHORT; } virtual void resizeElements(unsigned int numIndices) { resize(numIndices); } virtual void reserveElements(unsigned int numIndices) { reserve(numIndices); } virtual void setElement(unsigned int i, unsigned int v) { (*this)[i] = v; } virtual unsigned int getElement(unsigned int i) { return (*this)[i]; } virtual void addElement(unsigned int v) { push_back(GLushort(v)); } protected: virtual ~DrawElementsUShort(); }; class OSG_EXPORT DrawElementsUInt : public DrawElements, public VectorGLuint { public: typedef VectorGLuint vector_type; DrawElementsUInt(GLenum mode=0): DrawElements(DrawElementsUIntPrimitiveType,mode) {} DrawElementsUInt(const DrawElementsUInt& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY): DrawElements(array,copyop), vector_type(array) {} /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. * \param ptr Pointer to a GLuint to copy index data from. * \param numInstances When non zero passed as the number of draw instances to use re. */ DrawElementsUInt(GLenum mode, unsigned int no, const GLuint* ptr, int numInstances=0) : DrawElements(DrawElementsUIntPrimitiveType,mode,numInstances), vector_type(ptr,ptr+no) {} /** * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used. * \param no Number of intended elements. This will be the size of the underlying vector. */ DrawElementsUInt(GLenum mode, unsigned int no) : DrawElements(DrawElementsUIntPrimitiveType,mode), vector_type(no) {} template DrawElementsUInt(GLenum mode, InputIterator first,InputIterator last) : DrawElements(DrawElementsUIntPrimitiveType,mode), vector_type(first,last) {} virtual Object* cloneType() const { return new DrawElementsUInt(); } virtual Object* clone(const CopyOp& copyop) const { return new DrawElementsUInt(*this,copyop); } virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "DrawElementsUInt"; } virtual const GLvoid* getDataPointer() const { return empty()?0:&front(); } virtual unsigned int getTotalDataSize() const { return 4u*static_cast(size()); } virtual bool supportsBufferObject() const { return false; } virtual void draw(State& state, bool useVertexBufferObjects) const; virtual void accept(PrimitiveFunctor& functor) const; virtual void accept(PrimitiveIndexFunctor& functor) const; virtual unsigned int getNumIndices() const { return static_cast(size()); } virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; } virtual void offsetIndices(int offset); virtual GLenum getDataType() { return GL_UNSIGNED_INT; } virtual void resizeElements(unsigned int numIndices) { resize(numIndices); } virtual void reserveElements(unsigned int numIndices) { reserve(numIndices); } virtual void setElement(unsigned int i, unsigned int v) { (*this)[i] = v; } virtual unsigned int getElement(unsigned int i) { return (*this)[i]; } virtual void addElement(unsigned int v) { push_back(GLuint(v)); } protected: virtual ~DrawElementsUInt(); }; #ifdef OSG_HAS_MULTIDRAWARRAYS class OSG_EXPORT MultiDrawArrays : public osg::PrimitiveSet { public: MultiDrawArrays(GLenum mode=0): osg::PrimitiveSet(Type(MultiDrawArraysPrimitiveType), mode) {} MultiDrawArrays(const MultiDrawArrays& dal,const CopyOp& copyop=CopyOp::SHALLOW_COPY): osg::PrimitiveSet(dal,copyop), _firsts(dal._firsts), _counts(dal._counts) {} virtual osg::Object* cloneType() const { return new MultiDrawArrays(); } virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new MultiDrawArrays(*this,copyop); } virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "MultiDrawArrays"; } virtual void draw(osg::State& state, bool useVertexBufferObjects) const; virtual void accept(PrimitiveFunctor& functor) const; virtual void accept(PrimitiveIndexFunctor& functor) const; virtual unsigned int getNumIndices() const; virtual unsigned int index(unsigned int pos) const; virtual void offsetIndices(int offset); virtual unsigned int getNumPrimitives() const; typedef std::vector Firsts; void setFirsts(const Firsts& firsts) { _firsts = firsts; } Firsts& getFirsts() { return _firsts; } const Firsts& getFirsts() const { return _firsts; } typedef std::vector Counts; void setCounts(const Counts& firsts) { _counts = firsts; } Counts& getCounts() { return _counts; } const Counts& getCounts() const { return _counts; } void add(GLint first, GLsizei count); protected: Firsts _firsts; Counts _counts; }; #endif } #endif