(已更替)游戏数学: 计算射线与平面的交点(上帝视角)

发现自己想复杂了,有更简单的实现:
https://blog.csdn.net/ithot/article/details/125135656

游戏数学: 计算射线与平面的交点(上帝视角)

在这里插入图片描述

应用场景

上帝视角,点击屏幕,需要计算此时点中的平面上的位置,比如将物体移到点击的位置上,或者需要拖拽物体移动

数学计算

在这里,实际上是有几个前提的计算,或者说是简化版的射线与平面的交点
因为是上帝视角,所以射线的起点的y轴坐标一定为正,与y轴的夹角一定为锐角,且我们使用xy轴组成的平面作为交点计算的平面
在这里插入图片描述
我们假设射线起点为A点(ax, ay, az),与xy轴平面相交点为B点(bx, 0, bz),A点在xy轴平面的投影点为C点(ax, 0, az),我们的目标是要求解出B点的位置,A点位置已知,因此C点位置也是已知,我们可以以C点为原点重新建立坐标系,只需求解出向量CB,就可以求解出B点,射线方向已知,我们可以通过三角函数求出AB段的长度,由此求出AB向量,将其y轴置为0即可求得CB向量

或者假设原点为O
则有OB + BC = OC
则OB = OC - BC = OC + CB

故有求解公式如下:
AC长度 = ay
AB长度 = ay / cos(射线方向 与 AC向量的夹角)
AB向量 = 射线方向 * AB长度 = (abx, aby, abz)
CB向量 = (abx, 0, abz)
C点 = (ax, 0, az)
B点 = (ax + abx, 0, az + abz)

在Unity中的示例

我们在Unity中完成这一计算的验证


using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class InteractiveTest : UIBehaviour, IPointerClickHandler
{
    
    
    public Camera cam;
    public GameObject ctrlObj;
    
    public void OnPointerClick(PointerEventData pointerEventData)
    {
    
    
        var ray = cam.ScreenPointToRay(pointerEventData.position);
        SetObjPos(ray.origin, ray.direction);
    }
    void SetObjPos(Vector3 origin, Vector3 direction)
    {
    
    
        float lengthAC = origin.y;  //因为我们的相机的位置一定在xy平面上方
        float cosABAC = -direction.y; //direction和(0, -1, 0)之间的夹角,即为AB和AC之间的夹角,一定是锐角
        float lengthAB = lengthAC / cosABAC;
        Vector3 AB = lengthAB * direction;
        Vector3 CB = new Vector3(AB.x, 0, AB.z);
        Vector3 C = new Vector3(origin.x, 0, origin.z);
        Vector3 B = new Vector3(C.x + CB.x, 0, C.z + CB.z);
        ctrlObj.transform.position = B;
    }
}

我们简单的使用一个平面,一个球来做示例
在这里插入图片描述
点击屏幕任意位置,我们可以看到球都能准确的移到点击的位置上
在这里插入图片描述
在这里插入图片描述

总结

虽然该计算需要有条件限制,但是对于这种射线和平面相交的应用场景,我们使用这种计算方式消耗会更小,当然Unity的屏幕点击点转换到世界的射线也是可以拿出来自己计算的,这样子消耗就可以更小了。

猜你喜欢

转载自blog.csdn.net/ithot/article/details/125036624
今日推荐