第九章 碰撞检测_第1页
第九章 碰撞检测_第2页
第九章 碰撞检测_第3页
第九章 碰撞检测_第4页
第九章 碰撞检测_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 OpenGL高级编程高级编程 & 可视化系统开发可视化系统开发广东工业大学图学与数字媒体系 罗立宏第九章第九章 碰撞检测碰撞检测9.1碰撞检测概述碰撞检测概述碰撞检测是使系统更自然逼真的必须内容。碰撞检测的一般技术 (1)矩形包围盒或球形包围盒 (2)多边形集合 (3)物体的运动轨迹跟踪9.3 编程实例二编程实例二9.3.1 程序说明本例通过计算空间点与平面之间的距离来进行碰撞检测7.1.2 详细设计详细设计1 关键技术关键技术碰撞算法一 当 |D1|g_fSphere_radius 时,认为碰撞发生D1(i=1)D1(i=2)Z碰撞算法二 当 D0与D1异号时,可认为碰撞发生D1(i=1)

2、D1(i=2)ZvD0(i=1)D0(i=2)Zv2 详细设计详细设计(1) 画图设置好绘图坐标系设置好绘图坐标系刷新屏幕刷新屏幕绘制两弹性平面及连线绘制两弹性平面及连线跟据球的位置绘制球跟据球的位置绘制球处理OnDraw( )处理RenderScene ( )CollisionCheck()碰撞检测,状态调整碰撞检测,状态调整(2) 初始化初始化程序数据初始化程序数据初始化弹性平面和球的数据初始化弹性平面和球的数据设置设置OpenGL环境环境处理OnCreate( )(3) 弹性平面类typedef struct tagQuadvec3vVertices4; /四边形四个顶点vec3vNor

3、mal; /法线向量floatD; /离原点的距离RGBsColor; /颜色 QUAD;9.2.3 编程步骤编程步骤一步步来写代码,边写边调试:1.使用第二章做的OpenGL单文档模板生成程序框架2.画出两个弹力平面3.画出球4.球运动起来5.碰撞检测6.其他调整9.2.3.1生成OpenGL单文档框架新建工程选择OpenGL SD AppWizard编译,改正一个错误fatal error RC1015: cannot open include file resMySDOpenGL.rc2.双击该错误,代码跳到错误处。原来是文件MYWATER.RC中的这句: #include resMyS

4、DOpenGL.rc2“我们的程序名叫“MyWater”,查看资源管理器,在res目录下发现只有MyWater.rc2资源文件,因此把错误句改为: #include resMyWater.rc2“再编译,发现就可以了。这个是制作模板是留下的错误。把程序改为调试版,以方便后面调试程序右击工具栏空白处,点击“组建”,调出“组建”工具栏,选择“Win32 Debug”9.2.3.2 画出两个弹力平面先在视图类加入两个弹力平面的数据成员(1)编写弹力平面定义 在CMySDOpenGLView类头文件中,但在CMySDOpenGLView类外部加入:#include “vec3.h“ /描述矢量及运算的

5、头文件typedef struct tagRGB /定义颜色数据结构float r,g,b; RGB;typedef struct tagQuad /定义弹力平面vec3vVertices4; /四边形四个顶点vec3vNormal; /法线向量float D; /离原点的距离RGBsColor; /颜色 QUAD;(2)加入涉及的矢量定义文件 编译,发现错误,说“vec3.h”找不到。于是从课本代码中拷贝vec3.h到工程目录。再编译,通过了。但是工作区中还看不见_vec3矢量类,因此还需进行下列操作:点击菜单“工程”“添加工程”Files 注意不同的汉化版本,上面菜单文字可能稍有不同。然后

6、弹出选择文件对话框,选中“vec3.h”,点“确定”然后工作区中就可以看见_vec3类了。如右图此矢量类包括了矢量的定义和各种矢量运算,可以收集作为一个代码资源收集作为一个代码资源。(3) 在CMySDOpenGLView.h中加入两个弹力平面的定义:public: QUAD g_sQuads2;(4)做一些初始化工作 在CMySDOpenGLView.h中加入(在弹力平面定义的上面或下面)Init的函数声明: void Init();(5)在CMySDOpenGLView.cpp中末尾加入Init()的定义,在Init()写入两个弹力平面数据的初始化,和基本的OpenGL初始化代码void

