随笔 - 373  文章 - 1  评论 - 771  阅读 - 137万

3D有向包围盒与球体碰撞的算法

之前发的小游戏滚蛋躲方块中,用它来判断球体与立方体是否发生了碰撞.

http://www.cnblogs.com/WhyEngine/p/3350012.html

现在发布下该算法:

有向包围盒OBB,是有旋转变化的包围盒,由三种数据组成:

obbCenter表示包围盒的中心位置

obbAxes[3]表示包围盒XYZ三个坐标轴方向上的朝向,应该是正交的,否则意思着立方体有扭曲变形.并且应该是单位向量.

halfExtents表示包围盒三个方向上的长度.

该算法是多年前,已经不记得从什么地方找的了,自己又做了点修改.该代码其实可以更加简化一些,因为原代码中是可以计算球与包围盒的碰撞深度与碰撞的法线方向的.而这里只需要返回TRUE或FALSE即可.

算法的原理比较容易理解:判断球心到包围盒三个坐标轴的投影距离是否小于该轴的长度加上球的半径.如果三个轴都符合,则表示有碰撞.

该算法的基础是判断空间中一点是否在包围盒内部.

 

复制代码
 1 bool ObbSphereCollisionDetect(const Vector3& obbCenter, 
 2                               const Vector3 obbAxes[3], 
 3                               const Vector3& halfExtents, 
 4                               const Vector3& sphereCenter, 
 5                               float sphereRadius)
 6 {
 7     Vector3 kDiff = sphereCenter - obbCenter;
 8 
 9     float fSide[3] = { 1.0f, 1.0f, 1.0f };
10     float fS[3]    = { 0.0f, 0.0f, 0.0f };
11     float fD       = 0.0f;
12 
13     if (D3DXVec3Dot(&kDiff, &obbAxes[0]) < 0.0f)
14     {
15         fS[0] = D3DXVec3Dot(&( sphereCenter - ( obbCenter - ( obbAxes[0] * halfExtents.x ) ) ), &obbAxes[0]);
16 
17         if (fS[0] <= -sphereRadius)
18             return false;
19 
20         else if (fS[0] < 0.0f)
21             fD += fS[0] * fS[0];
22 
23         fS[0] += sphereRadius;
24     }
25     else
26     {
27         fS[0] = D3DXVec3Dot(&( ( obbCenter + ( obbAxes[0] * halfExtents.x ) ) - sphereCenter ), &obbAxes[0]);
28 
29         if (fS[0] <= -sphereRadius)
30             return false;
31 
32         else if (fS[0] < 0.0f)
33             fD += fS[0] * fS[0];
34 
35         fS[0] += sphereRadius;
36         fSide[0] = -1.0f;
37     }
38 
39     if (D3DXVec3Dot(&kDiff, &obbAxes[1]) < 0.0f)
40     {
41         fS[1] = D3DXVec3Dot(&( sphereCenter - ( obbCenter - ( obbAxes[1] * halfExtents.y ) ) ), &obbAxes[1]);
42 
43         if (fS[1] <= -sphereRadius)
44             return false;
45 
46         else if (fS[1] < 0.0f)
47             fD += fS[1] * fS[1];
48 
49         fS[1] += sphereRadius;
50     }
51     else
52     {
53         fS[1] = D3DXVec3Dot(&( ( obbCenter + ( obbAxes[1] * halfExtents.y ) ) - sphereCenter ), &obbAxes[1]);
54 
55         if (fS[1] <= -sphereRadius)
56             return false;
57 
58         else if (fS[1] < 0.0f)
59             fD += fS[1] * fS[1];
60 
61         fS[1] += sphereRadius;
62         fSide[1] = -1.0f;
63     }
64 
65     if (D3DXVec3Dot(&kDiff, &obbAxes[2]) < 0.0f)
66     {
67         fS[2] = D3DXVec3Dot(&( sphereCenter - ( obbCenter - ( obbAxes[2] * halfExtents.z ) ) ), &obbAxes[2]);
68 
69         if (fS[2] <= -sphereRadius)
70             return false;
71 
72         else if (fS[2] < 0.0f)
73             fD += fS[2] * fS[2];
74 
75         fS[2] += sphereRadius;
76     }
77     else
78     {
79         fS[2] = D3DXVec3Dot(&( ( obbCenter + ( obbAxes[2] * halfExtents.z ) ) - sphereCenter ), &obbAxes[2]);
80 
81         if (fS[2] <= -sphereRadius)
82             return false;
83 
84         else if (fS[2] < 0.0f)
85             fD += fS[2] * fS[2];
86 
87         fS[2] += sphereRadius;
88         fSide[2] = -1.0f;
89     }
90 
91     return (fD <= ( sphereRadius * sphereRadius ));
92 }
复制代码

 

 

posted on   叶飞影  阅读(2192)  评论(1编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示