mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-06-26 19:34:47 +00:00
137 lines
4.6 KiB
C#
137 lines
4.6 KiB
C#
|
using System;
|
|||
|
// using JNGame.Collision2D;
|
|||
|
using JNGame.Math;
|
|||
|
// using Debug = JNGame.Logging.Debug;
|
|||
|
|
|||
|
namespace JNGame.PathFinding
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 导航三角形在二叉空间分割树中的引用
|
|||
|
/// <para>一个导航三角形可能会被树分割为多个三角形引用</para>
|
|||
|
/// </summary>
|
|||
|
public class TriangleRef
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// 当前三角形引用关联的导航三角形索引
|
|||
|
/// </summary>
|
|||
|
public int index;
|
|||
|
/// <summary>
|
|||
|
/// 三角形顶点A
|
|||
|
/// </summary>
|
|||
|
public LVector2 vertexA;
|
|||
|
/// <summary>
|
|||
|
/// 三角形顶点B
|
|||
|
/// </summary>
|
|||
|
public LVector2 vertexB;
|
|||
|
/// <summary>
|
|||
|
/// 三角形顶点C
|
|||
|
/// </summary>
|
|||
|
public LVector2 vertexC;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 是否是分割的三角形
|
|||
|
/// </summary>
|
|||
|
public bool IsSplit { get; private set; } = false;
|
|||
|
/// <summary>
|
|||
|
/// 三角形的边框
|
|||
|
/// </summary>
|
|||
|
public SplitLine[] borders;
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 根据下标获取三角形的顶点,合法下标0/1/2
|
|||
|
/// </summary>
|
|||
|
/// <param name="index"></param>
|
|||
|
/// <returns></returns>
|
|||
|
/// <exception cref="IndexOutOfRangeException"></exception>
|
|||
|
public LVector2 this[int index]
|
|||
|
{
|
|||
|
get
|
|||
|
{
|
|||
|
return index switch
|
|||
|
{
|
|||
|
0 => vertexA,
|
|||
|
1 => vertexB,
|
|||
|
2 => vertexC,
|
|||
|
_ => throw new IndexOutOfRangeException("vector idx invalid" + index),
|
|||
|
};
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 根据原始导航三角形创建引用
|
|||
|
/// <para>由此构造的三角形引用认为是未切割过的三角形</para>
|
|||
|
/// </summary>
|
|||
|
/// <param name="srcTriangle">原始的导航三角形</param>
|
|||
|
public TriangleRef(NavTriangle srcTriangle)
|
|||
|
: this(srcTriangle.vertexA.ToLVector2XZ(), srcTriangle.vertexB.ToLVector2XZ(), srcTriangle.vertexC.ToLVector2XZ(), srcTriangle.index)
|
|||
|
{ }
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 根据分割的三个顶点和原始导航三角形创建引用
|
|||
|
/// <para>由此构造的三角形引用认为是切割过的三角形</para>
|
|||
|
/// </summary>
|
|||
|
/// <param name="vertexA">三角形顶点A</param>
|
|||
|
/// <param name="vertexB">三角形顶点B</param>
|
|||
|
/// <param name="vertexC">三角形顶点C</param>
|
|||
|
/// <param name="srcTriangle">原始的导航三角形</param>
|
|||
|
public TriangleRef(in LVector2 vertexA, in LVector2 vertexB, in LVector2 vertexC, TriangleRef srcTriangle)
|
|||
|
: this(vertexA, vertexB, vertexC, srcTriangle.index)
|
|||
|
{
|
|||
|
IsSplit = true;
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 私有构造
|
|||
|
/// </summary>
|
|||
|
/// <param name="vertexA">三角形顶点A</param>
|
|||
|
/// <param name="vertexB">三角形顶点B</param>
|
|||
|
/// <param name="vertexC">三角形顶点C</param>
|
|||
|
/// <param name="idx">引用的导航三角形索引</param>
|
|||
|
private TriangleRef(in LVector2 vertexA, in LVector2 vertexB, in LVector2 vertexC, int idx)
|
|||
|
{
|
|||
|
this.vertexA = vertexA;
|
|||
|
this.vertexB = vertexB;
|
|||
|
this.vertexC = vertexC;
|
|||
|
index = idx;
|
|||
|
borders = new SplitLine[]
|
|||
|
{
|
|||
|
new SplitLine(vertexA, vertexB),
|
|||
|
new SplitLine(vertexB, vertexC),
|
|||
|
new SplitLine(vertexC, vertexA)
|
|||
|
};
|
|||
|
//check valid
|
|||
|
CheckValid();
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 三角形三点不可重合
|
|||
|
/// </summary>
|
|||
|
private void CheckValid()
|
|||
|
{
|
|||
|
for (int i = 0; i < 3; i++)
|
|||
|
{
|
|||
|
if (borders[i].Direction == LVector2.Zero)
|
|||
|
{
|
|||
|
// Debug.Assert(false);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// 判断点是否在此三角形内
|
|||
|
/// </summary>
|
|||
|
/// <param name="pos"></param>
|
|||
|
/// <returns></returns>
|
|||
|
public bool Contain(in LVector2 pos)
|
|||
|
{
|
|||
|
// ABC三个顶点绕序为顺时针,三个叉积都需要为负,则点在三角形内
|
|||
|
var isRightA = LVector2.Cross(vertexB - vertexA, pos - vertexA) > 0;
|
|||
|
if (isRightA) return false;
|
|||
|
var isRightB = LVector2.Cross(vertexC - vertexB, pos - vertexB) > 0;
|
|||
|
if (isRightB) return false;
|
|||
|
var isRightC = LVector2.Cross(vertexA - vertexC, pos - vertexC) > 0;
|
|||
|
if (isRightC) return false;
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|