在进行游戏开发的时候,有时候会用到判断一个点是否在三角形内,那么其中的一种判定前提就是需判定该点和和三角形的几条向量之间的位置关系;这里的点的关系就是本节内容需要总结的一个知识点。
二维中的点我们可以考虑叉乘的做法来计算,计算结果有以下三种情况:
public static class Vector2Extend
{
///
/// 该扩展方法为静态类型 扩展二维向量的叉乘
///
/// 第一个参数使用this + 扩展类型 + 该类型对象
///
/// 返回叉乘结果
public static float Cross(this Vector2 vectorA, Vector2 vectorB)
{
return vectorA.x * vectorB.y - vectorB.x * vectorA.y;
}
}
从上面的效果演示中可以看出点B、点C和OA的关系上在不断变化的,通过这种方式可以直观的看出结果;
using UnityEditor;
using UnityEngine;
[ExecuteInEditMode]
public class Vector2Test : MonoBehaviour
{
[SerializeField] private Transform transformA;
[SerializeField] private Transform transformB;
[SerializeField] private Transform transformC;
private Vector3 positionO = Vector3.zero;
private Vector3 positionA = Vector3.zero;
private Vector3 positionB = Vector3.zero;
private Vector3 positionC = Vector3.zero;
Vector2 labelSize = new Vector2(40, 40);
Vector2 posA = Vector2.zero;
Vector2 posB = Vector2.zero;
Vector2 posC = Vector2.zero;
private void OnDrawGizmos()
{
posA.x = positionA.x = transformA.position.x;
posA.y = positionA.z = transformA.position.z;
posB.x = positionB.x = transformB.position.x;
posB.y = positionB.z = transformB.position.z;
posC.x = positionC.x = transformC.position.x;
posC.y = positionC.z = transformC.position.z;
//设置为边界线
Debug.DrawLine(positionO, positionA, Color.green);
Debug.DrawLine(positionO, positionB, Color.yellow);
Debug.DrawLine(positionO, positionC, Color.red);
DrawLabel(positionO, "O", Color.magenta, labelSize);
DrawLabel(positionA, "A", Color.green, labelSize);
DrawLabel(positionB, "B", Color.yellow, labelSize);
DrawLabel(positionC, "C", Color.red, labelSize);
//计算OA cross OB
float resultA = posA.Cross(posB); // positionA.x * positionB.z - positionB.x * positionA.z;
string axb = "OAxOB=" + resultA;
DrawLabel(new Vector3(-30, 0, 22), axb, Color.cyan, new Vector2(300, 40));
float resultB = posA.Cross(posC); // positionA.x * positionC.z - positionC.x * positionA.z;
string axc = "OAxOC=" + resultB;
DrawLabel(new Vector3(20, 0, 22), axc, Color.cyan, new Vector2(300, 40));
string descA = "B和A在同一条直线上";
if (resultA > 0 || resultA < 0)
{
descA = resultA > 0 ? "B点在A点的逆时针方向" : "B点在A点的顺时针方向";
}
string descB = "C和A在同一条直线上";
if (resultB > 0 || resultB < 0)
{
descB = resultB > 0 ? "C点在A点的逆时针方向" : "C点在A点的顺时针方向";
}
float result = resultA * resultB;
string desc = "ABC三点共线";
if (result > 0 || result < 0)
{
desc = result > 0 ? "BC在同一侧" : "BC点不在同一侧";
}
DrawLabel(new Vector3(-35, 0, 15), descA, Color.magenta, new Vector2(400, 40));
DrawLabel(new Vector3(25, 0, 15), descB, Color.magenta, new Vector2(400, 40));
DrawLabel(new Vector3(-5, 0, -15), desc, Color.yellow, new Vector2(400, 40));
}
void DrawLabel(Vector3 pos, string text, Color color, Vector2 size)
{
Vector2 pos2D = HandleUtility.WorldToGUIPoint(pos);
Handles.BeginGUI();
GUI.skin.label.fontSize = 35;
GUI.skin.label.normal.textColor = color;
GUI.Label(new Rect(pos2D.x - 15, pos2D.y - 15, size.x, size.y), text);
HandleUtility.Repaint();
Handles.EndGUI();
}
}
结语:
别把工作带入生活【valaki】