射线与圆、球相交检测

射线与圆、球相交检测

本篇讨论2D中射线和圆的相交检测,本方法同样适用于3D中射线和球的相交检测,这是因为可以在包含射线和球心的平面中进行检测,从而将3D问题转化为2D问题。如果射线穿过球心,那么平面不是唯一的,但是不影响问题的解。

下面直接降阶为 2D讨论射线与圆的相交检测。
射线与圆的三种关系:相交、相切、相离
其中相切是相交的特殊情况
看下图,
在这里插入图片描述

如何判断射线与圆是否相交?
如果相交,如何计算交点坐标?

下图中是射线与圆相交的一般情形。交点为E,其实相交时交点是两个,行切时交点是一个,我们只讨论第一个,感兴趣的同学可以自行求解两个不同交点坐标
在这里插入图片描述上图中加了辅助线和字母标记,帮助我们清晰理解求解过程
Vector3 source 射线起点坐标
Vector3 rayDirection 射线方向
Vector3 sphereCenter 球中心点坐标
float sphereRadius 球半径

P 射线起点坐标
O 球心坐标
E 射线与球的交点
A 球心到射线画垂线的交点

e = PO长度:射线与球中心连线长度
a = PA长度:向量PO 到 射线方向rayDirection 上的投影长度 Dot(PO, rayDirection)
b = OA长度:球中心到射线的距离, e、a、b 构成一个直角三角形,e 为斜边,a、b为直角边

如果射线与球相交才会有交点 E
t (小写字母T)= PE长度:射线源点到 射线与球的交点距离
f (小写字母F) = EA长度
PA = PE + EA

上边 PAO 三个点构成一个直角三角形,A为直角
上边 EAO 三个店构成一个直角三角形,A为直角

r 为圆半径

e x e = a x a + b x b
r x r = f x f + b x b
推导出
f x f = r x r - e x e + a x a
t = a - f
射线与球交点坐标为 source + rayDirection * t

逻辑代码如下

/// <summary>
/// 射线与球的相交检测
/// </summary>
///    
public class RaySphereCollision
{
    private float a;
    private float e;

    public bool IsCollision(Vector3 source, Vector3 rayDirection, Vector3 sphereCenter, float sphereRadius)
    {
        rayDirection.Normalize();
        Vector3 offset = sphereCenter - source;
        e = offset.magnitude;
        a = Dot(offset, rayDirection);
        return sphereRadius * sphereRadius - (e * e - a * a) >= 0;
    }

    public Vector3 CollisionPosition(Vector3 source, Vector3 rayDirection, Vector3 sphereCenter, float sphereRadius)
    {
        if (!IsCollision(source, rayDirection, sphereCenter, sphereRadius))
        {
            return Vector3.zero;
        }

        // 如果不相交 sphereRadius * sphereRadius - e * e + a * a < 0
        float f = (float)Math.Sqrt(sphereRadius * sphereRadius - e * e + a * a);
        float t = a - f;
        return source + rayDirection * t;
    }

    public float Dot(Vector3 vector1, Vector3 vector2)
    {
        return vector1.x * vector2.x + vector1.y * vector2.y + vector1.z * vector2.z;
    }
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值