fix: update logic check bush.

This commit is contained in:
Tungdv
2025-10-16 18:35:15 +07:00
parent de76d2dec0
commit 8ea53ac651
10 changed files with 579 additions and 92 deletions
+210 -73
View File
@@ -1,4 +1,6 @@
using BrewMonster.Scripts.World;
using BrewMonster.Scripts.Ornament;
using BrewMonster.Scripts.Player;
using BrewMonster.Scripts.World;
using CSNetwork.GPDataType;
using System;
using UnityEngine;
@@ -12,6 +14,7 @@ namespace BrewMonster.Scripts
public static LayerMask BrushMask { get; set; } = ~0;
public static LayerMask TerrainMask { get; set; } = ~0;
const float LOCAL_EPSILON = 1e-5f;
//[Flags]
public class CDR_EVN
{
@@ -63,20 +66,20 @@ namespace BrewMonster.Scripts
A3DVECTOR3 vWatNormal = new A3DVECTOR3();
bool bStart = false;
//@todo : TBD: use center or foot? By Kuiwu[10/10/2005]
if (CollideWithWater(pEnvTrc.vWatStart, pEnvTrc.vDelta, pEnvTrc.bWaterSolid, ref fFraction, ref vWatNormal, ref bStart)
&& fFraction < pEnvTrc.fFraction)
{
pEnvTrc.fFraction = fFraction;
pEnvTrc.vHitNormal = vWatNormal;
pEnvTrc.bStartSolid = bStart;
pEnvTrc.dwClsFlag = CDR_EVN.CDR_WATER;
//# ifdef CDR_DEBUG
// A3DVECTOR3 vHitPos(pEnvTrc.vWatStart +pEnvTrc.vDelta * fFraction);
// sprintf(msg, "collide water, fraction %f pos %f %f %f \n", fFraction, vHitPos.x, vHitPos.y, vHitPos.z);
// OUTPUT_DEBUG_INFO(msg);
//#endif
//if (CollideWithWater(pEnvTrc.vWatStart, pEnvTrc.vDelta, pEnvTrc.bWaterSolid, ref fFraction, ref vWatNormal, ref bStart)
// && fFraction < pEnvTrc.fFraction)
//{
// pEnvTrc.fFraction = fFraction;
// pEnvTrc.vHitNormal = vWatNormal;
// pEnvTrc.bStartSolid = bStart;
// pEnvTrc.dwClsFlag = CDR_EVN.CDR_WATER;
// //# ifdef CDR_DEBUG
// // A3DVECTOR3 vHitPos(pEnvTrc.vWatStart +pEnvTrc.vDelta * fFraction);
// // sprintf(msg, "collide water, fraction %f pos %f %f %f \n", fFraction, vHitPos.x, vHitPos.y, vHitPos.z);
// // OUTPUT_DEBUG_INFO(msg);
// //#endif
}
//}
}
return (pEnvTrc.fFraction < 1.0f + 1E-4f);
@@ -311,83 +314,217 @@ namespace BrewMonster.Scripts
if (vTPNormal != Vector3.zero) CDRInfo.vTPNormal = vTPNormal;
}
bool CollideWithTerrain(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, ref float fFraction, ref A3DVECTOR3 vHitNormal, ref bool bStart)
{
static bool SegmentTriangleIntersect(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, A3DVECTOR3[] vert, ref float fFraction, bool bCull)
{
float dist = 0f;
A3DVECTOR3 vDir = new A3DVECTOR3(vDelta);
dist = vDir.Normalize();
if (dist < 1E-5f)
{
//assert(0 && "too small dist!");
fFraction = 0.0f;
return true;
}
float t = 0f, u = 0f, v = 0f;
if (RayTriangleIntersect(vStart, vDir, vert, ref t, ref u, ref v, bCull) && (t >= 0.0f) && (t <= dist))
{
//fFraction = t/dist;
//fFraction = a_Max( 0.0f, fFraction -1E-4f); //put back
fFraction = (t - 5E-4f) / dist;
AAssist.a_ClampFloor(ref fFraction, 0.0f);
return true;
}
return false;
}
/*
* ray: origin + t* dir, triangle: p(u,v) = (1-u -v)vert[0] + u*vert[1] + v*vert[2]
* @desc :
* @param vDir: normalized direction
* @param bCull: cull back face if true
* @return :
* @note:
* @todo:
* @author: kuiwu [8/10/2005]
* @ref: Tomas Moller's JGT code
*/
static bool RayTriangleIntersect(A3DVECTOR3 vOrigin, A3DVECTOR3 vDir, A3DVECTOR3[] vert, ref float t, ref float u, ref float v, bool bCull)
{
// find vectors for two edges sharing vert0
A3DVECTOR3 edge1 = vert[1] - vert[0];
A3DVECTOR3 edge2 = vert[2] - vert[0];
// begin calculating determinant - also used to calculate U parameter
A3DVECTOR3 pvec = A3DVECTOR3.CrossProduct(vDir, edge2);
// if determinant is near zero, ray lies in plane of triangle
float det = A3DVECTOR3.DotProduct(edge1, pvec);
if (bCull)
{
if (det < LOCAL_EPSILON)
return false;
// From here, det is > 0.
// Calculate distance from vert0 to ray origin
A3DVECTOR3 tvec = vOrigin - vert[0];
// Calculate U parameter and test bounds
u = A3DVECTOR3.DotProduct(tvec, pvec);
if ((u < 0.0f) || (u > det))
return false;
// prepare to test V parameter
A3DVECTOR3 qvec = A3DVECTOR3.CrossProduct(tvec, edge1);
// calculate V parameter and test bounds
v = A3DVECTOR3.DotProduct(vDir, qvec);
if ((v < 0.0f) || (u + v > det))
return false;
// calculate t, ray intersects triangle
t = A3DVECTOR3.DotProduct(edge2, qvec);
// Det > 0 so we can early exit here
// Intersection point is valid if distance is positive
// (else it can just be a face behind the orig point)
if (t < 0.0f)
{
return false;
}
float OneOverDet = 1.0f / det;
t *= OneOverDet;
u *= OneOverDet;
v *= OneOverDet;
}
else
{
if (det > -LOCAL_EPSILON && det < LOCAL_EPSILON)
return false;
float OneOverDet = 1.0f / det;
// Calculate distance from vert0 to ray origin
A3DVECTOR3 tvec = vOrigin - vert[0];
// calculate U parameter and test bounds
u = A3DVECTOR3.DotProduct(tvec, pvec) * OneOverDet;
if ((u < 0.0f) || (u > 1.0f))
return false;
// prepare to test V parameter
A3DVECTOR3 qvec = A3DVECTOR3.CrossProduct(tvec, edge1);
// calculate V parameter and test bounds
v = A3DVECTOR3.DotProduct(vDir, qvec) * OneOverDet;
if ((v < 0.0f) || (u + v > 1.0f))
return false;
// calculate t, ray intersects triangle
t = A3DVECTOR3.DotProduct(edge2, qvec) * OneOverDet;
}
return true;
}
public static bool CollideWithTerrain(A3DVECTOR3 vStart, A3DVECTOR3 vDelta, ref float fFraction, ref A3DVECTOR3 vHitNormal, ref bool bStart)
{
CECWorld pWorld = CECWorld.Instance; //g_pGame.GetGameRun().GetWorld();
A3DTerrain2 pTerrain = pWorld.GetTerrain();
bStart = false;
float h1 = pTerrain.GetPosHeight(vStart, ref vHitNormal);
if (h1 > vStart.y + 1E-4f )
{//start under terrain
bStart = true;
fFraction = 0.0f;
return true;
}
float h1 = pTerrain.GetPosHeight(vStart, ref vHitNormal);
if (h1 > vStart.y + 1E-4f)
{//start under terrain
bStart = true;
fFraction = 0.0f;
return true;
}
int nWid, nHei; // in grid, 2 meters
int nWid, nHei; // in grid, 2 meters
float fMag = vDelta.Magnitude();
nWid = (int)Math.Ceiling(fMag / 2.0f);
nWid = Math.Max(3, nWid);
nHei = nWid;
int nTriangles = nWid * nHei * 2;
int nTriangles = nWid * nHei * 2;
A3DVECTOR3[] pVerts = new A3DVECTOR3[(nWid + 1) * (nHei + 1)];
//assert(pVerts != NULL);
//memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1));
WORD[] pIndices = new WORD[nTriangles * 3];
//assert(pIndices != NULL);
//memset(pIndices, 0, sizeof(WORD)* nTriangles * 3);
if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, pVerts, pIndices))
{
//a_freetemp(pVerts);
// a_freetemp(pIndices);
return false;
}
//assert(pVerts != NULL);
//memset(pVerts, 0, sizeof(A3DVECTOR3)* (nWid + 1) * (nHei + 1));
WORD[] pIndices = new WORD[nTriangles * 3];
//assert(pIndices != NULL);
//memset(pIndices, 0, sizeof(WORD)* nTriangles * 3);
if (!pTerrain.GetFacesOfArea(vStart, nWid, nHei, ref pVerts, ref pIndices))
{
//a_freetemp(pVerts);
// a_freetemp(pIndices);
return false;
}
int i;
A3DVECTOR3* vert[3];
//@note : Here init the fraction. By Kuiwu[9/10/2005]
fFraction = 100.0f;
float tmpFraction = fFraction;
A3DVECTOR3[] vert = new A3DVECTOR3[3];
//@note : Here init the fraction. By Kuiwu[9/10/2005]
fFraction = 100.0f;
float tmpFraction = fFraction;
for (i = 0; i < nTriangles; i++)
{
vert[0] = pVerts + pIndices[i * 3];
vert[1] = pVerts + pIndices[i * 3 + 1];
vert[2] = pVerts + pIndices[i * 3 + 2];
A3DVECTOR3 vPt;
for (i = 0; i < nTriangles; i++)
{
vert[0] = pVerts[pIndices[i * 3]];
vert[1] = pVerts[pIndices[i * 3 + 1]];
vert[2] = pVerts[pIndices[i * 3 + 2]];
//A3DVECTOR3 vPt;
//@note: Tomas Moller's JGT code : By Kuiwu[9/10/2005]
//@note: discard the engine version because it put back the hit point too much. By Kuiwu[13/10/2005]
// if(CLS_RayToTriangle(vStart, vDelta, *vert[0], *vert[1], *vert[2], vPt, true, &tmpFraction)
// && (tmpFraction <= 1.0f) && (tmpFraction < fFraction))
if (SegmentTriangleIntersect(vStart, vDelta, vert, tmpFraction, true) && (tmpFraction < fFraction))
{
//get the triangle normal
A3DVECTOR3 vEdge1((* vert[1]) -(*vert[0]) );
A3DVECTOR3 vEdge2((* vert[2]) -(*vert[0]) );
vHitNormal = CrossProduct(vEdge1, vEdge2);
vHitNormal.Normalize();
//@note: Tomas Moller's JGT code : By Kuiwu[9/10/2005]
//@note: discard the engine version because it put back the hit point too much. By Kuiwu[13/10/2005]
// if(CLS_RayToTriangle(vStart, vDelta, *vert[0], *vert[1], *vert[2], vPt, true, &tmpFraction)
// && (tmpFraction <= 1.0f) && (tmpFraction < fFraction))
if (SegmentTriangleIntersect(vStart, vDelta, vert, ref tmpFraction, true) && (tmpFraction < fFraction))
{
//get the triangle normal
A3DVECTOR3 vEdge1 = vert[1] - vert[0];
A3DVECTOR3 vEdge2 = vert[2] - vert[0];
vHitNormal = A3DVECTOR3.CrossProduct(vEdge1, vEdge2);
vHitNormal.Normalize();
//@note : may be redundant, but to assure. By Kuiwu[17/10/2005]
A3DVECTOR3 vDir;
Normalize(vDelta, vDir);
if (DotProduct(vHitNormal, vDir) > 0.01f)
{//leave the hit plane
assert(0 && "hit a plane with same direction!");
continue;
}
//@note : may be redundant, but to assure. By Kuiwu[17/10/2005]
A3DVECTOR3 vDir = new A3DVECTOR3();
A3DVECTOR3.Normalize(vDelta, out vDir);
if (A3DVECTOR3.DotProduct(vHitNormal, vDir) > 0.01f)
{//leave the hit plane
//assert(0 && "hit a plane with same direction!");
continue;
}
fFraction = a_Max(0.0f, tmpFraction);
}
}
a_freetemp(pVerts);
a_freetemp(pIndices);
fFraction = Math.Max(0.0f, tmpFraction);
}
return (fFraction <= 1.0f);
}
//a_freetemp(pVerts);
// a_freetemp(pIndices);
}
return (fFraction <= 1.0f);
}
public static bool AABBCollideWithBrush(ref BrushTraceInfo pInfo)
{
CECWorld pWorld = CECWorld.Instance; //g_pGame.GetGameRun().GetWorld();
CECOrnamentMan pOrnMan = pWorld.GetOrnamentMan();
bool bBrush = pOrnMan.TraceWithBrush(ref pInfo);
BrushTraceInfo info = pInfo;
CECMatterMan pMatterMan = pWorld.GetMatterMan();
if (pMatterMan.TraceWithBrush(&info) && info.fFraction < pInfo.fFraction)
{
*pInfo = info;
bBrush = true;
}
info = *pInfo;
CECNPCMan* pNPCMan = pWorld.GetNPCMan();
if (pNPCMan.TraceWithBrush(&info) && info.fFraction < pInfo.fFraction)
{
*pInfo = info;
bBrush = true;
}
return bBrush;
}
}
public struct OtherPlayer_Move_Info
{