void readRotationElement(KFbxTypedProperty<fbxDouble3>& prop, ERotationOrder fbxRotOrder, bool quatInterpolate, osgAnimation::UpdateMatrixTransform* pUpdate, osg::Matrix& staticTransform) { if (prop.GetKFCurve(KFCURVENODE_R_X) || prop.GetKFCurve(KFCURVENODE_R_Y) || prop.GetKFCurve(KFCURVENODE_R_Z)) { if (quatInterpolate) { if (!staticTransform.isIdentity()) { pUpdate->getStackedTransforms().push_back( new osgAnimation::StackedMatrixElement(staticTransform)); staticTransform.makeIdentity(); } pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedQuaternionElement( "quaternion", makeQuat(prop.Get(), fbxRotOrder))); } else { char* curveNames[3] = {KFCURVENODE_R_X, KFCURVENODE_R_Y, KFCURVENODE_R_Z}; osg::Vec3 axes[3] = {osg::Vec3(1,0,0), osg::Vec3(0,1,0), osg::Vec3(0,0,1)}; fbxDouble3 fbxPropValue = prop.Get(); fbxPropValue[0] = osg::DegreesToRadians(fbxPropValue[0]); fbxPropValue[1] = osg::DegreesToRadians(fbxPropValue[1]); fbxPropValue[2] = osg::DegreesToRadians(fbxPropValue[2]); int order[3] = {0, 1, 2}; getRotationOrder(fbxRotOrder, order); for (int i = 0; i < 3; ++i) { int j = order[2-i]; if (prop.GetKFCurve(curveNames[j])) { if (!staticTransform.isIdentity()) { pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedMatrixElement(staticTransform)); staticTransform.makeIdentity(); } pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedRotateAxisElement( std::string("rotate") + curveNames[j], axes[j], fbxPropValue[j])); } else { staticTransform.preMultRotate(osg::Quat(fbxPropValue[j], axes[j])); } } } } else { staticTransform.preMultRotate(makeQuat(prop.Get(), fbxRotOrder)); } }
void readUpdateMatrixTransform(osgAnimation::UpdateMatrixTransform* pUpdate, FbxNode* pNode, FbxScene& fbxScene) { osg::Matrix staticTransform; readTranslationElement(pNode->LclTranslation, pUpdate, staticTransform, fbxScene); FbxDouble3 fbxRotOffset = pNode->RotationOffset.Get(); FbxDouble3 fbxRotPiv = pNode->RotationPivot.Get(); staticTransform.preMultTranslate(osg::Vec3d( fbxRotPiv[0] + fbxRotOffset[0], fbxRotPiv[1] + fbxRotOffset[1], fbxRotPiv[2] + fbxRotOffset[2])); // When this flag is set to false, the RotationOrder, the Pre/Post rotation // values and the rotation limits should be ignored. bool rotationActive = pNode->RotationActive.Get(); EFbxRotationOrder fbxRotOrder = (rotationActive && pNode->RotationOrder.IsValid()) ? pNode->RotationOrder.Get() : eEulerXYZ; if (rotationActive) { staticTransform.preMultRotate(makeQuat(pNode->PreRotation.Get(), fbxRotOrder)); } readRotationElement(pNode->LclRotation, fbxRotOrder, pNode->QuaternionInterpolate.IsValid() && pNode->QuaternionInterpolate.Get(), pUpdate, staticTransform, fbxScene); if (rotationActive) { staticTransform.preMultRotate(makeQuat(pNode->PostRotation.Get(), fbxRotOrder)); } FbxDouble3 fbxSclOffset = pNode->ScalingOffset.Get(); FbxDouble3 fbxSclPiv = pNode->ScalingPivot.Get(); staticTransform.preMultTranslate(osg::Vec3d( fbxSclOffset[0] + fbxSclPiv[0] - fbxRotPiv[0], fbxSclOffset[1] + fbxSclPiv[1] - fbxRotPiv[1], fbxSclOffset[2] + fbxSclPiv[2] - fbxRotPiv[2])); readScaleElement(pNode->LclScaling, pUpdate, staticTransform, fbxScene); staticTransform.preMultTranslate(osg::Vec3d( -fbxSclPiv[0], -fbxSclPiv[1], -fbxSclPiv[2])); if (!staticTransform.isIdentity()) { pUpdate->getStackedTransforms().push_back(new osgAnimation::StackedMatrixElement(staticTransform)); } }
osgAnimation::Channel* readFbxChannelsQuat( KFbxAnimCurve* curveX, KFbxAnimCurve* curveY, KFbxAnimCurve* curveZ, const fbxDouble3& defaultValue, const char* targetName, ERotationOrder rotOrder) { if (!(curveX && curveX->KeyGetCount()) && !(curveY && curveY->KeyGetCount()) && !(curveZ && curveZ->KeyGetCount())) { return 0; } osgAnimation::QuatSphericalLinearChannel* pChannel = new osgAnimation::QuatSphericalLinearChannel; pChannel->setTargetName(targetName); pChannel->setName("quaternion"); typedef std::vector<osgAnimation::TemplateKeyframe<osg::Vec3> > KeyFrameCntr; KeyFrameCntr eulerFrameCntr; readKeys(curveX, curveY, curveZ, defaultValue, eulerFrameCntr, static_cast<float>(osg::PI / 180.0)); osgAnimation::QuatSphericalLinearSampler::KeyframeContainerType& quatFrameCntr = *pChannel->getOrCreateSampler()->getOrCreateKeyframeContainer(); quatFrameCntr.reserve(eulerFrameCntr.size()); for (KeyFrameCntr::iterator it = eulerFrameCntr.begin(), end = eulerFrameCntr.end(); it != end; ++it) { const osg::Vec3& euler = it->getValue(); quatFrameCntr.push_back(osgAnimation::QuatKeyframe( it->getTime(), makeQuat(euler, rotOrder))); } return pChannel; }
osg::Quat makeQuat(const osg::Vec3& radians, ERotationOrder fbxRotOrder) { fbxDouble3 degrees( osg::RadiansToDegrees(radians.x()), osg::RadiansToDegrees(radians.y()), osg::RadiansToDegrees(radians.z())); return makeQuat(degrees, fbxRotOrder); }
void makeLocalMatrix(const FbxNode* pNode, osg::Matrix& m) { /*From http://area.autodesk.com/forum/autodesk-fbx/fbx-sdk/the-makeup-of-the-local-matrix-of-an-kfbxnode/ Local Matrix = LclTranslation * RotationOffset * RotationPivot * PreRotation * LclRotation * PostRotation * RotationPivotInverse * ScalingOffset * ScalingPivot * LclScaling * ScalingPivotInverse LocalTranslation : translate (xform -query -translation) RotationOffset: translation compensates for the change in the rotate pivot point (xform -q -rotateTranslation) RotationPivot: current rotate pivot position (xform -q -rotatePivot) PreRotation : joint orientation(pre rotation) LocalRotation: rotate transform (xform -q -rotation & xform -q -rotateOrder) PostRotation : rotate axis (xform -q -rotateAxis) RotationPivotInverse: inverse of RotationPivot ScalingOffset: translation compensates for the change in the scale pivot point (xform -q -scaleTranslation) ScalingPivot: current scale pivot position (xform -q -scalePivot) LocalScaling: scale transform (xform -q -scale) ScalingPivotInverse: inverse of ScalingPivot */ // When this flag is set to false, the RotationOrder, the Pre/Post rotation // values and the rotation limits should be ignored. bool rotationActive = pNode->RotationActive.Get(); EFbxRotationOrder fbxRotOrder = rotationActive ? pNode->RotationOrder.Get() : eEulerXYZ; FbxDouble3 fbxLclPos = pNode->LclTranslation.Get(); FbxDouble3 fbxRotOff = pNode->RotationOffset.Get(); FbxDouble3 fbxRotPiv = pNode->RotationPivot.Get(); FbxDouble3 fbxPreRot = pNode->PreRotation.Get(); FbxDouble3 fbxLclRot = pNode->LclRotation.Get(); FbxDouble3 fbxPostRot = pNode->PostRotation.Get(); FbxDouble3 fbxSclOff = pNode->ScalingOffset.Get(); FbxDouble3 fbxSclPiv = pNode->ScalingPivot.Get(); FbxDouble3 fbxLclScl = pNode->LclScaling.Get(); m.makeTranslate(osg::Vec3d( fbxLclPos[0] + fbxRotOff[0] + fbxRotPiv[0], fbxLclPos[1] + fbxRotOff[1] + fbxRotPiv[1], fbxLclPos[2] + fbxRotOff[2] + fbxRotPiv[2])); if (rotationActive) { m.preMultRotate( makeQuat(fbxPostRot, fbxRotOrder) * makeQuat(fbxLclRot, fbxRotOrder) * makeQuat(fbxPreRot, fbxRotOrder)); } else { m.preMultRotate(makeQuat(fbxLclRot, fbxRotOrder)); } m.preMultTranslate(osg::Vec3d( fbxSclOff[0] + fbxSclPiv[0] - fbxRotPiv[0], fbxSclOff[1] + fbxSclPiv[1] - fbxRotPiv[1], fbxSclOff[2] + fbxSclPiv[2] - fbxRotPiv[2])); m.preMultScale(osg::Vec3d(fbxLclScl[0], fbxLclScl[1], fbxLclScl[2])); m.preMultTranslate(osg::Vec3d( -fbxSclPiv[0], -fbxSclPiv[1], -fbxSclPiv[2])); }
#include "Camera.h" #include "CommonDefs.h" #include <GLES2/gl2.h> #include "Log.h" #include <algorithm> static const Quatf makeQuat(const float hdg, const float pitch, const float roll) { return Quatf::fromAxisRot(Vector3f(static_cast<float>(std::sin(DEG2RAD(hdg))), 0, static_cast<float>(std::cos(DEG2RAD(hdg)))), pitch) * Quatf::fromAxisRot(Vector3f(0, 1, 0), hdg) * Quatf::fromAxisRot(Vector3f(1, 0, 0), roll); } const Quatf sQuats[] = { makeQuat(0, -45, 0), makeQuat(45, -45, 0), makeQuat(90, -45, 0), makeQuat(135, -45, 0), makeQuat(180, -45, 0), makeQuat(-135, -45, 0), makeQuat(-90, -45, 0), makeQuat(-45, -45, 0), makeQuat(0, -88, 0), makeQuat(0, -88, -90), makeQuat(0, -88, -180), makeQuat(0, -88, 90) }; const float Camera::sTransitionTime = 0.3f; const float Camera::sFOVNarrow = 45.0f;