拾取算法

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

拾取射线的计算
在观察坐标系中,拾取射线是一条从观察坐标原点出 发的射线,所以我们只需要再确定一个该射线经过的点, 就可以得到它在观察坐标系中的表示。假设我们要求的射 线上的另外一点为该射线与透视投影平截头体近剪切面的 交点,针对最普遍的透视投影而言,透视投影平截头体经 投影变换后,变成半个立方体如图:
Copyright 2008 By Neusoft Group. All rights reserved
它山之石
• 课下可选阅读材料: <<3D游戏程序设计入门 >>第15章
Copyright 2008 By Neusoft Group. All rights reserved
锦上添花
• 实现对人物选中后,设计人物完成选中 后所布置的任务,如实现简单攻击,人物 移动等.
窗口的转换
1.确定鼠标选取点的屏幕坐标 (使用Windows API中的GetCursorPos函数) 2.将屏幕上的点转换到透影窗口上 通过视口变换矩阵 可以将将投影窗口 上的点P(px,py,pz) 通过窗口变换产生 屏幕上的点S,同样 已知点S,通过逆变 换也就可以得到点P
Copyright 2008 By Neusoft Group. All rights reserved
实例: 实例:拾取立方体
• 实现效果图: 实现效果图:
Copyright 2008 By Neusoft Group. All rights reserved
拾取课堂练习
练习拾取一个圆柱体,效果如下图所示: 练习拾取一个圆柱体,效果如下图所示:
Copyright 2008 By Neusoft Group. All rights reserved
Copyright 2008 By Neusoft Group. All rights reserved
专题授课要点
• • • • •
窗口的转换 拾取射线的计算 射线与物体坐标系的统一 射线与物体相交的计算 实例
Copyright 2008 By Neusoft Group. All rights reserved
Copyright 2008 By Neusoft Group. All rights reserved
射线与物体的相交计算
bool RaySphereIntTest(Ray* ray, BoundingSphere* sphere) { D3DXVECTOR3 v = ray->_origin - sphere->_center; float b = 2.0f * D3DXVec3Dot(&ray->_direction, &v); float c = D3DXVec3Dot(&v, &v) - (sphere->_radius * sphere->_radius); // find the discriminant float discriminant = (b * b) - (4.0f * c); // test for imaginary number if( discriminant < 0.0f ) return false; discriminant = sqrtf(discriminant); float s0 = (-b + discriminant) / 2.0f; float s1 = (-b - discriminant) / 2.0f; // if a solution is >= 0, then we intersected the sphere if( s0 >= 0.0f || s1 >= 0.0f ) return true; return false; }
Copyright 2008 By Neusoft Group. All rights reserved
实例: 实例:拾取立方体
步骤: 步骤: 第1步:绘制立方体 第2步:实现屏幕到投影窗口的变换 第3步:计算拾取射线 第4步:将射线与立方体统一到同一坐标系 第5步:判断射线与立方体相交情况
Copyright 2008 By Neusoft Group. All rights reserved
统一射线与物体坐标系
void TransformRay(Ray* ray, D3DXMATRIX* T) { // transform the ray's origin, w = 1. D3DXVec3TransformCoord( &ray->_origin, &ray->_origin, T); // transform the ray's direction, w = 0. D3DXVec3TransformNormal( &ray->_direction, &ray->_direction, T); // normalize the direction D3DXVec3Normalize(&ray->_direction, &ray->_direction); }
Copyright 2008 By Neusoft Group. All rights reserved
射线与物体的相交计算
方法2 了解) 方法2(了解) • 使用D3D扩展函数,毕竟有时不能满足具体需求,掌握了该方法,我们才能 够获得最大的控制自由度,任意修改算法。 • 已知条件: 射线源点orginPoint,三角形三个顶点 v1,v2,v3,射线方向 Dir(均以 三维坐标向量形式表示) • 算法目的: 判断射线与三角形是否相交,如果相交求出交点的重心坐标(U,V) 和射线原点到交点的距离T。 • 我们可先假设射线与三角形相交则交点(注以下均为向量运算,*数乘, dot(X,Y) X,Y 点乘,cross(X,Y)X,Y叉乘;U,V,T为标量) 则: • IntersectPoint = V1 + U*(V2-V1) + V*(V3-V1) ; • IntersectPoint = originPoint + T*Dir; 所以 orginPoint + T*Dir = V1 + U*(V2-V1) + V*(V3-V1);
拾取射线的计算
• py = (sy-sHeight/2)/sHeight*2; (公式2) • pz =0;(实际该值可任意取,不影响最终结果。 为了处理简单,我们取改值为0,表示该点取在近 剪切面上)得到projPt后,我们需要做的是把该点 坐标从投影空间转换到观察空间(ViewSpace),根 据透视投影的定义, 可假设点(px,py,pz) 对应的齐次坐标为 (px*pw,py*pw,pz*pw,pw) 我们可以通过 GetTransform( D3DTS_PROJECTION, & proj) 函数获得投影矩阵proj;
Copyright 2008 By Neusoft Group. All rights reserved
统一射线与物体坐标系
我们前面所计算出来的拾取射线是在视图空间 中描述的.为了完成相交计算我们还需要将物体 与射线放到同一坐标系中.
Copyright 2008 By Neusoft Group. All rights reserved
Copyright 2008 By Neusoft Group. All rights reserved
拾取射线的计算
投影坐标系以近剪切面中心为坐标原点,该立方体 从z轴负向看过去与图形程序视区相对应,最终近剪切面 (前剪切面)上一点与屏幕坐标之间的对应关系如下图所 示:
Copyright 2008 By Neusoft Group. All rights reserved
Copyright 2008 By Neusoft Group. All rights reserved
拾取射线的代码实现
struct Ray { D3DXVECTOR3 _origin; D3DXVECTOR3 _direction; }; Ray CalcPickingRay(int x, int y) { float px = 0.0f; float py = 0.0f; D3DVIEWPORT9 vp; g_pD3DDevice->GetViewport(&vp); D3DXMATRIX proj; g_pD3DDevice->GetTransform(D3DTS_PROJECTION, &proj); px = ((( 2.0f*sx) / vp.Width) - 1.0f) / proj(0, 0); py = (((-2.0f*sy) / vp.Height) + 1.0f) / proj(1, 1); Ray ray; ray._origin = D3DXVECTOR3(0.0f, 0.0f, 0.0f); ray._direction = D3DXVECTOR3(px, py, 1.0f); return ray; }
抛砖引玉
Copyright 2008 By Neusoft Group. All rights reserved
抛砖引玉
Copyright 2008 By Neusoft Group. All rights reserved
专题7 专题 选择场景中的角色
• 学习目标: 1. 学习怎样实现拾取算法,弄懂它如何工作,主要 掌握如下四个方面: 1) 能够获得屏幕中的点S,找到它所对应的投影 窗口上的点P. 2)掌握如何计算拾取射线. 3)熟练掌握将射线与模型变换到同一坐标系中 4)掌握如何判断物体与射线相交 2.能够在程序中灵活运用拾取(重点)
Copyright 2008 By Neusoft Group. All rights reserved
射线与物体的相交计算
方法1 方法1:利用D3D提供的扩展函数D3DXIntersect
HRESULT D3DXIntersect( LPD3DXBASEMESH pMesh, CONST D3DXVECTOR3 *pRayPos, CONST D3DXVECTOR3 *pRayDir, BOOL *pHit, DWORD *pFaceIndex, FLOAT *pU, FLOAT *pV, FLOAT *pDist, LPD3DXBUFFER *ppAllHits, DWORD *pCountOfHits );
Copyright 2008 By Neusoft Group. All rights reserved
射线与物体的相交计算
lpMesh指向一个ID3DXBaseMesh的对象,最简单的方式是从.x文件获 得,描述了要进行相交检测的三角面元集合的信息,具体规范参阅 direct9 SDK pRayPos 指向射线发出点 pRayDir 指向前面我们辛辛苦苦求出的射线方向的向量 pHit 当检测到相交图元时,指向一个true,不与任何图元相交则为假 pU 用于返回重心坐标U分量 pV返回重心坐标V分量 pDist 返回射线发出点到相交点的长度 注意:以上红色字体部分均指最近的一个返回结果(即*pDist最小) ppAllHits用于如果存在多个相交三角面返回相交的所有结果 pCountOfHits 返回共有多少个三角形与该射线相交
专题7 选择场景中的角色 专题
Copyright 2008 By Neusoft Group. All rights reserved
Baidu Nhomakorabea
抛砖引玉
Copyright 2008 By Neusoft Group. All rights reserved
抛砖引玉
Copyright 2008 By Neusoft Group. All rights reserved
实例: 实例:拾取游戏角色
• 选择怪兽,选中后在怪兽身上显示闪烁光标, 选择怪兽,选中后在怪兽身上显示闪烁光标,表示怪 兽已经拾取成功. 兽已经拾取成功.
Copyright 2008 By Neusoft Group. All rights reserved
作业: 作业:
1.绘制一个正四面体,并实现拾取 绘制一个正四面体, 文件, 2.导入前面所提供的Yodan.x文件,并实现对人物的 文件 拾取. 拾取.
相关文档
最新文档