胶囊体与球相交检测

该博客详细介绍了胶囊体与球体相交检测的数学定义和判断逻辑,并提供了C#代码实现。通过点到线段距离的计算,判断球心到胶囊体两端线段的距离是否小于等于两半径之和,从而确定是否相交。代码中包括了三种位置关系的处理,确保了所有可能情况的覆盖。
摘要由CSDN通过智能技术生成

胶囊体是由中间一个长度为 d,半径为 r 的圆柱体和两端两个半径为 r 的半球连接在一起的3D模型,下图

胶囊体的数学定义:到一条线段(上图圆柱体中心的红线)距离 小于等于 r 的所有点的集合。

球的数学定义:到一个点距离小于等于 r 的所有点的集合。

胶囊体与球的相交检测可以转换为点到线段的距离判断。

胶囊体半径为 r1,长度为 d,圆柱体两端中心点坐标(上图红线段两端点)分别为 A、B

球半径为 r2,球心坐标为 P

则如果点 P 到线段 AB 的距离 小于等于 r1 + r2,则球与胶囊体相交。

连接向量 AB,向量 AP,会有如下三种位置关系

第一种:

t = AP * AB = -|AC| <= 0

P不在线段 AB 范围内,且P在A左侧,P到线段最短距离为 向量 AP的长度 length = |AP|

第二种:

t = AP * AB = |AD| * |AB| <= |AB| * |AB|

P在线段AB范围内,P点到线段最短距离为 PD 的长度 length = |PD|

第三种:

t = AP * AB = |AE| * |AB| > |AB| * |AB|

P不在线段AB范围内,且P在B右侧,P到线段最短距离为 向量 BP的长度 length = |BP|

代码逻辑如下

public class CapsuleSphereIntersect
{
    /// <summary>
    /// 球与胶囊器相交检测
    /// </summary>
    /// <param name="sphereCenter">球心坐标</param>
    /// <param name="sphereRadius">球半径</param>
    /// <param name="capusleStart">胶囊体圆柱体一端中心坐标</param>
    /// <param name="capusleEnd">胶囊体圆柱体另一端中心坐标</param>
    /// <param name="capusleRadius">胶囊体半径</param>
    /// <returns></returns>
    public bool IsIntersect(Vector3 sphereCenter, float sphereRadius, Vector3 capusleStart, Vector3 capusleEnd, float capusleRadius)
    {
        float radiusSquare = (sphereRadius + capusleRadius) * (sphereRadius + capusleRadius);
        float lengthSquare = PointToLineSquare(sphereCenter, capusleStart, capusleEnd);
        return radiusSquare >= lengthSquare;
    }

    /// <summary>
    /// 点到线段的距离
    /// </summary>
    /// <param name="point">点坐标</param>
    /// <param name="lineStart">线段起点坐标</param>
    /// <param name="lineEnd">线段终点坐标</param>
    /// <returns></returns>
    public float PointToLine(Vector3 point, Vector3 lineStart, Vector3 lineEnd)
    {
        float square = PointToLineSquare(point, lineStart, lineEnd);
        return (float)Math.Sqrt(square);
    }

    /// <summary>
    /// 点到线段的距离平方
    /// </summary>
    /// <param name="point">点坐标</param>
    /// <param name="lineStart">线段起点坐标</param>
    /// <param name="lineEnd">线段终点坐标</param>
    /// <returns></returns>
    public float PointToLineSquare(Vector3 point, Vector3 lineStart, Vector3 lineEnd)
    {
        Vector3 SP = point - lineStart;
        Vector3 SE = lineEnd - lineStart;

        float dot = Vector3.Dot(SP, SE);
        if (dot <= 0)
        {
            return Vector3.Dot(SP, SP);
        }
        else if (dot < Vector3.Dot(SE, SE))
        {
            return Vector3.Dot(SP, SP) - dot * dot / (Vector3.Dot(SE, SE));
        }
        else
        {
            Vector3 EP = point - lineEnd;
            return Vector3.Dot(EP, EP);
        }
    }
}

测试效果,变红说明相交

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值