日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ogre3D学习基础10 -- 键盘控制与鼠标控制(直接控制)

發(fā)布時間:2025/3/21 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ogre3D学习基础10 -- 键盘控制与鼠标控制(直接控制) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

要實現(xiàn)鍵盤,鼠標(biāo)對場景的控制,首先要幀監(jiān)聽,就是在每一幀的渲染前后對它進(jìn)行操作。這里的操作沒有用到緩沖區(qū),只是簡單的直接獲取。

  1、這些步驟和前面的一樣,直接上代碼,操作還是在createScene函數(shù)里。代碼如下:

1 void createScene() 2 { 3 //載入實體 4 mSceneMgr->setAmbientLight(ColourValue(0.25,0.25,0.25));//設(shè)置環(huán)境色 5 Entity *ent1 = mSceneMgr->createEntity("ninja","ninja.mesh"); 6 SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("ninjaNode"); 7 node1->attachObject(ent1); 8 9 //點光源 10 Light *light = mSceneMgr->createLight("light1"); 11 light->setType(Light::LT_POINT);//點光源 12 light->setPosition(Vector3(250,150,250)); 13 light->setDiffuseColour(ColourValue::White);//漫射光 14 light->setSpecularColour(ColourValue::White);//反射光 15 16 //第一個攝像機(jī)節(jié)點 17 node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode1",Vector3(-400,200,400)); 18 node1->yaw(Degree(-45));//繞y軸順時針旋轉(zhuǎn)45度 19 node1->attachObject(mCamera); 20 //第二個攝像機(jī)節(jié)點 21 node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode2",Vector3(0,200,400)); 22 }

  這些代碼就不解釋了,如果不懂,請往前看。

  2、綁定攝像機(jī)到節(jié)點

1 void createCamera() 2 { 3 //其他參數(shù)選擇默認(rèn) 4 mCamera = mSceneMgr->createCamera("PlayerCam"); 5 mCamera->setNearClipDistance(5); 6 }

  3、新建一個類ExampleTestFrameListener,父類為ExampleFrameListener,對鼠標(biāo)和鍵盤的控制主要在這里面進(jìn)行。其中是定義在ExampleApplication.h中的一個類,負(fù)責(zé)幀監(jiān)聽。構(gòu)造函數(shù)如下:ExampleTestFrameListener(RenderWindow *win,Camera *cam,SceneManager *sceneMgr);

  現(xiàn)在開始逐漸對他進(jìn)行完善:

  首先添加成員變量

1 bool mMouseDown; // 鼠標(biāo)左鍵是否在上一幀被按下 2 Real mToggle; // 直到下一次觸發(fā)的時間 3 Real mRotate; // 滾動常量 4 Real mMove; // 移動常量 5 SceneManager *mSceneMgr; // 當(dāng)前場景管理器 6 SceneNode *mCamNode; // 當(dāng)前攝像機(jī)所附在的場景節(jié)點

  在構(gòu)造函數(shù)里對他們進(jìn)行初始化

1 ExampleTestFrameListener(RenderWindow *win,Camera *cam,SceneManager *sceneMgr) 2 :ExampleFrameListener(win,cam,false,false)//第三個參數(shù)指明是否使用帶緩沖的鍵盤輸入,第四個參數(shù)指明是否使用帶緩沖的鼠標(biāo)輸入 3 { 4 mMouseDown = false;//鍵盤狀態(tài)記錄 5 mToggle = 0;//鼠標(biāo)狀態(tài)記錄 6 mCamNode = cam->getParentSceneNode();//始終指向父節(jié)點 7 mSceneMgr = sceneMgr; 8 mRotate = 0.13; 9 mMove = 250; 10 }

  然后我們在每一幀里執(zhí)行動作,方法就是在frameStarted()寫入我們的操作。這個函數(shù)會在每一幀渲染前執(zhí)行。

  第一,按下鼠標(biāo)左鍵打開關(guān)閉燈光。

    首先獲取鼠標(biāo)的控制權(quán),代碼:mMouse->capture();//俘獲鼠標(biāo)

    然后讀取鼠標(biāo)按鍵的當(dāng)前狀態(tài),代碼不難理解。

      bool currMouse = mMouse->getMouseState().buttonDown(OIS::MB_Left);//獲取鼠標(biāo)當(dāng)前的狀態(tài)

    最后判斷是否更改燈的狀態(tài)

    1 if(currMouse && !mMouseDown)2 {3 Light *light = mSceneMgr->getLight("light1");//獲取光源指針4 light->setVisible(!light->isVisible());//根據(jù)上一次的狀態(tài)改變,相當(dāng)于取反,由開到關(guān),由關(guān)到開。5 }6 7 mMouseDown = currMouse;//更新鼠標(biāo)的狀態(tài)

    關(guān)于鼠標(biāo):

    通常 0 是鼠標(biāo)左鍵,1 是右鍵,2 是中鍵。在某些系統(tǒng)里 1 是 中鍵、2 是右鍵。所以我們讀取鼠標(biāo)狀態(tài)沒有使用數(shù)字,而是使用了更加健壯的代碼

    mMouse->getMouseState().buttonDown(OIS::MB_Left);這樣能避免由于系統(tǒng)差別造成的問題。

  第二步,用鍵盤實現(xiàn)上下左右前后的移動。

    首先,也是捕獲鍵盤?mKeyboard->capture();//俘獲鍵盤

    其次,實現(xiàn)按下數(shù)字鍵1,2時切換不同的攝像機(jī)

   1      mToggle -= evt.timeSinceLastFrame;//減去從上一幀到現(xiàn)在所經(jīng)歷的時間,保證正在渲染時不切換攝像機(jī) 2 if ((mToggle <0.0f) && mKeyboard->isKeyDown(OIS::KC_1))//按下數(shù)字鍵1時選擇攝像機(jī)1 3 { 4 mToggle = 0.5f;// 5 mCamera->getParentSceneNode()->detachObject(mCamera);//將當(dāng)前攝像機(jī)從場景節(jié)點上卸載下來
   6 mCamNode = mSceneMgr->getSceneNode("CamNode1");//獲取攝像機(jī)1的指針 7 mCamNode->attachObject(mCamera);//重新綁定新的攝像機(jī) 8 }9 else if ((mToggle <0.0f) && mKeyboard->isKeyDown(OIS::KC_2))//按下數(shù)字鍵1時選擇攝像機(jī)110 {11 mToggle = 0.5f;//12 mCamera->getParentSceneNode()->detachObject(mCamera);//將當(dāng)前攝像機(jī)從場景節(jié)點上卸載下來13 mCamNode = mSceneMgr->getSceneNode("CamNode2");//獲取攝像機(jī)2的指針14 mCamNode->attachObject(mCamera);//重新綁定新的攝像機(jī)15 }

    其中的變量mToggle很關(guān)鍵,可以保證每一幀的渲染操作都是原子操作,不被中途打斷,避免產(chǎn)生不可預(yù)測問題。?

    再次,實現(xiàn)按鍵W,A,S,D的平移,這里需要一個三元組transVector3用來保存當(dāng)前攝像機(jī)的位置。

      實現(xiàn)前后的移動,其實就是讓坐標(biāo)z增大或者減小,代碼如下

  1      Vector3 transVector = Vector3::ZERO;//保存平移方位2 if (mKeyboard->isKeyDown(OIS::KC_UP) || mKeyboard->isKeyDown(OIS::KC_W))//3 {4 transVector.z -= mMove;//z軸負(fù)方向移動5 }6 if (mKeyboard->isKeyDown(OIS::KC_DOWN) || mKeyboard->isKeyDown(OIS::KC_S))//7 {8 transVector.z += mMove;//z軸正方向移動9 }

      其他的移動操作,基本一樣,只需改變z為x或y。具體代碼在最后面。

    OIS:  

    開放輸入系統(tǒng)(OIS)提供了三個主要的類來獲得輸入:Keyboard, Mouse, 和Joystick(搖桿) 。

  第三,實現(xiàn)按下鼠標(biāo)右鍵時以一定傾斜角度拖動攝像機(jī)

    按下鼠標(biāo)右鍵時拖動,攝像機(jī)以一定的傾斜角度改變

   //根據(jù)從上一幀開始鼠標(biāo)移動的距離來控制攝像機(jī)的俯仰偏斜。if (mMouse->getMouseState().buttonDown(OIS::MB_Right)){mCamNode->yaw(Degree(-mRotate * mMouse->getMouseState().X.rel),Node::TS_WORLD);//以y為基礎(chǔ)旋轉(zhuǎn) mCamNode->pitch(Degree(-mRotate * mMouse->getMouseState().Y.rel),Node::TS_LOCAL);//以x為基礎(chǔ)旋轉(zhuǎn) }

  第四,在ExampleTestApplication中注冊幀監(jiān)聽器

    具體操作時在createFrameListener()函數(shù)中,添加以下幾行代碼

  1      mFrameListener = new ExampleTestFrameListener(mWindow,mCamera,mSceneMgr);//創(chuàng)建一個幀監(jiān)聽器2 mRoot->addFrameListener(mFrameListener);//注冊到Root類中3 mFrameListener->showDebugOverlay(true);//在層上顯示幀狀態(tài)

  好了,完整代碼:

  

1 #include "ExampleApplication.h" 2 using namespace Ogre; 3 4 class ExampleTestFrameListener:public ExampleFrameListener 5 { 6 public: 7 ExampleTestFrameListener(RenderWindow *win,Camera *cam,SceneManager *sceneMgr) 8 :ExampleFrameListener(win,cam,false,false)//第三個參數(shù)指明是否使用 9 //帶緩沖的鍵盤輸入,第四個參數(shù)指明是否使用帶緩沖的鼠標(biāo)輸入( 10 { 11 mMouseDown = false;// 鍵盤和鼠標(biāo)狀態(tài)追蹤 12 mToggle = 0; 13 14 mCamNode = cam->getParentSceneNode(); 15 mSceneMgr = sceneMgr; 16 //設(shè)置旋轉(zhuǎn)和移動速度 17 mRotate = 0.13; 18 mMove = 250; 19 } 20 bool frameStarted(const FrameEvent& evt) 21 { 22 mMouse->capture();//俘獲鼠標(biāo) 23 mKeyboard->capture();//俘獲鍵盤 24 25 if (mKeyboard->isKeyDown(OIS::KC_ESCAPE))//按下esc鍵 26 { 27 return false; 28 } 29 30 bool currMouse = mMouse->getMouseState().buttonDown(OIS::MB_Left);//獲取鼠標(biāo)當(dāng)前的狀態(tài) 31 if(currMouse && !mMouseDown) 32 { 33 Light *light = mSceneMgr->getLight("light1");//獲取燈光指針 34 light->setVisible(!light->isVisible());//根據(jù)上一次的狀態(tài)改變 35 } 36 37 mMouseDown = currMouse;//更新鼠標(biāo)狀態(tài) 38 39 mToggle -= evt.timeSinceLastFrame;//減去從上一幀到現(xiàn)在所經(jīng)歷的時間,保證正在渲染時不切換攝像機(jī) 40 if ((mToggle <0.0f) && mKeyboard->isKeyDown(OIS::KC_1))//按下數(shù)字鍵1時選擇攝像機(jī)1 41 { 42 mToggle = 0.5f; 43 mCamera->getParentSceneNode()->detachObject(mCamera); 44 mCamNode = mSceneMgr->getSceneNode("CamNode1"); 45 mCamNode->attachObject(mCamera); 46 } 47 else if ((mToggle <0.0f) && mKeyboard->isKeyDown(OIS::KC_2))//按下數(shù)字鍵1時選擇攝像機(jī)1 48 { 49 mToggle = 0.5f; 50 mCamera->getParentSceneNode()->detachObject(mCamera); 51 mCamNode = mSceneMgr->getSceneNode("CamNode2"); 52 mCamNode->attachObject(mCamera); 53 } 54 55 Vector3 transVector = Vector3::ZERO;//保存平移方位 56 if (mKeyboard->isKeyDown(OIS::KC_UP) || mKeyboard->isKeyDown(OIS::KC_W))// 57 { 58 transVector.z -= mMove;//z軸負(fù)方向移動 59 } 60 if (mKeyboard->isKeyDown(OIS::KC_DOWN) || mKeyboard->isKeyDown(OIS::KC_S))// 61 { 62 transVector.z += mMove;//z軸正方向移動 63 } 64 if (mKeyboard->isKeyDown(OIS::KC_LEFT) || mKeyboard->isKeyDown(OIS::KC_A))// 65 { 66 transVector.x -= mMove;//x軸負(fù)方向移動 67 } 68 if (mKeyboard->isKeyDown(OIS::KC_RIGHT) || mKeyboard->isKeyDown(OIS::KC_D))// 69 { 70 transVector.x += mMove;//x軸正方向移動 71 } 72 if (mKeyboard->isKeyDown(OIS::KC_PGUP) || mKeyboard->isKeyDown(OIS::KC_Q))// 73 { 74 transVector.y -= mMove;//Y軸負(fù)方向移動 75 } 76 if (mKeyboard->isKeyDown(OIS::KC_PGDOWN) || mKeyboard->isKeyDown(OIS::KC_E))// 77 { 78 transVector.y += mMove;//Y軸正方向移動 79 } 80 81 //根據(jù)從上一幀開始鼠標(biāo)移動的距離來控制攝像機(jī)的俯仰偏斜。 82 if (mMouse->getMouseState().buttonDown(OIS::MB_Right)) 83 { 84 mCamNode->yaw(Degree(-mRotate * mMouse->getMouseState().X.rel),Node::TS_WORLD); 85 mCamNode->pitch(Degree(-mRotate * mMouse->getMouseState().Y.rel),Node::TS_LOCAL); 86 } 87 return true; 88 //return ExampleFrameListener::frameStarted(evt); 89 } 90 bool frameEnded(const FrameEvent& evt) 91 { 92 return ExampleFrameListener::frameEnded(evt); 93 } 94 protected: 95 bool mMouseDown;// 鼠標(biāo)左鍵是否在上一幀被按下 96 Real mToggle;//直到下一次觸發(fā)的時間間隔 97 Real mRotate;//滾動常量 98 Real mMove;//移動常量 99 SceneManager *mSceneMgr;//當(dāng)前的場景管理器 100 SceneNode *mCamNode;//當(dāng)前的攝像機(jī)所綁定的場景節(jié)點 101 private: 102 }; 103 104 105 class ExampleTestApplication:public ExampleApplication 106 { 107 public: 108 ExampleTestApplication() 109 { 110 111 } 112 ~ExampleTestApplication() 113 { 114 115 } 116 117 protected: 118 void createCamera() 119 { 120 //其他參數(shù)選擇默認(rèn) 121 mCamera = mSceneMgr->createCamera("PlayerCam"); 122 mCamera->setNearClipDistance(5); 123 } 124 void createScene() 125 { 126 //載入實體 127 mSceneMgr->setAmbientLight(ColourValue(0.25,0.25,0.25));//設(shè)置環(huán)境色 128 Entity *ent1 = mSceneMgr->createEntity("ninja","ninja.mesh"); 129 SceneNode *node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("ninjaNode"); 130 node1->attachObject(ent1); 131 132 //點光源 133 Light *light = mSceneMgr->createLight("light1"); 134 light->setType(Light::LT_POINT);//點光源 135 light->setPosition(Vector3(250,150,250)); 136 light->setDiffuseColour(ColourValue::White);//漫射光 137 light->setSpecularColour(ColourValue::White);//反射光 138 139 //第一個攝像機(jī)節(jié)點 140 node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode1",Vector3(-400,200,400)); 141 node1->yaw(Degree(-45));//繞y軸順時針旋轉(zhuǎn)45度 142 node1->attachObject(mCamera); 143 //第二個攝像機(jī)節(jié)點 144 node1 = mSceneMgr->getRootSceneNode()->createChildSceneNode("CamNode2",Vector3(0,200,400)); 145 } 146 void createFrameListener() 147 { 148 mFrameListener = new ExampleTestFrameListener(mWindow,mCamera,mSceneMgr);//創(chuàng)建一個幀監(jiān)聽器 149 mRoot->addFrameListener(mFrameListener);//注冊到Root類中 150 mFrameListener->showDebugOverlay(true);//在層上顯示幀狀態(tài) 151 } 152 }; 153 154 #include "windows.h" 155 156 157 158 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) 159 160 161 { 162 ExampleTestApplication app; 163 app.go(); 164 return 0; 165 } 全部代碼

  圖片就不上了,本來想截取幾個gif格式的動畫上來的,可一直沒找到好工具。

轉(zhuǎn)載于:https://www.cnblogs.com/songliquan/p/3302228.html

總結(jié)

以上是生活随笔為你收集整理的ogre3D学习基础10 -- 键盘控制与鼠标控制(直接控制)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。