当前位置: 首页 > news >正文

[翻译]XNA 3.0 Game Programming Recipes之twenty-two

PS:自己翻译的,转载请著明出处格
                                            4-10 使用BoundingSpheres的基本模式:碰撞检测
问题
    要检查两个模型是否碰撞了。如果您有许多模型在你的场景中,你不能再进行详细,每三角检查。要启动一个快速的方法来检查可能的碰撞和检查后精细的运行。
解决方案
       在进行碰撞检查,你会发现自己总是作出在速度和准确性之间的权衡。在大多数情况下,你需要解决的综合检查。在第一次执行中,您要扫描所有的物体的可能的碰撞使用非常快速检查以及以后进行详细的测试只适用于物体上的确定的响应在快速检查中。
       这节例子表明两个快速的方法检查存在的两模型之间可能的碰撞。
       最快的方法是找出模型的两个球体 BoundingSpheres,并且检查他们是否相撞用调用 Intersect方法在其中一个球体上。
      你可以延长一点以提高准确度。模型由几个 ModelMeshes组成,它保存这几何信息关于模型的不同部分。 ModelMeshes中的每一能产生它自己的 BoundingSphere,所以你可以执行一个碰撞检测在第一个模型的每一个 BoundingSpheres和第二个模型的每一个 BoundingSpheres之间。显然,这更高的精度达到一个更高的计算成本。
它是如何工作的
Fastest Check

       这个方法将使用 BoundingSphere包围整个模型。如果两个模型的这些 BoundingSpheres碰撞,它可能会是两个模型碰撞。
      在某些情况下,这可以是非常糟糕的结果,如在一个滑雪游戏要检测两个滑雪板的球员在哪里发生了碰撞。滑雪场的范围是巨大的与滑雪撬本身相比;滑雪撬将占用不到百分之一的体积范围。此检查将所有在球体里对象分类(如其他滑雪撬!)作为碰撞所示, 图4-13 。   
      然而,使用这种方法往往是作为第一个检查,因为它的速度快。 这将是一个耻辱,废物处理能力,以检查两个模型是否有碰撞,它其中球 BoundingSphere甚至不发生碰撞。

       执行最快的检查,开始加载模型和产生它们的球状 BoundingSphere作为说明在4-5节。这个 BoundingSphere将会被存储在模型的Tag属性中:
1  myModel = XNAUtils.LoadModelWithBoundingSphere( ref  modelTransforms, " tank " ,Content);
       这个 BoundingSphere将会包含模型的中心(它不需要在模型的 (0,0,0)点)和它的半径。
        当你绘制两个模型时,你需要一个不同的世界矩阵为每个模型,使它们在3D世界里移动(缩放/旋转)到正确的位置。当你移动(缩放/旋转)一个模型时,你同样需要移动 BoundingSphere的中心(缩放半径)。你可以使用我的 XNAUtils文件的 TransformBoundingSphere来实现这个。这个方法花费一个 BoundingSphere和一个世界矩阵。它移动中心和缩放球体的半径依照这个矩阵。结果球体被返回。
        所有你需要做的是检查两个模型之间的碰撞,它用相应模型的世界矩阵转化为每一个 BoundingSpheres,并且检查转化成的 BoundingSpheres是否相撞。