7、CMySDOpenGLView:Init(GLvoid)/红色弹力平面数据初始化/四点位置g_sQuads0.vVertices0 = vec3( -2.0 , 2.0 , -5.0f); g_sQuads0.vVertices1 = vec3( 2.0 , 2.0 , -5.0f);g_sQuads0.vVertices2 = vec3( 2.0 , -2.0 , -5.0f);g_sQuads0.vVertices3 = vec3( -2.0 , -2.0 , -5.0f);/法线g_sQuads0.vNormal = vec3(0,0,1); /与原点距离g_sQuads0.D = g_

8、sQuads0.vVertices0.z;/颜色g_sQuads0.sColor.r = 1.0f;g_sQuads0.sColor.g = 0.0f;g_sQuads0.sColor.b = 0.0f;/绿色弹力平面数据初始化g_sQuads1.vVertices0 = vec3( -2.0 , 2.0 , 5.0f);g_sQuads1.vVertices1 = vec3( 2.0 , 2.0 , 5.0f);g_sQuads1.vVertices2 = vec3( 2.0 , -2.0 , 5.0f);g_sQuads1.vVertices3 = vec3( -2.0 , -2.0 ,

9、5.0f);g_sQuads1.vNormal = vec3(0,0,1);g_sQuads1.D = g_sQuads1.vVertices1.z; g_sQuads1.sColor.r = 0.0f;g_sQuads1.sColor.g = 1.0f;g_sQuads1.sColor.b = 0.0f;/ 初始化openglglClearColor(0.0f, 0.0f, 0.0f, 1.0f); /设置清屏颜色glEnable(GL_DEPTH_TEST); /启用深度测试glDepthFunc(GL_LEQUAL); /深度使用“小于等于”的比较方法glPolygonMode (GL_

10、FRONT_AND_BACK, GL_FILL); /多边形前面背面都要渲染,要画出整个面(6) 在视图类的OnCreate()中调用Init():int CMySDOpenGLView :OnCreate(LPCREATESTRUCT lpCreateStruct) if (CView:OnCreate(lpCreateStruct) = -1)return -1;/ TODO: Add your specialized creation code here/初始化OpenGL和设置定时器m_pDC = new CClientDC(this);SetTimer(1, 20, NULL);In

