zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    用rpm安装软件的常用步骤
    将应用发布到WasLiberty的两种方法
    安装 ibm-java-x86_64-sdk-6.0-9.3.x86_64.rpm 的三步骤
    人是科技的第一生产力。不重视人的价值,不尊重人的需求,不解放人的生产力,必将被互联网时代快速淘汰。
    Java保存简单偏好的类
    实用快捷键Win+L=锁屏
    判断一件事有无技术含量的标准
    主动去平事 别等事找人
    看了某些蛊惑人心的招聘广告,实在忍不住想要提醒那些跃跃欲奉献的后生们
    ubuntu16.04在英文状态下安装中文语言包的过程(法二:命令行的方式)
  • 原文地址:https://www.cnblogs.com/WhyEngine/p/3416650.html
Copyright © 2011-2022 走看看