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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?