11、itializeOpenGL(m_pDC);/Init();return 0;(7)在RenderScene()中加入画弹力平面的代码:BOOL CMySDOpenGLView:RenderScene() /要做实际的绘图工作,将在这个空白里写int i=0;glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );glMatrixMode(GL_MODELVIEW); glLoadIdentity();/ 移动绘图坐标系(达到拉开摄像机的效果)glTranslatef(-5.0f,0.0f,-25.0f);glRotatef(-45,0.0f,

12、1.0f,0.0f);/ 绘制两个四边形代表两个平面glBegin(GL_QUADS);for (;i2;i+) int v=0; glColor3fv(const float*)&g_sQuadsi.sColor); for (v=0;vGetSafeHdc(); /交互缓冲区return TRUE;(8) 编译运行,发现一片黑什么也看不见。原来观察方法还没设置,在视图类OnSize()中加入观察方式的代码:void CMySDOpenGLView:OnSize(UINT nType, int cx, int cy) CView:OnSize(nType, cx, cy);/ TODO: A

13、dd your message handler code here/添加窗口缩放时的图形变换函数glViewport(0,0,cx,cy); / 改变视口大小/glMatrixMode(GL_PROJECTION); /矩阵堆栈切换成投影矩阵glLoadIdentity(); /矩阵重置为单位阵/使用透视投影,竖向视野角为45,横竖比率为窗口的长宽比,/ 最近面为1,最远面为999。详细见第七章ppt解释gluPerspective(45,(float)cx / cy,1,999); (9) 编译,运行,终于可以看见东西了。如下图:暗自兴奋一下,然后继续投入下一步的工作(10)画两个弹力平面的

14、四个角画4条线及z轴,运行变为右图BOOL CMySDOpenGLView:RenderScene() /前面画弹力平面的代码略/ 绘制4条线glBegin(GL_LINES);for (i=0;iGetSafeHdc();/交互缓冲区return TRUE;9.2.3.3 画出球(1)在CMySDOpenGLView.h中加入与球相关的三个变量public:void Init();QUAD g_sQuads2;float g_fSphere_radius; /小球半径GLUquadricObj *q; /二次曲面对象vec3 g_vSpherePos ; /小球的位置(2)在构造函数中初始化

15、他们的值(当然,在OnCreate里面也行的)CMySDOpenGLView:CMySDOpenGLView()/ TODO: add construction code hereg_fSphere_radius = 0.5f;q = NULL;g_vSpherePos = vec3(0,0,0);(3)在RenderScene()中加入绘制球的代码BOOL CMySDOpenGLView:RenderScene() /绘制弹力平面、4条连线、z轴的代码省略 / 绘制球体glTranslatef(g_vSpherePos.x,g_vSpherePos.y,g_vSpherePos.z); gl

16、uSphere(q,g_fSphere_radius,32,32);:SwapBuffers(m_pDC-GetSafeHdc(); /交互缓冲区return TRUE;(4)再编译,运行,如图: 但是球还不能动。9.2.3.4 让球动起来让球运动的代码其实是与碰撞检测联系在一起的,因此我们把控制球运动的代码写到CollisionCheck()函数中,虽然我们现在还没写到碰撞检测的实质代码。所以:(1)在视图类头文件中增加CollisionCheck()函数的定义。可以写到Init()的后面,还要增加一个小球运动速度的变量:void Init();void CollisionCheck();Q

17、UAD g_sQuads2; /两个弹力平面float g_fSphere_radius; /小球半径GLUquadricObj *q; /二次曲面对象vec3 g_vSpherePos ; /小球的位置vec3 g_vVelocity; /小球的速度(2)速度要进行初始化,因此在视图类构造函数中增加代码:CMySDOpenGLView:CMySDOpenGLView()/ TODO: add construction code hereg_fSphere_radius = 0.5f;q=NULL;g_vSpherePos = vec3(0,0,0);g_vVelocity = vec3(0,

18、0,0.1f);(3)在视图类cpp末尾增加CollisionCheck()函数的实现:void CMySDOpenGLView:CollisionCheck()/算得一个新位置vec3 g_vSphereAfter = g_vSpherePos + g_vVelocity;/把新位置作为小球的新位置,即移动球体g_vSpherePos = g_vSphereAfter;(4)在RenderScene()中调用CollisionCheck()BOOL CMySDOpenGLView:RenderScene() /绘制弹力平面、连线、z轴的代码省略/ 绘制球体glTranslatef(g_vSp

19、herePos.x,g_vSpherePos.y,g_vSpherePos.z);gluSphere(q,g_fSphere_radius,32,32);CollisionCheck();:SwapBuffers(m_pDC-GetSafeHdc();/交互缓冲区return TRUE;(5)编译,运行,发现球能运动了。但没有碰撞检测,球会飞出弹力平面,如图:9.2.3.5 碰撞检测对程序应用前述碰撞检测的两种方法(1)加入一个控制变量,以控制是用第一种碰撞检测方法还是第二种碰撞检测方法。在视图类头文件中增加:void Init();void CollisionCheck();QUAD g_s

20、Quads2; /两个弹力平面float g_fSphere_radius; /小球半径bool bDistanceCheck; /是否使用第一种碰撞检测方法GLUquadricObj *q; /二次曲面对象vec3 g_vSpherePos ; /小球的位置vec3 g_vVelocity; /小球的速度(2) 改写CollisionCheck,实现碰撞检测功能void CMySDOpenGLView:CollisionCheck()int i=0;bool collision=false;vec3 g_vSphereAfter = g_vSpherePos + g_vVelocity;for (;i2;i+) / 在两个平面内进行碰撞检测

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论