原创内容转载请注明:http://weibo.com/gdexqin
程序代码的的基础在http://blog.sina.com.cn/s/blog_7c03dc6f01012um2.html中
先看导入后的效果。
动画模型是用别人传到网上的(好像这个人物叫真名法典的样子,不太认识,但是感谢上传者),之前我们已经完成了通过OGREMAX导入静态的场景的效果,导入骨骼动画我们需要对OGREMAX的导出选项进行一些修改。
下面先了解一下OGREMAX的一些基本选项(转自网络):
-------------我是分割线----------------------------------------------------------------------
在OgreMax->Object Settings中可以对导出物体的属性进行设置。这里介绍一下其中比较重要的一些选项。
General
Type 这一项决定了导出物体在.scene文件中的类型。最常用的是Entity/Mesh,这个类型在导出以后会生成一个node以及挂载在该node上面的entity,同时会把3ds
max中的该物体导出为一个.mesh文件。然后就比较常用的就是Empty,这种类型会导出为一个没有挂任何东西的node。比如说我用一个box来代表NPC出现的位置,那么这个box就可以设置为Empty类型。
Rendering 在这里设置物体的可见性、渲染顺序、shader参数等等
Node Animation
在这里设置物体的Node动画,即位置、旋转、缩放上的动画。物体模型本身变化的动画在Mesh Animation中设置。具体的用法还没有仔细研究。
User Data
自己游戏所需要的自定义数据就在这里设置了。点Configure...按钮添加上面所说的userdatatypes.xml文件以后,User Data Class中就会出现自定义的数据类型。这样就可以直接把3ds
max作为一个关卡编辑器来使用了。虽说还是没有专门的编辑器那么方便,不过大多数情况下还是够用了。
Mesh
Mesh Name和Skeleton Name可以制定输出的模型和骨骼的文件名,如果不指定的话则会以3ds max中物体的名字命名。
Mesh Animation
这里用来设置顶点动画或骨骼动画。可以把整个场景中物体的任意某一段动画制定某个名字以供程序调用。点击Add..会弹出Animation Settings窗口。通常其中的Track类型已经设置好了,骨骼动画是Physicue,
定点动画是Morph。只需要制定动作的起始帧号就可以了。要注意的是一个场景中某个物体的骨骼动画只能导出为一个skeleton文件,如果你需要把不同的动作导出为不同的动画的话,需要把骨骼动画保存为不同的max文件然后飞别导出。
自定义文件的读取
OgreMax提供了从3ds max中导出为.scene文件的机制,然是我们还是缺一个读取它的程序。虽然OgreMax中自带了一个Viewer程序,但是要处理自定义数据显然还是得自己动手写一个。这里可以参考Ogre
Wiki中的一个.scene文件读取程序的例子,在它的基础上进行修改:
http://www.ogre3d.org/wiki/index.php/New_DotScene_Loader
但是这个程序在很多地方都只是写了一个函数名而没有实现,并且对场景文件的处理和OgreMax导出的格式还是有所区别,需要自己进行大量修改。
-------------我是分割线----------------------------------------------------------------------
在之前的工作中,我们已经完成了 .scene文件 读取的工作,所以我们现在需要做的只是导出,对不同的OGREMAX其中的选项有一些差异,我的版本是OgreMaxSceneExporter2.4.1是目前最新的版本。
首先读入模型,
在Mesh Animation中进行一些设置,注意动画类型要选对
如果导出的动画贴图有错误,在
中打上勾。
之后将导出的文件加入我们的资源文件夹中,在程序的resources.cfg中加入相应的路径,并在程序中读入我们导入的模型和骨骼动画。
代码在此,和上次一样,是基于以前的代码基础的,只修改了一个文件。
代码在此:EnvMapping.h
#include "Ogremaxscene.hpp"
#include "BaseApplication.h"
#include "SinbadCharacterController.h"
class EnvMapApplication : public BaseApplication
{
public:
EnvMapApplication() {}
OgreMax::OgreMaxScene *m_maxScene;
AnimationState * mAnimationState;
AnimationStateSet *mAnimationStateSet;
bool frameRenderingQueued(const FrameEvent& evt)
{
// let character update animations and camera
mChara->addTime(evt.timeSinceLastFrame);
mAnimationState->addTime( evt.timeSinceLastFrame );
return BaseApplication::frameRenderingQueued(evt);
}
bool keyPressed(const OIS::KeyEvent& evt)
{
// relay input events to character controller
if (!mTrayMgr->isDialogVisible()) mChara->injectKeyDown(evt);
return BaseApplication::keyPressed(evt);
}
bool keyReleased(const OIS::KeyEvent& evt)
{
// relay input events to character controller
if (!mTrayMgr->isDialogVisible()) mChara->injectKeyUp(evt);
return BaseApplication::keyReleased(evt);
}
#if OGRE_PLATFORM == OGRE_PLATFORM_IPHONE
bool touchPressed(const OIS::MultiTouchEvent& evt)
{
// relay input events to character controller
if (!mTrayMgr->isDialogVisible()) mChara->injectMouseDown(evt);
return SdkSample::touchPressed(evt);
}
bool touchMoved(const OIS::MultiTouchEvent& evt)
{
// relay input events to character controller
if (!mTrayMgr->isDialogVisible()) mChara->injectMouseMove(evt);
return SdkSample::touchMoved(evt);
}
#else
bool mouseMoved(const OIS::MouseEvent& evt)
{
// relay input events to character controller
if (!mTrayMgr->isDialogVisible()) mChara->injectMouseMove(evt);
return BaseApplication::mouseMoved(evt);
}
bool mousePressed(const OIS::MouseEvent& evt, OIS::MouseButtonID id)
{
// relay input events to character controller
if (!mTrayMgr->isDialogVisible()) mChara->injectMouseDown(evt, id);
return BaseApplication::mousePressed(evt, id);
}
#endif
protected:
// Just override the mandatory create scene method
void createScene(void)
{
m_maxScene = new OgreMax::OgreMaxScene();
// 1.scene是ogremax导出的场景文件名,,当然你也可以用绝对路径,但不建议那样做。
m_maxScene->Load("123.scene",mWindow,OgreMax::OgreMaxScene::NO_OPTIONS, 0, 0);
// 读取MaxScene文件中的设定的场景管理器
mSceneMgr = m_maxScene->GetSceneManager();
// 读取Max文件中的设定的Camera
// mCamera = mSceneMgr->getCamera("Camera02"); // 1.scene文件中指定的照相机名称
mCamera = mSceneMgr->Ogre::SceneManager::createCamera("Chara");
Ogre::Viewport* vp = mWindow->addViewport(mCamera);
vp->setBackgroundColour(Ogre::ColourValue(0,0,0));
mCamera->setAspectRatio(Ogre::Real(vp->getActualWidth())/Ogre::Real(vp->getActualHeight()));
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5, 0.5, 0.5));
// mCameraMan = new OgreBites::SdkCameraMan(mCamera);
//获取节点
//Entity *ent= mSceneMgr->getEntity("Teapot01");
//ent->setMaterialName("Examples/EnvMappedRustySteel");
setupContent();
Ogre::Entity* girl = mSceneMgr->createEntity("girl", "ms_01_4.mesh");
Ogre::SceneNode* girlNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("girlNode",Ogre::Vector3(
100, 0, 50 ));
girlNode->attachObject(girl);
girlNode->scale( .3, .3, .3);
SkeletonPtr skel = SkeletonManager::getSingleton().load("ms_01_4.skeleton",
ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
// Animation* anim = skel->getAnimation("girlkk");
mAnimationStateSet = girl->getAllAnimationStates();
mAnimationState = girl->getAnimationState( "123" );
mAnimationState->setLoop( true );
mAnimationState->setEnabled( true );
//设置光源
// Create a point light
Ogre::Light* l = mSceneMgr->createLight("MainLight");
// Accept default settings: point light, white diffuse, just set position
// NB I could attach the light to a SceneNode if I wanted it to move automatically with
// other objects, but I don‘t
l->setPosition(20,20,50);
}
void setupContent()
{
// set shadow properties
mSceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_MODULATIVE);
mSceneMgr->setShadowColour(ColourValue(0.5, 0.5, 0.5));
mSceneMgr->setShadowTextureSize(1024);
mSceneMgr->setShadowTextureCount(1);
// use a small amount of ambient lighting
mSceneMgr->setAmbientLight(ColourValue(0.3, 0.3, 0.3));
// add a bright light above the scene
Light* light = mSceneMgr->createLight();
light->setType(Light::LT_POINT);
light->setPosition(-10, 40, 20);
light->setSpecularColour(ColourValue::White);
// create a floor mesh resource
MeshManager::getSingleton().createPlane("floor", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Plane(Vector3::UNIT_Y, 0), 100, 100, 10, 10, true, 1, 10, 10, Vector3::UNIT_Z);
// create a floor entity, give it a material, and place it at the origin
Entity* floor = mSceneMgr->createEntity("Floorchara", "floor");
floor->setMaterialName("Examples/Rockwall");
floor->setCastShadows(false);
mSceneMgr->getRootSceneNode()->attachObject(floor);
// create our character controller
mChara = new SinbadCharacterController(mCamera);
}
void cleanupContent()
{
// clean up character controller and the floor mesh
if (mChara) delete mChara;
MeshManager::getSingleton().remove("floor");
}
SinbadCharacterController* mChara;
};