天龙八部制作教程及源码第一辑一步一步来吧...把OGRE嵌入到MFC里面,并实现了OIS缓冲输入和鼠标显示,看图:具体实现方法:一最好抛弃示例框架,实现一个自己的框架,因为有些东西需要修改,有些东西要自己实现,我自己写了一个框架demo来嵌入MFC,看简洁不少//我的帧监听类classMyFrameListener:publicFrameListener,publicOIS::MouseListener,publicOIS::KeyListener{public:MyFrameListener(OgreDemo*app,HWNDhMainWnd);~MyFrameListener();boolframeStarted(constFrameEvent&evt);boolmouseMoved(constOIS::MouseEvent&e);boolmousePressed(constOIS::MouseEvent&e,OIS::MouseButtonIDid);boolmouseReleased(constOIS::MouseEvent&e,OIS::MouseButtonIDid);boolkeyPressed(constOIS::KeyEvent&e);boolkeyReleased(constOIS::KeyEvent&e);protected:SceneManager*mSceneMgr;SceneNode*mCamNode;OIS::Keyboard*mKeyboard;OIS::Mouse*mMouse;OIS::InputManager*mInputManager;RealmRotate;//旋转常量RealmMove;//运动常量boolmContinue;//是否要继续渲染Vector3mDirection;//指向正确的移动方向};classOgreDemo{public:OgreDemo():mRoot(0),mWindow(0),mListener(0),mCamera(0),mSceneMgr(0),mCamNode(0){}~OgreDemo();voidsetup(HWNDm_hWnd,intwidth,intheight,HWNDhMainWnd);//获得成员变量Root*getRoot(void)const{returnmRoot;}Camera*getCamera(void)const{returnmCamera;}SceneNode*getCamNode(void)const{returnmCamNode;}SceneManager*getSceneManager(void)const{returnmSceneMgr;}RenderWindow*getRenderWindow(void)const{returnmWindow;}private:Root*mRoot;RenderWindow*mWindow;SceneManager*mSceneMgr;Camera*mCamera;SceneNode*mCamNode;MyFrameListener*mListener;voidcreateRoot();voiddefineResources();voidsetupRenderSystem();voidcreateRenderWindow(HWNDm_hWnd,intwidth,intheight);voidinitializeResourceGroups();voidsetupScene();voidcreateFrameListener(HWNDhMainWnd);};二,具体过程分析首先,因为用MFC打开,我们要去掉弹出的配置框,自己把渲染系统参数设置好:voidOgreDemo::setupRenderSystem(){//自己设置RenderSystem*rs=mRoot-getRenderSystemByName(Direct3D9RenderingSubsystem);mRoot-setRenderSystem(rs);rs-setConfigOption(FullScreen,No);rs-setConfigOption(VideoMode,800x600@32-bitcolour);}其次,要嵌入到MFC,那么就要用view视图来作为OGRE的窗口,那么就要在生成OGRE窗口的时候把vire窗口句柄传入,幸好,OGRE不但支持自动产生窗口,还支持外部窗口,具体生产方法://传入外部窗口句柄,这里是view类的句柄voidOgreDemo::createRenderWindow(HWNDm_hWnd,intwidth,intheight){//root初始化的时候,我们可以传入一个false值来告知Root不用给我们自动创建渲染窗口//这样我们可以用外部窗口来作为MFC窗口mRoot-initialise(false);NameValuePairListmiscParams;//参数列表,作为createRenderWindow函数的最后一个参数miscParams[externalWindowHandle]=StringConverter::toString((long)m_hWnd);mWindow=mRoot-createRenderWindow(OgreRenderWindow,width,height,false,&miscParams);}现在我们就是用外部程序的窗口来作为OGRE的窗口了.接着的问题是渲染循环!当你使用startRendering()的时候,因为渲染循环交给了系统,所以没有办法把Ogre结合到窗口系统的消息循环中去.那么WINDOWS的消息循环和startRendering()的这2个独立的循环就会产生冲突,比如WM_PAINT和OGRE一起渲染...解决办法就是做到一个循环中来,正好OGRE有提供只渲染一帧的方法renderOneFrame();我把循环做到view视图类的OnDraw函数里面,用时间函数来控制循环voidCTLBBView::OnDraw(CDC*/*pDC*/){CTLBBDoc*pDoc=GetDocument();ASSERT_VALID(pDoc);if(!pDoc)return;//TODO:在此处为本机数据添加绘制代码//创建OGRE程序//程序只初始化一次if(m_isFirstDraw){m_isFirstDraw=false;CRectrect;GetClientRect(&rect);app.setup(m_hWnd,rect.Width(),rect.Height(),AfxGetApp()-GetMainWnd()-GetSafeHwnd());//setup后root才被new出来,这时候才可以获得rootroot=app.getRoot();//10ms触发一次SetTimer(1,10,NULL);}if(m_isStart){root-renderOneFrame();}else{//}}voidCTLBBView::OnTimer(UINTnIDEvent){if(m_isStart){root-renderOneFrame();}}这里有个setTimer,不设置回调函数以后(NULL),就会调OnTimer这个函数,每隔10msOnTimer收到WM_TIMER消息就会绘制一次10msfps就是100啊,这里不要递归OnTimer,小心栈溢出哦既然OnTimer要收到WM_TIMER消息,就要代码中加上消息映射BEGIN_MESSAGE_MAP(CTLBBView,CView)ON_WM_TIMER()END_MESSAGE_MAP()这样,循环渲染的问题我们用2个timer就解决了,这下应该OK了吧,但是还有个键盘鼠标的问题,我们用OIS,但是OIS在创建输入系统的时候,他要控制的窗口必须是顶层窗口,就是说你传view视图的窗口句柄给他不行,必须要MFC程序的主窗口,所以又要多传一个参数了哇,算起来我们传了2个窗口参数了,一个MFC主窗口给OIS,一个view视图窗口作为渲染窗口看看我传的参数:app.setup(m_hWnd,rect.Width(),rect.Height(),AfxGetApp()-GetMainWnd()-GetSafeHwnd());第4个参数就是MFC主窗口参数有了,我们就需要把主窗口句柄传给OIS的OIS::InputManager//获得输入系统size_twindowHnd=0;std::ostringstreamwindowHndStr;OIS::ParamListpl;app-getRenderWindow()-getCustomAttribute(WINDOW,&windowHnd);windowHnd=(size_t)hMainWnd;//这里这个窗口句柄就是我们传入的MFC主窗口windowHndStrwindowHnd;//OIS的窗口必须要顶层窗口,所以只有传MFC的主窗口给他,传view就不行pl.insert(std::make_pair(std::string(WINDOW),windowHndStr.str()));//设置鼠标显示和非游戏独占,这样鼠标可以显示在屏幕上并可以移动到窗口外pl.insert(std::make_pair(std::string(w32_mouse),std::string(DISCL_FOREGROUND)));pl.insert(std::make_pair(std::string(w32_mouse),std::string(DISCL_NONEXCLUSIVE)));//键盘非游戏独占//pl.insert(std::make_pair(std::string(w32_keyboard),std::string(DISCL_FOREGROUND)));//pl.insert(std::make_pair(std::string(w32_keyboard),std::string(DISCL_NONEXCLUSIVE)));mInputManager=OIS::InputManager::createInputSystem(pl);//这样InputManager就建好了,但为了从键盘、鼠标、或是手柄中获得输入,你还必须创建这些对象:try{mKeyboard=static_castOIS::Keyboard*(mInputManager-createInputObject(OIS::OISKeyboard,true));mMouse=static_castOIS::Mouse*(mInputManager-createInputObject(OIS::OISMouse,true));//mJoy=static_castOIS::JoyStick*(mInputManager-createInputObject(OIS::OISJoyStick,false));}catch(constOIS::Exception&e){throwException(42,e.eText,OgreDemo::setupInputSystem);}上面代码还有一个重要的地方,就是//设置鼠标显示和非游戏独占,这样鼠标可以显示在屏幕上并可以移动到窗口外pl.insert(std::make_pair(std::string(w32_mouse),std::string(DISCL_FOREGROUND)));pl.insert(std::make_pair(std::string(w32_mouse),std::string(DISCL_NONEXCLUSIVE)));这样的话,你就可以看到鼠标了,还可以移出窗口外面任何地方,就像地图编辑器一样!还可以用