3D 碰撞检测- 游戏开发环境

文章推薦指數: 80 %
投票人數:10人

Axis-aligned bounding boxes(AABB 包围盒) ... 在游戏中,为了简化物体之间的碰撞检测运算,通常会对物体创建一个规则的几何外形将其包围。

其中,AABB( ... SkiptomaincontentSkiptosearchSkiptoselectlanguage游戏开发环境Techniquesforgamedevelopment3D碰撞检测ArticleActions中文(简体)此页面由社区从英文翻译而来。

了解更多并加入MDNWebDocs社区。

Axis-alignedboundingboxes(AABB包围盒)球体碰撞使用一个物理引擎SeealsoRelatedTopics Introduction Introduction Anatomy Examples APIsforgamedevelopment Canvas CSS Fullscreen Gamepad IndexedDB JavaScript PointerLock SVG TypedArrays WebAudio WebGL WebRTC WebSockets WebVR WebWorkers XMLHttpRequest Techniques Usingasyncscriptsforasm.js Optimizingstartupperformance UsingWebRTCpeer-to-peerdatachannels Efficientanimationforwebgames AudioforWebGames 2Dcollisiondetection Tilesandtilemapsoverview 3DgamesontheWeb 3DgamesontheWeboverview Explainingbasic3Dtheory BuildingupabasicdemowithA-Frame BuildingupabasicdemowithBabylon.js BuildingupabasicdemowithPlayCanvas BuildingupabasicdemowithThree.js WebVR 3Dcollisiondetection BoundingvolumecollisiondetectionwithTHREE.js Implementinggamecontrolmechanisms Controlmechanisms Mobiletouch Desktopwithmouseandkeyboard Desktopwithgamepad Other Tutorials 2DbreakoutgameusingpureJavaScript 2DbreakoutgameusingPhaser 2Dmaze_gamewithdeviceorientation 2DplatformgameusingPhaser Publishinggames Publishinggamesoverview Gamedistribution Gamepromotion Gamemonetization Axis-alignedboundingboxes(AABB包围盒)球体碰撞使用一个物理引擎Seealso3D碰撞检测本文介绍了用于在3D环境中实现不同边界体积碰撞检测的技术。

 后续文章将讨论特定3D库中的实现。

Axis-alignedboundingboxes(AABB包围盒)  在游戏中,为了简化物体之间的碰撞检测运算,通常会对物体创建一个规则的几何外形将其包围。

其中,AABB(axis-aligned bounding box)包围盒被称为轴对齐包围盒。

与2D碰撞检测一样,轴对齐包围盒是判断两个物体是否重叠的最快算法,物体被包裹在一个非旋转的(因此轴对齐的)盒中,并检查这些盒在三维坐标空间中的位置,以确定它们是否重叠。

由于性能原因,轴对齐是有一些约束的。

两个非旋转的盒子之间是否重叠可以通过逻辑比较进行检查,而旋转的盒子则需要三角运算,这会导致性能下降。

如果你有旋转的物体,可以通过修改边框的尺寸,这样盒子仍可以包裹物体,或者选择使用另一种边界几何类型,比如球体(球体旋转,形状不会变)。

下图是一个AABB物体旋转,动态调节盒大小适应物体的例子。

Note: 参考这里,使用Three.js进行边界体积碰撞检测。

点与 AABB如果检测到一个点是否在AABB内部就非常简单了 —我们只需要检查这个点的坐标是否在AABB内;分别考虑到每种坐标轴。

如果假设 Px,Py 和 Pz 是点的坐标, BminX–BmaxX,BminY–BmaxY,和 BminZ–BmaxZ 是AABB的每一个坐标轴的范围,我们可以使用以下公式计算两者之间的碰撞是否发生: f(P,B)=(Px>=BminX∧Px<=BmaxX)∧(Py>=BminY∧Py<=BmaxY)∧(Pz>=BminZ∧Pz<=BmaxZ)f(P,B)=(P_x>=B_{minX}\wedgeP_x<=B_{maxX})\wedge(P_y>=B_{minY}\wedgeP_y<=B_{maxY})\wedge(P_z>=B_{minZ}\wedgeP_z<=B_{maxZ}) 或者用JavaScript: functionisPointInsideAABB(point,box){ return(point.x>=box.minX&&point.x<=box.maxX)&& (point.y>=box.minY&&point.y<=box.maxY)&& (point.z>=box.minY&&point.z<=box.maxZ); }AABB与AABB检查一个AABB是否和另一个AABB相交类似于检测两个点一样。

我们只需要基于每一条坐标轴并利用盒子的边缘去检测。

下图显示了我们基于 X轴的检测 —当然, AminX–AmaxX 和 BminX–BmaxX 会不会重叠? 在数学上的表示就像这样: f(A,B)=(AminX<=BmaxX∧AmaxX>=BminX)∧(AminY<=BmaxY∧AmaxY>=BminY)∧(AminZ<=BmaxZ∧AmaxZ>=BminZ)f(A,B)= 在JavaScript我们可以这样: functionintersect(a,b){ return(a.minX<=b.maxX&&a.maxX>=b.minX)&& (a.minY<=b.maxY&&a.maxY>=b.minY)&& (a.minZ<=b.maxZ&&a.maxZ>=b.minZ); } 球体碰撞球体碰撞边缘检测比AABB盒子稍微复杂一点,但他的检测仍相当容易的。

球体的主要优势是他们不变的旋转,如果包装实体旋转,边界领域仍将是相同的。

他们的主要缺点是,除非他们包装的实体实际上是球形,包装的实体通常不是一个完美的球形(比如用这样的球形包装一个人将导致一些错误,而AABB盒子将更合适)。

点与球检查是否一个球体包含一个点,我们需要计算点和球体的中心之间的距离。

如果这个距离小于或等于球的半径,这个点就在里面。

两个点A和B之间的欧氏距离是 (Ax-Bx)2)+(Ay-By)2+(Az-Bz)\sqrt{(A_x-B_x)^2)+(A_y-B_y)^2+(A_z-B_z)},我们的公式指出,球体碰撞检测是: f(P,S)=Sradius>=(Px-Sx)2+(Py-Sy)2+(Pz-Sz)2f(P,S)=S_{radius}>=\sqrt{(P_x-S_x)^2+(P_y-S_y)^2+(P_z-S_z)^2} 或者用JavaScript: functionisPointInsideSphere(point,sphere){ //weareusingmultiplicationsbecauseisfasterthancallingMath.pow vardistance=Math.sqrt((point.x-sphere.x)*(point.x-sphere.x)+ (point.y-sphere.y)*(point.y-sphere.y)+ (point.z-sphere.z)*(point.z-sphere.z)); returndistance



請為這篇文章評分?