Added callbacks to allow users to modify the underlying functionality of
LOD, Billboard and Drawabel objects.
This commit is contained in:
parent
a4ea331f3a
commit
b00d103f4e
@ -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.
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user