From Javier Taibo, "ere is the new code with Billboard "rotate around axis" functionality.
A new AutoRotateMode was added. I named it ROTATE_TO_AXIS to be consistent with the other AutoRotateModes, even though it changes from how is called in Billboard (AXIAL_ROT). Setters and getters for rotation axis and normal were also added to the AutoTransform class interface. The implementation is mainly a copy-paste from Billboard code. "
This commit is contained in:
@@ -72,13 +72,25 @@ class OSG_EXPORT AutoTransform : public Transform
|
||||
{
|
||||
NO_ROTATION,
|
||||
ROTATE_TO_SCREEN,
|
||||
ROTATE_TO_CAMERA
|
||||
ROTATE_TO_CAMERA,
|
||||
ROTATE_TO_AXIS
|
||||
};
|
||||
|
||||
void setAutoRotateMode(AutoRotateMode mode) { _autoRotateMode = mode; _firstTimeToInitEyePoint = true; }
|
||||
void setAutoRotateMode(AutoRotateMode mode);
|
||||
|
||||
AutoRotateMode getAutoRotateMode() const { return _autoRotateMode; }
|
||||
|
||||
/** Set the rotation axis for the AutoTransform's child nodes.
|
||||
* Only utilized when _autoRotateMode==ROTATE_TO_AXIS. */
|
||||
void setAxis(const Vec3& axis);
|
||||
/** Get the rotation axis. */
|
||||
inline const Vec3& getAxis() const { return _axis; }
|
||||
|
||||
/** This normal defines child Nodes' front face direction when unrotated. */
|
||||
void setNormal(const Vec3& normal);
|
||||
/** Get the front face direction normal. */
|
||||
inline const Vec3& getNormal() const { return _normal; }
|
||||
|
||||
void setAutoScaleToScreen(bool autoScaleToScreen) { _autoScaleToScreen = autoScaleToScreen; _matrixDirty=true; }
|
||||
|
||||
bool getAutoScaleToScreen() const { return _autoScaleToScreen; }
|
||||
@@ -124,6 +136,24 @@ class OSG_EXPORT AutoTransform : public Transform
|
||||
|
||||
mutable bool _matrixDirty;
|
||||
mutable osg::Matrixd _cachedMatrix;
|
||||
|
||||
enum AxisAligned
|
||||
{
|
||||
AXIAL_ROT_X_AXIS=ROTATE_TO_AXIS+1,
|
||||
AXIAL_ROT_Y_AXIS,
|
||||
AXIAL_ROT_Z_AXIS,
|
||||
CACHE_DIRTY
|
||||
};
|
||||
|
||||
Vec3 _axis;
|
||||
Vec3 _normal;
|
||||
|
||||
// used internally as cache of which what _axis is aligned to help
|
||||
// decide which method of rotation to use.
|
||||
int _cachedMode;
|
||||
Vec3 _side;
|
||||
void updateCache();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,11 @@ AutoTransform::AutoTransform():
|
||||
_minimumScale(0.0),
|
||||
_maximumScale(DBL_MAX),
|
||||
_autoScaleTransitionWidthRatio(0.25),
|
||||
_matrixDirty(true)
|
||||
_matrixDirty(true),
|
||||
_axis(0.0f,0.0f,1.0f),
|
||||
_normal(0.0f,-1.0f,0.0f),
|
||||
_cachedMode(NO_ROTATION),
|
||||
_side(1.0f,0.0,0.0f)
|
||||
{
|
||||
// setNumChildrenRequiringUpdateTraversal(1);
|
||||
}
|
||||
@@ -44,11 +48,52 @@ AutoTransform::AutoTransform(const AutoTransform& pat,const CopyOp& copyop):
|
||||
_minimumScale(pat._minimumScale),
|
||||
_maximumScale(pat._maximumScale),
|
||||
_autoScaleTransitionWidthRatio(pat._autoScaleTransitionWidthRatio),
|
||||
_matrixDirty(true)
|
||||
_matrixDirty(true),
|
||||
_axis(pat._axis),
|
||||
_normal(pat._normal),
|
||||
_cachedMode(pat._cachedMode),
|
||||
_side(pat._side)
|
||||
{
|
||||
// setNumChildrenRequiringUpdateTraversal(getNumChildrenRequiringUpdateTraversal()+1);
|
||||
}
|
||||
|
||||
void AutoTransform::setAutoRotateMode(AutoRotateMode mode)
|
||||
{
|
||||
_autoRotateMode = mode;
|
||||
_firstTimeToInitEyePoint = true;
|
||||
_cachedMode = CACHE_DIRTY;
|
||||
updateCache();
|
||||
}
|
||||
|
||||
void AutoTransform::setAxis(const Vec3& axis)
|
||||
{
|
||||
_axis = axis;
|
||||
_axis.normalize();
|
||||
updateCache();
|
||||
}
|
||||
|
||||
void AutoTransform::setNormal(const Vec3& normal)
|
||||
{
|
||||
_normal = normal;
|
||||
_normal.normalize();
|
||||
updateCache();
|
||||
}
|
||||
|
||||
void AutoTransform::updateCache()
|
||||
{
|
||||
if (_autoRotateMode==ROTATE_TO_AXIS)
|
||||
{
|
||||
if (_axis==Vec3(1.0f,0.0,0.0f) && _normal==Vec3(0.0f,-1.0,0.0f)) _cachedMode = AXIAL_ROT_X_AXIS;
|
||||
else if (_axis==Vec3(0.0f,1.0,0.0f) && _normal==Vec3(1.0f, 0.0,0.0f)) _cachedMode = AXIAL_ROT_Y_AXIS;
|
||||
else if (_axis==Vec3(0.0f,0.0,1.0f) && _normal==Vec3(0.0f,-1.0,0.0f)) _cachedMode = AXIAL_ROT_Z_AXIS;
|
||||
else _cachedMode = ROTATE_TO_AXIS;
|
||||
}
|
||||
else _cachedMode = _autoRotateMode;
|
||||
|
||||
_side = _axis^_normal;
|
||||
_side.normalize();
|
||||
}
|
||||
|
||||
void AutoTransform::setScale(const Vec3d& scale)
|
||||
{
|
||||
_scale = scale;
|
||||
@@ -240,6 +285,80 @@ void AutoTransform::accept(NodeVisitor& nv)
|
||||
q.set(osg::Matrix::inverse(lookto));
|
||||
setRotation(q);
|
||||
}
|
||||
else if (_autoRotateMode==ROTATE_TO_AXIS)
|
||||
{
|
||||
Matrix matrix;
|
||||
Vec3 ev(eyePoint - _position);
|
||||
|
||||
switch(_cachedMode)
|
||||
{
|
||||
case(AXIAL_ROT_Z_AXIS):
|
||||
{
|
||||
ev.z() = 0.0f;
|
||||
float ev_length = ev.length();
|
||||
if (ev_length>0.0f)
|
||||
{
|
||||
//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 s = ev.x()*inv;
|
||||
float c = -ev.y()*inv;
|
||||
matrix(0,0) = c;
|
||||
matrix(1,0) = -s;
|
||||
matrix(0,1) = s;
|
||||
matrix(1,1) = c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(AXIAL_ROT_Y_AXIS):
|
||||
{
|
||||
ev.y() = 0.0f;
|
||||
float ev_length = ev.length();
|
||||
if (ev_length>0.0f)
|
||||
{
|
||||
//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 s = -ev.z()*inv;
|
||||
float c = ev.x()*inv;
|
||||
matrix(0,0) = c;
|
||||
matrix(2,0) = s;
|
||||
matrix(0,2) = -s;
|
||||
matrix(2,2) = c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(AXIAL_ROT_X_AXIS):
|
||||
{
|
||||
ev.x() = 0.0f;
|
||||
float ev_length = ev.length();
|
||||
if (ev_length>0.0f)
|
||||
{
|
||||
//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 s = -ev.z()*inv;
|
||||
float c = -ev.y()*inv;
|
||||
matrix(1,1) = c;
|
||||
matrix(2,1) = -s;
|
||||
matrix(1,2) = s;
|
||||
matrix(2,2) = c;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case(ROTATE_TO_AXIS): // need to implement
|
||||
{
|
||||
float ev_side = ev*_side;
|
||||
float ev_normal = ev*_normal;
|
||||
float rotation = atan2f(ev_side,ev_normal);
|
||||
matrix.makeRotate(rotation,_axis);
|
||||
break;
|
||||
}
|
||||
}
|
||||
Quat q;
|
||||
q.set(matrix);
|
||||
setRotation(q);
|
||||
}
|
||||
|
||||
_previousEyePoint = eyePoint;
|
||||
_previousLocalUp = localUp;
|
||||
|
||||
Reference in New Issue
Block a user