void CameraTrackSettingDialog::OnModifyManual(wxCommandEvent& event) { if (mCameraTrack && mCameraAnimState) { int index = Ogre::StringConverter::parseUnsignedInt( mPointIndexTextCtrl->GetValue().c_str() ) - 1; if (index < mCameraTrack->getNumKeyFrames()) { mCameraTrack->removeKeyFrame(index); float time = Ogre::StringConverter::parseReal( mTimeTextCtrl->GetValue().c_str() ); if (time >=0.0f && time <= mCameraAnimState->getLength()) { Ogre::TransformKeyFrame* keyFrame = mCameraTrack->createNodeKeyFrame(time); // startposition keyFrame->setTranslate( Ogre::StringConverter::parseVector3( mPositionTextCtrl->GetValue().c_str() ) ); keyFrame->setRotation( Ogre::StringConverter::parseQuaternion( mOrientationTextCtrl->GetValue().c_str() ) ); RefreshCodeText(); } else { wxMessageBox(_("the time is wrong!")); } } else { wxMessageBox(_("the index is wrong!")); } } }
void OgreApplication::SetupAnimation(Ogre::String object_name){ /* Retrieve scene manager and root scene node */ Ogre::SceneManager* scene_manager = ogre_root_->getSceneManager("MySceneManager"); Ogre::SceneNode* root_scene_node = scene_manager->getRootSceneNode(); /* Set up animation */ Ogre::Real duration = Ogre::Math::TWO_PI; Ogre::Real num_steps = 36; Ogre::Real step = duration/num_steps; Ogre::Animation* animation = scene_manager->createAnimation("Animation", duration); animation->setInterpolationMode(Ogre::Animation::IM_LINEAR); Ogre::Node *object_scene_node = root_scene_node->getChild(object_name); Ogre::NodeAnimationTrack* track = animation->createNodeTrack(0, object_scene_node); /* Set up frames for animation */ Ogre::TransformKeyFrame* key; Ogre::Quaternion quat; for (int i = 0; i < num_steps; i++){ Ogre::Real current = ((float) i) * step; key = track->createNodeKeyFrame(current); quat.FromAngleAxis(Ogre::Radian(-current), Ogre::Vector3(0, 1, 0)); key->setRotation(quat); key->setScale(Ogre::Vector3(0.5, 0.5, 0.5)); } /* Create animation state */ animation_state_ = scene_manager->createAnimationState("Animation"); animation_state_->setEnabled(true); animation_state_->setLoop(true); /* Turn on animating flag */ animating_ = true; }
void AssetLoader::createCamera(Ogre::SceneManager* sceneMgr, const aiScene* scene, Ogre::String camName) { for (size_t n = 0; n < scene->mNumCameras; n++) { // カメラを作成 Ogre::Camera* cam = sceneMgr->createCamera(scene->mCameras[n]->mName.data); std::cout << "Create Camra " << cam->getName() << " " << scene->mCameras[n]->mHorizontalFOV << std::endl; cam->setFOVy(Ogre::Radian(scene->mCameras[n]->mHorizontalFOV)); // 視点アニメーション用ノード Ogre::SceneNode* camNode = sceneMgr->getRootSceneNode()->createChildSceneNode(cam->getName()+"CamNode"); camNode->attachObject(cam); // アニメーションを走査 for (size_t na = 0; na < scene->mNumAnimations; na++) { aiAnimation* aiani = scene->mAnimations[na]; for (size_t nc = 0; nc < aiani->mNumChannels; nc++) { // カメラと同じ名前のチャネルを取得する if (Ogre::String(scene->mCameras[n]->mName.data) == cam->getName()) { //アニメーションを付けるトラックを作成しておく Ogre::Animation* ogani = sceneMgr->createAnimation(cam->getName()+"Animation", aiani->mDuration); std::cout << "Animation : " << ogani->getName() << std::endl; Ogre::NodeAnimationTrack* track = ogani->createNodeTrack(0, camNode); ogani->setInterpolationMode(Ogre::Animation::IM_LINEAR); // アニメーションチャネルからキーフレームアニメーションを取得 aiNodeAnim* chan = aiani->mChannels[n]; for (size_t np = 0; np < chan->mNumPositionKeys; np++) { aiVectorKey* vk = &(chan->mPositionKeys[np]); Ogre::TransformKeyFrame* key = track->createNodeKeyFrame(vk->mTime); key->setTranslate(Ogre::Vector3(vk->mValue[0], vk->mValue[1], vk->mValue[2])); aiQuatKey* qk = &(chan->mRotationKeys[np]); key->setRotation(Ogre::Quaternion(qk->mValue.w, qk->mValue.x, qk->mValue.y, qk->mValue.z)); } // 管理するアニメーションの名前を付けておく Ogre::AnimationState* aniState = sceneMgr->createAnimationState(ogani->getName()); aniState->setEnabled(true); aniState->setLoop(true); aniState->setTimePosition(0.0); //ループを抜ける na = scene->mNumAnimations; break; } } } } }
void MenuScene::createAnimation(void) { Ogre::SceneNode *titleNode = static_cast<Ogre::SceneNode *>(mSceneMgr->getRootSceneNode()->getChild("boomb_title")); Ogre::Animation *anim = mSceneMgr->createAnimation("title_animation", 3); anim->setInterpolationMode(Ogre::Animation::IM_SPLINE); Ogre::NodeAnimationTrack *track = anim->createNodeTrack(0, titleNode); Ogre::TransformKeyFrame *key = track->createNodeKeyFrame(0); key->setTranslate(Ogre::Vector3(0,0,100)); Ogre::Quaternion q1 = titleNode->getOrientation(); Ogre::Quaternion q2(Ogre::Degree(45), Ogre::Vector3::UNIT_X); key->setRotation(q2); key = track->createNodeKeyFrame(1.5); key->setTranslate(Ogre::Vector3(0,0,120)); key->setRotation(q2); key = track->createNodeKeyFrame(3); key->setTranslate(Ogre::Vector3(0,0,100)); key->setRotation(q2); mTitleAnimState = mSceneMgr->createAnimationState("title_animation"); mTitleAnimState->setEnabled(true); mTitleAnimState->setLoop(true); Ogre::SceneNode *backgroundNode = static_cast<Ogre::SceneNode *>(mSceneMgr->getRootSceneNode()->getChild("boomb_background")); anim = mSceneMgr->createAnimation("background_animation", 30); anim->setInterpolationMode(Ogre::Animation::IM_SPLINE); track = anim->createNodeTrack(0, backgroundNode); key = track->createNodeKeyFrame(0); key->setTranslate(Ogre::Vector3(20,0,20)); key = track->createNodeKeyFrame(15); key->setTranslate(Ogre::Vector3(-20,0,-20)); key = track->createNodeKeyFrame(30); key->setTranslate(Ogre::Vector3(20,0,20)); mBackgroundAnimState = mSceneMgr->createAnimationState("background_animation"); mBackgroundAnimState->setEnabled(true); mBackgroundAnimState->setLoop(true); }
void CameraTrackSettingDialog::OnAddPoint(wxCommandEvent& event) { const Ogre::Vector3& pos = mCamera->getPosition(); const Ogre::Quaternion& ori = mCamera->getOrientation(); float animLength = Ogre::StringConverter::parseReal( mAnimLengthTextCtrl->GetValue().c_str() ); float pointTime = Ogre::StringConverter::parseReal( mPointTimeTextCtrl->GetValue().c_str() ); if (animLength == 0.0f || pointTime > animLength) { wxMessageBox(_("the time is wrong")); return; } if (!mCameraNode) { mCameraNode = mSceneManipulator->getBaseSceneNode()->createChildSceneNode(); } if (mTrackClear) { mCameraAnimation = mSceneManipulator->getSceneManager()->createAnimation("CameraTrack", animLength); // Spline it for nice curves mCameraAnimation->setInterpolationMode(Ogre::Animation::IM_SPLINE); // Create a track to animate the camera's node mCameraTrack = mCameraAnimation->createNodeTrack(0, mCameraNode); mCameraAnimState = mSceneManipulator->getSceneManager()->createAnimationState("CameraTrack"); mTrackClear = false; } Ogre::TransformKeyFrame* key = mCameraTrack->createNodeKeyFrame(pointTime); // startposition key->setTranslate(pos); key->setRotation(ori); RefreshCodeText(); }
void CameraTrackSettingDialog::OnModifyPoint(wxCommandEvent& event) { if (mCameraTrack) { int index = mModifySpinCtrl->GetValue() - 1; if (index < mCameraTrack->getNumKeyFrames()) { Ogre::TransformKeyFrame* keyFrame = static_cast<Ogre::TransformKeyFrame*>( mCameraTrack->getKeyFrame(index) ); const Ogre::Vector3& pos = mCamera->getPosition(); const Ogre::Quaternion& ori = mCamera->getOrientation(); keyFrame->setTranslate(pos); keyFrame->setRotation(ori); RefreshCodeText(); } else { wxMessageBox(_("the index is wrong!")); } } }
void CameraTrackSettingDialog::OnLoadTrack(wxCommandEvent& event) { wxFileDialog fileDialog(this, _("Load track file"), "", "", "Track files (*.track)|*.track", wxOPEN | wxFILE_MUST_EXIST); if (fileDialog.ShowModal() != wxID_OK) return; // 先清除当前的轨迹 ClearTrack(); std::ifstream stream; stream.open( fileDialog.GetPath().c_str() ); if (stream) { Ogre::DataStreamPtr ifStream( new Ogre::FileStreamDataStream(&stream, false) ); Ogre::String line; line = ifStream->getAsString(); Ogre::StringVector paras = Ogre::StringUtil::split(line, ","); if (paras.size() >= 2) { float length = Ogre::StringConverter::parseReal(paras[0]); if (!mCameraNode) { mCameraNode = mSceneManipulator->getBaseSceneNode()->createChildSceneNode(); } if (mTrackClear) { mCameraAnimation = mSceneManipulator->getSceneManager()->createAnimation("CameraTrack", length); // Spline it for nice curves mCameraAnimation->setInterpolationMode(Ogre::Animation::IM_SPLINE); // Create a track to animate the camera's node mCameraTrack = mCameraAnimation->createNodeTrack(0, mCameraNode); mCameraAnimState = mSceneManipulator->getSceneManager()->createAnimationState("CameraTrack"); mTrackClear = false; } unsigned int keyCount = Ogre::StringConverter::parseUnsignedInt(paras[1]); for (unsigned int i=0; i<keyCount; ++i) { Ogre::Vector3 pos = Ogre::StringConverter::parseVector3(paras[2 + i*3]); Ogre::Quaternion ori = Ogre::StringConverter::parseQuaternion(paras[3 + i*3]); float time = Ogre::StringConverter::parseReal(paras[4 + i*3]); Ogre::TransformKeyFrame* key = mCameraTrack->createNodeKeyFrame(time); // startposition key->setTranslate(pos); key->setRotation(ori); } RefreshCodeText(); } } }
void MilkshapePlugin::doExportAnimations(msModel* pModel, Ogre::SkeletonPtr& ogreskel) { Ogre::LogManager& logMgr = Ogre::LogManager::getSingleton(); std::vector<SplitAnimationStruct> splitInfo; Ogre::String msg; int numFrames = msModel_GetTotalFrames(pModel); msg = "Number of frames: " + Ogre::StringConverter::toString(numFrames); logMgr.logMessage(msg); if (splitAnimations) { // Explain msg = "You have chosen to create multiple discrete animations by splitting up the frames in " "the animation sequence. In order to do this, you must supply a simple text file " "describing the separate animations, which has a single line per animation in the format: \n\n" "startFrame,endFrame,animationName\n\nFor example: \n\n" "1,20,Walk\n21,35,Run\n36,40,Shoot\n\n" "..creates 3 separate animations (the frame numbers are inclusive)." "You must browse to this file in the next dialog."; MessageBox(0,msg.c_str(), "Splitting Animations",MB_ICONINFORMATION | MB_OK); // Prompt for a file which contains animation splitting info OPENFILENAME ofn; memset (&ofn, 0, sizeof (OPENFILENAME)); char szFile[MS_MAX_PATH]; char szFileTitle[MS_MAX_PATH]; char szDefExt[32] = "skeleton"; char szFilter[128] = "All Files (*.*)\0*.*\0\0"; szFile[0] = '\0'; szFileTitle[0] = '\0'; ofn.lStructSize = sizeof (OPENFILENAME); ofn.lpstrDefExt = szDefExt; ofn.lpstrFilter = szFilter; ofn.lpstrFile = szFile; ofn.nMaxFile = MS_MAX_PATH; ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = MS_MAX_PATH; ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; ofn.lpstrTitle = "Open animation split configuration file"; if (!::GetOpenFileName (&ofn)) { msg = "Splitting aborted, generating a single animation called 'Default'"; MessageBox(0, msg.c_str(), "Info", MB_OK | MB_ICONWARNING); SplitAnimationStruct split; split.start = 1; split.end = numFrames; split.name = "Default"; splitInfo.push_back(split); } else { // Read file Ogre::String sline; char line[256]; SplitAnimationStruct newSplit; std::ifstream istr; istr.open(szFile); while (!istr.eof()) { istr.getline(line, 256); sline = line; // Ignore blanks & comments if (sline == "" || sline.substr(0,2) == "//") continue; // Split on ',' std::vector<Ogre::String> svec = Ogre::StringUtil::split(line, ",\n"); // Basic validation on number of elements if (svec.size() != 3) { MessageBox(0, "Warning: corrupt animation details in file. You should look into this. ", "Corrupt animations file", MB_ICONWARNING | MB_OK); continue; } // Remove any embedded spaces Ogre::StringUtil::trim(svec[0]); Ogre::StringUtil::trim(svec[1]); Ogre::StringUtil::trim(svec[2]); // Create split info newSplit.start = atoi(svec[0].c_str()); newSplit.end = atoi(svec[1].c_str()); newSplit.name = svec[2]; splitInfo.push_back(newSplit); } } } else { // No splitting SplitAnimationStruct split; split.start = 1; split.end = numFrames; split.name = "Default"; splitInfo.push_back(split); } // Get animation length // Map frames -> seconds, this can be changed in speed of animation anyway int numBones = msModel_GetBoneCount(pModel); unsigned int frameTime; float realTime; std::vector<SplitAnimationStruct>::iterator animsIt; for (animsIt = splitInfo.begin(); animsIt != splitInfo.end(); ++animsIt) { SplitAnimationStruct& currSplit = *animsIt; // Create animation frameTime = currSplit.end - currSplit.start; realTime = frameTime / fps; Ogre::LogManager::getSingleton().stream() << "Trying to create Animation object for animation " << currSplit.name << " For Frames " << currSplit.start << " to " << currSplit.end << " inclusive. "; Ogre::LogManager::getSingleton().stream() << "Frame time = " << frameTime << ", Seconds = " << realTime; Ogre::Animation *ogreanim = ogreskel->createAnimation(currSplit.name, realTime); logMgr.logMessage("Animation object created."); int i; // Create all the animation tracks for (i = 0; i < numBones; ++i) { msBone* bone = msModel_GetBoneAt(pModel, i); Ogre::Bone* ogrebone = ogreskel->getBone(bone->szName); // Create animation tracks msg = "Creating AnimationTrack for bone " + Ogre::StringConverter::toString(i); logMgr.logMessage(msg); Ogre::NodeAnimationTrack *ogretrack = ogreanim->createNodeTrack(i, ogrebone); logMgr.logMessage("Animation track created."); // OGRE uses keyframes which are both position and rotation // Milkshape separates them, but never seems to use the ability to // have a different # of pos & rot keys int numKeys = msBone_GetRotationKeyCount(bone); msg = "Number of keyframes: " + Ogre::StringConverter::toString(numKeys); logMgr.logMessage(msg); int currKeyIdx; msPositionKey* currPosKey; msRotationKey* currRotKey; for (currKeyIdx = 0; currKeyIdx < numKeys; ++currKeyIdx ) { currPosKey = msBone_GetPositionKeyAt(bone, currKeyIdx); currRotKey = msBone_GetRotationKeyAt(bone, currKeyIdx); // Make sure keyframe is in current time frame (for splitting) if (currRotKey->fTime >= currSplit.start && currRotKey->fTime <= currSplit.end) { msg = "Creating KeyFrame #" + Ogre::StringConverter::toString(currKeyIdx) + " for bone #" + Ogre::StringConverter::toString(i); logMgr.logMessage(msg); // Create keyframe // Adjust for start time, and for the fact that frames are numbered from 1 frameTime = currRotKey->fTime - currSplit.start; realTime = frameTime / fps; Ogre::TransformKeyFrame *ogrekey = ogretrack->createNodeKeyFrame(realTime); logMgr.logMessage("KeyFrame created"); Ogre::Vector3 kfPos; // Imported milkshape animations may not have positions // for all rotation keys if ( currKeyIdx < bone->nNumPositionKeys ) { kfPos.x = currPosKey->Position[0]; kfPos.y = currPosKey->Position[1]; kfPos.z = currPosKey->Position[2]; } else { kfPos.x = bone->Position[0]; kfPos.y = bone->Position[1]; kfPos.z = bone->Position[2]; } Ogre::Quaternion qx, qy, qz, kfQ; // Milkshape translations are local to own orientation, not parent kfPos = ogrebone->getOrientation() * kfPos; ogrekey->setTranslate(kfPos); qx.FromAngleAxis(Ogre::Radian(currRotKey->Rotation[0]), Ogre::Vector3::UNIT_X); qy.FromAngleAxis(Ogre::Radian(currRotKey->Rotation[1]), Ogre::Vector3::UNIT_Y); qz.FromAngleAxis(Ogre::Radian(currRotKey->Rotation[2]), Ogre::Vector3::UNIT_Z); kfQ = qz * qy * qx; ogrekey->setRotation(kfQ); Ogre::LogManager::getSingleton().stream() << "KeyFrame details: Adjusted Frame Time=" << frameTime << " Seconds: " << realTime << " Position=" << kfPos << " " << "Ms3d Rotation= {" << currRotKey->Rotation[0] << ", " << currRotKey->Rotation[1] << ", " << currRotKey->Rotation[2] << "} " << "Orientation=" << kfQ; } // keyframe creation } // keys } //Bones } // Animations }
void SkeletonSerializerEx::readAnimationTrack( Ogre::DataStreamPtr& stream, Ogre::Animation* anim, Ogre::Skeleton* pSkel) { // unsigned short boneIndex : Index of bone to apply to unsigned short boneHandle; readShorts(stream, &boneHandle, 1); // Find bone Ogre::Bone *targetBone = pSkel->getBone(boneHandle); // Create track Ogre::NodeAnimationTrack* pTrack = anim->createNodeTrack(boneHandle, targetBone); // Keep looking for nested keyframes if (!stream->eof()) { unsigned short streamID = readChunk(stream); while((streamID == Ogre::SKELETON_ANIMATION_TRACK_KEYFRAME || streamID == 0x4120 ) && !stream->eof()) { if (streamID == 0x4120) { unsigned short len; unsigned short flags; readShorts(stream, &len, 1); readShorts(stream, &flags, 1); float time; for (int i = 0; i < len; i += 1) { readFloats(stream, &time, 1); Ogre::TransformKeyFrame *kf = pTrack->createNodeKeyFrame(time); Ogre::Quaternion rot = Ogre::Quaternion::IDENTITY; if (flags & 1) { readObject(stream, rot); } kf->setRotation(rot); Ogre::Vector3 trans = Ogre::Vector3::ZERO; if (flags & 2) { readObject(stream, trans); } kf->setTranslate(trans); // 为正确解析天龙八部模型的骨骼动画 Ogre::Vector3 scale = Ogre::Vector3::UNIT_SCALE; if (flags & 4) { readObject(stream, scale); } kf->setScale(scale); } } else readKeyFrame(stream, pTrack, pSkel); if (!stream->eof()) { // Get next stream streamID = readChunk(stream); } } if (!stream->eof()) { // Backpedal back to start of this stream if we've found a non-keyframe stream->skip(-STREAM_OVERHEAD_SIZE); } } }
/* Function used to load an AnimationState to a sceneNode. * Params: * @scnManager the SceneManager * @node The SceneNode to load the AnimationStates * @elem The TiXmlElement where is the animation * Returns: * anim On success * 0 On error */ bool Util::getAnimation(Ogre::SceneManager *scnManager, Ogre::SceneNode *node, TiXmlElement *elem, std::list<Ogre::AnimationState *> &animList) { ASSERT(scnManager); ASSERT(node); ASSERT(elem); if(Ogre::String(elem->Value()) != "animations") { debug("Invalid animation xml: %s \n", elem->Value()); return false; } animList.clear(); TiXmlElement *pElement = elem->FirstChildElement("animation"); if(!pElement){ debug("No animations found\n"); return false; } while(pElement){ TiXmlElement *actualElement = pElement; Ogre::String nombreanimacion = actualElement->Attribute("name"); Ogre::String activada = actualElement->Attribute("enable"); Ogre::String loop = actualElement->Attribute("loop"); Ogre::String modointerpolacion = actualElement->Attribute("interpolationMode"); Ogre::String modointerpolacionrotacion = actualElement->Attribute("rotationInterpolationMode"); Ogre::Real longitud= Ogre::StringConverter::parseReal(actualElement->Attribute("length")); Ogre::SceneManager *sceneMgr = scnManager; Ogre::Animation *animrueda = sceneMgr->createAnimation(nombreanimacion,longitud); if (modointerpolacion == "spline") { animrueda->setInterpolationMode(Ogre::Animation::IM_SPLINE); } else //linear { animrueda->setInterpolationMode(Ogre::Animation::IM_LINEAR); } if (modointerpolacionrotacion == "spherical") { animrueda->setRotationInterpolationMode(Ogre::Animation::RIM_SPHERICAL); } else //linear { animrueda->setRotationInterpolationMode(Ogre::Animation::RIM_LINEAR); } Ogre::NodeAnimationTrack *track = animrueda->createNodeTrack( animrueda->getNumNodeTracks() + 1, node); actualElement = actualElement->FirstChildElement(); do { Ogre::Real tiempo = Ogre::StringConverter::parseReal( actualElement->Attribute("time")); Ogre::TransformKeyFrame *kf = track->createNodeKeyFrame(tiempo); kf->setTranslate( parseVector3(actualElement->FirstChildElement("translation"))); kf->setRotation( parseQuaternion( actualElement->FirstChildElement("rotation"))); kf->setScale( parseVector3( actualElement->FirstChildElement("scale"))); } while (actualElement = actualElement->NextSiblingElement()); // Create the animation and put it in the list Ogre::AnimationState *as = scnManager->createAnimationState(nombreanimacion); as->setEnabled(false); as->setLoop(false); ASSERT(as); animList.push_back(as); pElement = pElement->NextSiblingElement("animation"); } return true; }