From 96085619ee4d3f8ed4f2af841a25454d69153164 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 10 Oct 2001 20:20:14 +0000 Subject: [PATCH] Added support for DYNAMIC/STATIC osg::Transform types and added new osg::Drawable::getStats and supportsAttributeUpdate(..) and applyAttributeUpdate(...) methods which will be to enable hooks into Drawable subclasses. --- include/osg/Drawable | 112 +++++++++++++++++++++++++++------------- include/osg/NodeVisitor | 14 ++++- include/osg/Transform | 19 +++++++ src/osg/Transform.cpp | 2 + 4 files changed, 110 insertions(+), 37 deletions(-) diff --git a/include/osg/Drawable b/include/osg/Drawable index 116009362..e7bff0823 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -16,6 +16,13 @@ namespace osg { +class Statistics; +class Vec2; +class Vec3; +class Vec4; + + + /** Pure virtual base class for drawable Geometry. Contains no drawing primitives directly, these are provided by subclasses such as GeoSet. State attributes for a Drawable are maintained in StateSet which the Drawable maintains @@ -67,6 +74,8 @@ class SG_EXPORT Drawable : public Object /** Force a recompile on next draw() of any OpenGL display list associated with this geoset.*/ void dirtyDisplayList(); + + inline void dirtyBound() { _bbox_computed = false; } /** get bounding box of geoset. @@ -84,45 +93,11 @@ class SG_EXPORT Drawable : public Object * If the drawable has _useDisplayList set to true then use an OpenGL display * list, automatically compiling one if required. * Otherwise call drawImmediateMode(). - * Note, draw method should not be overridden in subclasses as it + * Note, draw method should *not* be overridden in subclasses as it * manages the optional display list. */ - inline void draw(State& state) - { - if (_useDisplayList) - { - - // get the contextID (user defined ID of 0 upwards) for the - // current OpenGL context. - uint contextID = state.getContextID(); + inline void draw(State& state); - // fill in array if required. - while (_globjList.size()<=contextID) _globjList.push_back(0); - - // get the globj for the current contextID. - uint& globj = _globjList[contextID]; - - // call the globj if already set otherwise compile and execute. - if( globj != 0 ) - { - glCallList( globj ); - } - else if (_useDisplayList) - { - globj = glGenLists( 1 ); - glNewList( globj, GL_COMPILE_AND_EXECUTE ); - drawImmediateMode(state); - glEndList(); - } - - } - else - { - // draw object as nature intended.. - drawImmediateMode(state); - } - } - /** Immediately compile this drawable into an OpenGL Display List. Note I, operation is ignored if _useDisplayList to false. Note II, compile is not intended to be overridden in subclasses.*/ @@ -143,6 +118,35 @@ class SG_EXPORT Drawable : public Object /** flush all the cached display list which need to be deleted * in the OpenGL context related to contextID.*/ static void flushDeletedDisplayLists(uint contextID); + + + /** Collect Stistics count from Drawable.*/ + virtual bool getStats(Statistics&) { return false; } + + + enum AttributeBitMask + { + COORDS = 0x1, + NORMALS = 0x2, + COLORS = 0x4, + TEXTURE_COORDS = 0x8, + TEXTURE_COORDS_0 = TEXTURE_COORDS, + TEXTURE_COORDS_1 = 0x16, + TEXTURE_COORDS_2 = 0x32, + TEXTURE_COORDS_3 = 0x64 + }; + + struct AttributeUpdateFunctor + { + virtual bool apply(AttributeBitMask abm,Vec2* begin,Vec2* end) { return false; } + virtual bool apply(AttributeBitMask abm,Vec3* begin,Vec3* end) { return false; } + virtual bool apply(AttributeBitMask abm,Vec4* begin,Vec4* end) { return false; } + }; + + virtual bool suppportsAttributeUpdate(AttributeBitMask) { return false; } + + virtual bool applyAttributeUpdate(AttributeBitMask,AttributeUpdateFunctor&) { return false; } + protected: @@ -174,6 +178,42 @@ class SG_EXPORT Drawable : public Object }; +inline void Drawable::draw(State& state) +{ + if (_useDisplayList) + { + + // get the contextID (user defined ID of 0 upwards) for the + // current OpenGL context. + uint contextID = state.getContextID(); + + // fill in array if required. + while (_globjList.size()<=contextID) _globjList.push_back(0); + + // get the globj for the current contextID. + uint& globj = _globjList[contextID]; + + // call the globj if already set otherwise compile and execute. + if( globj != 0 ) + { + glCallList( globj ); + } + else if (_useDisplayList) + { + globj = glGenLists( 1 ); + glNewList( globj, GL_COMPILE_AND_EXECUTE ); + drawImmediateMode(state); + glEndList(); + } + + } + else + { + // draw object as nature intended.. + drawImmediateMode(state); + } +} + }; #endif diff --git a/include/osg/NodeVisitor b/include/osg/NodeVisitor index 85b847db1..401383b18 100644 --- a/include/osg/NodeVisitor +++ b/include/osg/NodeVisitor @@ -22,7 +22,19 @@ class Impostor; class EarthSky; /** Visitor for type safe operations on osg::Node's. - Based on GOF's Visitor pattern.*/ + Based on GOF's Visitor pattern. The NodeVisitor + is useful for developing type safe operations to nodes + in the scene graph (as per Visitor pattern), and adds to this + support for optional scene graph traversal to allow + operations to be applied to whole scenes at once. The Visitor + pattern uses a technique of double dispatch as a mechanism to + called the appropriate apply(..) method of the NodeVisitor. To + use this feature one must use the Node::accept(NodeVisitor) which + is extended in each Node subclass, rather than the NodeVisitor + apply directly. So use root->accept(myVisitor); instead of + myVisitor.apply(*root). The later method will bypass the double + dispatch and the appropriate NodeVisitor::apply(..) method will + not be called. */ class SG_EXPORT NodeVisitor : public Referenced { public: diff --git a/include/osg/Transform b/include/osg/Transform index 749dca941..8683066d3 100644 --- a/include/osg/Transform +++ b/include/osg/Transform @@ -23,6 +23,24 @@ class SG_EXPORT Transform : public Group META_Node(Transform); + /** Range of type that the Transform can be.*/ + enum Type + { + DYNAMIC, + STATIC + }; + + /** Set the Transform Type, which can be DYNAMIC - the Marix + * value is updated duing the main loop, or STATIC - the Matrix + * is constant throughut the life of the main loop. STATIC + * Transforms can be optimized away is some instances, which + * can improve performanc so unless you plan to modify the + * Matrix explicity set the Matrix to STATIC. The default + * value is DYNAMIC.*/ + inline void setType(Type type) { _type = type; } + /** Get the Transform Type.*/ + inline const Type getType() const { return _type; } + void setMatrix(const Matrix& mat ); inline Matrix& getMatrix() { return *_matrix; } inline const Matrix& getMatrix() const { return *_matrix; } @@ -39,6 +57,7 @@ class SG_EXPORT Transform : public Group virtual const bool computeBound() const; + Type _type; ref_ptr _matrix; }; diff --git a/src/osg/Transform.cpp b/src/osg/Transform.cpp index 025ab671e..863f4e4e6 100644 --- a/src/osg/Transform.cpp +++ b/src/osg/Transform.cpp @@ -4,6 +4,7 @@ using namespace osg; Transform::Transform() { + _type = DYNAMIC; _matrix = new osg::Matrix(); _matrix->makeIdent(); } @@ -11,6 +12,7 @@ Transform::Transform() Transform::Transform(const Matrix& mat ) { + _type = DYNAMIC; (*_matrix) = mat; }