Added callbacks to allow users to modify the underlying functionality of

LOD, Billboard and Drawabel objects.
This commit is contained in:
Robert Osfield 2002-02-07 01:07:11 +00:00
parent a4ea331f3a
commit b00d103f4e
6 changed files with 134 additions and 88 deletions

View File

@ -78,7 +78,34 @@ class SG_EXPORT Billboard : public Geode
*/ */
virtual const bool removeDrawable( Drawable *gset ); 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: protected:
@ -86,6 +113,8 @@ class SG_EXPORT Billboard : public Geode
virtual const bool computeBound() const; 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 enum AxisAligned
{ {
AXIAL_ROT_X_AXIS=AXIAL_ROT+1, AXIAL_ROT_X_AXIS=AXIAL_ROT+1,
@ -94,9 +123,10 @@ class SG_EXPORT Billboard : public Geode
}; };
Mode _mode; Mode _mode;
Vec3 _axis; Vec3 _axis;
PositionList _positionList; PositionList _positionList;
ref_ptr<ComputeBillboardCallback> _computeBillboardCallback;
// used internally as cache of which what _axis is aligned to help // used internally as cache of which what _axis is aligned to help
// deicde which method of rotation to use. // deicde which method of rotation to use.

View File

@ -56,14 +56,7 @@ class SG_EXPORT Drawable : public Object
Drawable(); Drawable();
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/ /** Copy constructor using CopyOp to manage deep vs shallow copy.*/
Drawable(const Drawable& drawable,const CopyOp& copyop=CopyOp::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) {}
virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Drawable*>(obj)!=NULL; } virtual bool isSameKindAs(const Object* obj) const { return dynamic_cast<const Drawable*>(obj)!=NULL; }
virtual const char* className() const { return "Drawable"; } 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.*/ Note II, compile is not intended to be overridden in subclasses.*/
void compile(State& state); 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. /** draw directly ignoring an OpenGL display list which could be attached.
* This is the internal draw method which does the drawing itself, * This is the internal draw method which does the drawing itself,
* and is the method to override when deriving from Drawable. * and is the method to override when deriving from Drawable.
*/ */
virtual void drawImmediateMode(State& state) = 0; virtual void drawImmediateMode(State& state) = 0;
/** use deleteDisplayList instead of glDeleteList to allow /** use deleteDisplayList instead of glDeleteList to allow
* OpenGL display list to cached until they can be deleted * OpenGL display list to cached until they can be deleted
* by the OpenGL context in which they were created, specified * 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; } virtual AttributeBitMask applyAttributeOperation(AttributeFunctor&) { return 0; }
protected: protected:
Drawable& operator = (const Drawable&) { return *this;} Drawable& operator = (const Drawable&) { return *this;}
@ -217,6 +238,8 @@ class SG_EXPORT Drawable : public Object
mutable BoundingBox _bbox; mutable BoundingBox _bbox;
mutable bool _bbox_computed; mutable bool _bbox_computed;
ref_ptr<DrawCallback> _drawCallback;
// static cache of deleted display lists which can only // static cache of deleted display lists which can only
// by completely deleted once the appropriate OpenGL context // by completely deleted once the appropriate OpenGL context
// is set. // is set.
@ -250,14 +273,20 @@ inline void Drawable::draw(State& state)
#ifdef USE_SEPERATE_COMPILE_AND_EXECUTE #ifdef USE_SEPERATE_COMPILE_AND_EXECUTE
globj = glGenLists( 1 ); globj = glGenLists( 1 );
glNewList( globj, GL_COMPILE ); glNewList( globj, GL_COMPILE );
drawImmediateMode(state); if (_drawCallback.valid())
_drawCallback->drawImmediateMode(state,this);
else
drawImmediateMode(state);
glEndList(); glEndList();
glCallList( globj); glCallList( globj);
#else #else
globj = glGenLists( 1 ); globj = glGenLists( 1 );
glNewList( globj, GL_COMPILE_AND_EXECUTE ); glNewList( globj, GL_COMPILE_AND_EXECUTE );
drawImmediateMode(state); if (_drawCallback.valid())
_drawCallback->drawImmediateMode(state,this);
else
drawImmediateMode(state);
glEndList(); glEndList();
#endif #endif
} }
@ -266,7 +295,10 @@ inline void Drawable::draw(State& state)
else else
{ {
// draw object as nature intended.. // draw object as nature intended..
drawImmediateMode(state); if (_drawCallback.valid())
_drawCallback->drawImmediateMode(state,this);
else
drawImmediateMode(state);
} }
} }

View File

@ -56,21 +56,52 @@ class SG_EXPORT LOD : public Group
inline const Vec3& getCenter() const { return _center; } 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. /** return the child to traverse.
Selected by the distance between the eye point in local Selected by the distance between the eye point in local
coordinates and the LOD center, multiplied by the bias.*/ 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 : protected :
virtual ~LOD() {} virtual ~LOD() {}
virtual const int evaluateLODChild(const Vec3& eye_local,const float bias) const;
typedef std::vector<float> RangeList; typedef std::vector<float> RangeList;
RangeList _rangeList; RangeList _rangeList;
RangeList _rangeList2; RangeList _rangeList2;
ref_ptr<EvaluateLODCallback> _evaluateLODCallback;
Vec3 _center; Vec3 _center;
}; };
} }

View File

@ -19,6 +19,7 @@ Billboard::Billboard(const Billboard& billboard,const CopyOp& copyop):
_mode(billboard._mode), _mode(billboard._mode),
_axis(billboard._axis), _axis(billboard._axis),
_positionList(billboard._positionList), _positionList(billboard._positionList),
_computeBillboardCallback(_computeBillboardCallback),
_cachedMode(billboard._cachedMode) {} _cachedMode(billboard._cachedMode) {}
Billboard::~Billboard() Billboard::~Billboard()
@ -97,90 +98,32 @@ const bool Billboard::removeDrawable( Drawable *gset )
return false; 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); Vec3 ev(pos_local-eye_local);
switch(_cachedMode) 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; ev.z() = 0.0f;
float ev_length = ev.length(); float ev_length = ev.length();
if (ev_length>0.0f) if (ev_length>0.0f)
{ {
mat.makeIdentity(); matrix.makeIdentity();
//float rotation_zrotation_z = atan2f(ev.x(),ev.y()); //float rotation_zrotation_z = atan2f(ev.x(),ev.y());
//mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f); //mat.makeRotate(inRadians(rotation_z),0.0f,0.0f,1.0f);
float inv = 1.0f/ev_length; float inv = 1.0f/ev_length;
float c = ev.y()*inv; float c = ev.y()*inv;
float s = ev.x()*inv; float s = ev.x()*inv;
mat(0,0) = c; matrix(0,0) = c;
mat(0,1) = -s; matrix(0,1) = -s;
mat(1,0) = s; matrix(1,0) = s;
mat(1,1) = c; matrix(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;
} }
break; break;
} }
@ -209,14 +152,14 @@ void Billboard::calcTransform(const Vec3& eye_local, const Vec3& /*up_local*/, c
cp /= cp_len; cp /= cp_len;
float rotation_cp = acosf(dot); 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; break;
} }
} }
mat.setTrans(pos_local); matrix.setTrans(pos_local);
} }

View File

@ -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() Drawable::~Drawable()
{ {

View File

@ -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 // For cache coherency, use _rangeList2 exclusively
if (_rangeList2.empty()) return -1; if (_rangeList2.empty()) return -1;