Added osg::Drawable::PrimitiveFunctor and TriangleFunctor subclass for

querrying the primitive data inside Drawables.  Moved various support
classes over from being osg::GeoSet based to osg::Geometry based.
This commit is contained in:
Robert Osfield
2002-06-25 20:27:51 +00:00
parent 336c47e5fe
commit cbeeeefdab
20 changed files with 737 additions and 651 deletions

View File

@@ -15,7 +15,7 @@ class BoundingSphere;
/** General purpose axis-aligned bounding box class for enclosing objects/vertices.
Used to bounding the leaf objects in the scene,
i.e. osg::GeoSet's to assist in view frustum culling etc.
i.e. osg::Drawable's to assist in view frustum culling etc.
*/
class SG_EXPORT BoundingBox
{

View File

@@ -33,7 +33,7 @@ class Node;
#define USE_SEPERATE_COMPILE_AND_EXECUTE
/** Pure virtual base class for drawable Geometry. Contains no drawing primitives
directly, these are provided by subclasses such as GeoSet. State attributes
directly, these are provided by subclasses such as osg::Geometry. State attributes
for a Drawable are maintained in StateSet which the Drawable maintains
a referenced counted pointer to. Both Drawable's and StateSet's can
be shared for optimal memory usage and graphics performance.
@@ -41,7 +41,7 @@ class Node;
Subclasses should provide an instance of getStats(Statistics *st) if the subclass
contains drawing primitives. This member function should add the primitives it
draws into the Statistics class; for example add the number of quads, triangles etc
created. For an example see GeoSet.cpp:
created. For an example see Geometry.cpp:
getStats(osgUtil::Statistics *stat).
Failure to implement this routine will only result in the stats displayed for
your drawable being wrong.
@@ -261,6 +261,26 @@ class SG_EXPORT Drawable : public Object
virtual AttributeBitMask applyAttributeOperation(AttributeFunctor&) { return 0; }
class PrimitiveFunctor
{
public:
virtual void setVertexArray(unsigned int count,Vec3* vertices) = 0;
virtual void drawArrays(GLenum mode,GLint first,GLsizei count) = 0;
virtual void drawElements(GLenum mode,GLsizei count,unsigned char* indices) = 0;
virtual void drawElements(GLenum mode,GLsizei count,unsigned short* indices) = 0;
virtual void drawElements(GLenum mode,GLsizei count,unsigned int* indices) = 0;
virtual void begin(GLenum mode) = 0;
virtual void vertex(const Vec3& vert) = 0;
virtual void vertex(float x,float y,float z) = 0;
virtual void end() = 0;
};
/** apply the internal geometry as basic primitives to a PrimitiveFunctor.*/
virtual void applyPrimitiveOperation(PrimitiveFunctor&) {}
protected:
@@ -354,7 +374,329 @@ inline void Drawable::draw(State& state)
else
drawImmediateMode(state);
}
}
};
template<class T>
class TriangleFunctor : public Drawable::PrimitiveFunctor, public T
{
public:
TriangleFunctor()
{
_vertexArraySize=0;
_vertexArrayPtr=0;
_modeCache=0;
}
virtual ~TriangleFunctor() {}
virtual void setVertexArray(unsigned int count,Vec3* vertices)
{
_vertexArraySize = count;
_vertexArrayPtr = vertices;
}
virtual void drawArrays(GLenum mode,GLint first,GLsizei count)
{
if (_vertexArrayPtr==0 && count==0) return;
switch(mode)
{
case(GL_TRIANGLES):
{
Vec3* vlast = &_vertexArrayPtr[first+count];
for(Vec3* vptr=&_vertexArrayPtr[first];vptr<vlast;vptr+=3)
operator()(*(vptr),*(vptr+1),*(vptr+2));
break;
}
case(GL_TRIANGLE_STRIP):
{
Vec3* vptr = &_vertexArrayPtr[first];
for(GLsizei i=2;i<count;++i,++vptr)
{
if ((i%2)) operator()(*(vptr),*(vptr+2),*(vptr+1));
else operator()(*(vptr),*(vptr+1),*(vptr+2));
}
break;
}
case(GL_QUADS):
{
Vec3* vptr = &_vertexArrayPtr[first];
for(GLsizei i=3;i<count;i+=4,vptr+=4)
{
operator()(*(vptr),*(vptr+1),*(vptr+2));
operator()(*(vptr),*(vptr+2),*(vptr+3));
}
break;
}
case(GL_QUAD_STRIP):
{
Vec3* vptr = &_vertexArrayPtr[first];
for(GLsizei i=3;i<count;i+=2,vptr+=2)
{
operator()(*(vptr),*(vptr+1),*(vptr+2));
operator()(*(vptr),*(vptr+2),*(vptr+3));
}
break;
}
case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
case(GL_TRIANGLE_FAN):
{
Vec3* vfirst = &_vertexArrayPtr[first];
Vec3* vptr = vfirst+1;
for(GLsizei i=2;i<count;++i,++vptr)
{
operator()(*(vfirst),*(vptr),*(vptr+1));
}
break;
}
case(GL_POINTS):
case(GL_LINES):
case(GL_LINE_STRIP):
case(GL_LINE_LOOP):
default:
// can't be converted into to triangles.
break;
}
}
virtual void drawElements(GLenum mode,GLsizei count,unsigned char* indices)
{
if (indices==0 || count==0) return;
typedef unsigned char* IndexPointer;
switch(mode)
{
case(GL_TRIANGLES):
{
IndexPointer ilast = &indices[count];
for(IndexPointer iptr=indices;iptr<ilast;iptr+=3)
operator()(_vertexArrayPtr[*iptr],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
break;
}
case(GL_TRIANGLE_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=2;i<count;++i,++iptr)
{
if ((i%2)) operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+1)]);
else operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
}
break;
}
case(GL_QUADS):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=4,iptr+=4)
{
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)]);
}
break;
}
case(GL_QUAD_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=2,iptr+=2)
{
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)]);
}
break;
}
case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
case(GL_TRIANGLE_FAN):
{
IndexPointer iptr = indices;
Vec3& vfirst = _vertexArrayPtr[*iptr];
++iptr;
for(GLsizei i=2;i<count;++i,++iptr)
{
operator()(vfirst,_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)]);
}
break;
}
case(GL_POINTS):
case(GL_LINES):
case(GL_LINE_STRIP):
case(GL_LINE_LOOP):
default:
// can't be converted into to triangles.
break;
}
}
virtual void drawElements(GLenum mode,GLsizei count,unsigned short* indices)
{
if (indices==0 || count==0) return;
typedef unsigned short* IndexPointer;
switch(mode)
{
case(GL_TRIANGLES):
{
IndexPointer ilast = &indices[count];
for(IndexPointer iptr=indices;iptr<ilast;iptr+=3)
{
operator()(_vertexArrayPtr[*iptr],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
}
break;
}
case(GL_TRIANGLE_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=2;i<count;++i,++iptr)
{
if ((i%2)) operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+1)]);
else operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
}
break;
}
case(GL_QUADS):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=4,iptr+=4)
{
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)]);
}
break;
}
case(GL_QUAD_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=2,iptr+=2)
{
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)]);
}
break;
}
case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
case(GL_TRIANGLE_FAN):
{
IndexPointer iptr = indices;
Vec3& vfirst = _vertexArrayPtr[*iptr];
++iptr;
for(GLsizei i=2;i<count;++i,++iptr)
{
operator()(vfirst,_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)]);
}
break;
}
case(GL_POINTS):
case(GL_LINES):
case(GL_LINE_STRIP):
case(GL_LINE_LOOP):
default:
// can't be converted into to triangles.
break;
}
}
virtual void drawElements(GLenum mode,GLsizei count,unsigned int* indices)
{
if (indices==0 || count==0) return;
typedef unsigned int* IndexPointer;
switch(mode)
{
case(GL_TRIANGLES):
{
IndexPointer ilast = &indices[count];
for(IndexPointer iptr=indices;iptr<ilast;iptr+=3)
operator()(_vertexArrayPtr[*iptr],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
break;
}
case(GL_TRIANGLE_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=2;i<count;++i,++iptr)
{
if ((i%2)) operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+1)]);
else operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
}
break;
}
case(GL_QUADS):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=4,iptr+=4)
{
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)]);
}
break;
}
case(GL_QUAD_STRIP):
{
IndexPointer iptr = indices;
for(GLsizei i=3;i<count;i+=2,iptr+=2)
{
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)],_vertexArrayPtr[*(iptr+2)]);
operator()(_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+2)],_vertexArrayPtr[*(iptr+3)]);
}
break;
}
case(GL_POLYGON): // treat polygons as GL_TRIANGLE_FAN
case(GL_TRIANGLE_FAN):
{
IndexPointer iptr = indices;
Vec3& vfirst = _vertexArrayPtr[*iptr];
++iptr;
for(GLsizei i=2;i<count;++i,++iptr)
{
operator()(vfirst,_vertexArrayPtr[*(iptr)],_vertexArrayPtr[*(iptr+1)]);
}
break;
}
case(GL_POINTS):
case(GL_LINES):
case(GL_LINE_STRIP):
case(GL_LINE_LOOP):
default:
// can't be converted into to triangles.
break;
}
}
/** begin(..),vertex(..) & end() are convinience methods for adapting
* non vertex array primitives to vertex array based primitives.
* this is done to simplify the implementation of primtive functor
* subclasses - users only need override drawArray and drawElements.*/
inline void begin(GLenum mode)
{
_modeCache = mode;
_vertexCache.clear();
}
inline void vertex(const Vec3& vert) { _vertexCache.push_back(vert); }
inline void vertex(float x,float y,float z) { _vertexCache.push_back(osg::Vec3(x,y,z)); }
inline void end()
{
if (!_vertexCache.empty())
{
setVertexArray(_vertexCache.size(),&_vertexCache.front());
drawArrays(_modeCache,0,_vertexCache.size());
}
}
protected:
unsigned int _vertexArraySize;
Vec3* _vertexArrayPtr;
GLenum _modeCache;
std::vector<Vec3> _vertexCache;
};
}

