//----------------------------------------------------------------------- Transform::Ptr Transform::Rotate(const Quaternion& q, TransformSpace relativeTo) { // Normalise quaternion to avoid drift Quaternion qnorm = q; qnorm.Normalise(); switch(relativeTo) { case TS_PARENT: // Rotations are normally relative to local axes, transform up orientation = qnorm * orientation; break; case TS_WORLD: // Rotations are normally relative to local axes, transform up orientation = orientation * _getDerivedOrientation().Inverse() * qnorm * _getDerivedOrientation(); break; case TS_LOCAL: // Note the order of the mult, i.e. q comes after orientation = orientation * qnorm; break; } needUpdate(true); return ThisPtr(); }
//--------------------------------------------------------------------- void Bone::setBindingPose(void) { setInitialState(); // Save inverse derived position/scale/orientation, used for calculate offset transform later mBindDerivedInversePosition = - _getDerivedPosition(); mBindDerivedInverseScale = Vector3::UNIT_SCALE / _getDerivedScale(); mBindDerivedInverseOrientation = _getDerivedOrientation().Inverse(); }
//----------------------------------------------------------------------- void Node::rotate(const Quaternion& q, TransformSpace relativeTo) { switch(relativeTo) { case TS_PARENT: // Rotations are normally relative to local axes, transform up mOrientation = q * mOrientation; break; case TS_WORLD: // Rotations are normally relative to local axes, transform up mOrientation = mOrientation * _getDerivedOrientation().Inverse() * q * _getDerivedOrientation(); break; case TS_LOCAL: // Note the order of the mult, i.e. q comes after mOrientation = mOrientation * q; break; } needUpdate(); }
// [7/30/2008 zhangxiang] const Matrix4 &sgNode::getFullTransform(void) const{ if(m_bCachedTransformOutOfDate){ // Use derived values m_CachedTransform.makeTransform( _getDerivedPosition(), _getDerivedScale(), _getDerivedOrientation()); m_bCachedTransformOutOfDate = false; } return m_CachedTransform; }
// [7/30/2008 zhangxiang] void sgNode::rotate(const Quaternion &aq, int aRelativeTo /* = TS_LOCAL */){ switch(aRelativeTo){ case TS_PARENT: // Rotations are normally relative to local axes, transform up m_RelativeOrientation = aq * m_RelativeOrientation; break; case TS_WORLD: // Rotations are normally relative to local axes, transform up m_RelativeOrientation = m_RelativeOrientation * _getDerivedOrientation().inverse() * aq * _getDerivedOrientation(); break; case TS_LOCAL: // Note the order of the mult, i.e. q comes after m_RelativeOrientation = m_RelativeOrientation * aq; break; } needUpdate(); }
//--------------------------------------------------------------------- void Bone::_getOffsetTransform(Matrix4& m) const { // Combine scale with binding pose inverse scale, // NB just combine as equivalent axes, no shearing Vector3 scale = _getDerivedScale() * mBindDerivedInverseScale; // Combine orientation with binding pose inverse orientation Quaternion rotate = _getDerivedOrientation() * mBindDerivedInverseOrientation; // Combine position with binding pose inverse position, // Note that translation is relative to scale & rotation, // so first reverse transform original derived position to // binding pose bone space, and then transform to current // derived bone space. Vector3 translate = _getDerivedPosition() + rotate * (scale * mBindDerivedInversePosition); m.makeTransform(translate, scale, rotate); }
//----------------------------------------------------------------------- void SceneNode::setDirection(const Vector3& vec, TransformSpace relativeTo, const Vector3& localDirectionVector) { // Do nothing if given a zero vector if (vec == Vector3::ZERO) return; // The direction we want the local direction point to Vector3 targetDir = vec.normalisedCopy(); // Transform target direction to world space switch (relativeTo) { case TS_PARENT: if (mInheritOrientation) { if (mParent) { targetDir = mParent->_getDerivedOrientation() * targetDir; } } break; case TS_LOCAL: targetDir = _getDerivedOrientation() * targetDir; break; case TS_WORLD: // default orientation break; } // Calculate target orientation relative to world space Quaternion targetOrientation; if( mYawFixed ) { // Calculate the quaternion for rotate local Z to target direction Vector3 xVec = mYawFixedAxis.crossProduct(targetDir); xVec.normalise(); Vector3 yVec = targetDir.crossProduct(xVec); yVec.normalise(); Quaternion unitZToTarget = Quaternion(xVec, yVec, targetDir); if (localDirectionVector == Vector3::NEGATIVE_UNIT_Z) { // Specail case for avoid calculate 180 degree turn targetOrientation = Quaternion(-unitZToTarget.y, -unitZToTarget.z, unitZToTarget.w, unitZToTarget.x); } else { // Calculate the quaternion for rotate local direction to target direction Quaternion localToUnitZ = localDirectionVector.getRotationTo(Vector3::UNIT_Z); targetOrientation = unitZToTarget * localToUnitZ; } } else { const Quaternion& currentOrient = _getDerivedOrientation(); // Get current local direction relative to world space Vector3 currentDir = currentOrient * localDirectionVector; if ((currentDir+targetDir).squaredLength() < 0.00005f) { // Oops, a 180 degree turn (infinite possible rotation axes) // Default to yaw i.e. use current UP targetOrientation = Quaternion(-currentOrient.y, -currentOrient.z, currentOrient.w, currentOrient.x); } else { // Derive shortest arc to new direction Quaternion rotQuat = currentDir.getRotationTo(targetDir); targetOrientation = rotQuat * currentOrient; } } // Set target orientation, transformed to parent space if (mParent && mInheritOrientation) setOrientation(mParent->_getDerivedOrientation().UnitInverse() * targetOrientation); else setOrientation(targetOrientation); }
//----------------------------------------------------------------------- const Quaternion& Node::getWorldOrientation(void) const { return _getDerivedOrientation(); }
// [7/30/2008 zhangxiang] const Quaternion &sgNode::absoluteOrientation(void) const{ return _getDerivedOrientation(); }