射线与平面相交检测

射线与平面相交检测

3D 中射线与平面相交检测
本篇讨论的射线是无限长,平面无限大
下图展示的几种位置关系:相交、不相交
相交包括:只有一个交点 (射线3)、射线在平面内有无数交点 (射线4)
不相交:射线与平面平行 (射线1),射线与平面不平行也不相交 (射线2、射线5)

在这里插入图片描述

判断射线2和射线5和平面不相交,添加辅助线如下
在这里插入图片描述
在平面上任取一点C
射线2中:P1为射线起点,向量P1A 是射线的方向向量, 连接P1C
点乘:Dot(向量P1A,平面法向量 Normal) > 0
点乘:Dot(向量P1C,平面法向量 Normal < 0
两个点乘结果异号(一个大于0,一个小于0) 则判定射线2 与平面不相交

射线5中:P2为射线起点,向量 P2B 是射线的方向向量,连接P2C
点乘:Dot(向量P2B,平面法向量 Normal) < 0
点乘:Dot(向量P2C,平面法向量 Normal > 0
两个点乘结果异号(一个大于0,一个小于0) 则判定射线2 与平面不相交

判断射线1、射线4,添加辅助线如下图
在这里插入图片描述

在平面上任取一点C
射线1中:P1为射线起点,向量P1A 是射线的方向向量, 连接P1C
点乘:Dot(向量P1A,平面法向量 Normal) = 0 说明 P1A 垂直于平面法向量,则P1A平行于平面
点乘:Dot(向量P1C,平面法向量 Normal < 0 说明 P1C 至少一个端点不在平面上
两个点乘结果(一个等于0,一个小于0) 则判定射线2 与平面平行但不在平面内

射线4中:P2为射线起点,向量 P2B 是射线的方向向量,连接P2C
点乘:Dot(向量P2B,平面法向量 Normal) = 0 说明 P2B 垂直于平面法向量,则P2B平行于平面
点乘:Dot(向量P2C,平面法向量 Normal = 0 说明 P2C 垂直于平面法向量,则P2C平行于平面
则 P2BC 所组成的平面和原平面平行,C点又是原平面中的点,则P2BC和平面重合,则P2B在原平面内
结论射线4在平面内

射线3的相交检测,如果相交,求交点坐标。看下图辅助线以及标记
在这里插入图片描述
平面上任取一点C
PB 为从点P到平面做的垂线,h 为向量PB 在平面法向量 Normal 的投影长度
O为射线3与平面的交点,f 为向量PO的长度,
O点坐标 = P坐标 + 向量PO
向量PO = rayDirection * f
O点坐标 = P坐标 + rayDirection * f
我们通过点C来求解 f

在三角形 PBC 中
h = Dot(向量PC,平面法向量Normal)

在三角形 PBO 中
h = Dot(向量PO,平面法向量Normal)

h = Dot(rayDirection * f,平面法向量Normal), 其中 f 是标量,可以提取出来

h = f * Dot(rayDirection , 平面法向量 Normal)

f = h 除以 Dot(rayDirection, 平面法向量 Normal)

代码逻辑如下

/// <summary>
/// 射线与平面相交检测
/// </summary>
public class RayPlaneCollision
{

    float dot_rayDir_planeNormal;
    float dot_pc_planeNormal;

    /// <summary>
    /// 射线与平面相交检测
    /// </summary>
    /// <param name="source">射线起点坐标</param>
    /// <param name="rayDirection">射线方向</param>
    /// <param name="planePos">平面上任一点坐标</param>
    /// <param name="planeNormal">平面法向量</param>
    /// <returns></returns>
    public RayPlaneCollisionEnum IsCollision(Vector3 source, Vector3 rayDirection, Vector3 planePos, Vector3 planeNormal)
    {
        Vector3 PC = planePos - source;
        dot_rayDir_planeNormal = Dot(rayDirection, planeNormal);
        dot_pc_planeNormal = Dot(PC, planeNormal);

        // 射线平行于平面
        if (dot_rayDir_planeNormal == 0) 
        {
            if (dot_pc_planeNormal == 0)
            {
                // 射线和平面平行并且射线在平面内
                return RayPlaneCollisionEnum.IN_PLANE;
            }
            // 射线和平面平行但是射线不在平面内
            return RayPlaneCollisionEnum.SEPARATION;
        }

        if (dot_rayDir_planeNormal > 0 && dot_pc_planeNormal > 0)
        {
            return RayPlaneCollisionEnum.COLLISION;
        }

        if (dot_rayDir_planeNormal < 0 && dot_pc_planeNormal < 0)
        {
            return RayPlaneCollisionEnum.COLLISION;
        }

        return RayPlaneCollisionEnum.SEPARATION;
    }

    public Vector3 CollisionPosition(Vector3 source, Vector3 rayDirection, Vector3 planePos, Vector3 planeNormal)
    {
        if (IsCollision(source, rayDirection, planePos, planeNormal) != RayPlaneCollisionEnum.COLLISION)
        {
            return Vector3.zero;
        }
        float length = dot_pc_planeNormal / dot_rayDir_planeNormal;

        Debug.LogError(dot_pc_planeNormal + "   " + dot_rayDir_planeNormal);
        return source + rayDirection * length;
    }

    public float Dot(Vector3 vector1, Vector3 vector2)
    {
        return vector1.x * vector2.x + vector1.y * vector2.y + vector1.z * vector2.z;
    }
}

本篇开始说的限制条件 射线无限长、平面无限大,如果射线限制了长度 s,平面限制了区域(有N个顶点的多边形),对于不相交的判定没有影响

对于射线和平面相交的,如果射线限制长度,则 根据上边计算的长度 f 和 限制长度 s 比较,如果 s 小于 f,则射线长度不够,不相交
如果 s >= f,计算出 O 点坐标,然后判断 O点坐标是否在平面范围内

对于射线在平面内的思考下

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
破片射线与三角形面元相交算法中,存在一种直接判断的方法,即Möller–Trumbore算法(M-T算法)[1][2。M-T算法通过射线与三角形的相交检测来确定破片射线是否与三角形面元相交。这个算法利用了射线平面相交检测以及射线和三角形的相交检测。 具体来说,M-T算法使用了克莱姆法则和三矢量的混合积来判断射线和三角形的相交情况。通过计算射线与三角形的相交点,可以确定是否存在相交。该算法相比传统的求解方法更直接、更快速,并且适用于各种场景。 因此,使用Möller–Trumbore算法可以有效地判断破片射线与三角形面元是否相交。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [【收藏好文】一文读懂射线与三角形相交算法Moller-Trumbore算法](https://blog.csdn.net/oakchina/article/details/124385464)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [空间射线与三角形相交算法的两种实现](https://blog.csdn.net/charlee44/article/details/104348131)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值