View File

@@ -337,6 +337,8 @@ class SG_EXPORT GeoSet : public Drawable
/** return the attributes successully applied in applyAttributeUpdate.*/
virtual AttributeBitMask applyAttributeOperation(AttributeFunctor& auf);
/** apply the internal geometry as basic primitives to a PrimitiveFunctor.*/
virtual void applyPrimitiveOperation(PrimitiveFunctor& functor);
/** convinience function for converting GeoSet's to equivilant Geometry nodes.*/
Geometry* convertToGeometry();

View File

@@ -76,6 +76,10 @@ class TemplateArray : public AttributeArray, public std::vector<T>
AttributeArray(ta,copyop),
std::vector<T>(ta) {}
TemplateArray(unsigned int no) :
AttributeArray(ARRAYTYPE,DataSize,DataType),
std::vector<T>(no) {}
TemplateArray(unsigned int no,T* ptr) :
AttributeArray(ARRAYTYPE,DataSize,DataType),
std::vector<T>(ptr,ptr+no) {}
@@ -131,10 +135,14 @@ class Primitive : public Object
POLYGON = GL_POLYGON
};
Primitive(PrimitiveType primType=PrimitivePrimitiveType):_primitiveType(primType) {}
Primitive(PrimitiveType primType=PrimitivePrimitiveType,GLenum mode=0):
_primitiveType(primType),
_mode(mode) {}
Primitive(const Primitive& prim,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
Object(prim,copyop) {}
Object(prim,copyop),
_primitiveType(prim._primitiveType),
_mode(prim._mode) {}
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Primitive*>(obj)!=NULL; }
virtual const char* libraryName() const { return "osg"; }
@@ -142,9 +150,17 @@ class Primitive : public Object
PrimitiveType primitiveType() const { return _primitiveType; }
void setMode(GLenum mode) { _mode = mode; }
GLenum getMode() const { return _mode; }
virtual void draw() const = 0;
virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor&) {}
protected:
PrimitiveType _primitiveType;
GLenum _mode;
};
class DrawArrays : public Primitive
@@ -152,18 +168,16 @@ class DrawArrays : public Primitive
public:
DrawArrays():
Primitive(DrawArraysPrimitiveType)
Primitive(DrawArraysPrimitiveType,0)
{}
DrawArrays(GLenum mode, GLint first, GLsizei count):
Primitive(DrawArraysPrimitiveType),
_mode(mode),
Primitive(DrawArraysPrimitiveType,mode),
_first(first),
_count(count) {}
DrawArrays(const DrawArrays& da,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
Primitive(da,copyop),
_mode(da._mode),
_first(da._first),
_count(da._count) {}
@@ -174,30 +188,29 @@ class DrawArrays : public Primitive
virtual const char* className() const { return "DrawArrays"; }
void set(GLenum mode, GLint first, GLsizei count)
void set(GLenum mode,GLint first, GLsizei count)
{
_mode = mode;
_first = first;
_count = count;
}
void setMode(GLenum mode) { _mode = mode; }
GLenum getMode() const { return _mode; }
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() const
{
glDrawArrays(_mode,_first,_count);
}
GLenum _mode;
virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor)
{
functor.drawArrays(_mode,_first,_count);
}
GLint _first;
GLsizei _count;
};
@@ -208,42 +221,44 @@ class DrawElements : public Primitive, public std::vector<T>
public:
DrawElements(GLenum mode=0):
Primitive(PRIMTYPE),
_mode(mode),
Primitive(PRIMTYPE,mode),
_dataType(DataType) {}
DrawElements(const DrawElements& array,const CopyOp& copyop=CopyOp::SHALLOW_COPY):
Primitive(array,copyop),
std::vector<T>(array),
_mode(array._mode),
_dataType(array._dataType) {}
DrawElements(GLenum mode,unsigned int no,T* ptr) :
Primitive(PRIMTYPE),
Primitive(PRIMTYPE,mode),
std::vector<T>(ptr,ptr+no),
_mode(mode),
_dataType(DataType) {}
DrawElements(GLenum mode,unsigned int no) :
Primitive(PRIMTYPE,mode),
std::vector<T>(no),
_dataType(DataType) {}
DrawElements(GLenum mode, T* first,T* last) :
Primitive(PRIMTYPE),
Primitive(PRIMTYPE,mode),
std::vector<T>(first,last),
_mode(mode),
_dataType(DataType) {}
virtual Object* cloneType() const { return osgNew DrawElements(); }
virtual Object* clone(const CopyOp& copyop) const { return osgNew DrawElements(*this,copyop); }
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const DrawElements*>(obj)!=NULL; }
virtual const char* libraryName() const { return "osg"; }
void setMode(GLenum mode) { _mode = mode; }
GLenum getMode() const { return _mode; }
virtual void draw() const
{
glDrawElements(_mode,size(),_dataType,&front());
}
GLenum _mode;
virtual void applyPrimitiveOperation(Drawable::PrimitiveFunctor& functor)
{
if (!empty()) functor.drawElements(_mode,size(),&front());
}
GLenum _dataType;
};
@@ -255,8 +270,6 @@ typedef DrawElements<unsigned int,UIntDrawElementsPrimitiveType,GL_UNSIGNED_INT>
/* ******************************************************************************************************************* */
/** Experiemntal replacement for GeoSet.
*/
class SG_EXPORT Geometry : public Drawable
{
public:
@@ -280,15 +293,15 @@ class SG_EXPORT Geometry : public Drawable
BIND_PER_VERTEX,
};
void setVertexArray(Vec3Array* array) { _vertexArray = array; }
void setVertexArray(Vec3Array* array) { _vertexArray = array; dirtyDisplayList(); }
Vec3Array* getVertexArray() { return _vertexArray.get(); }
const Vec3Array* getVertexArray() const { return _vertexArray.get(); }
void setNormalBinding(AttributeBinding ab) { _normalBinding = ab; }
void setNormalBinding(AttributeBinding ab) { _normalBinding = ab; dirtyDisplayList(); }
AttributeBinding getNormalBinding() const { return _normalBinding; }
void setNormalArray(Vec3Array* array) { _normalArray = array; if (!_normalArray.valid()) _normalBinding=BIND_OFF; }
void setNormalArray(Vec3Array* array) { _normalArray = array; if (!_normalArray.valid()) _normalBinding=BIND_OFF; dirtyDisplayList(); }
Vec3Array* getNormalArray() { return _normalArray.get(); }
const Vec3Array* getNormalArray() const { return _normalArray.get(); }
@@ -296,7 +309,7 @@ class SG_EXPORT Geometry : public Drawable
void setColorBinding(AttributeBinding ab) { _colorBinding = ab; }
AttributeBinding getColorBinding() const { return _colorBinding; }
void setColorArray(AttributeArray* array) { _colorArray = array; if (!_colorArray.valid()) _colorBinding=BIND_OFF; }
void setColorArray(AttributeArray* array) { _colorArray = array; if (!_colorArray.valid()) _colorBinding=BIND_OFF; dirtyDisplayList(); }
AttributeArray* getColorArray() { return _colorArray.get(); }
const AttributeArray* getColorArray() const { return _colorArray.get(); }
@@ -315,11 +328,11 @@ class SG_EXPORT Geometry : public Drawable
typedef std::vector< ref_ptr<Primitive> > PrimitiveList;
void setPrimitiveList(const PrimitiveList& primitives) { _primitives = primitives; }
void setPrimitiveList(const PrimitiveList& primitives) { _primitives = primitives; dirtyDisplayList(); }
PrimitiveList& getPrimitiveList() { return _primitives; }
const PrimitiveList& getPrimitiveList() const { return _primitives; }
void addPrimitive(Primitive* primitive) { if (primitive) _primitives.push_back(primitive); }
void addPrimitive(Primitive* primitive) { if (primitive) _primitives.push_back(primitive); dirtyDisplayList(); }
@@ -340,6 +353,7 @@ class SG_EXPORT Geometry : public Drawable
/** return the attributes successully applied in applyAttributeUpdate.*/
virtual AttributeBitMask applyAttributeOperation(AttributeFunctor& auf);
virtual void applyPrimitiveOperation(PrimitiveFunctor&);
protected:

