Implement water rippling and fix CFluidPlane memory access errors

This commit is contained in:
Jack Andersen 2018-06-03 15:56:21 -10:00
parent 40fdfde691
commit e63102e180
12 changed files with 86 additions and 81 deletions

View File

@ -1043,8 +1043,10 @@ void CBooRenderer::AddParticleGen(const CParticleGen& gen)
void CBooRenderer::AddPlaneObject(const void* obj, const zeus::CAABox& aabb, const zeus::CPlane& plane, int type)
{
float closeDist = xb0_viewPlane.pointToPlaneDist(aabb.closestPointAlongVector(xb0_viewPlane.normal()));
float farDist = xb0_viewPlane.pointToPlaneDist(aabb.furthestPointAlongVector(xb0_viewPlane.normal()));
zeus::CVector3f closePoint = aabb.closestPointAlongVector(xb0_viewPlane.normal());
zeus::CVector3f farPoint = aabb.furthestPointAlongVector(xb0_viewPlane.normal());
float closeDist = xb0_viewPlane.pointToPlaneDist(closePoint);
float farDist = xb0_viewPlane.pointToPlaneDist(farPoint);
if (closeDist >= 0.f || farDist >= 0.f)
{
bool zOnly = plane.normal().isZero();

View File

@ -382,9 +382,8 @@ public:
++m_added;
if (m_added > 3 && (m_added & 1) == 0)
{
const VTX& last = m_vec.back();
m_vec.reserve(m_vec.size() + 3);
m_vec.push_back(last);
m_vec.push_back(m_vec.back());
m_vec.push_back(m_vec[m_start]);
}
m_vec.push_back(vert);
@ -396,9 +395,8 @@ public:
++m_added;
if (m_added > 3 && (m_added & 1) == 0)
{
const VTX& last = m_vec.back();
m_vec.reserve(m_vec.size() + 3);
m_vec.push_back(last);
m_vec.push_back(m_vec.back());
m_vec.push_back(m_vec[m_start]);
}
m_vec.emplace_back(std::forward<_Args>(args)...);

View File

@ -200,6 +200,7 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
// Load GX_TEXMTX3 with identity
zeus::CMatrix4f& texMtx = out.texMtxs[nextTexMtx++];
texMtx[0][0] = texMtx[1][1] = pttScale;
texMtx[3][0] = texMtx[3][1] = 0.5f;
// Load GX_PTTEXMTX0 with scale of pttScale
// Next: GX_TG_MTX2x4 GX_TG_NRM, GX_TEXMTX3, true, GX_PTTEXMTX0
@ -314,7 +315,7 @@ static bool PrepareRipple(const CRipple& ripple, const CFluidPlaneCPURender::SPa
return !(rippleOut.x14_gfromX > rippleOut.x18_gtoX || rippleOut.x1c_gfromY > rippleOut.x20_gtoY);
}
static void ApplyTurbulence(float t, CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], const u8 (&flags)[9][9],
static void ApplyTurbulence(float t, CFluidPlaneCPURender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9],
const float sineWave[256], const CFluidPlaneCPURender::SPatchInfo& info,
const CFluidPlaneCPU& fluidPane, const zeus::CVector3f& areaCenter)
{
@ -348,7 +349,7 @@ static void ApplyTurbulence(float t, CFluidPlaneCPURender::SHFieldSample (&heigh
}
static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo,
CFluidPlaneCPURender::SHFieldSample (&heights)[45][45],
CFluidPlaneCPURender::SHFieldSample (&heights)[46][46],
u8 (&flags)[9][9], const float sineWave[256], const CFluidPlaneCPURender::SPatchInfo& info)
{
float lookupT = 256.f * (1.f - rippleInfo.x0_ripple.GetTime() * rippleInfo.x0_ripple.GetOOTimeFalloff() *
@ -421,7 +422,7 @@ static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo,
if (u8 val = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * f11)])
{
heights[k][l].height += val * rippleInfo.x0_ripple.GetAmplitude() *
sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT)];
sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT) & 0xff];
}
else
{
@ -475,7 +476,7 @@ static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo,
{
heights[k][l].height += val * rippleInfo.x0_ripple.GetAmplitude() *
sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() +
lookupT)];
lookupT) & 0xff];
}
else
{
@ -498,7 +499,7 @@ static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo,
}
static void ApplyRipples(const rstl::reserved_vector<CFluidPlaneCPURender::SRippleInfo, 32>& rippleInfos,
CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], u8 (&flags)[9][9],
CFluidPlaneCPURender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9],
const float sineWave[256], const CFluidPlaneCPURender::SPatchInfo& info)
{
for (const CFluidPlaneCPURender::SRippleInfo& rippleInfo : rippleInfos)
@ -513,7 +514,7 @@ static void ApplyRipples(const rstl::reserved_vector<CFluidPlaneCPURender::SRipp
flags[CFluidPlaneCPURender::numTilesInHField+1][i+1] |= 2;
}
static void UpdatePatchNoNormals(CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], const u8 (&flags)[9][9],
static void UpdatePatchNoNormals(CFluidPlaneCPURender::SHFieldSample (&heights)[46][46], const u8 (&flags)[9][9],
const CFluidPlaneCPURender::SPatchInfo& info)
{
for (int i=1 ; i <= (info.x1_ySubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 2) /
@ -587,7 +588,7 @@ static void UpdatePatchNoNormals(CFluidPlaneCPURender::SHFieldSample (&heights)[
}
}
static void UpdatePatchWithNormals(CFluidPlaneCPURender::SHFieldSample (& heights)[45][45], const u8 (& flags)[9][9],
static void UpdatePatchWithNormals(CFluidPlaneCPURender::SHFieldSample (& heights)[46][46], const u8 (& flags)[9][9],
const CFluidPlaneCPURender::SPatchInfo& info)
{
float normalScale = -(2.f * info.x18_rippleResolution);
@ -745,7 +746,7 @@ static void UpdatePatchWithNormals(CFluidPlaneCPURender::SHFieldSample (& height
}
static bool UpdatePatch(float time, const CFluidPlaneCPURender::SPatchInfo& info,
CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], u8 (&flags)[9][9],
CFluidPlaneCPURender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9],
const CFluidPlaneCPU& fluidPane, const zeus::CVector3f& areaCenter,
const std::experimental::optional<CRippleManager>& rippleManager,
int fromX, int toX, int fromY, int toY)
@ -776,7 +777,7 @@ static bool UpdatePatch(float time, const CFluidPlaneCPURender::SPatchInfo& info
return false;
}
static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFieldSample (&heights)[45][45],
static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], int startYDiv,
const CFluidPlaneCPURender::SPatchInfo& info,
std::vector<CFluidPlaneShader::Vertex>& vOut)
@ -790,7 +791,6 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
float tileMid = info.x18_rippleResolution * midDiv;
float yMin = curY;
float yMid = curY + tileMid;
float xMin = info.x4_localMin.x;
float curX = info.x4_localMin.x;
int gridCell = info.x28_tileX + info.x2a_gridDimX * (info.x2e_tileY + yTile - 1);
@ -853,7 +853,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
for (; remSubdivs>0 ; --remSubdivs, ++curYDiv, curTileY+=info.x18_rippleResolution)
{
size_t start = vOut.size();
float curTileX = xMin;
float curTileX = curX;
for (int v=0 ; v<stripDivCount ; ++v)
{
func(curTileX, curTileY, heights[curYDiv][i+v]);
@ -900,7 +900,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
{
int curYDiv0 = startYDiv;
int curYDiv1 = startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile;
float curTileX = xMin;
float curTileX = curX;
for (int v=0 ; v<stripDivCount ; ++v)
{
int curXDiv = v * CFluidPlaneCPURender::numSubdivisionsInTile + i;
@ -910,7 +910,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
samp0.MakeNormal(), samp0.MakeColor(info));
vOut.emplace_back(zeus::CVector3f(curTileX, yMin + info.x14_tileSize, samp1.height),
samp1.MakeNormal(), samp1.MakeColor(info));
curTileX += info.x18_rippleResolution;
curTileX += info.x14_tileSize;
}
break;
}
@ -918,7 +918,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
{
int curYDiv0 = startYDiv;
int curYDiv1 = startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile;
float curTileX = xMin;
float curTileX = curX;
for (int v=0 ; v<stripDivCount ; ++v)
{
int curXDiv = v * CFluidPlaneCPURender::numSubdivisionsInTile + i;
@ -930,7 +930,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
vOut.emplace_back(zeus::CVector3f(curTileX, yMin + info.x14_tileSize, samp1.height),
samp1.MakeNormal(), samp1.MakeBinormal(), samp1.MakeTangent(),
samp1.MakeColor(info));
curTileX += info.x18_rippleResolution;
curTileX += info.x14_tileSize;
}
break;
}
@ -974,11 +974,11 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
break;
}
func(tileMid + xMin, yMid, heights[startYDiv+midDiv][i+midDiv]);
func(tileMid + curX, yMid, heights[startYDiv+midDiv][i+midDiv]);
int curXDiv = i;
int curYDiv = startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile;
float curTileX = xMin;
float curTileX = curX;
float curTileY = yMin + info.x14_tileSize;
for (int v=0 ; v<(r19 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v)
{
@ -989,7 +989,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
curXDiv = i + CFluidPlaneCPURender::numSubdivisionsInTile;
curYDiv = startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile;
curTileX = xMin + info.x14_tileSize;
curTileX = curX + info.x14_tileSize;
curTileY = yMin + info.x14_tileSize;
for (int v=0 ; v<(r18 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v)
{
@ -1000,7 +1000,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
curXDiv = i + CFluidPlaneCPURender::numSubdivisionsInTile;
curYDiv = startYDiv;
curTileX = xMin + info.x14_tileSize;
curTileX = curX + info.x14_tileSize;
curTileY = yMin;
for (int v=0 ; v<(r17 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v)
{
@ -1011,11 +1011,11 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
curXDiv = i;
curYDiv = startYDiv;
curTileX = xMin;
curTileX = curX;
curTileY = yMin;
if (r16)
{
for (int v=0 ; v<CFluidPlaneCPURender::numSubdivisionsInTile ; ++v)
for (int v=0 ; v<CFluidPlaneCPURender::numSubdivisionsInTile+1 ; ++v)
{
const CFluidPlaneCPURender::SHFieldSample& samp = heights[curYDiv+v][curXDiv];
func(curTileX, curTileY, samp);
@ -1043,7 +1043,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
}
void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info,
const CFluidPlaneCPURender::SHFieldSample (&heights)[45][45],
const CFluidPlaneCPURender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], bool noRipples, bool flagIs1,
std::vector<CFluidPlaneShader::Vertex>& vOut)
{
@ -1153,9 +1153,10 @@ void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info,
size_t start = vOut.size();
for (int v = 0 ; v < nextXTile - curXTile + 1 ; ++v)
{
vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMax + info.x14_tileSize, 0.f),
zeus::CColor::skBlack);
zeus::CVector3f::skUp, zeus::CColor::skBlack);
xMax += info.x14_tileSize;
}
CGraphics::DrawArray(start, vOut.size() - start);
@ -1259,6 +1260,11 @@ void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info,
}
}
/* Used to be part of locked cache
* These are too big for stack allocation */
static CFluidPlaneCPURender::SHFieldSample lc_heights[46][46] = {};
static u8 lc_flags[9][9] = {};
void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum,
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
@ -1375,12 +1381,9 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
else
toY = info.x1_ySubdivs;
CFluidPlaneCPURender::SHFieldSample heights[45][45];
u8 flags[9][9] = {};
bool noRipples = UpdatePatch(mgr.GetFluidPlaneManager()->GetUVT(), info, heights, flags,
bool noRipples = UpdatePatch(mgr.GetFluidPlaneManager()->GetUVT(), info, lc_heights, lc_flags,
*this, areaCenter, rippleManager, fromX, toX, fromY, toY);
RenderPatch(info, heights, flags, noRipples, renderFlags == 1, m_verts);
RenderPatch(info, lc_heights, lc_flags, noRipples, renderFlags == 1, m_verts);
}
}
curX += ripplePitch.x;

View File

@ -207,7 +207,7 @@ public:
};
void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info,
const CFluidPlaneCPURender::SHFieldSample (&heights)[45][45],
const CFluidPlaneCPURender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], bool noRipples, bool flagIs1,
std::vector<CFluidPlaneShader::Vertex>& vOut);