1  private   bool  ModelsCollode1(Model model1,Matrix world1,Model model2,Matrix world2)
2  {
3     BoundingSphere origShpere1 = (BoundingSphere)model1.Tag;
4     BoundingSphere sphere1 = XNAUtils.TransformBoundingSphere(origSphere1,world1);
5     BoundingSphere origShpere2 = (BoundingSphere)model2.Tag;
6     BoundingSphere sphere2 = XNAUtils.TransformBoundingSphere(origSphere2,world2);  
7      bool  collision = sphere1.Intersects(sphere2);
8      return  collision; 
9  }
         因为这个一个模型的 Tag属性能真实的包含任何东西(对象类是C#的根类),你需要告诉你的编译器在这种情况下,它包含的一个 BoundingSphere被转化成一个 cast.如果这个被转化的 BoundingSpheres碰撞了,这个方法返回一个 true
More Accurate, a Bit Slower
       每一个模型由多个成员组成,它的几何数据被存储在模型的 Meshes集合中,在4-1节有解释。每一个如 ModeMesh能生成它自己的 BoundingSphere。所有这些小的 BoundingSpheres的总量将会比模型的球体的 BoundingSphere还会小。如图4-14所显示那样。在图象的右部,你可以看见分割开的 BoundingSphere为模型的所有部分。
       图象的左侧,两个 BoundingSpheres碰撞,所以第一检查表明了两个模型之间的碰撞。换句话说,没有一个 BoundingShperes是正确的碰撞,所以这个检查将会正确的表明两个模型并没有碰撞。第二种方法经常给一个好的结果;尽管,第一种情况只需要一次检查,同时第二种情况要求(模型1的内部元素)*(模型2的内部元素)检查。
     下面的方法是根据第二种情况的检测碰撞:
 1  private   bool  FinerCheck(Model model1,Matrix world1,Model model2,Matrix world2)
 2  {
 3       if (CoarseCheck(model1,world1,model2,world2) == false )
 4          return   false ;
 5       bool  collision = false ;
 6      Matrix[] model1Transforms = new  Matrix[model1.Bones.Count];
 7      Matrix[] model2Transforms = new  Matrix[model2.Bones.Count];
 8      model1.CopyAbsoluteBoneTransformsTo(model1Transforms);
 9      model2.CopyAbsoluteBoneTransformsTo(model2Transforms);
10       foreach (ModeMesh mesh1  in  model1.Meshes)
11      {
12          BoundingSphere origSphere1 = mesh1.BoundingSphere;
13          Matrix trans1 = model1Transforms[mesh1.ParentBone.Index] * world1;
14          BoundingSphere transSphere1 = XNAUtils.TransformBoundingSphere(origSphere1,trans1);
15           foreach (ModeMesh mesh2  in  model2.Meshes)
16          {
17              BoundingSphere origSphere2 = mesh2.BoundingSphere;
18              Matrix trans2 = model2Transforms[mesh2.ParentBone.Index] * world2;
19              BoundingSphere transSphere2 = XNAUtils.TransformBoundingSphere(origSphere2,trans2);    
20               if (transSphere1.Intersects(transSphere2))
21                    collision = true ;         
22          }
23      }
24        return  collision;
25  }
        你开始执行快速检查。如果这个检查返回false,但肯定没有需要执行的精细检查。
       如果粗糙的检查表明有碰撞的可能,你继续前移。你首先设置碰撞变量为 false,它会继续这样直到你遇到一个碰撞。因为你需要移动每一个小的 BoundingSphere到它正确的位置在模型中,你需要绝对的 Bone矩阵为两个模型。
       为了执行这个检查,第一个模型的每一个 ModelMesh,你转化它的 BoundingSphere到它在 3D世界的绝对位置。为此,你需要考虑在这个模型中的 BoundingSphere的位置在 3D世界里。
       下一步,您翻阅模型2的所有部分,并把这些 BoundingSphere转化成三维世界的绝对位置。
       对于模型1的每一个 BoundingSphere,检查模型2的任何 BoundingSphere是否与它发生碰撞,如果发生了,设置碰撞变量为true.
       最后,碰撞变量将会表示模型的最后一个 BoundingSpheres和模型2的其中一个 BoundingSpheres发生了碰撞,然后返回这个变量。
Optimization
       由于模型的每一部分,模型2的所有 BoundingSpheres每一次都会被用相同的方法转变,这种方法能明显得到优化。例如,您可以做到这一点,靠首先改变了模型1的 BoundingSpheres和模型2的 BoundingSpheres,在这个方法的开始,把它们保存进一个数组。在此之后,你可以简单的检查这些转变过的 BoundingSpheres之间的碰撞。
        这是 FinerCheck方法下一个版本所做的事情:
 1  private   bool  FinerCheck(Model model1,Matrix world1,Model model2,Matrix world2)
 2  {
 3       if (CoarseCheck(model1,world1,model2,world2) == false )
 4          return   false ;
 5      Matrix[] model1Transforms = new  Matrix[model1.Bones.Count];
 6      model1.CopyAbsoluteBoneTransformsTo(model1Transforms);
 7      BoundingSphere[] model1Spheres = new  BoundingSphere[model1.Meshes.Count];
 8       for ( int  i = 0 ;i < model1.Meshes.Count;i ++ )
 9      {
10          ModelMesh mesh = model1.Meshes[i];
11          BoundingSphere origSphere = mesh.BoundingSphere;
12          Matrix trans = model1Transform[mesh.ParentBone.Index] * world1;
13          BoundingSphere transSphere = XNAUtils.TransformBoundingSphere(origSphere,trans);
14          model1Spheres[i] = transSphere;
15      }
16      Matrix[] model2Transforms = new  Matrix[model2.Bones.Count];
17      model2.CopyAbsoluteBoneTransformsTo(model2Transforms);
18      BoundingSphere[] model2Spheres = new  BoundingSphere[model2.Meshes.Count];
19       for ( int  i = 0 ;i < model1.Meshes.Count;i ++ )
20      {
21          ModelMesh mesh = model2.Meshes[i];
22          BoundingSphere origSphere = mesh.BoundingSphere;
23          Matrix trans = model2Transform[mesh.ParentBone.Index] * world2;
24          BoundingSphere transSphere = XNAUtils.TransformBoundingSphere(origSphere,trans);
25          model2Spheres[i] = transSphere;
26      }
27       bool  collision = false
28       for ( int  i = 0 ;i < model1Sphere.Length;i ++
29           for ( int  j = 0 ;j < model2Spheres.Length;j ++ )
30               if (model1Spheres[i].Intersects(model2Spheres[j]
))
31                     return   true ;
32       return  collision;
33  }
注意 CopyAbsoluteBoneTransformsTo方法最好是在模型的 Bone矩阵已经被更新是被调用。
代码
       CoarseCheckFinerCheck两个方法在早期都会被列出来。下面的 Draw方法定义两个世界矩阵到两个模型的位置在不同的地方。随着时间的过去,一个模型接近另一个模型。在它们之间检测出一个碰撞,背景闪烁红色:
 1  protected   override   void  Draw(GameTime gameTime)
 2  {
 3               // define World matrices
 4               float  time  =  ( float )gameTime.TotalGameTime.TotalMilliseconds  /   1000.0f ;
 5              Matrix worldM1  =  Matrix.CreateScale( 0.01f *  Matrix.CreateRotationY(MathHelper.PiOver2)  *  Matrix.CreateTranslation( - 10 0 0 );
 6              Matrix worldM2  =  Matrix.CreateScale( 0.01f *  Matrix.CreateRotationY( - MathHelper.PiOver2)  *  Matrix.CreateTranslation( 10 3 0 );
 7              worldM2  =  worldM2  *  Matrix.CreateTranslation( - time  *   3.0f 0 0 );
 8               // check for collision
 9               if  (FinerCheck(myModel, worldM1, myModel, worldM2))
10              {
11                  Window.Title  =   " Collision!! " ;
12                  device.Clear(ClearOptions.Target  |  ClearOptions.DepthBuffer, Color.Red,  1 0 );
13              }
14               else
15              {
16                  Window.Title  =   " No collision  " ;
17                  device.Clear(ClearOptions.Target  |  ClearOptions.DepthBuffer, Color.CornflowerBlue,  1 0 );
18              }
19               // render scene
20              cCross.Draw(fpsCam.ViewMatrix, fpsCam.ProjectionMatrix);
21              DrawModel(myModel, worldM1, modelTransforms);
22              DrawModel(myModel, worldM2, modelTransforms);
23               base .Draw(gameTime);
24  }

转载于:https://www.cnblogs.com/315358525/archive/2009/07/31/1536119.html

相关文章:

  • 轻松实现二级无刷新联动菜单
  • 全新研发的Web OS操作 Palm智能机Pre不足3000
  • 一步一步自制网线
  • PowerDesigner 学习 收集整理
  • 2009年8月小记(DES加密模式, vim, DOS隐藏与排序,tinyget压力测试,线程等待)
  • .net MySql
  • 关于 VB.NET 中 Obsolete 特性的问题
  • pjsip pjsua test
  • l转 Js 获取屏幕坐标值
  • HTML中id属性使用的几种情况
  • [转载]sns是seo发展之路?
  • (zt)基于Facebook和Flash平台的应用架构解析
  • 关于CSS兼容性的问题
  • 支持掘金,支持甜瓜安东尼.
  • 月亮湾赏月
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • AHK 中 = 和 == 等比较运算符的用法
  • hadoop集群管理系统搭建规划说明
  • PAT A1017 优先队列
  • Swoft 源码剖析 - 代码自动更新机制
  • webgl (原生)基础入门指南【一】
  • 看图轻松理解数据结构与算法系列(基于数组的栈)
  • 前端之React实战:创建跨平台的项目架构
  • 事件委托的小应用
  • 数据结构java版之冒泡排序及优化
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 《TCP IP 详解卷1:协议》阅读笔记 - 第六章
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • #我与Java虚拟机的故事#连载18:JAVA成长之路
  • (06)金属布线——为半导体注入生命的连接
  • (4)Elastix图像配准:3D图像
  • (Redis使用系列) Springboot 实现Redis消息的订阅与分布 四
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .NET CF命令行调试器MDbg入门(一)
  • .NET Micro Framework初体验(二)
  • .net redis定时_一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
  • .net Stream篇(六)
  • .Net高阶异常处理第二篇~~ dump进阶之MiniDumpWriter
  • .Net转前端开发-启航篇,如何定制博客园主题
  • ??myeclipse+tomcat
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • @RequestMapping-占位符映射
  • @德人合科技——天锐绿盾 | 图纸加密软件有哪些功能呢?
  • [2016.7.test1] T2 偷天换日 [codevs 1163 访问艺术馆(类似)]
  • [BT]BUUCTF刷题第8天(3.26)
  • [Docker]三.Docker 部署nginx,以及映射端口,挂载数据卷
  • [Everyday Mathematics]20150130
  • [Invalid postback or callback argument]昨晚调试程序时出现的问题,MARK一下
  • [ios] IOS文件操作的两种方式:NSFileManager操作和流操作【转】
  • [Kubernetes]8. K8s使用Helm部署mysql集群(主从数据库集群)