View File

@@ -14,7 +14,7 @@ namespace osg {
* Statistics base class. Used to extract primitive information from
* the renderBin(s). Add a case of getStats(osgUtil::Statistics *stat)
* for any new drawable (or drawable derived class) that you generate
* (eg see GeoSet.cpp). There are 20 types of drawable counted - actually only
* (eg see Geometry.cpp). There are 20 types of drawable counted - actually only
* 14 cases can occur in reality. these represent sets of GL_POINTS, GL_LINES
* GL_LINESTRIPS, LOOPS, TRIANGLES, TRI-fans, tristrips, quads, quadstrips etc
* The number of triangles rendered is inferred:

View File

@@ -8,7 +8,6 @@
#include <osg/NodeVisitor>
#include <osg/LineSegment>
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/Matrix>
#include <osgUtil/Export>
@@ -51,7 +50,7 @@ class OSGUTIL_EXPORT Hit
osg::ref_ptr<osg::LineSegment> _localLineSegment;
osg::NodePath _nodePath;
osg::ref_ptr<osg::Geode> _geode;
osg::ref_ptr<osg::GeoSet> _geoset;
osg::ref_ptr<osg::Drawable> _drawable;
osg::ref_ptr<osg::Matrix> _matrix;
osg::ref_ptr<osg::Matrix> _inverse;
@@ -139,7 +138,7 @@ class OSGUTIL_EXPORT IntersectVisitor : public osg::NodeVisitor
};
bool intersect(osg::GeoSet& gset);
bool intersect(osg::Drawable& gset);
void pushMatrix(const osg::Matrix& matrix);
void popMatrix();

View File

@@ -7,7 +7,7 @@
#include <osg/NodeVisitor>
#include <osg/Geode>
#include <osg/GeoSet>
#include <osg/Geometry>
#include <osgUtil/Export>
@@ -30,7 +30,7 @@ class OSGUTIL_EXPORT TriStripVisitor : public osg::NodeVisitor
* NvTriStrip. Converts all primitive types except points
* and lines, linestrips which it leaves unchanged.
*/
static void stripify(osg::GeoSet& gset);
static void stripify(osg::Geometry& drawable);
/// apply stripify method to all geode geosets.
virtual void apply(osg::Geode& geode);