View File

@ -50,6 +50,11 @@ CFluidPlaneDoor::RenderSetup(const CStateManager& mgr, float alpha, const zeus::
return out;
}
/* Used to be part of locked cache
* These are too big for stack allocation */
static CFluidPlaneCPURender::SHFieldSample lc_heights[46][46] = {};
static u8 lc_flags[9][9] = {};
void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum,
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
@ -86,10 +91,7 @@ void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::
CFluidPlaneCPURender::NormalMode::None,
0, 0, 0, 0, 0, 0, 0, nullptr);
CFluidPlaneCPURender::SHFieldSample heights[45][45];
u8 flags[9][9] = {};
RenderPatch(patchInfo, heights, flags, true, true, m_verts);
RenderPatch(patchInfo, lc_heights, lc_flags, true, true, m_verts);
}
}
}

View File

@ -15,8 +15,8 @@ CRipple::CRipple(TUniqueId id, const zeus::CVector3f& center, float intensity)
x14_timeFalloff = 0.5f * tmp + 1.5f;
x18_distFalloff = 4.f * tmp + 8.f;
x1c_frequency = 2.f + tmp;
x20_ = 0.15f * tmp + 0.1f;
x24_amplitude = x20_ / 255.f;
x20_preAmplitude = 0.15f * tmp + 0.1f;
x24_amplitude = x20_preAmplitude / 255.f;
}
x28_ooTimeFalloff = 1.f / x14_timeFalloff;

