First steps to updating the calcTransform function in Billboard to fix

z axis contraint on rotation axis.
This commit is contained in:
Robert Osfield 2002-01-18 22:15:59 +00:00
parent baeb396ade
commit 58ead9aead
2 changed files with 118 additions and 35 deletions

View File

@ -18,24 +18,25 @@ class SG_EXPORT Billboard : public Geode
public: public:
enum Mode { enum Mode {
AXIAL_ROT,
POINT_ROT_EYE, POINT_ROT_EYE,
POINT_ROT_WORLD POINT_ROT_WORLD,
AXIAL_ROT
}; };
Billboard(); Billboard();
META_Node(Billboard); META_Node(Billboard);
/** Set the billboard rotation mode. */
void setMode(const Mode mode);
/** Get the billboard rotation mode. */
inline const Mode getMode() const { return _mode; }
/** Set the axis about which all the billboard's drawable rotate. */ /** Set the axis about which all the billboard's drawable rotate. */
inline void setAxis(const Vec3& axis) { _axis = axis; } void setAxis(const Vec3& axis);
/** Get the axis about which all the billboard's drawable rotate. */ /** Get the axis about which all the billboard's drawable rotate. */
inline const Vec3& getAxis() const { return _axis; } inline const Vec3& getAxis() const { return _axis; }
/** Set the billboard rotation mode. */
inline void setMode(const Mode mode) { _mode = mode; }
/** Get the billboard rotation mode. */
inline const Mode getMode() const { return _mode; }
/** Set the position of specified drawable. */ /** Set the position of specified drawable. */
inline void setPos(int i,const Vec3& pos) { _positionList[i] = pos; } inline void setPos(int i,const Vec3& pos) { _positionList[i] = pos; }
@ -74,8 +75,7 @@ class SG_EXPORT Billboard : public Geode
*/ */
virtual const bool removeDrawable( Drawable *gset ); virtual const bool removeDrawable( Drawable *gset );
void calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix& mat) const; void calcTransform(const Vec3& eye_local, const Vec3& up_local, const Vec3& pos_local,Matrix& mat) const;
void calcTransform(const Vec3& eye_local, const Vec3& pos_local,Matrix& mat) const;
protected: protected:
@ -83,11 +83,24 @@ class SG_EXPORT Billboard : public Geode
virtual const bool computeBound() const; virtual const bool computeBound() const;
enum AxisAligned
{
AXIAL_ROT_X_AXIS=AXIAL_ROT+1,
AXIAL_ROT_Y_AXIS,
AXIAL_ROT_Z_AXIS,
};
Mode _mode; Mode _mode;
Vec3 _axis; Vec3 _axis;
PositionList _positionList; PositionList _positionList;
// used internally as cache of which what _axis is aligned to help
// deicde which method of rotation to use.
int _cachedMode;
void setCachedMode();
}; };
}; };

View File

@ -11,6 +11,7 @@ Billboard::Billboard()
{ {
_mode = AXIAL_ROT; _mode = AXIAL_ROT;
_axis.set(0.0f,0.0f,1.0f); _axis.set(0.0f,0.0f,1.0f);
setCachedMode();
} }
@ -18,6 +19,29 @@ Billboard::~Billboard()
{ {
} }
void Billboard::setMode(const Mode mode)
{
_mode = mode;
setCachedMode();
}
void Billboard::setAxis(const Vec3& axis)
{
_axis = axis;
setCachedMode();
}
void Billboard::setCachedMode()
{
if (_mode==AXIAL_ROT)
{
if (_axis==osg::Vec3(1.0f,0.0,0.0f)) _cachedMode = AXIAL_ROT_X_AXIS;
else if (_axis==osg::Vec3(0.0f,1.0,0.0f)) _cachedMode = AXIAL_ROT_Y_AXIS;
else if (_axis==osg::Vec3(0.0f,0.0,1.0f)) _cachedMode = AXIAL_ROT_Z_AXIS;
else _cachedMode = AXIAL_ROT;
}
else _cachedMode = _mode;
}
const bool Billboard::addDrawable(Drawable *gset) const bool Billboard::addDrawable(Drawable *gset)
{ {
@ -67,21 +91,18 @@ 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::calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix& mat) const
{ {
switch(_mode) Vec3 ev(pos_local-eye_local);
switch(_cachedMode)
{ {
case(AXIAL_ROT): case(AXIAL_ROT_Z_AXIS):
{ {
// note currently assumes that axis is (0,0,1) for speed of
// executation and implementation. This will be rewritten
// on second pass of Billboard. Robert Osfield Jan 2001.
Vec3 ev = pos_local-eye_local;
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(); mat.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);
@ -95,6 +116,69 @@ void Billboard::calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix
} }
break; 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;
}
case(POINT_ROT_WORLD): case(POINT_ROT_WORLD):
case(POINT_ROT_EYE): case(POINT_ROT_EYE):
{ {
@ -105,15 +189,12 @@ void Billboard::calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix
// have to be added to the above method paramters. // have to be added to the above method paramters.
// Robert Osfield, Jan 2001. // Robert Osfield, Jan 2001.
Vec3 ev = pos_local-eye_local;
ev.normalize();
float ev_len = ev.length(); float ev_len = ev.length();
if (ev_len != 0.0f) if (ev_len != 0.0f)
{ {
ev /= ev_len; ev /= ev_len;
Vec3 cp = ev^Vec3(0.0f,1.0f,0.0f); Vec3 cp(ev^Vec3(0.0f,1.0f,0.0f));
float dot = ev*Vec3(0.0f,1.0f,0.0f); float dot = ev*Vec3(0.0f,1.0f,0.0f);
float cp_len = cp.length(); float cp_len = cp.length();
@ -128,19 +209,8 @@ void Billboard::calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix
break; break;
} }
} }
}
mat.setTrans(pos_local);
void Billboard::calcTransform(const Vec3& eye_local, const Vec3& pos_local,Matrix& mat) const
{
// mat.makeTranslate(pos_local[0],pos_local[1],pos_local[2]);
// mat.makeIdentity();
calcRotation(eye_local,pos_local,mat);
// mat.postTrans(pos_local[0],pos_local[1],pos_local[2]);
mat(3,0) += pos_local[0];
mat(3,1) += pos_local[1];
mat(3,2) += pos_local[2];
} }