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 AFile::addTo( Ogre::SkeletonPtr skeleton, const String& name ) const { if( skeleton->hasAnimation( name) ) return; Ogre::Real length( ( m_frames.size() - 1 ) * FRAME_DURATION ); Ogre::Animation *anim( skeleton->createAnimation(name, length )); uint16 track_handle( 0 ); Ogre::Bone* bone( skeleton->getBone( "root" ) ); Ogre::NodeAnimationTrack* track; track = anim->createNodeTrack( track_handle++, bone ); Ogre::Real time; size_t index( 0 ); for( FrameList::const_iterator frame( m_frames.begin()) ;frame != m_frames.end(); ++frame ) { time = (index++) * FRAME_DURATION; Ogre::TransformKeyFrame* key_frame( track->createNodeKeyFrame( time ) ); key_frame->setTranslate( frame->root_translation ); setFrameRotation( key_frame, frame->root_rotation ); } for( uint32 i(0); i < m_bone_count; ++i ) { if (i + 1 >= skeleton->getNumBones()) { // TODO: Figure out why this happens/fix it LOG_ERROR("Bone " + std::to_string(i + 1) + " is out of bounds " + std::to_string(skeleton->getNumBones()) + " for: " + name + " in: " + skeleton->getName()); } else { bone = skeleton->getBone(i + 1); track = anim->createNodeTrack(track_handle++, bone); time = 0; for (FrameList::const_iterator frame(m_frames.begin()) ; frame != m_frames.end(); ++frame) { const Ogre::Vector3& rot(frame->bone_rotations[i]); Ogre::TransformKeyFrame* key_frame(track->createNodeKeyFrame(time)); setFrameRotation(key_frame, rot); time += FRAME_DURATION; } } } }
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 WheelAnimalSceneObj::load(const std::string & filename) { //Ogre::ru * s = Orz::OgreGraphicsManager::getSingleton().getSceneManager()->getRootSceneNode()->createChildSceneNode(Ogre::Vector3(0, 0 ,0)); //导入场景资源 _impl = BaseSceneImpl::create(_osm, filename); //创建总场景节点 _senceNode = Orz::OgreGraphicsManager::getSingleton().getSceneManager()->getRootSceneNode()->createChildSceneNode(); //创建场景 _osm->createScene(_senceNode); _senceNode->setVisible(true); //s->setVisible(false); /*_impl->getCamera(SCENE_CAMERA)->setPosition(Ogre::Vector3(-98.851, 164.283, 237.886)); _impl->getCamera(SCENE_CAMERA)->setOrientation(Ogre::Quaternion(0.999578, -0.0192806, -0.0226839));*/ //创建摄像机的节点 _cameraSn = OgreGraphicsManager::getSingleton().getSceneManager()->getRootSceneNode()->createChildSceneNode(); //获取场景的摄像机 Ogre::Camera * camera = _impl->getCamera(SCENE_CAMERA); //创建摄像机的节点并设置它的位置 _cameraSn = camera->getParentSceneNode()->createChildSceneNode(Ogre::Vector3(0.f, 164.283f, 237.886f)); //_cameraSn->setPosition(Ogre::Vector3(-98.851, 164.283, 237.886)); //_cameraSn->setOrientation(Ogre::Quaternion(0.999578, -0.0192806, -0.0226839)); //camera->detatchFromParent(); //脱离原有的节点 camera->detachFromParent(); //摄像机绑定在节点上 _cameraSn->attachObject(_impl->getCamera(SCENE_CAMERA)); //创建场景的中心节点 Ogre::SceneNode * sn = getBaseCenter()->createChildSceneNode(Ogre::Vector3(0, 100,0)); //setAutoTracking可以让你的摄像机总是盯着你场景中的某一个节点 //方法中第一个参数确定是否打开自动跟踪,在任何一帧渲染之前都可以重新设置它。 //二个参数是被跟踪节点得指针,除非你第一个参数是false(这时候可以用NULL),否则你必须确定调用的时候指针指向的节点必须有效 camera->setAutoTracking(true, sn); // std::cout<<_camera->getPosition()<<"!"<<_camera->getOrientation()<<std::endl; //获取场景管理器 Ogre::SceneManager * sm = Orz::OgreGraphicsManager::getSingleton().getSceneManager(); // set up spline animation of node //定义动画,指定动画的名称及长度(这里为4秒) _anim = sm->createAnimation("Cam_", 4); //// Spline it for nice curves // // 指定动画关键帧之间的插值方式(包括线性插值和样条插值) _anim->setInterpolationMode(Ogre::Animation::IM_LINEAR); //定义动画的一个动画轨迹,并指定这个轨迹是作用到_cameraSn节点上的 //// Create a track to animate the camera's node Ogre::NodeAnimationTrack * track = _anim->createNodeTrack(0, _cameraSn); // 定义动画轨迹包含的关键帧,下面定义了3个关键帧,加上起始帧 // 4个关健帧形成了一个曲线的动画 Ogre::TransformKeyFrame* key = track->createNodeKeyFrame(0); // startposition key->setTranslate(Ogre::Vector3(0.f, 0.3f, 237.886f)); key = track->createNodeKeyFrame(3); // startposition key->setTranslate(Ogre::Vector3(0.f, 0.3f, 237.886f)); key = track->createNodeKeyFrame(4); key->setTranslate(Ogre::Vector3(0.f, -80.f, -400.f)); ////////////////////////////////// //定义动画的一个动画轨迹,并指定这个轨迹是作用到创建场景的中心节点sn上的 track = _anim->createNodeTrack(1, sn); key = track->createNodeKeyFrame(0); // startposition key->setTranslate(Ogre::Vector3(0, 0,0)); key = track->createNodeKeyFrame(3); // startposition key->setTranslate(Ogre::Vector3(0, 0,0)); key = track->createNodeKeyFrame(4); key->setTranslate(Ogre::Vector3(0, 200,0)); //// Create a new animation state to track this //定义AnimationState类的对象,它和刚才定义的动画类相对应。设置动画的状态为启用: _animState = sm->createAnimationState("Cam_"); _animState->setEnabled(true);// 启用该动画 _animState->setLoop(false); /* Ogre::MaterialPtr material = Ogre::MaterialPtr(Ogre::MaterialManager::getSingleton().getByName("Material_#11/lanseshuijing")); material->getTechnique(0)->getPass(0)->getTextureUnitState(0)->setTextureName("shuijing-lv.dds");*/ }
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 CSceletalAnimationView::EngineSetup(void) { Ogre::Root *Root = ((CSceletalAnimationApp*)AfxGetApp())->m_Engine->GetRoot(); Ogre::SceneManager *SceneManager = NULL; SceneManager = Root->createSceneManager(Ogre::ST_GENERIC, "Animation"); // // Create a render window // This window should be the current ChildView window using the externalWindowHandle // value pair option. // Ogre::NameValuePairList parms; parms["externalWindowHandle"] = Ogre::StringConverter::toString((long)m_hWnd); parms["vsync"] = "true"; CRect rect; GetClientRect(&rect); Ogre::RenderTarget *RenderWindow = Root->getRenderTarget("Mouse Input"); if (RenderWindow == NULL) { try { m_RenderWindow = Root->createRenderWindow("Mouse Input", rect.Width(), rect.Height(), false, &parms); } catch(...) { MessageBox("Cannot initialize\nCheck that graphic-card driver is up-to-date", "Initialize Render System", MB_OK | MB_ICONSTOP); exit(EXIT_SUCCESS); } } // Load resources Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); // Create the camera m_Camera = SceneManager->createCamera("Camera"); m_Camera->setNearClipDistance(0.5); m_Camera->setFarClipDistance(5000); m_Camera->setCastShadows(false); m_Camera->setUseRenderingDistance(true); m_Camera->setPosition(Ogre::Vector3(5.0, 5.0, 10.0)); Ogre::SceneNode *CameraNode = NULL; CameraNode = SceneManager->getRootSceneNode()->createChildSceneNode("CameraNode"); Ogre::Viewport* Viewport = NULL; if (0 == m_RenderWindow->getNumViewports()) { Viewport = m_RenderWindow->addViewport(m_Camera); Viewport->setBackgroundColour(Ogre::ColourValue(0.8f, 0.8f, 0.8f)); } // Alter the camera aspect ratio to match the viewport m_Camera->setAspectRatio(Ogre::Real(rect.Width()) / Ogre::Real(rect.Height())); m_Camera->lookAt(Ogre::Vector3(0.5, 0.5, 0.5)); m_Camera->setPolygonMode(Ogre::PolygonMode::PM_WIREFRAME); Ogre::ManualObject* ManualObject = NULL; ManualObject = SceneManager->createManualObject("Animation"); ManualObject->setDynamic(false); ManualObject->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OT_TRIANGLE_LIST); //face 1 ManualObject->position(0, 0, 0);//0 ManualObject->position(1, 0, 0);//1 ManualObject->position(1, 1, 0);//2 ManualObject->triangle(0, 1, 2);//3 ManualObject->position(0, 0, 0);//4 ManualObject->position(1, 1, 0);//5 ManualObject->position(0, 1, 0);//6 ManualObject->triangle(3, 4, 5);//7 //face 2 ManualObject->position(0, 0, 1);//8 ManualObject->position(1, 0, 1);//9 ManualObject->position(1, 1, 1);//10 ManualObject->triangle(6, 7, 8);//11 ManualObject->position(0, 0, 1);//12 ManualObject->position(1, 1, 1);//13 ManualObject->position(0, 1, 1);//14 ManualObject->triangle(9, 10, 11);//15 //face 3 ManualObject->position(0, 0, 0);//16 ManualObject->position(1, 0, 0);//17 ManualObject->position(1, 0, 1);//18 ManualObject->triangle(12, 13, 14);//19 ManualObject->position(0, 0, 0); ManualObject->position(1, 0, 1); ManualObject->position(0, 1, 1); ManualObject->triangle(15, 16, 17); //face 4 ManualObject->position(1, 0, 0); ManualObject->position(1, 1, 0); ManualObject->position(1, 1, 1); ManualObject->triangle(18, 19, 20); ManualObject->position(1, 0, 0); ManualObject->position(1, 1, 1); ManualObject->position(1, 0, 1); ManualObject->triangle(21, 22, 23); //face 5 ManualObject->position(0, 1, 0); ManualObject->position(1, 1, 0); ManualObject->position(0, 1, 1); ManualObject->triangle(24, 25, 26); ManualObject->position(1, 1, 0); ManualObject->position(1, 1, 1); ManualObject->position(0, 1, 1); ManualObject->triangle(27, 28, 29); //face 6 ManualObject->position(0, 0, 0); ManualObject->position(0, 1, 1); ManualObject->position(0, 0, 1); ManualObject->triangle(30, 31, 32); ManualObject->position(0, 0, 0); ManualObject->position(0, 1, 0); ManualObject->position(0, 1, 1); ManualObject->triangle(33, 34, 35); ManualObject->end(); Ogre::MeshPtr MeshPtr = ManualObject->convertToMesh("Animation"); Ogre::SubMesh* sub = MeshPtr->getSubMesh(0); Ogre::SkeletonPtr Skeleton = Ogre::SkeletonManager::getSingleton().create("Skeleton", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); MeshPtr.getPointer()->_notifySkeleton(Skeleton); Ogre::Bone *Root1 = NULL; Ogre::Bone *Child1 = NULL; Ogre::Bone *Child2 = NULL; Root1 = Skeleton.getPointer()->createBone("Root"); Root1->setPosition(Ogre::Vector3(0.0, 0.0, 0.0)); Root1->setOrientation(Ogre::Quaternion::IDENTITY); Child1 = Root1->createChild(1); Child1->setPosition(Ogre::Vector3(4.0, 0.0, 0.0)); Child1->setOrientation(Ogre::Quaternion::IDENTITY); Child2 = Root1->createChild(2); Child2->setPosition(Ogre::Vector3(5.0, 0.0, 0.0)); Child2->setOrientation(Ogre::Quaternion::IDENTITY); Ogre::VertexBoneAssignment Assignment; Assignment.boneIndex = 0; Assignment.vertexIndex = 0; Assignment.weight = 1.0; Skeleton->setBindingPose(); sub->addBoneAssignment(Assignment); Assignment.vertexIndex = 1; sub->addBoneAssignment(Assignment); Assignment.vertexIndex = 2; sub->addBoneAssignment(Assignment); Ogre::Animation *Animation = MeshPtr->createAnimation("HandAnimation", 100.0); Ogre::NodeAnimationTrack *Track = Animation->createNodeTrack(0, Root1); Ogre::TransformKeyFrame *KeyFrame = NULL; for (float FrameTime = 0.0; FrameTime < 100.0; FrameTime += 0.1) { KeyFrame = Track->createNodeKeyFrame(FrameTime); KeyFrame->setTranslate(Ogre::Vector3(10.0, 0.0, 0.0)); } Root1->setManuallyControlled(true); Child1->setManuallyControlled(true); Child2->setManuallyControlled(true); MeshPtr->load(); MeshPtr.getPointer()->_notifySkeleton(Skeleton); // Ogre::SkeletonSerializer skeletonSerializer; // skeletonSerializer.exportSkeleton(Skeleton.get(), "C:\\Users\\Ilya\\Documents\\Visual Studio 2010\\Projects\\Recipes\\media\\models\\testskeleton.skeleton"); // Ogre::MeshSerializer ser; // ser.exportMesh(MeshPtr.get(), "C:\\Users\\Ilya\\Documents\\Visual Studio 2010\\Projects\\Recipes\\media\\models\\testskeleton.mesh"); Ogre::Entity *Entity = SceneManager->createEntity("Animation", "Animation"/*"testskeleton.mesh"*/); Ogre::SceneNode *SceneNode = SceneManager->getRootSceneNode()->createChildSceneNode(); SceneNode->attachObject(Entity); Entity->setDisplaySkeleton(true); m_AnimationState = Entity->getAnimationState("HandAnimation"); m_AnimationState->setEnabled(true); m_AnimationState->setLoop(true); m_Camera->setPolygonMode(Ogre::PolygonMode::PM_WIREFRAME); Root->renderOneFrame(); }
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); } } }
void EC_OgreAnimationController::Update(f64 frametime) { Ogre::Entity* entity = GetEntity(); if (!entity) return; std::vector<std::string> erase_list; // Loop through all animations & update them as necessary for (AnimationMap::iterator i = animations_.begin(); i != animations_.end(); ++i) { Ogre::AnimationState* animstate = GetAnimationState(entity, i->first); if (!animstate) continue; switch(i->second.phase_) { case PHASE_FADEIN: // If period is infinitely fast, skip to full weight & PLAY status if (i->second.fade_period_ == 0.0f) { i->second.weight_ = 1.0f; i->second.phase_ = PHASE_PLAY; } else { i->second.weight_ += (1.0f / i->second.fade_period_) * frametime; if (i->second.weight_ >= 1.0f) { i->second.weight_ = 1.0f; i->second.phase_ = PHASE_PLAY; } } break; case PHASE_PLAY: if (i->second.auto_stop_ || i->second.num_repeats_ != 1) { if ((i->second.speed_factor_ >= 0.f && animstate->getTimePosition() >= animstate->getLength()) || (i->second.speed_factor_ < 0.f && animstate->getTimePosition() <= 0.f)) { if (i->second.num_repeats_ != 1) { if (i->second.num_repeats_ > 1) i->second.num_repeats_--; Ogre::Real rewindpos = i->second.speed_factor_ >= 0.f ? (animstate->getTimePosition() - animstate->getLength()) : animstate->getLength(); animstate->setTimePosition(rewindpos); } else { i->second.phase_ = PHASE_FADEOUT; } } } break; case PHASE_FADEOUT: // If period is infinitely fast, skip to disabled status immediately if (i->second.fade_period_ == 0.0f) { i->second.weight_ = 0.0f; i->second.phase_ = PHASE_STOP; } else { i->second.weight_ -= (1.0f / i->second.fade_period_) * frametime; if (i->second.weight_ <= 0.0f) { i->second.weight_ = 0.0f; i->second.phase_ = PHASE_STOP; } } break; } // Set weight & step the animation forward if (i->second.phase_ != PHASE_STOP) { Ogre::Real advance = i->second.speed_factor_ * frametime; Ogre::Real new_weight = i->second.weight_ * i->second.weight_factor_; if (new_weight != animstate->getWeight()) animstate->setWeight((Ogre::Real)i->second.weight_ * i->second.weight_factor_); if (advance != 0.0f) animstate->addTime((Ogre::Real)(i->second.speed_factor_ * frametime)); if (!animstate->getEnabled()) animstate->setEnabled(true); } else { // If stopped, disable & remove this animation from list animstate->setEnabled(false); erase_list.push_back(i->first); } } for (uint i = 0; i < erase_list.size(); ++i) { animations_.erase(erase_list[i]); } // High-priority/low-priority blending code if (entity->hasSkeleton()) { Ogre::SkeletonInstance* skel = entity->getSkeleton(); if (!skel) return; if (highpriority_mask_.size() != skel->getNumBones()) highpriority_mask_.resize(skel->getNumBones()); if (lowpriority_mask_.size() != skel->getNumBones()) lowpriority_mask_.resize(skel->getNumBones()); for (uint i = 0; i < skel->getNumBones(); ++i) { highpriority_mask_[i] = 1.0; lowpriority_mask_[i] = 1.0; } // Loop through all high priority animations & update the lowpriority-blendmask based on their active tracks for (AnimationMap::iterator i = animations_.begin(); i != animations_.end(); ++i) { Ogre::AnimationState* animstate = GetAnimationState(entity, i->first); if (!animstate) continue; // Create blend mask if animstate doesn't have it yet if (!animstate->hasBlendMask()) animstate->createBlendMask(skel->getNumBones()); if ((i->second.high_priority_) && (i->second.weight_ > 0.0)) { // High-priority animations get the full weight blend mask animstate->_setBlendMaskData(&highpriority_mask_[0]); if (!skel->hasAnimation(animstate->getAnimationName())) continue; Ogre::Animation* anim = skel->getAnimation(animstate->getAnimationName()); Ogre::Animation::NodeTrackIterator it = anim->getNodeTrackIterator(); while (it.hasMoreElements()) { Ogre::NodeAnimationTrack* track = it.getNext(); unsigned id = track->getHandle(); // For each active track, reduce corresponding bone weight in lowpriority-blendmask // by this animation's weight if (id < lowpriority_mask_.size()) { lowpriority_mask_[id] -= i->second.weight_; if (lowpriority_mask_[id] < 0.0) lowpriority_mask_[id] = 0.0; } } } } // Now set the calculated blendmask on low-priority animations for (AnimationMap::iterator i = animations_.begin(); i != animations_.end(); ++i) { Ogre::AnimationState* animstate = GetAnimationState(entity, i->first); if (!animstate) continue; if (i->second.high_priority_ == false) animstate->_setBlendMaskData(&lowpriority_mask_[0]); } } }
/* 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; }
void AnimationFile::GetData( std::vector< s16 >& skeleton_length, const Unit& unit, const int offset_to_animations, const int number_of_animation, const int start_animation, Ogre::SkeletonPtr skeleton) { for (int i = 0; i < number_of_animation; ++i) { /*LOGGER->Log(LOGGER_INFO, "Animation Header %02x%02x %02x %02x %02x %02x %02x%02x %02x%02x %02x%02x %02x%02x%02x%02x", GetU8(offset_to_animations + i * 0x10 + 0x00), GetU8(offset_to_animations + i * 0x10 + 0x01), GetU8(offset_to_animations + i * 0x10 + 0x02), GetU8(offset_to_animations + i * 0x10 + 0x03), GetU8(offset_to_animations + i * 0x10 + 0x04), GetU8(offset_to_animations + i * 0x10 + 0x05), GetU8(offset_to_animations + i * 0x10 + 0x06), GetU8(offset_to_animations + i * 0x10 + 0x07), GetU8(offset_to_animations + i * 0x10 + 0x08), GetU8(offset_to_animations + i * 0x10 + 0x09), GetU8(offset_to_animations + i * 0x10 + 0x0A), GetU8(offset_to_animations + i * 0x10 + 0x0B), GetU8(offset_to_animations + i * 0x10 + 0x0C), GetU8(offset_to_animations + i * 0x10 + 0x0D), GetU8(offset_to_animations + i * 0x10 + 0x0E), GetU8(offset_to_animations + i * 0x10 + 0x0F)); */ AnimationHeader header; header.number_of_frames = GetU16LE(offset_to_animations + i * 0x10 + 0x00); header.number_of_bones = GetU8(offset_to_animations + i * 0x10 + 0x02); header.number_of_frames_translation = GetU8(offset_to_animations + i * 0x10 + 0x03); header.number_of_static_translation = GetU8(offset_to_animations + i * 0x10 + 0x04); header.number_of_frames_rotation = GetU8(offset_to_animations + i * 0x10 + 0x05); header.offset_to_frames_translation_data = GetU16LE(offset_to_animations + i * 0x10 + 0x06); header.offset_to_static_translation_data = GetU16LE(offset_to_animations + i * 0x10 + 0x08); header.offset_to_frames_rotation_data = GetU16LE(offset_to_animations + i * 0x10 + 0x0A); header.offset_to_animation_data = GetU32LE(offset_to_animations + i * 0x10 + 0x0C) - 0x80000000; m_AnimationHeaders.push_back(header); } for (size_t i = 0; (i < static_cast<size_t>(number_of_animation)) && (start_animation + i < unit.animations.size()); ++i) { if (unit.animations[start_animation + i] == "" || unit.animations[start_animation + i] == " ") { continue; } /* File file(mpBuffer, m_AnimationHeaders[i].offset_to_animation_data, 0x04 + m_AnimationHeaders[i].number_of_bones * 0x08 + m_AnimationHeaders[i].number_of_frames_translation * m_AnimationHeaders[i].number_of_frames * 0x02 + m_AnimationHeaders[i].number_of_static_translation * 0x02 + m_AnimationHeaders[i].number_of_frames_rotation * m_AnimationHeaders[i].number_of_frames); file.WriteFile(RString((Ogre::String("dump/") + Ogre::String("animation_") + Ogre::StringConverter::toString(i) + Ogre::String("_data")).c_str())); */ Ogre::Animation* anim = skeleton->createAnimation(unit.animations[start_animation + i], (float)(m_AnimationHeaders[i].number_of_frames - 1) / 30.0f); for (u32 j = 0; j < m_AnimationHeaders[i].number_of_frames; ++j) { Frame frame; // root bone Ogre::Bone* root = skeleton->getBone(0); Ogre::NodeAnimationTrack* track; if (j == 0) { track = anim->createNodeTrack(0, root); track->removeAllKeyFrames(); } else { track = anim->getNodeTrack(0); } Ogre::TransformKeyFrame* frame_root = track->createNodeKeyFrame((float)j / 30.0f); Ogre::Quaternion rot; Ogre::Matrix3 mat; mat.FromEulerAnglesZXY(Ogre::Radian(Ogre::Degree(180)), Ogre::Radian(Ogre::Degree(0)), Ogre::Radian(Ogre::Degree(0))); rot.FromRotationMatrix(mat); frame_root->setRotation(rot); for (u32 k = 0; k < m_AnimationHeaders[i].number_of_bones; ++k) { BonePosition position; u8 flag = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x00); u8 rx = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x01); u8 ry = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x02); u8 rz = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x03); u8 tx = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x04); u8 ty = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x05); u8 tz = GetU8(m_AnimationHeaders[i].offset_to_animation_data + 0x04 + k * 0x08 + 0x06); // rotation if (flag & 0x01) { position.rotation_x = 360.0f * GetU8(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_rotation_data + rx * m_AnimationHeaders[i].number_of_frames + j) / 255.0f; } else { position.rotation_x = 360.0f * rx / 255.0f; } if (flag & 0x02) { position.rotation_y = 360.0f * GetU8(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_rotation_data + ry * m_AnimationHeaders[i].number_of_frames + j) / 255.0f; } else { position.rotation_y = 360.0f * ry / 255.0f; } if (flag & 0x04) { position.rotation_z = 360.0f * GetU8(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_rotation_data + rz * m_AnimationHeaders[i].number_of_frames + j) / 255.0f; } else { position.rotation_z = 360.0f * rz / 255.0f; } // translation position.translation_x = 0; position.translation_y = 0; position.translation_z = 0; if (flag & 0x10) { position.translation_x = static_cast<float>( -(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_translation_data + tx * m_AnimationHeaders[i].number_of_frames * 2 + j * 2)); } else if (tx != 0xFF) { position.translation_x = static_cast<float>(-(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_static_translation_data + tx * 2)); } if (flag & 0x20) { position.translation_y = static_cast<float>(-(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_translation_data + ty * m_AnimationHeaders[i].number_of_frames * 2 + j * 2)); } else if (ty != 0xFF) { position.translation_y = static_cast<float>(-(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_static_translation_data + ty * 2)); } if (flag & 0x40) { position.translation_z = static_cast<float>(-(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_frames_translation_data + tz * m_AnimationHeaders[i].number_of_frames * 2 + j * 2)); } else if (tz != 0xFF) { position.translation_z = static_cast<float>(-(s16)GetU16LE(m_AnimationHeaders[i].offset_to_animation_data + m_AnimationHeaders[i].offset_to_static_translation_data + tz * 2)); } //LOGGER->Log(LOGGER_INFO, "%d %d", m_AnimationHeaders[i].number_of_frames, j); //LOGGER->Log(LOGGER_INFO, "animation (%f %f %f) (%f %f %f)", position.rotation_x, position.rotation_y, position.rotation_z, position.translation_x, position.translation_y, position.translation_z); frame.bone.push_back(position); Ogre::Bone* bone1 = skeleton->getBone(k * 2 + 1); Ogre::Bone* bone2 = skeleton->getBone(k * 2 + 2); Ogre::NodeAnimationTrack* track1; Ogre::NodeAnimationTrack* track2; if (j == 0) { track1 = anim->createNodeTrack(k * 2 + 1, bone1); track1->removeAllKeyFrames(); track2 = anim->createNodeTrack(k * 2 + 2, bone2); track2->removeAllKeyFrames(); } else { track1 = anim->getNodeTrack(k * 2 + 1); track2 = anim->getNodeTrack(k * 2 + 2); } Ogre::TransformKeyFrame* frame1 = track1->createNodeKeyFrame((float)j / 30.0f); Ogre::TransformKeyFrame* frame2 = track2->createNodeKeyFrame((float)j / 30.0f); float length = skeleton_length[ k ]; frame1->setTranslate(Ogre::Vector3(position.translation_x, position.translation_z - length, position.translation_y) / 1024); Ogre::Quaternion rot; Ogre::Matrix3 mat; mat.FromEulerAnglesZXY(Ogre::Radian(Ogre::Degree(-position.rotation_y)), Ogre::Radian(Ogre::Degree(-position.rotation_x)), Ogre::Radian(Ogre::Degree(-position.rotation_z))); rot.FromRotationMatrix(mat); frame2->setRotation(rot); } } } }