View File

@ -15,7 +15,7 @@ private:
float x14_timeFalloff = 2.f;
float x18_distFalloff = 12.f;
float x1c_frequency = 3.f;
float x20_ = 0.25f;
float x20_preAmplitude = 0.25f;
float x24_amplitude = 0.00098039221f;
float x28_ooTimeFalloff = 0.f;
float x2c_ooDistFalloff = 0.f;

View File

@ -3,8 +3,8 @@
namespace urde
{
CRippleManager::CRippleManager(int maxRipples, float f1)
: x14_(f1)
CRippleManager::CRippleManager(int maxRipples, float alpha)
: x14_alpha(alpha)
{
Init(maxRipples);
}
@ -16,11 +16,6 @@ void CRippleManager::Init(int maxRipples)
r.SetTime(9999.f);
}
void CRippleManager::SetTime(float)
{
}
void CRippleManager::Update(float dt)
{
for (CRipple& ripple : x4_ripples)
@ -43,17 +38,20 @@ float CRippleManager::GetLastRippleDeltaTime(TUniqueId rippler) const
void CRippleManager::AddRipple(const CRipple& ripple)
{
float maxTime = 0.f;
auto oldestRipple = x4_ripples.end();
for (auto it = x4_ripples.begin() ; it != x4_ripples.end() ; ++it)
if (it->GetTime() > maxTime)
{
oldestRipple = it;
maxTime = it->GetTime();
}
}
void CRippleManager::SetMaxTimeFalloff(float time)
{
}
float CRippleManager::GetMaxTimeFalloff() const
{
return 0.f;
if (oldestRipple != x4_ripples.end())
{
*oldestRipple = ripple;
x0_maxTimeFalloff = std::max(x0_maxTimeFalloff, ripple.GetTimeFalloff());
}
}
}

