ImageVerifierCode 换一换
格式:DOCX , 页数:16 ,大小:24.17KB ,
资源ID:11797540      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/11797540.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(NO64OGRE中级教程4.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

NO64OGRE中级教程4.docx

1、NO64OGRE中级教程4OGRE中级教程四From OGRE 3D 中文Jump to: navigation, search目录 1 介绍 2 先决条件 3 ManualObject对象 3.1 3D对象的快速入门 3.2 介绍 3.3 代码 4 体积选取 4.1 设置 4.2 鼠标处理 4.3 PlaneBoundedVolumeListSceneQuery 5 最后关于包围盒的注意事项 介绍在这一课里,我们将涉及如何进行体积选取。意思就是,当你在屏幕上点击并且拖拽鼠标时,一个白色矩形会追踪你正在选择的区域。当鼠标移动时,所有在选择区域里的物体都会被高亮。为了实现它,我们将学习两种对象:

2、ManualObject(创建矩形)和PlaneBoundedVolumeListSceneQuery。注意,当我们涉及ManualObject的基本用法时,只是对它的简单介绍,而不是教你如何完全用它创建3D物体。我们只会涉及我们所需要的。 你能在这里找到本课的代码。当你学习本课时,你应该逐个地往你的工程里添加代码,编译后观察相应的结果。 先决条件用你喜欢的IDE创建一个cpp,并添加以下代码: #include #include #include ExampleApplication.h class SelectionRectangle: public ManualObject public

3、: SelectionRectangle(const String &name) : ManualObject(name) /* * Sets the corners of the SelectionRectangle. Every parameter should be in the * range 0, 1 representing a percentage of the screen the SelectionRectangle * should take up. */ void setCorners(float left, float top, float right, float b

4、ottom) void setCorners(const Vector2 &topLeft, const Vector2 &bottomRight) setCorners(topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); ; class DemoListener: public ExampleFrameListener, public OIS:MouseListener public: DemoListener(RenderWindow* win, Camera* cam, SceneManager *sceneManager) : Ex

5、ampleFrameListener(win, cam, false, true), mSceneMgr(sceneManager), mSelecting(false) mMouse-setEventCallback(this); / DemoListener DemoListener() /* MouseListener callbacks. */ bool mouseMoved(const OIS:MouseEvent &arg) CEGUI:System:getSingleton().injectMouseMove(arg.state.X.rel, arg.state.Y.rel);

6、return true; bool mousePressed(const OIS:MouseEvent &arg, OIS:MouseButtonID id) return true; bool mouseReleased(const OIS:MouseEvent &arg, OIS:MouseButtonID id) return true; void performSelection(const Vector2 &first, const Vector2 &second) void deselectObjects() std:list:iterator itr; for (itr = mS

7、elected.begin(); itr!= mSelected.end(); +itr) (*itr)-getParentSceneNode()-showBoundingBox(false); void selectObject(MovableObject *obj) obj-getParentSceneNode()-showBoundingBox(true); mSelected.push_back(obj); private: Vector2 mStart, mStop; SceneManager *mSceneMgr; PlaneBoundedVolumeListSceneQuery

8、*mVolQuery; std:list mSelected; SelectionRectangle *mRect; bool mSelecting; static void swap(float &x, float &y) float tmp = x; x = y; y = tmp; ; class DemoApplication: public ExampleApplication public: DemoApplication() : mRenderer(0), mSystem(0) DemoApplication() if (mSystem) delete mSystem; if (m

9、Renderer) delete mRenderer; protected: CEGUI:OgreCEGUIRenderer *mRenderer; CEGUI:System *mSystem; void createScene(void) mRenderer = new CEGUI:OgreCEGUIRenderer(mWindow, Ogre:RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr); mSystem = new CEGUI:System(mRenderer); CEGUI:SchemeManager:getSingleton().load

10、Scheme(CEGUI:utf8*)TaharezLookSkin.scheme); CEGUI:MouseCursor:getSingleton().setImage(CEGUI:utf8*)TaharezLook, (CEGUI:utf8*)MouseArrow); mCamera-setPosition(-60, 100, -60); mCamera-lookAt(60, 0, 60); mSceneMgr-setAmbientLight(ColourValue:White); for (int i = 0; i 10; +i) for (int j = 0; j createEnti

11、ty(Robot + StringConverter:toString(i + j * 10), robot.mesh); SceneNode *node = mSceneMgr-getRootSceneNode()-createChildSceneNode(Vector3(i * 15, 0, j * 15); node-attachObject(ent); node-setScale(0.1, 0.1, 0.1); void createFrameListener(void) mFrameListener = new DemoListener(mWindow, mCamera, mScen

12、eMgr); mFrameListener-showDebugOverlay(true); mRoot-addFrameListener(mFrameListener); ; #if OGRE_PLATFORM = OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include windows.h INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT) #else int main(int argc, char *argv) #endif / Create ap

13、plication object DemoApplication app; try app.go(); catch(Exception& e) #if OGRE_PLATFORM = OGRE_PLATFORM_WIN32 MessageBoxA(NULL, e.getFullDescription().c_str(), An exception has occurred!, MB_OK | MB_ICONERROR | MB_TASKMODAL); #else fprintf(stderr, An exception has occurred: %sn, e.getFullDescripti

14、on().c_str(); #endif return 0; 继续之前,请确保这段代码能够编译。当你运行它时,你应该能够移动鼠标指针,但程序目前不能做其它的。按ESC退出。 ManualObject对象3D对象的快速入门在我们开始进入制作网格(mesh)之前,有必要讲一下mesh是什么,以及它的构成。尽管非常简化,mesh大致由两部分组成:顶点缓存(Vertex buffer)和索引缓存(Index buffer)。 顶点缓存在3D空间里定义点集。顶点缓存里的每一个元素由若干你能设置的属性来定义。唯一一个你必须设置的属性就是顶点的坐标。除了这个,你还有设置其它可选的属性,比如顶点颜色、纹理坐标

15、等。你实际需要的属性取决于mesh的用途。 索引缓存通过从顶点缓存选取顶点,以“把点连起来”。索引缓存里每三个顶点定义了一个由GPU绘制的三角形。你在索引缓存里选取顶点的顺序,告诉了显卡这个三角形的朝向。逆时针绘制的三角形是朝向你的,顺时针绘制的三角形是背向你的。一般情况下只有三角形的正面才被绘制,所以确保你的三角形被正确载入是很重要的。 虽然所有的mesh都有顶点缓存,但不一定都有索引缓存。比如,我们只要创建一个空的三角形(而不是实心的),我们创建的mesh就不需要索引缓存。最后要注意,顶点缓存和索引缓存通常保存在显卡自己的内存里,所以你的软件只要发送一些离散的命令,告诉它使用预定义的缓存来

16、一口气渲染整个3D网格。 介绍在Ogre里有两种方法来创建你自己的网格。第一种是继承SimpleRenderable,并直接提供给它顶点和索引缓存。这是最直接的创建方式,但也是最不直观的。为了使事情更简单,Ogre提供一个更棒的接口叫做ManualObject,它能让你用一些简单的函数来定义一个网格,而不用往缓存里写原始数据。你仅仅调用position和colour函数,而不用往缓存里丢位置、颜色等数据。 在本课里,当我们拖动鼠标去选择物体时,我们要创建并显示一个白色矩形。在Ogre里并没有真正的用来显示2D矩形的类。我们必须自己找一个解决办法。我们可以使用一个Overlay并缩放它,以显示一

17、个矩形选择框,但这样做带来的问题是,选择框的图像可能会随着拉升而难看变形。取而代之,我们将生成一个非常简单的2D网格,来作为我们的选择矩形。 代码当我们创建选择矩形的时候,我们想让它以2D的形式呈现。我们还想保证当在屏幕里发生重叠时,它显示在所有其它物体之上。实现这个非常简单。找到SelectionRectangle的构造器,并添加如下代码: setRenderQueueGroup(RENDER_QUEUE_OVERLAY); setUseIdentityProjection(true); setUseIdentityView(true);第一个函数把这个物体的渲染队列设置成重叠队列(Over

18、lay queue)。接下来的两个函数把投影矩阵(projection matrix)和视图矩阵(view matrix)设置成identity。投影矩阵和视图矩阵被很多渲染系统所使用(比如OpenGL和DirectX),以定义物体在世界中的坐标。既然Ogre为我们做了抽象,我们不必深究这些矩阵是什么样的或他们干了些什么。然而,你需要知道如果你把投影矩阵和视图矩阵设置成identity,就像刚才那样,我们基本上就是在绘制2D物体。这样定义之后,坐标系统发生了一些改变。我们不再需要Z轴(若你被要求提供Z轴,设置成-1)。取而代之,我们有一个新的坐标系统,X和Y的范围分别都是-1到1。最后,我们将

19、把这个物体的查询标记设置成0,如下: setQueryFlags(0);现在,对象设置好了,我们来实际构建这个矩形。我们开始之前还有一个小小阻碍,我们将使用鼠标坐标来调用这个函数。也就是,传给我们一个0到1之间的数字为每个坐标轴,然而我们需要把这个数字转换成范围-1,1的。还有更复杂的,y坐标要反向。在CEGUI里,鼠标指针在屏幕顶部时,值为+1,在底部时,值为-1。感谢上帝,用一个快速转换就能解决这个问题。找到setCorners函数并添加如下代码: left = left * 2 - 1; right = right * 2 - 1; top = 1 - top * 2; bottom =

20、 1 - bottom * 2;现在转换成新坐标系统了。下面,我们来真正创建这个对象。为此,我们首先调用begin方法。它需要两个参数,物体的这一部分所使用的材质,以及它所使用的渲染操作。因为我们不使用纹理,把这个材质置空。第二个参数是渲染操作(RenderOperation)。我们可以使用点、线、三角形来渲染这个网格。如果我们要渲染一个实心的网格,可以用三角形。但我们只需要一个空的矩形,所以我们使用线条(line strip)。从你定义的前一个顶点到现在的顶点,线条绘制一条直线。所以为了创建我们的矩形,需要定义5个点(第一个和最后一个是相同的,这样才能连接成整个矩形): clear(); b

21、egin(, RenderOperation:OT_LINE_STRIP); position(left, top, -1); position(right, top, -1); position(right, bottom, -1); position(left, bottom, -1); position(left, top, -1); end();注意,因为我们将在后面多次调用它,我们在最前面加入clear函数,在重新绘制矩形之前移除上次的矩形。当定义一个手动物体时,你可能要多次调用begin/end来创建多个子网格(它们可能有不同的材质/渲染操作)。注意,我们把Z参数设成-1,因为我们

22、只定义一个2D对象而不必使用Z轴。把它设置为-1,可以保证当渲染时我们不处在摄像机之上或之后。 最后我们还要为这个物体设置包围盒。许多场景管理器会把远离屏幕的物体剔除掉。尽管我们创建的差不多是一个2D物体,但Ogre仍是一个3D引擎,它把2D物体当作在3D空间里对待。这意味着,如果我们创建这个物体,并把它绑在场景节点上(正如我们下面要做的那样),当我们远一点观看时会消失。为了修正这个问题,我们将把这个物体的包围盒设置成无限大,这样摄像机就永远在它里面: AxisAlignedBox box; box.setInfinite(); setBoundingBox(box);请注意,我们在调用cle

23、ar()之后添加这段代码的。当每你调用ManualObject:clear,包围盒都会被重置,所以当你创建经常清空的ManualObject时要格外小心,每当你重新创建它的时候,也要重新设置包围盒。 好了,我们要为SelectionRectangle类所做的全部就是这些。继续下去之前请保证能编译你的代码,但目前还没有为程序添加功能。 体积选取设置在我们进入选取操作的代码之前,先来设置一些东西。首先,我们要创建一个SelectionRectangle类的实例,然后让SceneManager来为我们创建一个体积查询: mRect = new SelectionRectangle(Selection

24、 SelectionRectangle); mSceneMgr-getRootSceneNode()-createChildSceneNode()-attachObject(mRect); mVolQuery = mSceneMgr-createPlaneBoundedVolumeQuery(PlaneBoundedVolumeList();再来,我们要保证结束时帧监听器做一些清理。把下面的代码加到DemoListener: mSceneMgr-destroyQuery(mVolQuery); delete mRect;注意,我们让SceneManager为我们进行清理,而不是直接删除。 鼠标

25、处理我们要展示的特性是体积选取。这意味着当用户点击鼠标并拖拽时,屏幕里将绘制一个矩形。随着鼠标的移动,所有在矩形内的物体将被选取。首先,我们要处理鼠标的点击事件。我们要保存鼠标的起始位置,并且把SelectionRectangle设置成可见的。找到mousePressed函数并添加如下代码: if (id = OIS:MB_Left) CEGUI:MouseCursor *mouse = CEGUI:MouseCursor:getSingletonPtr(); mStart.x = mouse-getPosition().d_x / (float)arg.state.width; mStart

26、.y = mouse-getPosition().d_y / (float)arg.state.height; mStop = mStart; mSelecting = true; mRect-clear(); mRect-setVisible(true); 注意,我们使用的是CEGUI:MouseCursor的x和y坐标,而不是OIS的鼠标坐标。这是因为有时OIS反映的坐标与CEGUI实际显示的不一样。为了保证我们与用户所看到的相一致,我们使用CEGUI的鼠标坐标。 接下来我们要做的是,当用户释放鼠标按钮时,停止显示选择框,并执行这个选取查询。在mouseReleased里加入以下代码: i

27、f (id = OIS:MB_Left) performSelection(mStart, mStop); mSelecting = false; mRect-setVisible(false); 最后,每当鼠标移动时,我们需要更新矩形的坐标: if (mSelecting) CEGUI:MouseCursor *mouse = CEGUI:MouseCursor:getSingletonPtr(); mStop.x = mouse-getPosition().d_x / (float)arg.state.width; mStop.y = mouse-getPosition().d_y / (

28、float)arg.state.height; mRect-setCorners(mStart, mStop); 每当鼠标移动时,我们都调整mStop向量,这样我们就能轻松地使用setCorners成员函数了。编译并运行你的程序,现在你能用鼠标绘制一个矩形了。 PlaneBoundedVolumeListSceneQuery 现在,我们可以让SelectionRectangle正确地渲染了,我们还想执行一个体积选择。找到performSelection函数,并添加如下代码: float left = first.x, right = second.x, top = first.y, botto

29、m = second.y; if (left right) swap(left, right); if (top bottom) swap(top, bottom);在这段代码里,我们分别为left、right、top、botton变量赋予向量参数。if语句保证了我们实际的left和top值最小。(如果这个矩形是“反向”画出来的,意味着从右下角到左上角,我们就要进行这种交换。) 接下来,我们要检查并了解矩形区域的实际小大。如果这个矩形太小了,我们的创建平面包围体积的方法就会失败,并且导致选取太多或太少的物体。如果这个矩形小于屏幕的某个百分比,我们只将它返回而不执行这个选取。我随意地选择0.00

30、01作为取消查询的临界点,但在你的程序里你应该自己决定它的值。还有,在真实的应用里,你应该找到这个矩形的中心,并执行一个标准查询,而不是什么都不做: if (right - left) * (bottom - top) 0.0001) return;现在,我们进入了这个函数的核心,我们要执行这个查询本身。PlaneBoundedVolumeQueries使用平面来包围一个区域,所以所有在区域里的物体都被选取。我们将创建一个被五个平面包围的区域,它是朝向里面的。为了创建这些平面,我们建立了4条射线,每一条都是矩形的一个角产生的。一旦我们有四条射线, For this example we will build an area enclosed by five

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1