Files
test/Assets/PerfectWorld/Scripts/Managers/HalfSpace.cs
Tungdv 001a16cf32 fix: update namespace.
feat: add new logic EC_World.
2025-10-14 18:34:16 +07:00

167 lines
5.4 KiB
C#

using CSNetwork.GPDataType;
using System;
using UnityEngine;
using UnityEngine.UIElements;
namespace BrewMonster.Scripts
{
public class CHalfSpace
{
public static float DistThresh; //空间一顶点到halfspace平面的距离阈值,作为判断是在半空间内部、外部,or 边界上
//该阈值属于整个类而不是某一个对象,因此定义为静态成员
//根据三个顶点构造平面及半空间区域
//Attributes
public const float HS_DEFAULT_DISTTHRESH = 0.000001f; //距离差的阈值,作为判断是在半空间内部or边界上
protected A3DVECTOR3 m_vNormal;
protected float m_d;
public void Set(A3DVECTOR3 v1, A3DVECTOR3 v2)
{
m_vNormal = A3DVECTOR3.CrossProduct(v2 - v1, new A3DVECTOR3(0.0f, 0.0f, 1.0f));
m_vNormal.Normalize();
m_d = A3DVECTOR3.DotProduct(v1, m_vNormal);
}
public void Set(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 v3)
{
m_vNormal = A3DVECTOR3.CrossProduct(v2 - v1, v3 - v1);
m_vNormal.Normalize();
m_d = A3DVECTOR3.DotProduct(v1, m_vNormal);
}
//直接设置法向
public void SetNormal(A3DVECTOR3 n) { m_vNormal = n; m_vNormal.Normalize(); }
public float GetDist() { return m_d; }
//直接设置距离d
public void SetD(float d) { m_d = d; }
public CHalfSpace(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 v3)
{
Set(v1, v2, v3);
}
//根据两个顶点构造平行于Z轴的平面及半空间区域
public CHalfSpace(A3DVECTOR3 v1, A3DVECTOR3 v2)
{
Set(v1, v2);
}
public CHalfSpace()
{
}
public CHalfSpace(CHalfSpace hs)
{
m_vNormal = hs.m_vNormal;
m_d = hs.m_d;
}
// 对决定Halfspace的平面进行变换!变换矩阵为mtxTrans
public virtual void Transform(A3DMATRIX4 mtxTrans)
{
//从mtxTrans分解出Scale,Rotate,Translate分量
A3DVECTOR3 vTranslate = mtxTrans.GetRow(3);
float fScale = mtxTrans.GetCol(0).Magnitude();
// 与mtxTrans一样,仍定义为右乘矩阵
A3DMATRIX3 mtx3Rotate = new A3DMATRIX3();
mtx3Rotate.m = new float[3 * 3];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
mtx3Rotate.m[(i * 3) + j] = mtxTrans.m[(i * 4) + j] / fScale;
//对于平面方程N.X=D的变换(s,R,t)如下:
// N'=NR
SetNormal(m_vNormal * mtx3Rotate);
//D'=s*D+N'.t
SetD(fScale * m_d + A3DVECTOR3.DotProduct(m_vNormal, vTranslate));
}
public void Translate(float Delta) { m_d += Delta; } //沿法线方向作一个平移
public void Inverse() { m_d = -m_d; m_vNormal = -m_vNormal; } //翻转半空间的正反方向
//点v到半空间定义平面的距离,此距离带符号!
public float DistV2Plane(A3DVECTOR3 v)
{
float d = A3DVECTOR3.DotProduct(v, m_vNormal);
return (d - m_d);
}
//与线段求交
public int IntersectLineSeg(A3DVECTOR3 v1, A3DVECTOR3 v2, A3DVECTOR3 vIntersection)
{
vIntersection = new A3DVECTOR3(0.0f, 0.0f, 0.0f);
//先处理在平面上的情况
bool v1InPlane = OnPlane(v1);
bool v2InPlane = OnPlane(v2);
if (v1InPlane && v2InPlane) return 3;
if (v1InPlane) return 1;
if (v2InPlane) return 2;
if (Outside(v1) ^ Outside(v2))
{
//两顶点分别在两侧,计算交点
A3DVECTOR3 vd = v2 - v1;
float t = m_d - A3DVECTOR3.DotProduct(m_vNormal, v1);
t /= A3DVECTOR3.DotProduct(m_vNormal, vd);
//assert(t < 1.0f && t > 0.0f);
vIntersection = v1 + t * vd;
return 4;
}
else
return 0;
}
////////////////////////////////////////////////////////////
// 判断一个三维点是否处于半空间内部,或者说处于平面的一侧
// 注意halfspace的OutSide,Inside定义方式
// /\
// /||\
// ||
// || normal (Outside)
//------------------------------------------Plane
// (Inside)
//
public bool Inside(A3DVECTOR3 v)
{
float d = A3DVECTOR3.DotProduct(v, m_vNormal);
bool bInside = (m_d - d > DistThresh);
return (bInside);
}
public bool Outside(A3DVECTOR3 v)
{
float d = A3DVECTOR3.DotProduct(v, m_vNormal);
bool bOutside = (d - m_d > DistThresh);
return (bOutside);
}
public bool OnPlane(A3DVECTOR3 v)
{
float d = A3DVECTOR3.DotProduct(v, m_vNormal);
bool bOnPlane = (Math.Abs(m_d - d) <= DistThresh);
return bOnPlane;
}
//set && get operations
public static void SetDistThresh(float DThresh = HS_DEFAULT_DISTTHRESH) //并设定一个缺省值
{
DistThresh = DThresh;
}
public A3DVECTOR3 GetNormal() { return m_vNormal; }
//点法式
public void SetNV(A3DVECTOR3 n, A3DVECTOR3 v)
{
m_vNormal = n;
m_vNormal.Normalize();
m_d = A3DVECTOR3.DotProduct(m_vNormal, v);
}
}
}