View File

@ -9,20 +9,21 @@ namespace urde
class CRippleManager
{
float x0_ = 0.f;
float x0_maxTimeFalloff = 0.f;
std::vector<CRipple> x4_ripples;
float x14_;
float x14_alpha;
public:
CRippleManager(int maxRipples, float);
CRippleManager(int maxRipples, float alpha);
void Init(int maxRipples);
void SetTime(float);
std::vector<CRipple>& Ripples() { return x4_ripples; }
const std::vector<CRipple>& GetRipples() const { return x4_ripples; }
void Update(float dt);
float GetLastRippleDeltaTime(TUniqueId rippler) const;
void AddRipple(const CRipple& ripple);
void SetMaxTimeFalloff(float time);
float GetMaxTimeFalloff() const;
void SetMaxTimeFalloff(float time) { x0_maxTimeFalloff = time; }
float GetMaxTimeFalloff() const { return x0_maxTimeFalloff; }
void SetAlpha(float a) { x14_alpha = a; }
float GetAlpha() const { return x14_alpha; }
};
}

View File

@ -103,10 +103,10 @@ void CScriptWater::SetupGrid(bool recomputeClipping)
zeus::CAABox triggerAABB = GetTriggerBoundsWR();
auto dimX = u32((triggerAABB.max.x - triggerAABB.min.x + x2c0_tileSize) / x2c0_tileSize);
auto dimY = u32((triggerAABB.max.y - triggerAABB.min.y + x2c0_tileSize) / x2c0_tileSize);
x2e4_gridCellCount2 = x2cc_gridCellCount = (dimX + 1) * (dimY + 1);
x2e4_computedGridCellCount = x2cc_gridCellCount = (dimX + 1) * (dimY + 1);
x2dc_vertIntersects.reset();
if (!x2d8_tileIntersects || dimX != x2c4_gridDimX || dimY != x2c8_gridDimY)
x2d8_tileIntersects.reset(new bool[dimX * dimY]);
x2d8_tileIntersects.reset(new bool[x2cc_gridCellCount]);
x2c4_gridDimX = dimX;
x2c8_gridDimY = dimY;
for (int i=0 ; i<x2c8_gridDimY ; ++i)
@ -127,12 +127,12 @@ void CScriptWater::SetupGridClipping(CStateManager& mgr, int computeVerts)
{
if (x2e8_28_recomputeClipping)
{
x2e4_gridCellCount2 = 0;
x2e4_computedGridCellCount = 0;
x2dc_vertIntersects.reset();
x2e8_28_recomputeClipping = false;
}
if (x2e4_gridCellCount2 >= x2cc_gridCellCount)
if (x2e4_computedGridCellCount >= x2cc_gridCellCount)
return;
if (!x2dc_vertIntersects)
@ -140,11 +140,12 @@ void CScriptWater::SetupGridClipping(CStateManager& mgr, int computeVerts)
zeus::CAABox triggerBounds = GetTriggerBoundsWR();
zeus::CVector3f basePos = triggerBounds.min;
basePos.z = triggerBounds.max.z + 0.8f;
auto gridDiv = std::div(int(x2e4_gridCellCount2), int(x2c4_gridDimX + 1));
auto gridDiv = std::div(int(x2e4_computedGridCellCount), int(x2c4_gridDimX + 1));
float yOffset = x2c0_tileSize * gridDiv.quot;
float xOffset = x2c0_tileSize * gridDiv.rem;
float mag = std::min(120.f, 2.f * (x130_bounds.max.z - x130_bounds.min.z) + 0.8f);
for (int i = x2e4_gridCellCount2; i < std::min(x2e4_gridCellCount2 + computeVerts, x2cc_gridCellCount); ++i)
for (int i = x2e4_computedGridCellCount;
i < std::min(x2e4_computedGridCellCount + computeVerts, x2cc_gridCellCount); ++i)
{
zeus::CVector3f pos = basePos;
pos.x += xOffset;
@ -159,12 +160,12 @@ void CScriptWater::SetupGridClipping(CStateManager& mgr, int computeVerts)
gridDiv.rem = 0;
}
}
x2e4_gridCellCount2 += computeVerts;
if (x2e4_gridCellCount2 < x2cc_gridCellCount)
x2e4_computedGridCellCount += computeVerts;
if (x2e4_computedGridCellCount < x2cc_gridCellCount)
return;
x2e4_gridCellCount2 = x2cc_gridCellCount;
x2d8_tileIntersects.reset(new bool[x2c4_gridDimX * x2c8_gridDimY]);
x2e4_computedGridCellCount = x2cc_gridCellCount;
x2d8_tileIntersects.reset(new bool[x2cc_gridCellCount]);
for (int i = 0; i < x2c8_gridDimY; ++i)
{
@ -608,12 +609,12 @@ bool CScriptWater::CanRippleAtPoint(const zeus::CVector3f& point) const
if (!x2d8_tileIntersects)
return true;
auto xTile = int((point.x - GetTriggerBoundsOR().min.x) / x2c0_tileSize);
auto xTile = int((point.x - GetTriggerBoundsWR().min.x) / x2c0_tileSize);
if (xTile < 0 || xTile >= x2c4_gridDimX)
return false;
auto yTile = int((point.y - GetTriggerBoundsOR().min.y) / x2c0_tileSize);
if (xTile < 0 || xTile >= x2c8_gridDimY)
auto yTile = int((point.y - GetTriggerBoundsWR().min.y) / x2c0_tileSize);
if (yTile < 0 || yTile >= x2c8_gridDimY)
return false;
return x2d8_tileIntersects[yTile * x2c4_gridDimX + xTile];

View File

@ -58,7 +58,7 @@ private:
std::unique_ptr<bool[]> x2d8_tileIntersects;
std::unique_ptr<bool[]> x2dc_vertIntersects;
std::unique_ptr<u8[]> x2e0_patchIntersects; // 0: all clear, 1: all intersect, 2: partial intersect
int x2e4_gridCellCount2 = 0;
int x2e4_computedGridCellCount = 0;
union
{
struct

@ -1 +1 @@
Subproject commit b2185695f53c20dac3c1353852f8a4979859c1cd
Subproject commit ef3219dae294c3a83f6089a41ee4d37a491459c3