2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-09 07:07:42 +00:00

Work on CFluidPlaneCPU

This commit is contained in:
Jack Andersen
2017-08-09 21:05:27 -10:00
parent 3650a58a1e
commit dc637f251d
18 changed files with 816 additions and 94 deletions

View File

@@ -6,6 +6,7 @@
#include "CWorld.hpp"
#include "World/CScriptWater.hpp"
#include "TCastTo.hpp"
#include "Camera/CGameCamera.hpp"
#define kTableSize 2048
@@ -43,7 +44,7 @@ CFluidPlaneCPU::CTurbulence::CTurbulence(float speed, float distance, float freq
}
CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texColor, ResId bumpMap, ResId envMap,
ResId envBumpMap, ResId unkMap, float unitsPerLightmapTexel, float tileSize,
ResId envBumpMap, ResId lightMap, float unitsPerLightmapTexel, float tileSize,
u32 tileSubdivisions, EFluidType fluidType, float alpha,
const zeus::CVector3f& bumpLightDir, float bumpScale, const CFluidUVMotion& mot,
float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin,
@@ -51,7 +52,7 @@ CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texCo
float specularMin, float specularMax, float reflectionBlend, float reflectionSize,
float fluidPlaneF2)
: CFluidPlane(texPattern1, texPattern2, texColor, alpha, fluidType, fluidPlaneF2, mot),
xa0_texIdBumpMap(bumpMap), xa4_texIdEnvMap(envMap), xa8_texIdEnvBumpMap(envBumpMap), xac_texId4(unkMap),
xa0_texIdBumpMap(bumpMap), xa4_texIdEnvMap(envMap), xa8_texIdEnvBumpMap(envBumpMap), xac_texId4(lightMap),
xf0_bumpLightDir(bumpLightDir), xfc_bumpScale(bumpScale), x100_tileSize(tileSize),
x104_tileSubdivisions(tileSubdivisions & ~0x1),
x108_rippleResolution(x100_tileSize / float(x104_tileSubdivisions)),
@@ -98,6 +99,18 @@ void CFluidPlaneCPU::CalculateLightmapMatrix(const zeus::CTransform& areaXf, con
zeus::CVector3f(offX, offY, 0.f)) * toLocal).toMatrix4f();
}
static bool sSineWaveInitialized = false;
static float sGlobalSineWave[256] = {};
static const float* InitializeSineWave()
{
if (sSineWaveInitialized)
return sGlobalSineWave;
for (int i=0 ; i<256 ; ++i)
sGlobalSineWave[i] = std::sin(2.f * M_PIF * (i / 256.f));
sSineWaveInitialized = true;
return sGlobalSineWave;
}
#define kEnableWaterBumpMaps true
CFluidPlaneCPU::RenderSetupInfo
@@ -111,6 +124,7 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
bool doubleLightmapBlend = false;
bool hasEnvMap = mgr.GetCameraManager()->GetFluidCounter() == 0 && HasEnvMap();
bool hasEnvBumpMap = HasEnvBumpMap();
InitializeSineWave();
CGraphics::SetModelMatrix(xf);
if (hasBumpMap)
@@ -289,6 +303,439 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
return out;
}
class CFluidPlaneCPURender
{
public:
enum class RenderMode
{
None,
Normal,
Subdivided,
BumpMapped
};
static int numTilesInHField;
static int numSubdivisionsInTile;
static int numSubdivisionsInHField;
struct SPatchInfo
{
u8 x0_xSubdivs, x1_ySubdivs;
zeus::CVector2f x4_localMin, xc_globalMin;
float x14_rippleSideLen;
float x18_rippleResolution;
float x1c_rippleHypRadius;
float x20_ooRippleSideLen;
float x24_ooRippleResolution;
u16 x28_tileX;
u16 x2a_gridDimX;
u16 x2c_gridDimY;
u16 x2e_tileY;
const bool* x30_gridFlags;
bool x34_r14;
u8 x35_r22;
u8 x36_r23;
RenderMode x37_renderMode;
float x38_tileSize;
public:
SPatchInfo(const zeus::CVector3f& localMin, const zeus::CVector3f& localMax, const zeus::CVector3f& pos,
float rippleResolution, float rippleSideLen, float tileSize, int numSubdivisionsInHField,
RenderMode renderMode, bool r14, int r22, int r23, u32 tileX, u32 gridDimX, u32 gridDimY,
u32 tileY, const bool* gridFlags)
{
x0_xSubdivs = std::min(s16((localMax.x - localMin.x) / rippleResolution + 1.f - FLT_EPSILON) + 2,
numSubdivisionsInHField + 2);
x1_ySubdivs = std::min(s16((localMax.y - localMin.y) / rippleResolution + 1.f - FLT_EPSILON) + 2,
numSubdivisionsInHField + 2);
float rippleHypRadius = rippleSideLen * rippleSideLen * 2 * 0.25f;
x4_localMin.x = localMin.x;
x4_localMin.y = localMin.y;
xc_globalMin = x4_localMin + zeus::CVector2f(pos.x, pos.y);
x14_rippleSideLen = rippleSideLen;
x18_rippleResolution = rippleResolution;
if (rippleHypRadius != 0.f)
rippleHypRadius = std::sqrt(rippleHypRadius);
x1c_rippleHypRadius = rippleHypRadius;
x20_ooRippleSideLen = 1.f / x14_rippleSideLen;
x24_ooRippleResolution = 1.f / x18_rippleResolution;
x28_tileX = u16(tileX);
x2a_gridDimX = u16(gridDimX);
x2c_gridDimY = u16(gridDimY);
x2e_tileY = u16(tileY);
x30_gridFlags = gridFlags;
x34_r14 = r14;
x35_r22 = u8(r22);
x36_r23 = u8(r23);
x37_renderMode = renderMode;
x38_tileSize = tileSize;
}
};
struct SRippleInfo
{
const CRipple& x0_ripple;
int x4_fromX;
int x8_toX;
int xc_fromY;
int x10_toY;
int x14_gfromX;
int x18_gtoX;
int x1c_gfromY;
int x20_gtoY;
public:
SRippleInfo(const CRipple& ripple, int fromX, int toX, int fromY, int toY)
: x0_ripple(ripple), x14_gfromX(fromX), x18_gtoX(toX), x1c_gfromY(fromY), x20_gtoY(toY) {}
};
struct SHFieldSample
{
float f1;
u8 f2;
};
};
int CFluidPlaneCPURender::numTilesInHField;
int CFluidPlaneCPURender::numSubdivisionsInTile;
int CFluidPlaneCPURender::numSubdivisionsInHField;
static bool PrepareRipple(const CRipple& ripple, const CFluidPlaneCPURender::SPatchInfo& info,
CFluidPlaneCPURender::SRippleInfo& rippleOut)
{
auto lifeIdx = int((1.f - (ripple.GetTimeFalloff() - ripple.GetTime()) / ripple.GetTimeFalloff()) * 64.f);
float dist = CFluidPlaneManager::RippleMaxs[lifeIdx] * (ripple.GetDistanceFalloff() / 256.f);
dist *= dist;
if (dist != 0)
dist = std::sqrt(dist);
dist = info.x24_ooRippleResolution * dist + 1.f;
float centerX = info.x24_ooRippleResolution * (ripple.GetCenter().x - info.xc_globalMin.x);
float centerY = info.x24_ooRippleResolution * (ripple.GetCenter().y - info.xc_globalMin.y);
int fromX = int(centerX - dist) - 1;
int toX = int(centerX + dist) + 1;
int fromY = int(centerY - dist) - 1;
int toY = int(centerY + dist) + 1;
rippleOut.x4_fromX = std::max(0, fromX);
rippleOut.x8_toX = std::min(int(info.x0_xSubdivs), toX);
rippleOut.xc_fromY = std::max(0, fromY);
rippleOut.x10_toY = std::min(int(info.x1_ySubdivs), toY);
rippleOut.x14_gfromX = std::max(rippleOut.x14_gfromX, fromX);
rippleOut.x18_gtoX = std::min(rippleOut.x18_gtoX, toX);
rippleOut.x1c_gfromY = std::max(rippleOut.x1c_gfromY, fromY);
rippleOut.x20_gtoY = std::min(rippleOut.x20_gtoY, toY);
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],
const float sineWave[256], const CFluidPlaneCPURender::SPatchInfo& info,
const CFluidPlaneCPU& fluidPane, const zeus::CVector3f& areaCenter)
{
if (!fluidPane.HasTurbulence())
{
memset(&heights, 0, sizeof(heights));
return;
}
float scaledT = t * fluidPane.GetOOTurbulenceSpeed();
float curY = info.x4_localMin.y - info.x18_rippleResolution - areaCenter.y;
int xDivs = (info.x0_xSubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 4) /
CFluidPlaneCPURender::numSubdivisionsInTile * CFluidPlaneCPURender::numSubdivisionsInTile + 2;
int yDivs = (info.x1_ySubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 4) /
CFluidPlaneCPURender::numSubdivisionsInTile * CFluidPlaneCPURender::numSubdivisionsInTile + 2;
for (int i=0 ; i<=yDivs ; ++i)
{
float curYSq = curY * curY;
float curX = info.x4_localMin.x - info.x18_rippleResolution - areaCenter.x;
for (int j=0 ; j<=xDivs ; ++j)
{
float distFac = curX * curX + curYSq;
if (distFac != 0.f)
distFac = std::sqrt(distFac);
heights[i][j].f1 = fluidPane.GetTurbulenceHeight(fluidPane.GetOOTurbulenceDistance() * distFac + scaledT);
curX += info.x18_rippleResolution;
}
curY += info.x18_rippleResolution;
}
}
static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo,
CFluidPlaneCPURender::SHFieldSample (&heights)[45][45],
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() *
rippleInfo.x0_ripple.GetOOTimeFalloff()) * rippleInfo.x0_ripple.GetFrequency();
auto lifeIdx = int(64.f * rippleInfo.x0_ripple.GetTime() * rippleInfo.x0_ripple.GetOOTimeFalloff());
float distMul = rippleInfo.x0_ripple.GetDistanceFalloff() / 255.f;
float minDist = CFluidPlaneManager::RippleMins[lifeIdx] * distMul;
float minDistSq = minDist * minDist;
if (minDistSq != 0.f)
minDist = std::sqrt(minDistSq);
float maxDist = CFluidPlaneManager::RippleMaxs[lifeIdx] * distMul;
float maxDistSq = maxDist * maxDist;
if (maxDistSq != 0.f)
maxDist = std::sqrt(maxDistSq);
int fromY = (rippleInfo.x1c_gfromY + CFluidPlaneCPURender::numSubdivisionsInTile - 1) /
CFluidPlaneCPURender::numSubdivisionsInTile;
int fromX = (rippleInfo.x14_gfromX + CFluidPlaneCPURender::numSubdivisionsInTile - 1) /
CFluidPlaneCPURender::numSubdivisionsInTile;
int toY = (rippleInfo.x20_gtoY + CFluidPlaneCPURender::numSubdivisionsInTile - 1) /
CFluidPlaneCPURender::numSubdivisionsInTile;
int toX = (rippleInfo.x18_gtoX + CFluidPlaneCPURender::numSubdivisionsInTile - 1) /
CFluidPlaneCPURender::numSubdivisionsInTile;
float curY = rippleInfo.x0_ripple.GetCenter().y - info.xc_globalMin.y -
(0.5f * info.x14_rippleSideLen + (fromY - 1) * info.x14_rippleSideLen);
int curGridY = info.x2a_gridDimX * (info.x2e_tileY + fromY - 1);
int startGridX = (info.x28_tileX + fromX - 1);
int gridCells = info.x2a_gridDimX * info.x2c_gridDimY;
float f11 = 64.f * rippleInfo.x0_ripple.GetOODistanceFalloff();
int curYDiv = rippleInfo.xc_fromY;
for (int i=fromY ; i<=toY ; ++i, curY -= info.x14_rippleSideLen)
{
int nextYDiv = (i+1) * CFluidPlaneCPURender::numSubdivisionsInTile;
float curYSq = curY * curY;
int curGridX = startGridX;
int curXDiv = rippleInfo.x4_fromX;
float curX = rippleInfo.x0_ripple.GetCenter().x - info.xc_globalMin.x -
(0.5f * info.x14_rippleSideLen + (fromX - 1) * info.x14_rippleSideLen);
for (int j=fromX ; j<=toX ; ++j, curX -= info.x14_rippleSideLen, ++curGridX)
{
float dist = curX * curX + curYSq;
if (dist != 0.f)
dist = std::sqrt(dist);
if (maxDist < dist - info.x1c_rippleHypRadius || minDist > dist + info.x1c_rippleHypRadius)
continue;
bool addedRipple = false;
int nextXDiv = (j+1) * CFluidPlaneCPURender::numSubdivisionsInTile;
float curXMod =
(rippleInfo.x0_ripple.GetCenter().x - info.xc_globalMin.x) - info.x18_rippleResolution * curXDiv;
float curYMod =
(rippleInfo.x0_ripple.GetCenter().y - info.xc_globalMin.y) - info.x18_rippleResolution * curYDiv;
if (!info.x30_gridFlags || (info.x30_gridFlags && curGridY >= 0 && curGridY < gridCells && curGridX >= 0 &&
curGridX < info.x2a_gridDimX && info.x30_gridFlags[curGridX + curGridY]))
{
for (int k=curYDiv ; k<=std::min(rippleInfo.x10_toY, nextYDiv-1) ; ++k,
curYMod -= info.x18_rippleResolution)
{
float tmpXMod = curXMod;
float curYModSq = curYMod * curYMod;
for (int l=curXDiv ; l<=std::min(rippleInfo.x8_toX, nextXDiv-1) ; ++l,
tmpXMod -= info.x18_rippleResolution)
{
float divDistSq = tmpXMod * tmpXMod + curYModSq;
if (divDistSq < minDistSq || divDistSq > maxDistSq)
continue;
float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f;
if (u8 val = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * f11)])
{
heights[k][l].f1 += val * rippleInfo.x0_ripple.GetAmplitude() *
sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT)];
}
else
{
heights[k][l].f1 += 0.f;
}
addedRipple = true;
}
}
if (addedRipple)
flags[i][j] = 0x1f;
}
else
{
int yMin = nextYDiv - 1;
int yMax = nextYDiv - CFluidPlaneCPURender::numSubdivisionsInTile + 1;
int xMin = nextXDiv - 1;
int xMax = nextXDiv - CFluidPlaneCPURender::numSubdivisionsInTile + 1;
if (curGridX >= 0.f && curGridX < info.x2a_gridDimX && curGridY - info.x2a_gridDimX >= 0 &&
!info.x30_gridFlags[curGridX + curGridY - info.x2a_gridDimX])
yMax -= 2;
if (curGridX >= 0.f && curGridX < info.x2a_gridDimX && curGridY + info.x2a_gridDimX < gridCells &&
!info.x30_gridFlags[curGridX + info.x2a_gridDimX])
yMin += 2;
if (curGridY >= 0 && curGridY < info.x2c_gridDimY && curGridX > 0 &&
!info.x30_gridFlags[curGridX - 1])
xMax -= 2;
if (curGridY >= 0 && curGridY < info.x2c_gridDimY && curGridX + 1 < info.x2a_gridDimX &&
!info.x30_gridFlags[curGridX + 1])
xMin += 2;
for (int k=curYDiv ; k<=std::min(rippleInfo.x10_toY, nextYDiv-1) ; ++k,
curYMod -= info.x18_rippleResolution)
{
float tmpXMod = curXMod;
float curYModSq = curYMod * curYMod;
for (int l=curXDiv ; l<=std::min(rippleInfo.x8_toX, nextXDiv-1) ; ++l,
tmpXMod -= info.x18_rippleResolution)
{
if (k <= yMax || k >= yMin || l <= xMax || l >= xMin)
{
float divDistSq = tmpXMod * tmpXMod + curYModSq;
if (divDistSq < minDistSq || divDistSq > maxDistSq)
continue;
float divDist = (divDistSq != 0.f) ? std::sqrt(divDistSq) : 0.f;
if (u8 val = CFluidPlaneManager::RippleValues[lifeIdx][int(divDist * f11)])
{
heights[k][l].f1 += val * rippleInfo.x0_ripple.GetAmplitude() *
sineWave[int(divDist * rippleInfo.x0_ripple.GetLookupPhase() + lookupT)];
}
else
{
heights[k][l].f1 += 0.f;
}
addedRipple = true;
}
}
}
if (addedRipple)
flags[i][j] = 0xf;
}
curXDiv = nextXDiv;
}
curYDiv = nextYDiv;
curGridY += info.x2a_gridDimX;
}
}
static void ApplyRipples(const rstl::reserved_vector<CFluidPlaneCPURender::SRippleInfo, 32>& rippleInfos,
CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], u8 (&flags)[9][9],
const float sineWave[256], const CFluidPlaneCPURender::SPatchInfo& info)
{
for (const CFluidPlaneCPURender::SRippleInfo& rippleInfo : rippleInfos)
ApplyRipple(rippleInfo, heights, flags, sineWave, info);
for (int i=0 ; i<CFluidPlaneCPURender::numTilesInHField ; ++i)
flags[0][i+1] |= 1;
for (int i=0 ; i<CFluidPlaneCPURender::numTilesInHField ; ++i)
flags[i+1][0] |= 8;
for (int i=0 ; i<CFluidPlaneCPURender::numTilesInHField ; ++i)
flags[i+1][CFluidPlaneCPURender::numTilesInHField+1] |= 4;
for (int i=0 ; i<CFluidPlaneCPURender::numTilesInHField ; ++i)
flags[CFluidPlaneCPURender::numTilesInHField+1][i+1] |= 2;
}
static void UpdatePatchNormal(CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], const u8 (&flags)[9][9],
const CFluidPlaneCPURender::SPatchInfo& info)
{
for (int i=1 ; i <= (info.x1_ySubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 2) /
CFluidPlaneCPURender::numSubdivisionsInTile ; ++i)
{
int r10 = i * CFluidPlaneCPURender::numSubdivisionsInTile + 1;
int r9 = std::max(0, r10 - CFluidPlaneCPURender::numSubdivisionsInTile);
int x24 = std::min(r10, info.x1_ySubdivs + 1);
for (int j=1 ; j <= (info.x0_xSubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 2) /
CFluidPlaneCPURender::numSubdivisionsInTile ; ++j)
{
int r29 = j * CFluidPlaneCPURender::numSubdivisionsInTile + 1;
int r11 = std::max(0, r29 - CFluidPlaneCPURender::numSubdivisionsInTile);
int x28 = std::min(r29, info.x0_xSubdivs + 1);
if ((flags[i][j] & 0x1f) == 0x1f)
{
for (int k=r9 ; k<x24 ; ++k)
{
for (int l=r11 ; l<x28 ; ++l)
{
CFluidPlaneCPURender::SHFieldSample& sample = heights[k][l];
if (sample.f1 > 0.f)
sample.f2 = u8(std::min(255, int(info.x38_tileSize * sample.f1)));
else
sample.f2 = 0;
}
}
}
else
{
if (i > 0 && i < CFluidPlaneCPURender::numTilesInHField + 1 &&
r10 > 0 && r10 < CFluidPlaneCPURender::numTilesInHField + 1)
{
int halfSubdivs = CFluidPlaneCPURender::numSubdivisionsInTile / 2;
CFluidPlaneCPURender::SHFieldSample& sample = heights[halfSubdivs + r9][halfSubdivs + r11];
if (sample.f1 > 0.f)
sample.f2 = u8(std::min(255, int(info.x38_tileSize * sample.f1)));
else
sample.f2 = 0;
}
if (i != 0)
{
for (int k=r11 ; k<x28 ; ++k)
{
CFluidPlaneCPURender::SHFieldSample& sample = heights[i][k];
if (sample.f1 > 0.f)
sample.f2 = u8(std::min(255, int(info.x38_tileSize * sample.f1)));
else
sample.f2 = 0;
}
}
if (j != 0)
{
for (int k=r9+1 ; k<x24 ; ++k)
{
CFluidPlaneCPURender::SHFieldSample& sample = heights[k][r11];
if (sample.f1 > 0.f)
sample.f2 = u8(std::min(255, int(info.x38_tileSize * sample.f1)));
else
sample.f2 = 0;
}
}
}
}
}
}
static void UpdatePatchSubdivided(const CFluidPlaneCPURender::SHFieldSample (&heights)[45][45], const u8 (&flags)[9][9],
const CFluidPlaneCPURender::SPatchInfo& info)
{
}
static bool UpdatePatch(float time, const CFluidPlaneCPURender::SPatchInfo& info, const CFluidPlaneCPU& fluidPane,
const zeus::CVector3f& areaCenter,
const std::experimental::optional<CRippleManager>& rippleManager,
int fromX, int toX, int fromY, int toY)
{
rstl::reserved_vector<CFluidPlaneCPURender::SRippleInfo, 32> rippleInfos;
if (rippleManager)
{
for (const CRipple& ripple : rippleManager->GetRipples())
{
if (ripple.GetTime() >= ripple.GetTimeFalloff())
continue;
CFluidPlaneCPURender::SRippleInfo rippleInfo(ripple, fromX, toX, fromY, toY);
if (PrepareRipple(ripple, info, rippleInfo))
rippleInfos.push_back(rippleInfo);
}
}
if (rippleInfos.empty())
return true;
CFluidPlaneCPURender::SHFieldSample heights[45][45];
u8 flags[9][9] = {};
ApplyTurbulence(time, heights, flags, sGlobalSineWave, info, fluidPane, areaCenter);
ApplyRipples(rippleInfos, heights, flags, sGlobalSineWave, info);
if (info.x37_renderMode == CFluidPlaneCPURender::RenderMode::Normal)
UpdatePatchNormal(heights, flags, info);
else
UpdatePatchSubdivided(heights, flags, info);
return false;
}
static void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info, bool updateResult)
{
}
void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum,
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
@@ -296,7 +743,123 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
{
TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(waterId);
RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr());
m_shader->draw(setupInfo.texMtxs, setupInfo.normMtx, setupInfo.indScale, setupInfo.lights, setupInfo.kColors);
CFluidPlaneCPURender::RenderMode renderMode;
if (xb0_bumpMap && kEnableWaterBumpMaps)
renderMode = CFluidPlaneCPURender::RenderMode::BumpMapped;
else if (!noSubdiv)
renderMode = CFluidPlaneCPURender::RenderMode::Subdivided;
else
renderMode = CFluidPlaneCPURender::RenderMode::Normal;
// Set Position and color format
switch (renderMode)
{
case CFluidPlaneCPURender::RenderMode::BumpMapped:
// Set NBT format
break;
case CFluidPlaneCPURender::RenderMode::Subdivided:
// Set Normal format
break;
default:
break;
}
float rippleResolutionRecip = 1.f / x108_rippleResolution;
CFluidPlaneCPURender::numSubdivisionsInTile = x104_tileSubdivisions;
CFluidPlaneCPURender::numTilesInHField = std::min(7, 42 / CFluidPlaneCPURender::numSubdivisionsInTile);
CFluidPlaneCPURender::numSubdivisionsInHField =
CFluidPlaneCPURender::numTilesInHField * CFluidPlaneCPURender::numSubdivisionsInTile;
zeus::CVector3f aabbCenter = aabb.center();
zeus::CVector2f center2D(aabbCenter.x, aabbCenter.y);
zeus::CVector2f ripplePitch(x108_rippleResolution * CFluidPlaneCPURender::numSubdivisionsInHField);
bool r14 = false;
int r22 = 0;
int r23 = 0;
float rippleSideLen = g_tweakGame->GetRippleSideLengthNormal();
switch (x44_fluidType)
{
case EFluidType::PoisonWater:
rippleSideLen = g_tweakGame->GetRippleSideLengthPoison();
r14 = true;
r23 = 1;
break;
case EFluidType::Lava:
case EFluidType::Five:
rippleSideLen = g_tweakGame->GetRippleSideLengthLava();
r23 = 8;
r22 = 8;
break;
default:
break;
}
if (water)
{
float cameraPenetration =
mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation().dot(zeus::CVector3f::skUp) -
water->GetTriggerBoundsWR().max.z;
rippleSideLen *= (cameraPenetration >= 0.5f || cameraPenetration < 0.f) ? 1.f : 2.f * cameraPenetration;
}
u32 patchDimX = (water && water->GetPatchDimensionX()) ? water->GetPatchDimensionX() : 128;
u32 patchDimY = (water && water->GetPatchDimensionY()) ? water->GetPatchDimensionY() : 128;
u32 tileY = 0;
float curY = aabb.min.y;
for (int i=0 ; curY < aabb.max.y && i<patchDimY ; ++i)
{
u32 tileX = 0;
float curX = aabb.min.x;
float _remDivsY = (aabb.max.y - curY) * rippleResolutionRecip;
for (int j=0 ; curX < aabb.max.x && j<patchDimX ; ++j)
{
if (water->CanRenderPatch(j, i))
{
s16 remDivsX = std::min(s16((aabb.max.x - curX) * rippleResolutionRecip),
s16(CFluidPlaneCPURender::numSubdivisionsInHField));
s16 remDivsY = std::min(s16(_remDivsY), s16(CFluidPlaneCPURender::numSubdivisionsInHField));
zeus::CVector3f localMax(x108_rippleResolution * remDivsX + curX,
x108_rippleResolution * remDivsY + curY, aabb.max.z);
zeus::CVector3f localMin(curX, curY, aabb.min.z);
zeus::CAABox testaabb(localMin + xf.origin, localMax + xf.origin);
if (frustum.aabbFrustumTest(testaabb))
{
CFluidPlaneCPURender::SPatchInfo info(localMin, localMax, xf.origin, x108_rippleResolution,
rippleSideLen, x100_tileSize,
CFluidPlaneCPURender::numSubdivisionsInHField, renderMode,
r14, r22, r23, tileX, gridDimX, gridDimY, tileY, gridFlags);
int fromX = tileX != 0 ? (2 - CFluidPlaneCPURender::numSubdivisionsInTile) : 0;
int toX;
if (tileX != gridDimX - 1)
toX = info.x0_xSubdivs + (CFluidPlaneCPURender::numSubdivisionsInTile - 2);
else
toX = info.x0_xSubdivs;
int fromY = tileY != 0 ? (2 - CFluidPlaneCPURender::numSubdivisionsInTile) : 0;
int toY;
if (tileY != gridDimY - 1)
toY = info.x1_ySubdivs + (CFluidPlaneCPURender::numSubdivisionsInTile - 2);
else
toY = info.x1_ySubdivs;
bool result = UpdatePatch(mgr.GetFluidPlaneManager()->GetUVT(), info, *this, areaCenter,
rippleManager, fromX, toX, fromY, toY);
RenderPatch(info, result);
}
}
curX += ripplePitch.x;
tileX += CFluidPlaneCPURender::numTilesInHField;
}
curY += ripplePitch.y;
tileY += CFluidPlaneCPURender::numTilesInHField;
}
//m_shader->draw(setupInfo.texMtxs, setupInfo.normMtx, setupInfo.indScale, setupInfo.lights, setupInfo.kColors);
}
void CFluidPlaneCPU::RenderCleanup() const