- fbx: handle arbitrary rotation orders (all combinations of euler angles etc).

pull/14/head
Alexander Gessler 2012-08-11 02:17:22 +02:00
parent 1bdf39448a
commit 826b97a4fa
1 changed files with 98 additions and 41 deletions

View File

@ -89,11 +89,6 @@ public:
}; };
/** supported rotation modes */
enum RotationMode
{
RotationMode_Euler_XYZ
};
public: public:
@ -451,31 +446,90 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void GetRotationMatrix(RotationMode mode, const aiVector3D& rotation, aiMatrix4x4& out) void GetRotationMatrix(Model::RotOrder mode, const aiVector3D& rotation, aiMatrix4x4& out)
{ {
const float angle_epsilon = 1e-6f; if(mode == Model::RotOrder_SphericXYZ) {
aiMatrix4x4 temp; FBXImporter::LogError("Unsupported RotationMode: SphericXYZ");
out = aiMatrix4x4();
out = aiMatrix4x4();
switch(mode)
{
case RotationMode_Euler_XYZ:
if(fabs(rotation.z) > angle_epsilon) {
out = aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z),temp);
}
if(fabs(rotation.y) > angle_epsilon) {
out = out * aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y),temp);
}
if(fabs(rotation.x) > angle_epsilon) {
out = out * aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x),temp);
}
return; return;
} }
ai_assert(false); const float angle_epsilon = 1e-6f;
out = aiMatrix4x4();
bool is_id[3] = { true, true, true };
aiMatrix4x4 temp[3];
if(fabs(rotation.z) > angle_epsilon) {
aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z),temp[2]);
is_id[2] = false;
}
if(fabs(rotation.y) > angle_epsilon) {
aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y),temp[1]);
is_id[1] = false;
}
if(fabs(rotation.x) > angle_epsilon) {
aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x),temp[0]);
is_id[0] = false;
}
int order[3] = {-1, -1, -1};
// note: rotation order is inverted since we're left multiplying as is usual in assimp
switch(mode)
{
case Model::RotOrder_EulerXYZ:
order[0] = 2;
order[1] = 1;
order[2] = 0;
break;
case Model::RotOrder_EulerXZY:
order[0] = 1;
order[1] = 2;
order[2] = 0;
break;
case Model::RotOrder_EulerYZX:
order[0] = 0;
order[1] = 2;
order[2] = 1;
break;
case Model::RotOrder_EulerYXZ:
order[0] = 2;
order[1] = 0;
order[2] = 1;
break;
case Model::RotOrder_EulerZXY:
order[0] = 1;
order[1] = 0;
order[2] = 2;
break;
case Model::RotOrder_EulerZYX:
order[0] = 0;
order[1] = 1;
order[2] = 2;
break;
default:
ai_assert(false);
}
if(!is_id[order[0]]) {
out = temp[order[0]];
}
if(!is_id[order[1]]) {
out = out * temp[order[1]];
}
if(!is_id[order[2]]) {
out = out * temp[order[2]];
}
} }
@ -521,9 +575,7 @@ private:
std::vector<aiNode*>& output_nodes) std::vector<aiNode*>& output_nodes)
{ {
const PropertyTable& props = model.Props(); const PropertyTable& props = model.Props();
const Model::RotOrder rot = model.RotationOrder();
// XXX handle different rotation modes
const RotationMode rot = RotationMode_Euler_XYZ;
bool ok; bool ok;
@ -1891,7 +1943,7 @@ private:
ScopeGuard<aiNodeAnim> na(new aiNodeAnim()); ScopeGuard<aiNodeAnim> na(new aiNodeAnim());
na->mNodeName.Set(name); na->mNodeName.Set(name);
ConvertRotationKeys(na, curves, layer_map, max_time,min_time); ConvertRotationKeys(na, curves, layer_map, max_time,min_time, target.RotationOrder());
// dummy scaling key // dummy scaling key
na->mScalingKeys = new aiVectorKey[1]; na->mScalingKeys = new aiVectorKey[1];
@ -2019,7 +2071,8 @@ private:
ConvertRotationKeys(na, (*chain[TransformationComp_Rotation]).second, ConvertRotationKeys(na, (*chain[TransformationComp_Rotation]).second,
layer_map, layer_map,
max_time, max_time,
min_time); min_time,
target.RotationOrder());
} }
else { else {
na->mRotationKeys = new aiQuatKey[1]; na->mRotationKeys = new aiQuatKey[1];
@ -2027,8 +2080,8 @@ private:
na->mRotationKeys[0].mTime = 0.; na->mRotationKeys[0].mTime = 0.;
na->mRotationKeys[0].mValue = EulerToQuaternion( na->mRotationKeys[0].mValue = EulerToQuaternion(
PropertyGet(props,"Lcl Rotation",aiVector3D(0.f,0.f,0.f)) PropertyGet(props,"Lcl Rotation",aiVector3D(0.f,0.f,0.f)),
); target.RotationOrder());
} }
if(chain[TransformationComp_Translation] != iter_end) { if(chain[TransformationComp_Translation] != iter_end) {
@ -2214,7 +2267,8 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void InterpolateKeys(aiQuatKey* valOut,const KeyTimeList& keys, const KeyFrameListList& inputs, const bool geom, void InterpolateKeys(aiQuatKey* valOut,const KeyTimeList& keys, const KeyFrameListList& inputs, const bool geom,
double& maxTime, double& maxTime,
double& minTime) double& minTime,
Model::RotOrder order)
{ {
ai_assert(keys.size()); ai_assert(keys.size());
ai_assert(valOut); ai_assert(valOut);
@ -2225,17 +2279,17 @@ private:
for (size_t i = 0, c = keys.size(); i < c; ++i) { for (size_t i = 0, c = keys.size(); i < c; ++i) {
valOut[i].mTime = temp[i].mTime; valOut[i].mTime = temp[i].mTime;
valOut[i].mValue = EulerToQuaternion(temp[i].mValue); valOut[i].mValue = EulerToQuaternion(temp[i].mValue, order);
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// euler xyz -> quat // euler xyz -> quat
aiQuaternion EulerToQuaternion(const aiVector3D& rot) aiQuaternion EulerToQuaternion(const aiVector3D& rot, Model::RotOrder order)
{ {
aiMatrix4x4 m; aiMatrix4x4 m;
GetRotationMatrix(RotationMode_Euler_XYZ, rot, m); GetRotationMatrix(order, rot, m);
return aiQuaternion(aiMatrix3x3(m)); return aiQuaternion(aiMatrix3x3(m));
} }
@ -2262,7 +2316,8 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& layers, void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& layers,
double& maxTime, double& maxTime,
double& minTime) double& minTime)
{ {
@ -2279,9 +2334,11 @@ private:
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& layers, void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
const LayerMap& layers,
double& maxTime, double& maxTime,
double& minTime) double& minTime,
Model::RotOrder order)
{ {
ai_assert(nodes.size()); ai_assert(nodes.size());
@ -2291,7 +2348,7 @@ private:
na->mNumRotationKeys = static_cast<unsigned int>(keys.size()); na->mNumRotationKeys = static_cast<unsigned int>(keys.size());
na->mRotationKeys = new aiQuatKey[keys.size()]; na->mRotationKeys = new aiQuatKey[keys.size()];
InterpolateKeys(na->mRotationKeys, keys, inputs, false, maxTime, minTime); InterpolateKeys(na->mRotationKeys, keys, inputs, false, maxTime, minTime, order);
} }