From b00d103f4e68dfde8294421b8728bfe8540496eb Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 7 Feb 2002 01:07:11 +0000 Subject: [PATCH] Added callbacks to allow users to modify the underlying functionality of LOD, Billboard and Drawabel objects. --- include/osg/Billboard | 38 +++++++++++++++++-- include/osg/Drawable | 54 +++++++++++++++++++++------ include/osg/LOD | 33 ++++++++++++++++- src/osg/Billboard.cpp | 85 +++++++------------------------------------ src/osg/Drawable.cpp | 10 +++++ src/osg/LOD.cpp | 2 +- 6 files changed, 134 insertions(+), 88 deletions(-) diff --git a/include/osg/Billboard b/include/osg/Billboard index b580abb9c..6b0a4022d 100644 --- a/include/osg/Billboard +++ b/include/osg/Billboard @@ -77,8 +77,35 @@ class SG_EXPORT Billboard : public Geode * and do not the reference count of gset is left unchanged. */ virtual const bool removeDrawable( Drawable *gset ); + - void calcTransform(const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local,Matrix& mat) const; + /** Callback attached to an Billboard which allows the users to customize the billboard orientation calculation during cull traversal.*/ + struct ComputeBillboardCallback : public osg::Referenced + { + /** Get the transformation matrix which moves from local coords to world coords.*/ + virtual void computeMatrix(const Matrix& matrix, const Billboard* billboard, const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local) const; + }; + + friend struct osg::Billboard::ComputeBillboardCallback; + + /** Set the ComputeBillboardCallback which allows users to attach custom computation of the local transformation as + * seen by cull traversers and alike.*/ + void setComputeBillboardCallback(ComputeBillboardCallback* ctc) { _computeBillboardCallback=ctc; } + + /** Get the non const ComputeBillboardCallback.*/ + ComputeBillboardCallback* getComputeBillboardCallback() { return _computeBillboardCallback.get(); } + + /** Get the const ComputeBillboardCallback.*/ + const ComputeBillboardCallback* getComputeBillboardCallback() const { return _computeBillboardCallback.get(); } + + + inline void getMatrix(Matrix& matrix, const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local) const + { + if (_computeBillboardCallback.valid()) + return _computeBillboardCallback->computeMatrix(matrix,this,eye_local,up_local,pos_local); + else + return computeMatrix(matrix,eye_local,up_local,pos_local); + } protected: @@ -86,6 +113,8 @@ class SG_EXPORT Billboard : public Geode virtual const bool computeBound() const; + virtual void computeMatrix(Matrix& matrix, const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local) const; + enum AxisAligned { AXIAL_ROT_X_AXIS=AXIAL_ROT+1, @@ -94,9 +123,10 @@ class SG_EXPORT Billboard : public Geode }; - Mode _mode; - Vec3 _axis; - PositionList _positionList; + Mode _mode; + Vec3 _axis; + PositionList _positionList; + ref_ptr _computeBillboardCallback; // used internally as cache of which what _axis is aligned to help // deicde which method of rotation to use. diff --git a/include/osg/Drawable b/include/osg/Drawable index b2842e770..f784c26cd 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -56,14 +56,7 @@ class SG_EXPORT Drawable : public Object Drawable(); /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ - Drawable(const Drawable& drawable,const CopyOp& copyop=CopyOp::SHALLOW_COPY): - Object(drawable,copyop), - _dstate(copyop(drawable._dstate.get())), - _supportsDisplayList(drawable._supportsDisplayList), - _useDisplayList(drawable._useDisplayList), - _globjList(drawable._globjList), - _bbox(drawable._bbox), - _bbox_computed(drawable._bbox_computed) {} + Drawable(const Drawable& drawable,const CopyOp& copyop=CopyOp::SHALLOW_COPY); virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* className() const { return "Drawable"; } @@ -135,12 +128,38 @@ class SG_EXPORT Drawable : public Object Note II, compile is not intended to be overridden in subclasses.*/ void compile(State& state); + + /** Callback attached to an Drawable which allows the users to customize the drawing of an exist Drawable object. + * The draw callback is implement as a replacement to the Drawable's own drawImmediateMode() method, if the + * the user intends to decorate the exist draw code then simple call the drawable->drawImmediateMode() from + * with the callbacks drawImmediateMode() method. This allows the users to do both pre and post callbacks + * without fuss and can even diable the inner draw in required.*/ + struct DrawCallback : public osg::Referenced + { + /** do customized draw code.*/ + virtual void drawImmediateMode(State& state,osg::Drawable* drawable) const; + }; + + friend struct osg::Drawable::DrawCallback; + + /** Set the DrawCallback which allows users to attach customize the drawing of existing Drawable object.*/ + void setDrawCallback(DrawCallback* dc) { _drawCallback=dc; dirtyBound(); } + + /** Get the non const ComputerTransfromCallback.*/ + DrawCallback* getDrawCallback() { return _drawCallback.get(); } + + /** Get the const ComputerTransfromCallback.*/ + const DrawCallback* getDrawCallback() const { return _drawCallback.get(); } + + /** draw directly ignoring an OpenGL display list which could be attached. * This is the internal draw method which does the drawing itself, * and is the method to override when deriving from Drawable. */ virtual void drawImmediateMode(State& state) = 0; + + /** use deleteDisplayList instead of glDeleteList to allow * OpenGL display list to cached until they can be deleted * by the OpenGL context in which they were created, specified @@ -196,6 +215,8 @@ class SG_EXPORT Drawable : public Object virtual AttributeBitMask applyAttributeOperation(AttributeFunctor&) { return 0; } + + protected: Drawable& operator = (const Drawable&) { return *this;} @@ -217,6 +238,8 @@ class SG_EXPORT Drawable : public Object mutable BoundingBox _bbox; mutable bool _bbox_computed; + ref_ptr _drawCallback; + // static cache of deleted display lists which can only // by completely deleted once the appropriate OpenGL context // is set. @@ -250,14 +273,20 @@ inline void Drawable::draw(State& state) #ifdef USE_SEPERATE_COMPILE_AND_EXECUTE globj = glGenLists( 1 ); glNewList( globj, GL_COMPILE ); - drawImmediateMode(state); + if (_drawCallback.valid()) + _drawCallback->drawImmediateMode(state,this); + else + drawImmediateMode(state); glEndList(); glCallList( globj); #else globj = glGenLists( 1 ); glNewList( globj, GL_COMPILE_AND_EXECUTE ); - drawImmediateMode(state); + if (_drawCallback.valid()) + _drawCallback->drawImmediateMode(state,this); + else + drawImmediateMode(state); glEndList(); #endif } @@ -266,7 +295,10 @@ inline void Drawable::draw(State& state) else { // draw object as nature intended.. - drawImmediateMode(state); + if (_drawCallback.valid()) + _drawCallback->drawImmediateMode(state,this); + else + drawImmediateMode(state); } } diff --git a/include/osg/LOD b/include/osg/LOD index 67221d9a6..ea1feb5fd 100644 --- a/include/osg/LOD +++ b/include/osg/LOD @@ -56,21 +56,52 @@ class SG_EXPORT LOD : public Group inline const Vec3& getCenter() const { return _center; } + /** Callback attached to an LOD which allows the users to customize the selection of LOD children.*/ + struct EvaluateLODCallback : public osg::Referenced + { + /** Compute the child to select.*/ + virtual const int evaluateLODChild(const osg::LOD* lod, const Vec3& eye_local, const float bias) const; + }; + + friend struct osg::LOD::EvaluateLODCallback; + + /** Set the EvaluateLODCallback which allows users to attach customize computation of the the selection of LOD children.*/ + void setEvaluateLODCallback(EvaluateLODCallback* cbc) { _evaluateLODCallback=cbc; } + + /** Get the non const ComputeBillboardCallback.*/ + EvaluateLODCallback* getEvaluateLODCallback() { return _evaluateLODCallback.get(); } + + /** Get the const ComputeBillboardCallback.*/ + const EvaluateLODCallback* getEvaluateLODCallback() const { return _evaluateLODCallback.get(); } + + + /** return the child to traverse. Selected by the distance between the eye point in local coordinates and the LOD center, multiplied by the bias.*/ - const int evaluate(const Vec3& eye_local,const float bias=1.0f) const; + inline const int evaluate(const Vec3& eye_local,const float bias=1.0f) const + { + if (_evaluateLODCallback.valid()) + return _evaluateLODCallback->evaluateLODChild(this,eye_local,bias); + else + return evaluateLODChild(eye_local,bias); + } protected : virtual ~LOD() {} + virtual const int evaluateLODChild(const Vec3& eye_local,const float bias) const; + typedef std::vector RangeList; RangeList _rangeList; RangeList _rangeList2; + + ref_ptr _evaluateLODCallback; Vec3 _center; + }; } diff --git a/src/osg/Billboard.cpp b/src/osg/Billboard.cpp index 03b55f747..3c5b9d5d3 100644 --- a/src/osg/Billboard.cpp +++ b/src/osg/Billboard.cpp @@ -19,6 +19,7 @@ Billboard::Billboard(const Billboard& billboard,const CopyOp& copyop): _mode(billboard._mode), _axis(billboard._axis), _positionList(billboard._positionList), + _computeBillboardCallback(_computeBillboardCallback), _cachedMode(billboard._cachedMode) {} Billboard::~Billboard() @@ -97,90 +98,32 @@ const bool Billboard::removeDrawable( Drawable *gset ) return false; } -void Billboard::calcTransform(const Vec3& eye_local, const Vec3& /*up_local*/, const Vec3& pos_local, Matrix& mat) const +void Billboard::computeMatrix(Matrix& matrix, const Vec3& eye_local, const Vec3& /*up_local*/, const Vec3& pos_local) const { + Vec3 ev(pos_local-eye_local); switch(_cachedMode) { - case(AXIAL_ROT_Z_AXIS): + case(AXIAL_ROT): // need to implement + case(AXIAL_ROT_Z_AXIS): // need to implement + case(AXIAL_ROT_Y_AXIS): // need to implement + case(AXIAL_ROT_X_AXIS): // implemented correctly.. { ev.z() = 0.0f; float ev_length = ev.length(); if (ev_length>0.0f) { - mat.makeIdentity(); + matrix.makeIdentity(); //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); float inv = 1.0f/ev_length; float c = ev.y()*inv; float s = ev.x()*inv; - mat(0,0) = c; - mat(0,1) = -s; - mat(1,0) = s; - mat(1,1) = c; - } - break; - } - - case(AXIAL_ROT_Y_AXIS): - { - ev.z() = 0.0f; - float ev_length = ev.length(); - if (ev_length>0.0f) - { - - mat.makeIdentity(); - //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); - //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); - float inv = 1.0f/ev_length; - float c = ev.y()*inv; - float s = ev.x()*inv; - mat(0,0) = c; - mat(0,1) = -s; - mat(1,0) = s; - mat(1,1) = c; - } - break; - } - case(AXIAL_ROT_X_AXIS): - { - ev.z() = 0.0f; - float ev_length = ev.length(); - if (ev_length>0.0f) - { - - mat.makeIdentity(); - //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); - //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); - float inv = 1.0f/ev_length; - float c = ev.y()*inv; - float s = ev.x()*inv; - mat(0,0) = c; - mat(0,1) = -s; - mat(1,0) = s; - mat(1,1) = c; - } - break; - } - - case(AXIAL_ROT): - { - ev.z() = 0.0f; - float ev_length = ev.length(); - if (ev_length>0.0f) - { - - mat.makeIdentity(); - //float rotation_zrotation_z = atan2f(ev.x(),ev.y()); - //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); - float inv = 1.0f/ev_length; - float c = ev.y()*inv; - float s = ev.x()*inv; - mat(0,0) = c; - mat(0,1) = -s; - mat(1,0) = s; - mat(1,1) = c; + matrix(0,0) = c; + matrix(0,1) = -s; + matrix(1,0) = s; + matrix(1,1) = c; } break; } @@ -209,14 +152,14 @@ void Billboard::calcTransform(const Vec3& eye_local, const Vec3& /*up_local*/, c cp /= cp_len; float rotation_cp = acosf(dot); - mat.makeRotate(-inRadians(rotation_cp),cp[0],cp[1],cp[2]); + matrix.makeRotate(-inRadians(rotation_cp),cp[0],cp[1],cp[2]); } } break; } } - mat.setTrans(pos_local); + matrix.setTrans(pos_local); } diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index 5005a0395..8f914ff29 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -24,6 +24,16 @@ Drawable::Drawable() } +Drawable::Drawable(const Drawable& drawable,const CopyOp& copyop): + Object(drawable,copyop), + _dstate(copyop(drawable._dstate.get())), + _supportsDisplayList(drawable._supportsDisplayList), + _useDisplayList(drawable._useDisplayList), + _globjList(drawable._globjList), + _bbox(drawable._bbox), + _bbox_computed(drawable._bbox_computed), + _drawCallback(drawable._drawCallback) +{} Drawable::~Drawable() { diff --git a/src/osg/LOD.cpp b/src/osg/LOD.cpp index f45db7db3..a21864dea 100644 --- a/src/osg/LOD.cpp +++ b/src/osg/LOD.cpp @@ -39,7 +39,7 @@ void LOD::setRange(const unsigned int index, const float range) } -const int LOD::evaluate(const Vec3& eye_local, const float bias) const +const int LOD::evaluateLODChild(const Vec3& eye_local, const float bias) const { // For cache coherency, use _rangeList2 exclusively if (_rangeList2.empty()) return -1;