From 58ead9aeadfab22da98ac593af8f4e622134e84c Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 18 Jan 2002 22:15:59 +0000 Subject: [PATCH] First steps to updating the calcTransform function in Billboard to fix z axis contraint on rotation axis. --- include/osg/Billboard | 35 +++++++++---- src/osg/Billboard.cpp | 118 +++++++++++++++++++++++++++++++++--------- 2 files changed, 118 insertions(+), 35 deletions(-) diff --git a/include/osg/Billboard b/include/osg/Billboard index 81c09eb55..8c46994f5 100644 --- a/include/osg/Billboard +++ b/include/osg/Billboard @@ -18,24 +18,25 @@ class SG_EXPORT Billboard : public Geode public: enum Mode { - AXIAL_ROT, POINT_ROT_EYE, - POINT_ROT_WORLD + POINT_ROT_WORLD, + AXIAL_ROT }; Billboard(); META_Node(Billboard); - /** Set the axis about which all the billboard's drawable rotate. */ - inline void setAxis(const Vec3& axis) { _axis = axis; } - /** Get the axis about which all the billboard's drawable rotate. */ - inline const Vec3& getAxis() const { return _axis; } - /** Set the billboard rotation mode. */ - inline void setMode(const Mode mode) { _mode = mode; } + void setMode(const Mode mode); /** Get the billboard rotation mode. */ - inline const Mode getMode() const { return _mode; } + inline const Mode getMode() const { return _mode; } + + /** Set the axis about which all the billboard's drawable rotate. */ + void setAxis(const Vec3& axis); + /** Get the axis about which all the billboard's drawable rotate. */ + inline const Vec3& getAxis() const { return _axis; } + /** Set the position of specified drawable. */ 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 ); - void calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix& mat) const; - void calcTransform(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; protected: @@ -83,10 +83,23 @@ class SG_EXPORT Billboard : public Geode virtual const bool computeBound() const; + enum AxisAligned + { + AXIAL_ROT_X_AXIS=AXIAL_ROT+1, + AXIAL_ROT_Y_AXIS, + AXIAL_ROT_Z_AXIS, + }; + Mode _mode; Vec3 _axis; 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(); }; diff --git a/src/osg/Billboard.cpp b/src/osg/Billboard.cpp index 9f6477e64..5fae55fe2 100644 --- a/src/osg/Billboard.cpp +++ b/src/osg/Billboard.cpp @@ -11,6 +11,7 @@ Billboard::Billboard() { _mode = AXIAL_ROT; _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) { @@ -67,21 +91,18 @@ const bool Billboard::removeDrawable( Drawable *gset ) return false; } - -void Billboard::calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix& mat) const +void Billboard::calcTransform(const Vec3& eye_local, const Vec3& up_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; 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); @@ -95,6 +116,69 @@ void Billboard::calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix } 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_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. // Robert Osfield, Jan 2001. - Vec3 ev = pos_local-eye_local; - ev.normalize(); - float ev_len = ev.length(); if (ev_len != 0.0f) { 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 cp_len = cp.length(); @@ -128,19 +209,8 @@ void Billboard::calcRotation(const Vec3& eye_local, const Vec3& pos_local,Matrix break; } } -} - -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]; + mat.setTrans(pos_local); }