《2022年OGRE基础教程基础教程五 .pdf》由会员分享,可在线阅读,更多相关《2022年OGRE基础教程基础教程五 .pdf(14页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、文档: 教程: 基础教程 : 基础教程五出自 Ogre3D开放资源地带跳转到 : 导航, 搜索目录?1 先决条件?2 介绍?3 从这开始?4 简单的缓冲输入o4.1 介绍o4.2 键盘监听界面o4.3 鼠标监听界面?5 代码o5.1 TutorialFrameListener的构造函数o5.2 变量o5.3 TutorialFrameListener构造函数o5.4 键盘绑定o5.5 鼠标绑定?6 其他输入系统先决条件本教程假定你已经拥有了c+程序设计的知识,并且已经安装和编译了一个Ogre的应用程序(如果你在设置你的应用程序中有困难,请参考this guide获得更详细的编译步骤)。这个教程
2、同时也是建立 在上一章基础上 的,因此默认你已经了 解了上个教程的 内容。介绍在这一 课里, 你将学会 OIS的带缓冲的输入 , 这不同于上节课 中无缓冲的输入。而且在这 节课中,当鼠标键盘的 事件发生时,我们会立即处理它 ,不会像上节课那样每 一帧只处理 一次。请注意这里只是对 缓冲输入的一个简单介绍,而不是完整 的如何使用 OIS的教程。 若想了解更多内容 ,请查阅相关 的 OIS使用教程。你可以找 到这节课的源代码。在你 学习本课的时候,你应 该逐个地将这些代码添加到你自己的工程里去,然后构建并观察结 果。从这开始名师资料总结 - - -精品资料欢迎下载 - - - - - - - -
3、- - - - - - - - - - 名师精心整理 - - - - - - - 第 1 页,共 14 页 - - - - - - - - - 本课是基于上 一课的,但我们将改 变输入的 方式。既然功能基 本上是相 同的,我们就使 用上次的 TutorialApplication类,但我们会 从TutorialFrameListener开始。用你 喜欢的编译器创建 一个工程,再添加 一个包含如下代码的 源文件:#include ExampleApplication.h class TutorialFrameListener : public ExampleFrameListener, publ
4、ic OIS:MouseListener, public OIS:KeyListener public: TutorialFrameListener(RenderWindow* win, Camera* cam, SceneManager *sceneMgr) : ExampleFrameListener(win, cam, true, true) bool frameStarted(const FrameEvent &evt) if(mMouse) mMouse-capture(); if(mKeyboard) mKeyboard-capture(); return mContinue; /
5、 MouseListener bool mouseMoved(const OIS:MouseEvent &e) return true; bool mousePressed(const OIS:MouseEvent &e, OIS:MouseButtonID id) return true; bool mouseReleased(const OIS:MouseEvent &e, OIS:MouseButtonID id) return true; / KeyListener bool keyPressed(const OIS:KeyEvent &e) return true; bool key
6、Released(const OIS:KeyEvent &e) return true; protected: Real mRotate; / The rotate constant Real mMove; / The movement constant SceneManager *mSceneMgr; / The current SceneManager SceneNode *mCamNode; / The SceneNode the camera is currently attached to 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - -
7、- - - - - 名师精心整理 - - - - - - - 第 2 页,共 14 页 - - - - - - - - - bool mContinue; / Whether to continue rendering or not Vector3 mDirection; / Value to move in the correct direction ; class TutorialApplication : public ExampleApplication public: void createCamera(void) / create camera, but leave at defa
8、ult position mCamera = mSceneMgr-createCamera(PlayerCam); mCamera-setNearClipDistance(5); void createScene(void) mSceneMgr-setAmbientLight(ColourValue(0.25, 0.25, 0.25); / add the ninja Entity *ent = mSceneMgr-createEntity(Ninja, ninja.mesh); SceneNode *node = mSceneMgr-getRootSceneNode()-createChil
9、dSceneNode(NinjaNode); node-attachObject(ent); / create the light Light *light = mSceneMgr-createLight(Light1); light-setType(Light:LT_POINT); light-setPosition(Vector3(250, 150, 250); light-setDiffuseColour(ColourValue:White); light-setSpecularColour(ColourValue:White); / Create the scene node node
10、 = mSceneMgr-getRootSceneNode()-createChildSceneNode(CamNode1, Vector3(-400, 200, 400); / Make it look towards the ninja node-yaw(Degree(-45); / Create the pitch node node = node-createChildSceneNode(PitchNode1); node-attachObject(mCamera); / create the second camera node/pitch node 名师资料总结 - - -精品资料
11、欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 3 页,共 14 页 - - - - - - - - - node = mSceneMgr-getRootSceneNode()-createChildSceneNode(CamNode2, Vector3(0, 200, 400); node = node-createChildSceneNode(PitchNode2); void createFrameListener(void) / Create the FrameListener mFrameListener
12、 = new TutorialFrameListener(mWindow, mCamera, mSceneMgr); mRoot-addFrameListener(mFrameListener); / Show the frame stats overlay mFrameListener-showDebugOverlay(true); ; #if OGRE_PLATFORM = PLATFORM_WIN32 | OGRE_PLATFORM = OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include windows.h INT WINAP
13、I WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT) #else int main(int argc, char *argv) #endif / Create application object TutorialApplication app; try app.go(); catch(Exception& e) #if OGRE_PLATFORM = PLATFORM_WIN32 | OGRE_PLATFORM = OGRE_PLATFORM_WIN32 MessageBox(NULL, e.getFullDescripti
14、on().c_str(), An exception has occurred!, MB_OK | MB_ICONERROR | MB_TASKMODAL); #else fprintf(stderr, An exception has occurred: %sn, e.getFullDescription().c_str(); #endif return 0; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 4 页,共 14 页 - - - - - - - - - 如果你 是在 W
15、indows下使用 OgreSDK 的,请 确定添加“OgreSDK_DIRECTORYsamplesinclude”目录 到这个 工程(ExampleApplication.h文件所在的位置)除了标准包含以 外。如果 使用的是Ogre的源代码包,这个 文件应该在“OgreSource_DIRECTORYSamplesCommoninclude”目录 中。不要试着 去运行程序, 因为我们还没有定义键盘的 行为。如果你有 问题,请查看这个 Wiki页获得设置你编译 器的信息,如果 仍然有问题请试着去看看帮助栏 。注意: 如果你 没有把你的工程设置 成使用 Ansi C+ ,并收到关于 Messa
16、geBox的错误信息 ,你可能需要把 对 MessageBox 的引用改成 MessageBoxA 。程序的 控制与 上一课的相同。简单的缓冲输入介绍在上一次课里 ,我们使用的是无缓冲的输入,也 就是说,在每一帧里我们查 询OIS:Keyboard 和 OIS:Mouse 实例的状态,以判断它们是 否被按 下。而缓冲输入使用了一个 listener接口,以便在事件发生 时通知你的程序。 比如,当一个键被按下时,会触发一个 KeyListener:keyPressed 事件,而当这个键 被释放(不再按下)时, KeyListener:keyReleased 事件被触发给所有已注册的KeyList
17、ener类。这些能用在追踪按 键的时 间,或判断按 键在上一帧中是否没有被按下。通过 OIS:JoystickListener 接口,OIS也支持 无缓冲的 操纵杆 事件,但在本课我们不会 涉及到。关于 OIS的监听系统有一 点要注意的是,对于每 一个Keyboard,Mouse,Joystick对象只能有一个监听 器。这样是为了简单(也 为了速度)。多次调用 setEventCallback函数( 后面会讲到)的 结果是只有最后一次注册的监听 器才得到事件消息。如果你有 多个对象需要 获得 Key,Mouse,或Joystick事件,你 只有自己写一个消息分 发。还有,千万记 得在 fram
18、eStarted方法里调用 Keyboard:capture和 Mouse:capture 。OIS不会使 用线程(或其它玩意儿)来确定键盘鼠标的 状态,所以你必须指明什 么时候去获取输入。键盘监听界面OIS的 KeyListener接口提供了两个纯虚函数。 第一个是 keyPressed 函数( 每次按下某个键时 调用它),还一个是 keyReleased(每次离开某个键时 调用它)。传入这些函数的参数 是一个 KeyEvent,它包含 被按下/ 释放的按键的键码。名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理
19、- - - - - - - 第 5 页,共 14 页 - - - - - - - - - 鼠标监听界面MouseListener 接口比 KeyListener接口要 稍微复杂 一些。它包含查 看何时鼠标键被按下/ 释放的函数 : MouseListener:mousePressed 和MouseListener:mouseReleased. 它还包含一个 mouseMoved 函数, 当鼠标移动时调用它。这些函数都接收一个 MouseEvent对象,在state变量里保存着当前鼠标的 状态。需要注意的是,MouseState 对象即包含 了鼠标 移动的相对 XY坐标(即,从上一次调用 Mou
20、seListener:mouseMoved 开始, 它所移动的距离),还包含了绝对 XY坐标(即,屏幕上的准确位 置)。代码TutorialFrameListener的构造函数在我们开始修改 TutorialFrameListener之前 ,请注意我们对TutorialFrameListener类做了两处大的改变:class TutorialFrameListener : public ExampleFrameListener, public OIS:MouseListener, public OIS:KeyListener 我们继承了 OIS的MouseListener 和 KeyListe
21、ner类,这样我们 才能从它们那里 接收事件。注意,OIS的 MouseListener 处理鼠标按钮事件,也 处理鼠标移动事件。同样,ExampleFrameListener 的构造函数也有变 化: : ExampleFrameListener(win, cam, true, true) 这个true, true参数指明了我们将 要使用带缓冲的键盘鼠标输入。 我们接下面会深入介绍如 何手动地设置 OIS,以及 Ogre 的其它部分。变量上一课的变量在这 里有些改变。我移除了 mToggle和 mMouseDown 变量( 再也用不到了)。 我还添加了一些其它的: Real mRotate;
22、/ 旋转常量 Real mMove; / 运动常量 SceneManager *mSceneMgr; / 当前的场景管 理器 SceneNode *mCamNode; / 当前摄像机附着的场景节点 bool mContinue; / 是否要继续渲染 Vector3 mDirection; / 指向正确的移动方向名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 6 页,共 14 页 - - - - - - - - - mRotate, mMove, mSceneMgr, 以及 mCamN
23、ode 与上一课的相同(虽然我们会改变 mRotate 的值,因为它有不同的用 处)。 mContinue 变量是 frameStarted方法的返回值 。当 mContinue 为 false的时候,程序退出。mDirection变量指定了在 每一个帧里我们 如何移动摄 像机节点。TutorialFrameListener构造函数在构造函数 里,我们像 在上一课那样 初始化一些变量,并 把 mContinue 设成true 。添加如下代码到 TutorialFrameListener的构造函数 里: / Populate the camera and scene manager contai
24、ners mCamNode = cam-getParentSceneNode(); mSceneMgr = sceneMgr; / 设置旋转和移动速度 mRotate = 0.13; mMove = 250; / 继续渲染 mContinue = true; 在 ExampleFrameListener 的构造函数 里已经 取得了 OIS的 mMouse 和mKeyboard对象。我们调用这些输入对象的 setEventCallback方法,把TutorialFrameListener注册成一个监听 器。 mMouse-setEventCallback(this); mKeyboard-set
25、EventCallback(this); 最后,我们还要把 mDirection初始化成零向 量(因为我们最开始不需要它动): mDirection = Vector3:ZERO; 键盘绑定在我们深入之前,我们应该设置 Escape键用 来退出程序。 找到TutorialFrameListener:keyPressed方法,每当键盘上一个键 被按下时,都会调用这个 方法并传入一个 KeyEvent 对象。我们能 够通过这个对象的key 变量来获取按键的键码 (KC_*) 。基于这个值,我们构造一个 switch ,为绑定所有程序里用到的 按钮。 bool keyPressed(const OI
26、S:KeyEvent &e) switch (e.key) 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 7 页,共 14 页 - - - - - - - - - case OIS:KC_ESCAPE: mContinue = false; break; return true; 我们继续之前 请保证以上都能编译和 运行。我们需要在 switch 语句里为其它按钮做绑定。 首先我们要让用户按 1、2 键进行视口的切换。代码基本上与上节课相 同(需要包括进 switch 语句),除了
27、不需要处理mToggle变量: case OIS:KC_1: mCamera-getParentSceneNode()-detachObject(mCamera); mCamNode = mSceneMgr-getSceneNode(CamNode1); mCamNode-attachObject(mCamera); break; case OIS:KC_2: mCamera-getParentSceneNode()-detachObject(mCamera); mCamNode = mSceneMgr-getSceneNode(CamNode2); mCamNode-attachObject
28、(mCamera); break; 瞧!这比用临时变量 来保存按键时间要干净多了。接下来我们要添加键盘移动。每次用户按下移动按键,我们都要朝正确的方向加上或者减去 mMove : case OIS:KC_UP: case OIS:KC_W: mDirection.z -= mMove; break; case OIS:KC_DOWN: case OIS:KC_S: mDirection.z += mMove; break; case OIS:KC_LEFT: case OIS:KC_A: mDirection.x -= mMove; 名师资料总结 - - -精品资料欢迎下载 - - - - -
29、 - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 8 页,共 14 页 - - - - - - - - - break; case OIS:KC_RIGHT: case OIS:KC_D: mDirection.x += mMove; break; case OIS:KC_PGDOWN: case OIS:KC_E: mDirection.y -= mMove; break; case OIS:KC_PGUP: case OIS:KC_Q: mDirection.y += mMove; break; 当按键被释放 时,我们要立即取消 mDire
30、ction向量上的移动。找到keyReleased 方法,添加如下代码: switch (e.key) case OIS:KC_UP: case OIS:KC_W: mDirection.z += mMove; break; case OIS:KC_DOWN: case OIS:KC_S: mDirection.z -= mMove; break; case OIS:KC_LEFT: case OIS:KC_A: mDirection.x += mMove; break; case OIS:KC_RIGHT: case OIS:KC_D: mDirection.x -= mMove; brea
31、k; case OIS:KC_PGDOWN: case OIS:KC_E: mDirection.y += mMove; 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 9 页,共 14 页 - - - - - - - - - break; case OIS:KC_PGUP: case OIS:KC_Q: mDirection.y -= mMove; break; / switch return true; 好了,我们能 根据按键输入 对 mDirection 进行更新了,我们还需要
32、 让它真正移动起来。下面的代码 与上节课是 一样的,添加到 frameStarted函数里: mCamNode-translate(mDirection * evt.timeSinceLastFrame, Node:TS_LOCAL); 编译并 运行程序。 我们现在已经有了 带缓冲的输入 来控制运 动!鼠标绑定现在我们已经完成了键盘绑定, 接下来轮到鼠标了。 我们从点击鼠标左键来控制灯的开关开始。 找到 mousePressed函数并 看看它的参数。用 OIS,我们可以访问 MouseEvent和 MouseButtonID。我们用 MouseButtonID 作为 switch 条件,来确定
33、按下的是哪个按钮。用下面的代码 替换掉 mousePressed函数里的: Light *light = mSceneMgr-getLight(Light1); switch (id) case OIS:MB_Left: light-setVisible(! light-isVisible(); break; return true; 编译并 运行。 噢耶! 成功了,剩下来的事情就是绑定鼠标 右键来进入鼠标 观察模式。每当鼠标移动时我们都检查右键是否按下。如果 是,我们基于相对 运动来转动摄像机。通过传入函数的 MouseEvent对象,我们能 获取相对运动。它包含一个state变量, 里面有
34、鼠标的 状态(是关于 鼠标的详细 信息)。MouseState:buttonDown告诉我们是 否一个特定的按钮被按下,而“X”和“Y”变量告诉我们鼠标的 相对运动。找到 mouseMoved 方法,用以下代码替换掉原来的: if (e.state.buttonDown(OIS:MB_Right) mCamNode-yaw(Degree(-mRotate * e.state.X.rel), Node:TS_WORLD); 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 10 页,共
35、14 页 - - - - - - - - - mCamNode-pitch(Degree(-mRotate * e.state.Y.rel), Node:TS_LOCAL); return true; 编译并 运行程序。 当鼠标右键被按下时,摄像机就以自 由视角的模式工作。其他输入系统OIS是非常棒的,应 该满足你的应用程序的 大部分需求。话说回来,你也有其它的选择。有的 窗口系统像 wxWidgets 也许正是你想要的,人们已经成功地把它整合进了 Ogre。如果你 不介意你的应用程序 是特定平台的,你也 可以使 用标准的 Windows消息系统, 或者从 Linux GUI 工具集中选择一个
36、。你也可以试一试 SDL ,它是一个跨平台 的带窗口输入系统,并 支持摇杆/ 手柄输入。我不能 指导你用 Ogre如何设置 wx/gtk/qt这些(因为我自己 也没搞过-_-),但我有许多将 SDL的摇杆/ 手柄输入整合进 Ogre的成功经验。为了使 SDL的操纵杆系统生效,通过调 用 SDL_Init 和 SDL_Quit,把你的应用程序 包裹起来(放在你的程序 main 函数里,或放在你的应用 对象里): SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE); SDL_JoystickEventState(SDL_ENABLE); app.g
37、o(); SDL_Quit(); 为了设置 Joystick ,调用 SDL_JoystickOpen 并传入操纵杆 编号(你能通过 0、1、2. 来指定多个操纵杆 ): SDL_Joystick* mJoystick; mJoystick = SDL_JoystickOpen(0); if ( mJoystick = NULL ) ; / error handling 如果 JoystickOpen 返回 NULL ,表示打 开 joystick有问题。这基本上意味着你请求的摇杆不存在。使用 SDL_NumJoysticks来确定连接在系统 上的摇杆数量。当你结束之后,需要关闭摇杆: SDL
38、_JoystickClose(mJoystick); 为了使用摇杆,调用 JoystickGetButton和 JoystickGetAxis。我个人使用的是 PS2的手柄,所以我有四个轴向和 12 个按钮来玩。这是我的操纵代码:名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 11 页,共 14 页 - - - - - - - - - SDL_JoystickUpdate(); mTrans.z += evt.timeSinceLastFrame * mMoveAmount * SD
39、L_JoystickGetAxis(mJoystick, 1) / 32767; mTrans.x += evt.timeSinceLastFrame * mMoveAmount * SDL_JoystickGetAxis(mJoystick, 0) / 32767; xRot -= evt.timeSinceLastFrame * mRotAmount * SDL_JoystickGetAxis(mJoystick, 3) / 32767; yRot -= evt.timeSinceLastFrame * mRotAmount * SDL_JoystickGetAxis(mJoystick,
40、 2) / 32767; mTrans在后面要传入到摄像机的 SceneNode:translate方法,xRot 传入到SceneNode:yaw,而 yRot 传入到 SceneNode:pitch 。注意,SDL_JoystickGetAxis返回一个从 -32767 到 32767 的值,所以我得把它缩小到-1 到 1 的范围。这应 该可以 让你开始 使用 SDL摇杆输入了。 若你想查看更多关于这个领域的信息,SDL joystick的头文件是最好的文档。如果你 想要认真地在你的程序时 使用 SDL ,你应该查阅 标准 SDL文档。原文上一章节:基础 教程四下一章节:基础 教程六目录取
41、自 http:/ 查看?页面?讨论?源码?历史个人工具?登录创建账户导航名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 12 页,共 14 页 - - - - - - - - - ?首页?社区?当前事件?最近更改?随机页面?帮助搜索进入搜索Google 搜索 your search terms t search form earch工具箱?链入页面?链出更改?特殊页面?可打印版?永久链 接Google Adsense ?这页的最后修订在 2009 年 5 月 14日 ( 星期四 ) 07:52 。?本页面已经 被浏览 1,344 次。?隐私政策?关于 Ogre3D开放资源地带?沪 ICP备 09049564号名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 13 页,共 14 页 - - - - - - - - - 名师资料总结 - - -精品资料欢迎下载 - - - - - - - - - - - - - - - - - - 名师精心整理 - - - - - - - 第 14 页,共 14 页 - - - - - - - - -