天气与日历 切换到窄版

 找回密码
 立即注册
中国膜结构网
十大进口膜材评选 十大国产膜材评选 十大膜结构设计评选 十大膜结构公司评选
查看: 60|回复: 0

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

[复制链接]

该用户从未签到

主题

0

回帖

2912

积分

管理员

积分
2912
发表于 2024-6-22 09:46:18 | 显示全部楼层 |阅读模式
现在发布下该算法:

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

obbCenter表示包围盒的中心位置

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

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

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

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

该算法的基础是判断空间中一点是否在包围盒内部.
[code]bool ObbSphereCollisionDetect(const Vector3& obbCenter,
                              const Vector3 obbAxes[3],
                              const Vector3& halfExtents,
                              const Vector3& sphereCenter,
                              float sphereRadius)
{
    Vector3 kDiff = sphereCenter - obbCenter;

    float fSide[3] = { 1.0f, 1.0f, 1.0f };
    float fS[3]    = { 0.0f, 0.0f, 0.0f };
    float fD       = 0.0f;

    if (D3DXVec3Dot(&kDiff, &obbAxes[0]) < 0.0f)
    {
        fS[0] = D3DXVec3Dot(&( sphereCenter - ( obbCenter - ( obbAxes[0] * halfExtents.x ) ) ), &obbAxes[0]);

        if (fS[0] <= -sphereRadius)
            return false;

        else if (fS[0] < 0.0f)
            fD += fS[0] * fS[0];

        fS[0] += sphereRadius;
    }
    else
    {
        fS[0] = D3DXVec3Dot(&( ( obbCenter + ( obbAxes[0] * halfExtents.x ) ) - sphereCenter ), &obbAxes[0]);

        if (fS[0] <= -sphereRadius)
            return false;

        else if (fS[0] < 0.0f)
            fD += fS[0] * fS[0];

        fS[0] += sphereRadius;
        fSide[0] = -1.0f;
    }

    if (D3DXVec3Dot(&kDiff, &obbAxes[1]) < 0.0f)
    {
        fS[1] = D3DXVec3Dot(&( sphereCenter - ( obbCenter - ( obbAxes[1] * halfExtents.y ) ) ), &obbAxes[1]);

        if (fS[1] <= -sphereRadius)
            return false;

        else if (fS[1] < 0.0f)
            fD += fS[1] * fS[1];

        fS[1] += sphereRadius;
    }
    else
    {
        fS[1] = D3DXVec3Dot(&( ( obbCenter + ( obbAxes[1] * halfExtents.y ) ) - sphereCenter ), &obbAxes[1]);

        if (fS[1] <= -sphereRadius)
            return false;

        else if (fS[1] < 0.0f)
            fD += fS[1] * fS[1];

        fS[1] += sphereRadius;
        fSide[1] = -1.0f;
    }

    if (D3DXVec3Dot(&kDiff, &obbAxes[2]) < 0.0f)
    {
        fS[2] = D3DXVec3Dot(&( sphereCenter - ( obbCenter - ( obbAxes[2] * halfExtents.z ) ) ), &obbAxes[2]);

        if (fS[2] <= -sphereRadius)
            return false;

        else if (fS[2] < 0.0f)
            fD += fS[2] * fS[2];

        fS[2] += sphereRadius;
    }
    else
    {
        fS[2] = D3DXVec3Dot(&( ( obbCenter + ( obbAxes[2] * halfExtents.z ) ) - sphereCenter ), &obbAxes[2]);

        if (fS[2] <= -sphereRadius)
            return false;

        else if (fS[2] < 0.0f)
            fD += fS[2] * fS[2];

        fS[2] += sphereRadius;
        fSide[2] = -1.0f;
    }

    return (fD <= ( sphereRadius * sphereRadius ));
}[/code]

 

 

 

 

3D有向包围盒与球体碰撞的算法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|中国膜结构网|中国膜结构协会|进口膜材|国产膜材|ETFE|PVDF|PTFE|设计|施工|安装|车棚|看台|污水池|中国膜结构网_中国空间膜结构协会

GMT+8, 2024-11-1 10:21 , Processed in 0.147761 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表