1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
14#ifndef OSG_PRIMITIVESET
15#define OSG_PRIMITIVESET 1
19#include <osg/buffered_value>
26#include <osg/MixinVector>
28#include <osg/BufferObject>
32#define OSG_HAS_MULTIDRAWARRAYS
36typedef MixinVector<GLsizei> VectorGLsizei;
37typedef MixinVector<GLubyte> VectorGLubyte;
38typedef MixinVector<GLushort> VectorGLushort;
39typedef MixinVector<GLuint> VectorGLuint;
43/** A \c PrimitiveFunctor is used (in conjunction with
44 * <tt>osg::Drawable::accept (PrimitiveFunctor&)</tt>) to get access to the
45 * primitives that compose the things drawn by OSG.
46 * <p>If \c osg::Drawable::accept() is called with a \c PrimitiveFunctor
47 * parameter, the \c Drawable will "pretend" it is drawing itself, but instead
48 * of calling real OpenGL functions, it will call <tt>PrimitiveFunctor</tt>'s
49 * member functions that "mimic" the OpenGL calls.
50 * <p>Concrete subclasses of \c PrimitiveFunctor must implement these methods
51 * so that they performs whatever they want.
57 virtual ~PrimitiveFunctor() {}
59 /** Sets the array of vertices used to describe the primitives. Somehow
60 * mimics the OpenGL \c glVertexPointer() function.
62 virtual void setVertexArray(unsigned int count,const Vec2* vertices) = 0;
64 /** Sets the array of vertices used to describe the primitives. Somehow
65 * mimics the OpenGL \c glVertexPointer() function.
67 virtual void setVertexArray(unsigned int count,const Vec3* vertices) = 0;
69 /** Sets the array of vertices used to describe the primitives. Somehow
70 * mimics the OpenGL \c glVertexPointer() function.
72 virtual void setVertexArray(unsigned int count,const Vec4* vertices) = 0;
74 /** Sets the array of vertices used to describe the primitives. Somehow
75 * mimics the OpenGL \c glVertexPointer() function.
77 virtual void setVertexArray(unsigned int count,const Vec2d* vertices) = 0;
79 /** Sets the array of vertices used to describe the primitives. Somehow
80 * mimics the OpenGL \c glVertexPointer() function.
82 virtual void setVertexArray(unsigned int count,const Vec3d* vertices) = 0;
84 /** Sets the array of vertices used to describe the primitives. Somehow
85 * mimics the OpenGL \c glVertexPointer() function.
87 virtual void setVertexArray(unsigned int count,const Vec4d* vertices) = 0;
89 /// Mimics the OpenGL \c glDrawArrays() function.
90 virtual void drawArrays(GLenum mode,GLint first,GLsizei count) = 0;
92 /// Mimics the OpenGL \c glDrawElements() function.
93 virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices) = 0;
95 /// Mimics the OpenGL \c glDrawElements() function.
96 virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices) = 0;
98 /// Mimics the OpenGL \c glDrawElements() function.
99 virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices) = 0;
102class PrimitiveIndexFunctor
106 virtual ~PrimitiveIndexFunctor() {}
108 virtual void setVertexArray(unsigned int count,const Vec2* vertices) = 0;
109 virtual void setVertexArray(unsigned int count,const Vec3* vertices) = 0;
110 virtual void setVertexArray(unsigned int count,const Vec4* vertices) = 0;
112 virtual void setVertexArray(unsigned int count,const Vec2d* vertices) = 0;
113 virtual void setVertexArray(unsigned int count,const Vec3d* vertices) = 0;
114 virtual void setVertexArray(unsigned int count,const Vec4d* vertices) = 0;
116 virtual void drawArrays(GLenum mode,GLint first,GLsizei count) = 0;
117 virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices) = 0;
118 virtual void drawElements(GLenum mode,GLsizei count,const GLushort* indices) = 0;
119 virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices) = 0;
124class OSG_EXPORT PrimitiveSet : public BufferData
131 DrawArraysPrimitiveType,
132 DrawArrayLengthsPrimitiveType,
133 DrawElementsUBytePrimitiveType,
134 DrawElementsUShortPrimitiveType,
135 DrawElementsUIntPrimitiveType,
136 MultiDrawArraysPrimitiveType,
137 DrawArraysIndirectPrimitiveType,
138 DrawElementsUByteIndirectPrimitiveType,
139 DrawElementsUShortIndirectPrimitiveType,
140 DrawElementsUIntIndirectPrimitiveType,
141 MultiDrawArraysIndirectPrimitiveType,
142 MultiDrawElementsUByteIndirectPrimitiveType,
143 MultiDrawElementsUShortIndirectPrimitiveType,
144 MultiDrawElementsUIntIndirectPrimitiveType
151 LINE_STRIP = GL_LINE_STRIP,
152 LINE_LOOP = GL_LINE_LOOP,
153 TRIANGLES = GL_TRIANGLES,
154 TRIANGLE_STRIP = GL_TRIANGLE_STRIP,
155 TRIANGLE_FAN = GL_TRIANGLE_FAN,
157 QUAD_STRIP = GL_QUAD_STRIP,
158 POLYGON = GL_POLYGON,
159 LINES_ADJACENCY = GL_LINES_ADJACENCY,
160 LINE_STRIP_ADJACENCY = GL_LINE_STRIP_ADJACENCY,
161 TRIANGLES_ADJACENCY = GL_TRIANGLES_ADJACENCY,
162 TRIANGLE_STRIP_ADJACENCY = GL_TRIANGLE_STRIP_ADJACENCY,
166 PrimitiveSet(Type primType=PrimitiveType,GLenum mode=0, int numInstances=0):
167 _primitiveType(primType),
168 _numInstances(numInstances),
171 PrimitiveSet(const PrimitiveSet& prim,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
172 BufferData(prim,copyop),
173 _primitiveType(prim._primitiveType),
174 _numInstances(prim._numInstances),
177 virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const PrimitiveSet*>(obj)!=NULL; }
178 virtual const char* libraryName() const { return "osg"; }
179 virtual const char* className() const { return "PrimitiveSet"; }
181 Type getType() const { return _primitiveType; }
183 virtual osg::PrimitiveSet* asPrimitiveSet() { return this; }
184 virtual const osg::PrimitiveSet* asPrimitiveSet() const { return this; }
186 virtual const GLvoid* getDataPointer() const { return 0; }
187 virtual unsigned int getTotalDataSize() const { return 0; }
188 virtual bool supportsBufferObject() const { return false; }
190 virtual DrawElements* getDrawElements() { return 0; }
191 virtual const DrawElements* getDrawElements() const { return 0; }
193 void setNumInstances(int n) { _numInstances = n; }
194 int getNumInstances() const { return _numInstances; }
196 void setMode(GLenum mode) { _mode = mode; }
197 GLenum getMode() const { return _mode; }
199 virtual void draw(State& state, bool useVertexBufferObjects) const = 0;
201 virtual void accept(PrimitiveFunctor& functor) const = 0;
202 virtual void accept(PrimitiveIndexFunctor& functor) const = 0;
204 virtual unsigned int index(unsigned int pos) const = 0;
205 virtual unsigned int getNumIndices() const = 0;
206 virtual void offsetIndices(int offset) = 0;
208 virtual unsigned int getNumPrimitives() const;
210 virtual void computeRange() const {}
214 virtual ~PrimitiveSet() {}
221class OSG_EXPORT DrawArrays : public PrimitiveSet
225 DrawArrays(GLenum mode=0):
226 PrimitiveSet(DrawArraysPrimitiveType,mode),
230 DrawArrays(GLenum mode, GLint first, GLsizei count, int numInstances=0):
231 PrimitiveSet(DrawArraysPrimitiveType, mode, numInstances),
235 DrawArrays(const DrawArrays& da,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
236 PrimitiveSet(da,copyop),
240 virtual Object* cloneType() const { return new DrawArrays(); }
241 virtual Object* clone(const CopyOp& copyop) const { return new DrawArrays(*this,copyop); }
242 virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const DrawArrays*>(obj)!=NULL; }
243 virtual const char* libraryName() const { return "osg"; }
244 virtual const char* className() const { return "DrawArrays"; }
247 void set(GLenum mode,GLint first, GLsizei count)
254 void setFirst(GLint first) { _first = first; }
255 GLint getFirst() const { return _first; }
257 void setCount(GLsizei count) { _count = count; }
258 GLsizei getCount() const { return _count; }
260 virtual void draw(State& state, bool useVertexBufferObjects) const;
262 virtual void accept(PrimitiveFunctor& functor) const;
263 virtual void accept(PrimitiveIndexFunctor& functor) const;
265 virtual unsigned int getNumIndices() const { return static_cast<unsigned int>(_count); }
266 virtual unsigned int index(unsigned int pos) const { return static_cast<unsigned int>(_first)+pos; }
267 virtual void offsetIndices(int offset) { _first += offset; }
271 virtual ~DrawArrays() {}
277class OSG_EXPORT DrawArrayLengths : public PrimitiveSet, public VectorGLsizei
281 typedef VectorGLsizei vector_type;
283 DrawArrayLengths(GLenum mode=0):
284 PrimitiveSet(DrawArrayLengthsPrimitiveType,mode),
287 DrawArrayLengths(const DrawArrayLengths& dal,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
288 PrimitiveSet(dal,copyop),
290 _first(dal._first) {}
292 DrawArrayLengths(GLenum mode, GLint first, unsigned int no, GLsizei* ptr) :
293 PrimitiveSet(DrawArrayLengthsPrimitiveType,mode),
294 vector_type(ptr,ptr+no),
297 DrawArrayLengths(GLenum mode,GLint first, unsigned int no) :
298 PrimitiveSet(DrawArrayLengthsPrimitiveType,mode),
302 DrawArrayLengths(GLenum mode,GLint first) :
303 PrimitiveSet(DrawArrayLengthsPrimitiveType,mode),
308 virtual Object* cloneType() const { return new DrawArrayLengths(); }
309 virtual Object* clone(const CopyOp& copyop) const { return new DrawArrayLengths(*this,copyop); }
310 virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const DrawArrayLengths*>(obj)!=NULL; }
311 virtual const char* libraryName() const { return "osg"; }
312 virtual const char* className() const { return "DrawArrayLengths"; }
315 void setFirst(GLint first) { _first = first; }
316 GLint getFirst() const { return _first; }
318 virtual void draw(State& state, bool useVertexBufferObjects) const;
320 virtual void accept(PrimitiveFunctor& functor) const;
321 virtual void accept(PrimitiveIndexFunctor& functor) const;
323 virtual unsigned int getNumIndices() const;
324 virtual unsigned int index(unsigned int pos) const { return _first+pos; }
325 virtual void offsetIndices(int offset) { _first += offset; }
327 virtual unsigned int getNumPrimitives() const;
331 virtual ~DrawArrayLengths() {}
336class DrawElements : public PrimitiveSet
340 DrawElements(Type primType=PrimitiveType, GLenum mode=0, int numInstances=0):
341 PrimitiveSet(primType,mode, numInstances) {}
343 DrawElements(const DrawElements& copy,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
344 PrimitiveSet(copy,copyop) {}
347 virtual DrawElements* getDrawElements() { return this; }
348 virtual const DrawElements* getDrawElements() const { return this; }
350 /** Set the ElementBufferObject.*/
351 inline void setElementBufferObject(osg::ElementBufferObject* ebo) { setBufferObject(ebo); }
353 /** Get the ElementBufferObject. If no EBO is assigned returns NULL*/
354 inline osg::ElementBufferObject* getElementBufferObject() { return dynamic_cast<osg::ElementBufferObject*>(_bufferObject.get()); }
356 /** Get the const ElementBufferObject. If no EBO is assigned returns NULL*/
357 inline const osg::ElementBufferObject* getElementBufferObject() const { return dynamic_cast<const osg::ElementBufferObject*>(_bufferObject.get()); }
359 virtual GLenum getDataType() = 0;
360 virtual void resizeElements(unsigned int numIndices) = 0;
361 virtual void reserveElements(unsigned int numIndices) = 0;
362 virtual void setElement(unsigned int, unsigned int) = 0;
363 virtual unsigned int getElement(unsigned int) = 0;
364 virtual void addElement(unsigned int) = 0;
368 virtual ~DrawElements() {}
371class OSG_EXPORT DrawElementsUByte : public DrawElements, public VectorGLubyte
375 typedef VectorGLubyte vector_type;
377 DrawElementsUByte(GLenum mode=0):
378 DrawElements(DrawElementsUBytePrimitiveType,mode) {}
380 DrawElementsUByte(const DrawElementsUByte& array, const CopyOp& copyop=CopyOp::SHALLOW_COPY):
381 DrawElements(array,copyop),
382 vector_type(array) {}
385 * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used.
386 * \param no Number of intended elements. This will be the size of the underlying vector.
387 * \param ptr Pointer to a GLubyte to copy index data from.
388 * \param numInstances When non zero passed as the number of draw instances to use re.
390 DrawElementsUByte(GLenum mode, unsigned int no, const GLubyte* ptr, int numInstances=0) :
391 DrawElements(DrawElementsUBytePrimitiveType,mode,numInstances),
392 vector_type(ptr,ptr+no) {}
395 * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used.
396 * \param no Number of intended elements. This will be the size of the underlying vector.
398 DrawElementsUByte(GLenum mode, unsigned int no) :
399 DrawElements(DrawElementsUBytePrimitiveType,mode),
402 virtual Object* cloneType() const { return new DrawElementsUByte(); }
403 virtual Object* clone(const CopyOp& copyop) const { return new DrawElementsUByte(*this,copyop); }
404 virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const DrawElementsUByte*>(obj)!=NULL; }
405 virtual const char* libraryName() const { return "osg"; }
406 virtual const char* className() const { return "DrawElementsUByte"; }
408 virtual const GLvoid* getDataPointer() const { return empty()?0:&front(); }
409 virtual unsigned int getTotalDataSize() const { return static_cast<unsigned int>(size()); }
410 virtual bool supportsBufferObject() const { return false; }
412 virtual void draw(State& state, bool useVertexBufferObjects) const ;
414 virtual void accept(PrimitiveFunctor& functor) const;
415 virtual void accept(PrimitiveIndexFunctor& functor) const;
417 virtual unsigned int getNumIndices() const { return static_cast<unsigned int>(size()); }
418 virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; }
419 virtual void offsetIndices(int offset);
421 virtual GLenum getDataType() { return GL_UNSIGNED_BYTE; }
422 virtual void resizeElements(unsigned int numIndices) { resize(numIndices); }
423 virtual void reserveElements(unsigned int numIndices) { reserve(numIndices); }
424 virtual void setElement(unsigned int i, unsigned int v) { (*this)[i] = v; }
425 virtual unsigned int getElement(unsigned int i) { return (*this)[i]; }
426 virtual void addElement(unsigned int v) { push_back(GLubyte(v)); }
430 virtual ~DrawElementsUByte();
434class OSG_EXPORT DrawElementsUShort : public DrawElements, public VectorGLushort
438 typedef VectorGLushort vector_type;
440 DrawElementsUShort(GLenum mode=0):
441 DrawElements(DrawElementsUShortPrimitiveType,mode) {}
443 DrawElementsUShort(const DrawElementsUShort& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
444 DrawElements(array,copyop),
445 vector_type(array) {}
448 * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used.
449 * \param no Number of intended elements. This will be the size of the underlying vector.
450 * \param ptr Pointer to a GLushort to copy index data from.
451 * \param numInstances When non zero passed as the number of draw instances to use re.
453 DrawElementsUShort(GLenum mode, unsigned int no, const GLushort* ptr, int numInstances=0) :
454 DrawElements(DrawElementsUShortPrimitiveType,mode,numInstances),
455 vector_type(ptr,ptr+no) {}
458 * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used.
459 * \param no Number of intended elements. This will be the size of the underlying vector.
461 DrawElementsUShort(GLenum mode, unsigned int no) :
462 DrawElements(DrawElementsUShortPrimitiveType,mode),
465 template <class InputIterator>
466 DrawElementsUShort(GLenum mode, InputIterator first,InputIterator last) :
467 DrawElements(DrawElementsUShortPrimitiveType,mode),
468 vector_type(first,last) {}
470 virtual Object* cloneType() const { return new DrawElementsUShort(); }
471 virtual Object* clone(const CopyOp& copyop) const { return new DrawElementsUShort(*this,copyop); }
472 virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const DrawElementsUShort*>(obj)!=NULL; }
473 virtual const char* libraryName() const { return "osg"; }
474 virtual const char* className() const { return "DrawElementsUShort"; }
476 virtual const GLvoid* getDataPointer() const { return empty()?0:&front(); }
477 virtual unsigned int getTotalDataSize() const { return 2u*static_cast<unsigned int>(size()); }
478 virtual bool supportsBufferObject() const { return false; }
480 virtual void draw(State& state, bool useVertexBufferObjects) const;
482 virtual void accept(PrimitiveFunctor& functor) const;
483 virtual void accept(PrimitiveIndexFunctor& functor) const;
485 virtual unsigned int getNumIndices() const { return static_cast<unsigned int>(size()); }
486 virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; }
487 virtual void offsetIndices(int offset);
489 virtual GLenum getDataType() { return GL_UNSIGNED_SHORT; }
490 virtual void resizeElements(unsigned int numIndices) { resize(numIndices); }
491 virtual void reserveElements(unsigned int numIndices) { reserve(numIndices); }
492 virtual void setElement(unsigned int i, unsigned int v) { (*this)[i] = v; }
493 virtual unsigned int getElement(unsigned int i) { return (*this)[i]; }
494 virtual void addElement(unsigned int v) { push_back(GLushort(v)); }
498 virtual ~DrawElementsUShort();
501class OSG_EXPORT DrawElementsUInt : public DrawElements, public VectorGLuint
505 typedef VectorGLuint vector_type;
507 DrawElementsUInt(GLenum mode=0):
508 DrawElements(DrawElementsUIntPrimitiveType,mode) {}
510 DrawElementsUInt(const DrawElementsUInt& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
511 DrawElements(array,copyop),
512 vector_type(array) {}
515 * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used.
516 * \param no Number of intended elements. This will be the size of the underlying vector.
517 * \param ptr Pointer to a GLuint to copy index data from.
518 * \param numInstances When non zero passed as the number of draw instances to use re.
520 DrawElementsUInt(GLenum mode, unsigned int no, const GLuint* ptr, int numInstances=0) :
521 DrawElements(DrawElementsUIntPrimitiveType,mode,numInstances),
522 vector_type(ptr,ptr+no) {}
525 * \param mode One of osg::PrimitiveSet::Mode. Determines the type of primitives used.
526 * \param no Number of intended elements. This will be the size of the underlying vector.
528 DrawElementsUInt(GLenum mode, unsigned int no) :
529 DrawElements(DrawElementsUIntPrimitiveType,mode),
532 template <class InputIterator>
533 DrawElementsUInt(GLenum mode, InputIterator first,InputIterator last) :
534 DrawElements(DrawElementsUIntPrimitiveType,mode),
535 vector_type(first,last) {}
537 virtual Object* cloneType() const { return new DrawElementsUInt(); }
538 virtual Object* clone(const CopyOp& copyop) const { return new DrawElementsUInt(*this,copyop); }
539 virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const DrawElementsUInt*>(obj)!=NULL; }
540 virtual const char* libraryName() const { return "osg"; }
541 virtual const char* className() const { return "DrawElementsUInt"; }
543 virtual const GLvoid* getDataPointer() const { return empty()?0:&front(); }
544 virtual unsigned int getTotalDataSize() const { return 4u*static_cast<unsigned int>(size()); }
545 virtual bool supportsBufferObject() const { return false; }
547 virtual void draw(State& state, bool useVertexBufferObjects) const;
549 virtual void accept(PrimitiveFunctor& functor) const;
550 virtual void accept(PrimitiveIndexFunctor& functor) const;
552 virtual unsigned int getNumIndices() const { return static_cast<unsigned int>(size()); }
553 virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; }
554 virtual void offsetIndices(int offset);
556 virtual GLenum getDataType() { return GL_UNSIGNED_INT; }
557 virtual void resizeElements(unsigned int numIndices) { resize(numIndices); }
558 virtual void reserveElements(unsigned int numIndices) { reserve(numIndices); }
559 virtual void setElement(unsigned int i, unsigned int v) { (*this)[i] = v; }
560 virtual unsigned int getElement(unsigned int i) { return (*this)[i]; }
561 virtual void addElement(unsigned int v) { push_back(GLuint(v)); }
565 virtual ~DrawElementsUInt();
568#ifdef OSG_HAS_MULTIDRAWARRAYS
569class OSG_EXPORT MultiDrawArrays : public osg::PrimitiveSet
573 MultiDrawArrays(GLenum mode=0):
574 osg::PrimitiveSet(Type(MultiDrawArraysPrimitiveType), mode) {}
576 MultiDrawArrays(const MultiDrawArrays& dal,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
577 osg::PrimitiveSet(dal,copyop),
578 _firsts(dal._firsts),
579 _counts(dal._counts) {}
581 virtual osg::Object* cloneType() const { return new MultiDrawArrays(); }
582 virtual osg::Object* clone(const osg::CopyOp& copyop) const { return new MultiDrawArrays(*this,copyop); }
583 virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const MultiDrawArrays*>(obj)!=NULL; }
584 virtual const char* libraryName() const { return "osg"; }
585 virtual const char* className() const { return "MultiDrawArrays"; }
588 virtual void draw(osg::State& state, bool useVertexBufferObjects) const;
590 virtual void accept(PrimitiveFunctor& functor) const;
591 virtual void accept(PrimitiveIndexFunctor& functor) const;
593 virtual unsigned int getNumIndices() const;
594 virtual unsigned int index(unsigned int pos) const;
595 virtual void offsetIndices(int offset);
597 virtual unsigned int getNumPrimitives() const;
599 typedef std::vector<GLint> Firsts;
600 void setFirsts(const Firsts& firsts) { _firsts = firsts; }
601 Firsts& getFirsts() { return _firsts; }
602 const Firsts& getFirsts() const { return _firsts; }
604 typedef std::vector<GLsizei> Counts;
605 void setCounts(const Counts& firsts) { _counts = firsts; }
606 Counts& getCounts() { return _counts; }
607 const Counts& getCounts() const { return _counts; }
609 void add(GLint first, GLsizei count);