您的位置:首页 > 编程语言

游戏编程精粹学习 - 线段与非无限平面相交检测

2017-09-02 20:12 323 查看
参考自《游戏编程精粹1》多边形相交部分,用该方法除了知道是否相交以外还可以得到相交点,从而用于其他判断。



原文用到了平面方程Ax+By+Cz+D=0,通过三角形求出平面,然后用方程求出线段交点

这里直接使用平面,然后再拿相交点和平面所占区域进行判断,以下为Unity中的实现代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Practice : MonoBehaviour
{
public Transform p0;
public Transform p1;
public Transform planeLocation;
public float size = 5f;

void OnDrawGizmos()
{
if (p0 == null) return;
if (p1 == null) return;
if (planeLocation == null) return;

var cacheColor = Gizmos.color;

var r = GetIntersectPoint(planeLocation.forward, planeLocation.position, p0.position, p1.position);

if (r != null)
{
var matrix = Matrix4x4.TRS(planeLocation.position, Quaternion.FromToRotation(planeLocation.forward, Vector3.forward), planeLocation.localScale);
var temp = matrix.inverse.MultiplyPoint(r.Value);
var sizeHalf = size * 0.5f;

if (temp.x <= sizeHalf
&& temp.x >= -sizeHalf
&& temp.y <= sizeHalf
&& temp.y >= -sizeHalf)
{
Gizmos.color = Color.red;
}

Gizmos.DrawWireSphere(r.Value, 0.1f);
}

var cacheMatrix = Gizmos.matrix;
Gizmos.matrix = Matrix4x4.TRS(planeLocation.position, planeLocation.rotation, Vector3.one);
Gizmos.DrawWireCube(Vector3.zero, new Vector3(size, size, 0f));
Gizmos.matrix = cacheMatrix;
Gizmos.color = cacheColor;
}

/// <summary>
/// 检测相交点的原始函数,没有相交点返回空,否则返回相交点。
/// </summary>
/// <param name="planeNormal">平面的法线朝向</param>
/// <param name="planePosition">平面的位置</param>
/// <param name="p0">线段点0</param>
/// <param name="p1">线段点1</param>
Vector3? GetIntersectPoint(Vector3 planeNormal, Vector3 planePosition, Vector3 p0, Vector3 p1)
{
var sign1 = Mathf.Sign(Vector3.Dot(planeNormal, (planePosition - p0).normalized));
var sign2 = Mathf.Sign(Vector3.Dot(planeNormal, (planePosition - p1).normalized));
if (Mathf.Approximately(sign1, sign2)) return null;//同侧异侧.

var a = planeNormal.x;
var b = planeNormal.y;
var c = planeNormal.z;
var d = -a * planePosition.x - b * planePosition.y - c * planePosition.z;

var i0 = a * p0.x + b * p0.y + c * p0.z;
var i1 = a * p1.x + b * p1.y + c * p1.z;
var final_t = -(i1 + d) / (i0 - i1);

var finalPoint = new Vector3()
{
x = p0.x * final_t + p1.x * (1 - final_t),
y = p0.y * final_t + p1.y * (1 - final_t),
z = p0.z * final_t + p1.z * (1 - final_t),
};

return finalPoint;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: