diff --git a/code/BVHLoader.cpp b/code/BVHLoader.cpp index 0b2a818ae..8fa2a6f7f 100644 --- a/code/BVHLoader.cpp +++ b/code/BVHLoader.cpp @@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include using namespace Assimp; using namespace Assimp::Formatter; @@ -461,6 +462,13 @@ void BVHLoader::CreateAnimation( aiScene* pScene) aiNodeAnim* nodeAnim = new aiNodeAnim; anim->mChannels[a] = nodeAnim; nodeAnim->mNodeName.Set( nodeName); + std::map channelMap; + + //Build map of channels + for (unsigned int channel = 0; channel < node.mChannels.size(); ++channel) + { + channelMap[node.mChannels[channel]] = channel; + } // translational part, if given if( node.mChannels.size() == 6) @@ -472,16 +480,24 @@ void BVHLoader::CreateAnimation( aiScene* pScene) { poskey->mTime = double( fr); - // Now compute all translations in the right order - for( unsigned int channel = 0; channel < 3; ++channel) + // Now compute all translations + for(BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel +1)) { - switch( node.mChannels[channel]) - { - case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break; - case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break; - case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break; - default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName ); - } + //Find channel in node + std::map::iterator mapIter = channelMap.find(channel); + + if (mapIter == channelMap.end()) + throw DeadlyImportError("Missing position channel in node " + nodeName); + else { + int channelIdx = mapIter->second; + switch (channel) + { + case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channelIdx]; break; + case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channelIdx]; break; + case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channelIdx]; break; + } + + } } ++poskey; } @@ -497,12 +513,6 @@ void BVHLoader::CreateAnimation( aiScene* pScene) // rotation part. Always present. First find value offsets { - unsigned int rotOffset = 0; - if( node.mChannels.size() == 6) - { - // Offset all further calculations - rotOffset = 3; - } // Then create the number of rotation keys nodeAnim->mNumRotationKeys = mAnimNumFrames; @@ -512,20 +522,26 @@ void BVHLoader::CreateAnimation( aiScene* pScene) { aiMatrix4x4 temp; aiMatrix3x3 rotMatrix; + for (BVHLoader::ChannelType channel = Channel_RotationX; channel <= Channel_RotationZ; channel = (BVHLoader::ChannelType)(channel + 1)) + { + //Find channel in node + std::map::iterator mapIter = channelMap.find(channel); - for( unsigned int channel = 0; channel < 3; ++channel) - { - // translate ZXY euler angels into a quaternion - const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f; + if (mapIter == channelMap.end()) + throw DeadlyImportError("Missing rotation channel in node " + nodeName); + else { + int channelIdx = mapIter->second; + // translate ZXY euler angels into a quaternion + const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; - // Compute rotation transformations in the right order - switch (node.mChannels[rotOffset+channel]) - { - case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; - case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; - case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break; - default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName ); - } + // Compute rotation transformations in the right order + switch (channel) + { + case Channel_RotationX: aiMatrix4x4::RotationX(angle, temp); rotMatrix *= aiMatrix3x3(temp); break; + case Channel_RotationY: aiMatrix4x4::RotationY(angle, temp); rotMatrix *= aiMatrix3x3(temp); break; + case Channel_RotationZ: aiMatrix4x4::RotationZ(angle, temp); rotMatrix *= aiMatrix3x3(temp); break; + } + } } rotkey->mTime = double( fr);