void Animation::SplitAnimation() { unsigned int startFrame = 0; double startTime = 0; unsigned int numKeyFrames = m_aiImporter->GetScene()->mAnimations[0]->mChannels[0]->mNumPositionKeys; m_logging->LogText(LogTag::RESOURCE, LogLevel::DEBUG_PRINT, "[ANIMATION] Animation has %d key frames", numKeyFrames); for (unsigned int keyFrame = 0; keyFrame < numKeyFrames; keyFrame++) { bool tPose = true; for (unsigned int channel = 0; channel < m_aiImporter->GetScene()->mAnimations[0]->mNumChannels; channel++) { aiQuaternion rotkey = m_aiImporter->GetScene()->mAnimations[0]->mChannels[channel]->mRotationKeys[keyFrame].mValue; if (!(rotkey == aiQuaternion(0,0,0))) { tPose = false; break; } } if(tPose) { AnimClip clip; clip.m_startTime = startTime; clip.m_duration = m_aiImporter->GetScene()->mAnimations[0]->mChannels[0]->mRotationKeys[keyFrame - 1].mTime - startTime; clip.m_startFrame = startFrame; clip.m_stopFrame = keyFrame - 1; m_animClips.push_back(clip); startTime = m_aiImporter->GetScene()->mAnimations[0]->mChannels[0]->mRotationKeys[keyFrame + 1].mTime; startFrame = keyFrame + 1; } } m_logging->LogText(LogTag::RESOURCE, LogLevel::DEBUG_PRINT, "[ANIMATION] Animation has %d animation clips", m_animClips.size()); }
/* Specialization for aiQuaternion */ template<> aiQuaternion comparer_context :: cmp<aiQuaternion >(const std::string& name) { const float w = cmp<float>(name+".w"); const float x = cmp<float>(name+".x"); const float y = cmp<float>(name+".y"); const float z = cmp<float>(name+".z"); return aiQuaternion(w,x,y,z); }
void OgreXmlSerializer::ReadAnimationKeyFrames(Animation *anim, VertexAnimationTrack *dest) { const aiVector3D zeroVec(0.f, 0.f, 0.f); NextNode(); while(m_currentNodeName == nnKeyFrame) { TransformKeyFrame keyframe; keyframe.timePos = ReadAttribute<float>("time"); NextNode(); while(m_currentNodeName == nnTranslate || m_currentNodeName == nnRotate || m_currentNodeName == nnScale) { if (m_currentNodeName == nnTranslate) { keyframe.position.x = ReadAttribute<float>(anX); keyframe.position.y = ReadAttribute<float>(anY); keyframe.position.z = ReadAttribute<float>(anZ); } else if (m_currentNodeName == nnRotate) { float angle = ReadAttribute<float>("angle"); if (NextNode() != nnAxis) { throw DeadlyImportError("No axis specified for keyframe rotation in animation " + anim->name); } aiVector3D axis; axis.x = ReadAttribute<float>(anX); axis.y = ReadAttribute<float>(anY); axis.z = ReadAttribute<float>(anZ); if (axis.Equal(zeroVec)) { axis.x = 1.0f; if (angle != 0) { DefaultLogger::get()->warn("Found invalid a key frame with a zero rotation axis in animation: " + anim->name); } } keyframe.rotation = aiQuaternion(axis, angle); } else if (m_currentNodeName == nnScale) { keyframe.scale.x = ReadAttribute<float>(anX); keyframe.scale.y = ReadAttribute<float>(anY); keyframe.scale.z = ReadAttribute<float>(anZ); } NextNode(); } dest->transformKeyFrames.push_back(keyframe); } }
//Draw the animation frame given time in seconds void drawFrame(double time) { model.createFrame(0, time); unsigned int boneId=model.boneName2boneId.at("head"); aiVector3D oldScale; aiQuaternion oldRotation; aiVector3D oldPosition; model.bones[boneId].transformation.Decompose(oldScale, oldRotation, oldPosition); aiMatrix3x3 newRotation; aiMatrix3x3::Rotation(cos(time*10.0), aiVector3D(0, 0, 1), newRotation); model.bones[boneId].transformation=aiMatrix4x4Compose(oldScale, aiQuaternion(newRotation)*oldRotation, oldPosition); for(auto& mesh: model.meshes) { auto meshFrame=model.getMeshFrame(mesh); model.drawMeshFrame(meshFrame); } }
void OgreXmlSerializer::ReadBones(Skeleton *skeleton) { DefaultLogger::get()->debug(" - Bones"); NextNode(); while(m_currentNodeName == nnBone) { Bone *bone = new Bone(); bone->id = ReadAttribute<uint16_t>("id"); bone->name = ReadAttribute<std::string>("name"); NextNode(); while(m_currentNodeName == nnPosition || m_currentNodeName == nnRotation || m_currentNodeName == nnScale) { if (m_currentNodeName == nnPosition) { bone->position.x = ReadAttribute<float>(anX); bone->position.y = ReadAttribute<float>(anY); bone->position.z = ReadAttribute<float>(anZ); } else if (m_currentNodeName == nnRotation) { float angle = ReadAttribute<float>("angle"); if (NextNode() != nnAxis) { throw DeadlyImportError(Formatter::format() << "No axis specified for bone rotation in bone " << bone->id); } aiVector3D axis; axis.x = ReadAttribute<float>(anX); axis.y = ReadAttribute<float>(anY); axis.z = ReadAttribute<float>(anZ); bone->rotation = aiQuaternion(axis, angle); } else if (m_currentNodeName == nnScale) { /// @todo Implement taking scale into account in matrix/pose calculations! if (HasAttribute("factor")) { float factor = ReadAttribute<float>("factor"); bone->scale.Set(factor, factor, factor); } else { if (HasAttribute(anX)) bone->scale.x = ReadAttribute<float>(anX); if (HasAttribute(anY)) bone->scale.y = ReadAttribute<float>(anY); if (HasAttribute(anZ)) bone->scale.z = ReadAttribute<float>(anZ); } } NextNode(); } skeleton->bones.push_back(bone); } // Order bones by Id std::sort(skeleton->bones.begin(), skeleton->bones.end(), BoneCompare); // Validate that bone indexes are not skipped. /** @note Left this from original authors code, but not sure if this is strictly necessary as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */ for (size_t i=0, len=skeleton->bones.size(); i<len; ++i) { Bone *b = skeleton->bones[i]; DefaultLogger::get()->debug(Formatter::format() << " " << b->id << " " << b->name); if (b->id != static_cast<uint16_t>(i)) { throw DeadlyImportError(Formatter::format() << "Bone ids are not in sequence starting from 0. Missing index " << i); } } }