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

@ -1,6 +1,9 @@
<component name="InspectionProjectProfileManager"> <component name="InspectionProjectProfileManager">
<profile version="1.0"> <profile version="1.0">
<option name="myName" value="Project Default" /> <option name="myName" value="Project Default" />
<inspection_tool class="ClangTidyInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="clangTidyChecks" value="*,-cert-env33-c,-cppcoreguidelines-no-malloc,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-cstyle-cast,-cppcoreguidelines-pro-type-union-access,-google-*,google-default-arguments,google-explicit-constructor,google-runtime-member-string-references,google-runtime-memset,google-runtime-operator,-llvm-*,-readability-simplify-boolean-expr,-readability-braces-around-statements,-readability-identifier-naming,-readability-function-size,-misc-bool-pointer-implicit-conversion,-misc-unused-parameters,-modernize-use-using,-safety-no-assembler,-clang-diagnostic-*,-clang-analyzer-*,-cert-flp30-c" />
</inspection_tool>
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false"> <inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" /> <option name="processCode" value="true" />
<option name="processLiterals" value="true" /> <option name="processLiterals" value="true" />

View File

@ -12,6 +12,9 @@ struct ITweakGame : ITweak
virtual bool GetSplashScreensDisabled() const = 0; virtual bool GetSplashScreensDisabled() const = 0;
virtual float GetFirstPersonFOV() const = 0; virtual float GetFirstPersonFOV() const = 0;
virtual float GetPressStartDelay() const = 0; virtual float GetPressStartDelay() const = 0;
virtual float GetRippleSideLengthNormal() const = 0;
virtual float GetRippleSideLengthPoison() const = 0;
virtual float GetRippleSideLengthLava() const = 0;
virtual float GetFluidEnvBumpScale() const = 0; virtual float GetFluidEnvBumpScale() const = 0;
virtual float GetHardModeDamageMultiplier() const = 0; virtual float GetHardModeDamageMultiplier() const = 0;
virtual float GetHardModeWeaponMultiplier() const = 0; virtual float GetHardModeWeaponMultiplier() const = 0;

View File

@ -19,10 +19,10 @@ struct CTweakGame : ITweakGame
Value<bool> x2a_unknown3; Value<bool> x2a_unknown3;
Value<bool> x2b_splashScreensDisabled; Value<bool> x2b_splashScreensDisabled;
Value<float> x2c_unknown5; Value<float> x2c_unknown5;
Value<float> x30_presStartDelay; Value<float> x30_pressStartDelay;
Value<float> x34_unknown7; Value<float> x34_rippleSideLenNormal;
Value<float> x38_unknown8; Value<float> x38_rippleSideLenPoison;
Value<float> x3c_unknown9; Value<float> x3c_rippleSideLenLava;
Value<float> x40_unknown10; Value<float> x40_unknown10;
Value<float> x44_unknown11; Value<float> x44_unknown11;
Value<float> x48_unknown12; Value<float> x48_unknown12;
@ -34,13 +34,16 @@ struct CTweakGame : ITweakGame
Value<float> x60_hardmodeDamageMult; Value<float> x60_hardmodeDamageMult;
Value<float> x64_hardmodeWeaponMult; Value<float> x64_hardmodeWeaponMult;
virtual const std::string& GetWorldPrefix() const { return x4_worldPrefix; } const std::string& GetWorldPrefix() const { return x4_worldPrefix; }
virtual bool GetSplashScreensDisabled() const { return x2b_splashScreensDisabled; } bool GetSplashScreensDisabled() const { return x2b_splashScreensDisabled; }
virtual float GetFirstPersonFOV() const { return x24_fov; } float GetFirstPersonFOV() const { return x24_fov; }
virtual float GetPressStartDelay() const { return x30_presStartDelay; } float GetPressStartDelay() const { return x30_pressStartDelay; }
virtual float GetFluidEnvBumpScale() const { return x4c_fluidEnvBumpScale; } float GetRippleSideLengthNormal() const { return x34_rippleSideLenNormal; }
virtual float GetHardModeDamageMultiplier() const { return x60_hardmodeDamageMult; } float GetRippleSideLengthPoison() const { return x38_rippleSideLenPoison; }
virtual float GetHardModeWeaponMultiplier() const { return x64_hardmodeWeaponMult; } float GetRippleSideLengthLava() const { return x3c_rippleSideLenLava; }
float GetFluidEnvBumpScale() const { return x4c_fluidEnvBumpScale; }
float GetHardModeDamageMultiplier() const { return x60_hardmodeDamageMult; }
float GetHardModeWeaponMultiplier() const { return x64_hardmodeWeaponMult; }
CTweakGame() = default; CTweakGame() = default;
CTweakGame(athena::io::IStreamReader& in) CTweakGame(athena::io::IStreamReader& in)
{ {

View File

@ -457,7 +457,7 @@ void CActorLights::BuildDynamicLightList(const CStateManager& mgr, const zeus::C
x299_26_ = false; x299_26_ = false;
x144_dynamicLights.clear(); x144_dynamicLights.clear();
if (!x29a_) if (!x29a_findNearestDynamicLights)
{ {
for (const CLight& light : mgr.GetDynamicLightList()) for (const CLight& light : mgr.GetDynamicLightList())
{ {
@ -555,6 +555,13 @@ void CActorLights::ActivateLights(CBooModel& model) const
} }
} }
void CActorLights::DisableAreaLights()
{
x2b8_maxAreaLights = 0;
x298_26_hasAreaLights = false;
x298_28_inArea = false;
}
const CLight& CActorLights::GetLight(u32 idx) const const CLight& CActorLights::GetLight(u32 idx) const
{ {
if (x298_28_inArea) if (x298_28_inArea)

View File

@ -39,7 +39,7 @@ class CActorLights
}; };
u16 _dummy = 0; u16 _dummy = 0;
}; };
bool x29a_ = false; bool x29a_findNearestDynamicLights = false;
u32 x29c_shadowLightValIdx = -1; u32 x29c_shadowLightValIdx = -1;
u32 x2a0_shadowLightIdx = -1; u32 x2a0_shadowLightIdx = -1;
u32 x2a4_lastUpdateFrame = 0; u32 x2a4_lastUpdateFrame = 0;
@ -75,6 +75,10 @@ public:
void ActivateLights(CBooModel& model) const; void ActivateLights(CBooModel& model) const;
void SetCastShadows(bool v) { x298_25_castShadows = v; } void SetCastShadows(bool v) { x298_25_castShadows = v; }
void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; } void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; }
void SetAmbientChannelOverflow(bool v) { x298_29_ambientChannelOverflow = v; }
void DisableAreaLights();
void SetMaxDynamicLights(int l) { x2bc_maxDynamicLights = l; }
void SetFindNearestDynamicLights(bool v) { x29a_findNearestDynamicLights = v; }
void SetAmbientColor(const zeus::CColor& color) { x288_ambientColor = color; } void SetAmbientColor(const zeus::CColor& color) { x288_ambientColor = color; }
const zeus::CColor& GetAmbientColor() const { return x288_ambientColor; } const zeus::CColor& GetAmbientColor() const { return x288_ambientColor; }

View File

@ -96,9 +96,9 @@ void CActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateMana
void CActor::CalculateRenderBounds() void CActor::CalculateRenderBounds()
{ {
if (x64_modelData && (x64_modelData->AnimationData() || x64_modelData->GetNormalModel())) if (x64_modelData && (x64_modelData->AnimationData() || x64_modelData->GetNormalModel()))
x9c_aabox = x64_modelData->GetBounds(x34_transform); x9c_renderBounds = x64_modelData->GetBounds(x34_transform);
else else
x9c_aabox = zeus::CAABox(x34_transform.origin, x34_transform.origin); x9c_renderBounds = zeus::CAABox(x34_transform.origin, x34_transform.origin);
} }
CHealthInfo* CActor::HealthInfo() { return nullptr; } CHealthInfo* CActor::HealthInfo() { return nullptr; }
@ -167,7 +167,7 @@ void CActor::OnScanStateChanged(EScanState state, CStateManager& mgr)
SendScriptMsgs(EScriptObjectState::ScanDone, mgr, EScriptObjectMessage::None); SendScriptMsgs(EScriptObjectState::ScanDone, mgr, EScriptObjectMessage::None);
} }
zeus::CAABox CActor::GetSortingBounds(const CStateManager&) const { return x9c_aabox; } zeus::CAABox CActor::GetSortingBounds(const CStateManager&) const { return x9c_renderBounds; }
void CActor::DoUserAnimEvent(CStateManager&, CInt32POINode&, EUserEventType, float dt) {} void CActor::DoUserAnimEvent(CStateManager&, CInt32POINode&, EUserEventType, float dt) {}

View File

@ -37,7 +37,7 @@ protected:
std::unique_ptr<CActorLights> x90_actorLights; std::unique_ptr<CActorLights> x90_actorLights;
std::unique_ptr<CSimpleShadow> x94_simpleShadow; std::unique_ptr<CSimpleShadow> x94_simpleShadow;
std::unique_ptr<TToken<CScannableObjectInfo>> x98_scanObjectInfo; std::unique_ptr<TToken<CScannableObjectInfo>> x98_scanObjectInfo;
zeus::CAABox x9c_aabox; zeus::CAABox x9c_renderBounds;
CModelFlags xb4_drawFlags; CModelFlags xb4_drawFlags;
float xbc_time = 0.f; float xbc_time = 0.f;
float xc0_pitchBend = 0.f; float xc0_pitchBend = 0.f;

View File

@ -6,6 +6,7 @@
#include "CWorld.hpp" #include "CWorld.hpp"
#include "World/CScriptWater.hpp" #include "World/CScriptWater.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "Camera/CGameCamera.hpp"
#define kTableSize 2048 #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, 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, u32 tileSubdivisions, EFluidType fluidType, float alpha,
const zeus::CVector3f& bumpLightDir, float bumpScale, const CFluidUVMotion& mot, const zeus::CVector3f& bumpLightDir, float bumpScale, const CFluidUVMotion& mot,
float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin, 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 specularMin, float specularMax, float reflectionBlend, float reflectionSize,
float fluidPlaneF2) float fluidPlaneF2)
: CFluidPlane(texPattern1, texPattern2, texColor, alpha, fluidType, fluidPlaneF2, mot), : 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), xf0_bumpLightDir(bumpLightDir), xfc_bumpScale(bumpScale), x100_tileSize(tileSize),
x104_tileSubdivisions(tileSubdivisions & ~0x1), x104_tileSubdivisions(tileSubdivisions & ~0x1),
x108_rippleResolution(x100_tileSize / float(x104_tileSubdivisions)), 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(); 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 #define kEnableWaterBumpMaps true
CFluidPlaneCPU::RenderSetupInfo CFluidPlaneCPU::RenderSetupInfo
@ -111,6 +124,7 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
bool doubleLightmapBlend = false; bool doubleLightmapBlend = false;
bool hasEnvMap = mgr.GetCameraManager()->GetFluidCounter() == 0 && HasEnvMap(); bool hasEnvMap = mgr.GetCameraManager()->GetFluidCounter() == 0 && HasEnvMap();
bool hasEnvBumpMap = HasEnvBumpMap(); bool hasEnvBumpMap = HasEnvBumpMap();
InitializeSineWave();
CGraphics::SetModelMatrix(xf); CGraphics::SetModelMatrix(xf);
if (hasBumpMap) if (hasBumpMap)
@ -289,6 +303,439 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
return out; 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, 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 zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum,
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId, 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); TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(waterId);
RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr()); 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 void CFluidPlaneCPU::RenderCleanup() const

View File

@ -66,11 +66,12 @@ class CFluidPlaneCPU : public CFluidPlane
}; };
public: public:
CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texColor, ResId bumpMap, ResId envMap, ResId envBumpMap, CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texColor, ResId bumpMap, ResId envMap, ResId envBumpMap,
ResId unkMap, float unitsPerLightmapTexel, float tileSize, u32 tileSubdivisions, EFluidType fluidType, float alpha, ResId lightMap, float unitsPerLightmapTexel, float tileSize, u32 tileSubdivisions,
const zeus::CVector3f& bumpLightDir, float bumpScale, const CFluidUVMotion& mot, float turbSpeed, EFluidType fluidType, float alpha, const zeus::CVector3f& bumpLightDir, float bumpScale,
float turbDistance, float turbFreqMax, float turbFreqMin, float turbPhaseMax, float turbPhaseMin, const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax,
float turbAmplitudeMax, float turbAmplitudeMin, float specularMin, float specularMax, float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
float reflectionBlend, float reflectionSize, float fluidPlaneF2); float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend,
float reflectionSize, float fluidPlaneF2);
void CreateRipple(const CRipple& ripple, CStateManager& mgr); void CreateRipple(const CRipple& ripple, CStateManager& mgr);
void CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf, void CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf,
const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const; const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const;

View File

@ -878,7 +878,7 @@ void CPlayer::CalculateRenderBounds()
if (x2f8_morphTransState == EPlayerMorphBallState::Morphed) if (x2f8_morphTransState == EPlayerMorphBallState::Morphed)
{ {
float rad = x768_morphball->GetBallRadius(); float rad = x768_morphball->GetBallRadius();
x9c_aabox = zeus::CAABox(GetTranslation() - zeus::CVector3f(rad, rad, 0.f), x9c_renderBounds = zeus::CAABox(GetTranslation() - zeus::CVector3f(rad, rad, 0.f),
GetTranslation() + zeus::CVector3f(rad, rad, rad * 2.f)); GetTranslation() + zeus::CVector3f(rad, rad, rad * 2.f));
} }
else else

View File

@ -1,5 +1,28 @@
#include "CRipple.hpp" #include "CRipple.hpp"
#include "CRandom16.hpp"
namespace urde namespace urde
{ {
CRipple::CRipple(TUniqueId, const zeus::CVector3f&, float) {} static CRandom16 sRippleRandom(0xABBA);
CRipple::CRipple(TUniqueId id, const zeus::CVector3f& center, float intensity)
: x0_id(id), x8_center(center)
{
if (intensity >= 0.f && intensity <= 1.f)
{
float tmp =
2.f * std::min(1.f, std::max(0.f, intensity * (sRippleRandom.Float() - 0.5f) * 2.f * 0.1f + 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;
}
x28_ooTimeFalloff = 1.f / x14_timeFalloff;
x2c_ooDistFalloff = 1.f / x18_distFalloff;
x30_ooPhase = x18_distFalloff / 2.5f;
x34_phase = 1.f / x30_ooPhase;
x38_lookupPhase = 256.f * x34_phase;
}
} }

View File

@ -11,26 +11,33 @@ class CRipple
private: private:
TUniqueId x0_id; TUniqueId x0_id;
float x4_time = 0.f; float x4_time = 0.f;
zeus::CVector3f x8_; zeus::CVector3f x8_center;
float x14_ = 2.f; float x14_timeFalloff = 2.f;
float x18_ = 12.f; float x18_distFalloff = 12.f;
float x1c_ = 3.f; float x1c_frequency = 3.f;
float x20_ = 0.25f; float x20_ = 0.25f;
float x24_ = 0.00098039221f; float x24_amplitude = 0.00098039221f;
float x28_ooTimeFalloff = 0.f;
float x2c_ooDistFalloff = 0.f;
float x30_ooPhase = 0.f;
float x34_phase = 0.f;
float x38_lookupPhase = 0.f;
u32 x3c_ = 0;
public: public:
CRipple(TUniqueId, const zeus::CVector3f&, float); CRipple(TUniqueId id, const zeus::CVector3f& center, float intensity);
void SetTime(float t) { x4_time = t; } void SetTime(float t) { x4_time = t; }
float GetTime() const { return x4_time; } float GetTime() const { return x4_time; }
float GetTimeFalloff() const; float GetTimeFalloff() const { return x14_timeFalloff; }
TUniqueId GetUniqueId() const { return x0_id; } TUniqueId GetUniqueId() const { return x0_id; }
float GetFequency() const; float GetFrequency() const { return x1c_frequency; }
float GetAmplitude() const; float GetAmplitude() const { return x24_amplitude; }
float GetOODistanceFalloff() const; float GetOODistanceFalloff() const { return x2c_ooDistFalloff; }
float GetDistanceFalloff() const; float GetDistanceFalloff() const { return x18_distFalloff; }
zeus::CVector3f GetCenter() const; const zeus::CVector3f& GetCenter() const { return x8_center; }
float GetOOTimeFalloff() const; float GetOOTimeFalloff() const { return x28_ooTimeFalloff; }
float GetLookupPhase() const { return x38_lookupPhase; }
}; };
} }
#endif // __URDE_CRIPPLE_HPP__ #endif // __URDE_CRIPPLE_HPP__

View File

@ -21,16 +21,6 @@ void CRippleManager::SetTime(float)
} }
void CRippleManager::Ripples()
{
}
void CRippleManager::GetRipples() const
{
}
void CRippleManager::Update(float dt) void CRippleManager::Update(float dt)
{ {

View File

@ -16,8 +16,8 @@ public:
CRippleManager(int maxRipples, float); CRippleManager(int maxRipples, float);
void Init(int maxRipples); void Init(int maxRipples);
void SetTime(float); void SetTime(float);
void Ripples(); std::vector<CRipple>& Ripples() { return x4_ripples; }
void GetRipples() const; const std::vector<CRipple>& GetRipples() const { return x4_ripples; }
void Update(float dt); void Update(float dt);
float GetLastRippleDeltaTime(TUniqueId rippler) const; float GetLastRippleDeltaTime(TUniqueId rippler) const;
void AddRipple(const CRipple& ripple); void AddRipple(const CRipple& ripple);
@ -26,5 +26,5 @@ public:
}; };
} }
;
#endif // __URDE_CRIPPLEMANAGER_HPP__ #endif // __URDE_CRIPPLEMANAGER_HPP__

View File

@ -45,7 +45,7 @@ void CScriptPointOfInterest::CalculateRenderBounds()
if (xe8_pointSize == 0.f) if (xe8_pointSize == 0.f)
CActor::CalculateRenderBounds(); CActor::CalculateRenderBounds();
else else
x9c_aabox = zeus::CAABox(x34_transform.origin - xe8_pointSize, x34_transform.origin + xe8_pointSize); x9c_renderBounds = zeus::CAABox(x34_transform.origin - xe8_pointSize, x34_transform.origin + xe8_pointSize);
} }
rstl::optional_object<zeus::CAABox> CScriptPointOfInterest::GetTouchBounds() const rstl::optional_object<zeus::CAABox> CScriptPointOfInterest::GetTouchBounds() const

View File

@ -1,6 +1,8 @@
#include "CScriptWater.hpp" #include "CScriptWater.hpp"
#include "CStateManager.hpp" #include "CStateManager.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
namespace urde namespace urde
{ {
@ -13,15 +15,97 @@ const float CScriptWater::kSplashScales[6] =
CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, const std::string& name, const CEntityInfo& info, CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, const std::string& name, const CEntityInfo& info,
const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo, const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo,
zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool b1, bool b2, ResId, ResId, ResId, zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool b1, bool b2,
ResId, ResId, ResId, ResId, const zeus::CVector3f&, float, float, float, bool active, ResId patternMap1, ResId patternMap2, ResId colorMap, ResId bumpMap, ResId envMap,
CFluidPlane::EFluidType, bool, float, const CFluidUVMotion&, float, float, float, float, ResId envBumpMap, ResId unusedMap, const zeus::CVector3f& bumpLightDir, float bumpScale,
float, float, float, float, const zeus::CColor&, const zeus::CColor&, ResId, ResId, ResId, float f2, float f3, bool active, CFluidPlane::EFluidType fluidType, bool b4, float alpha,
ResId, ResId, s32, s32, s32, s32, s32, float, u32, float, float, float, float, float, float, const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax,
float, float, const zeus::CColor&, urde::ResId, float, float, float, u32, u32, bool, s32, float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
s32, const u32*) float turbAmplitudeMin, const zeus::CColor& c1, const zeus::CColor& c2, ResId splashParticle1,
: CScriptTrigger(uid, name, info, pos, box, dInfo, orientedForce, triggerFlags, active, false, false) ResId splashParticle2, ResId splashParticle3, ResId particle4, ResId particle5, s32 i1,
s32 visorRunoffSfx, s32 splashSfx1, s32 splashSfx2, s32 splashSfx3, float tileSize,
u32 tileSubdivisions, float specularMin, float specularMax, float reflectionSize,
float fluidPlaneF2, float reflectionBlend, float slF6, float slF7, float slF8,
const zeus::CColor& c3, ResId lightmapId, float unitsPerLightmapTexel, float lF2, float lF3,
u32, u32, bool, s32, s32, std::unique_ptr<u32[]>&& u32Arr)
: CScriptTrigger(uid, name, info, pos, box, dInfo, orientedForce, triggerFlags, active, false, false),
x1b8_position(pos), x1c4_extent(box.max - box.min), x1d0_f2(f2), x1d4_position2(pos), x1e0_extent2(box.max - box.min),
x1ec_damage(dInfo.GetDamage()), x1f0_damage2(dInfo.GetDamage()), x1f4_(f3), x214_(slF6), x218_(slF7), x21c_(slF6),
x220_(slF7), x224_(slF8), x228_(c3), x22c_splashParticle1Id(splashParticle1), x230_splashParticle2Id(splashParticle2),
x234_splashParticle3Id(splashParticle3), x238_particle4Id(particle4), x24c_particle5Id(particle5),
x260_(CSfxManager::TranslateSFXID(i1)), x262_visorRunoffSfx(CSfxManager::TranslateSFXID(visorRunoffSfx)),
x2a4_c1(c1), x2a8_c2(c2), x2ac_lf2(lF2), x2b0_lf3(lF3), x2b4_((lF2 != 0.f) ? 1.f / lF2 : 0.f),
x2b8_((lF3 != 0.f) ? 1.f / lF3 : 0.f), x2bc_alpha(alpha), x2c0_tileSize(tileSize)
{ {
zeus::CAABox triggerAABB = GetTriggerBoundsWR();
x2c4_gridDimX = u32((x2c0_tileSize + triggerAABB.max.x - triggerAABB.min.x - 0.01f) / x2c0_tileSize);
x2c8_gridDimY = u32((x2c0_tileSize + triggerAABB.max.y - triggerAABB.min.y - 0.01f) / x2c0_tileSize);
x2cc_gridCellCount = (x2c4_gridDimX + 1) * (x2c8_gridDimY + 1);
x2e8_24_b4 = b4;
x2e8_27_b2 = b2;
x2e8_28 = true;
x1b4_fluidPlane = std::make_unique<CFluidPlaneCPU>(patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap,
lightmapId, unitsPerLightmapTexel, tileSize, tileSubdivisions,
fluidType, x2bc_alpha, bumpLightDir, bumpScale, uvMot,
turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax,
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin,
specularMax, reflectionBlend, reflectionSize, fluidPlaneF2);
u32Arr.reset();
x264_splashEffects.resize(3);
if (x22c_splashParticle1Id != kInvalidResId)
x264_splashEffects[0].emplace(g_SimplePool->GetObj({FOURCC('PART'), x22c_splashParticle1Id}));
if (x230_splashParticle2Id != kInvalidResId)
x264_splashEffects[1].emplace(g_SimplePool->GetObj({FOURCC('PART'), x230_splashParticle2Id}));
if (x234_splashParticle3Id != kInvalidResId)
x264_splashEffects[2].emplace(g_SimplePool->GetObj({FOURCC('PART'), x234_splashParticle3Id}));
if (x238_particle4Id != kInvalidResId)
x23c_.emplace(g_SimplePool->GetObj({FOURCC('PART'), x238_particle4Id}));
if (x24c_particle5Id != kInvalidResId)
x250_visorRunoffEffect.emplace(g_SimplePool->GetObj({FOURCC('PART'), x24c_particle5Id}));
x298_splashSounds.push_back(CSfxManager::TranslateSFXID(splashSfx1));
x298_splashSounds.push_back(CSfxManager::TranslateSFXID(splashSfx2));
x298_splashSounds.push_back(CSfxManager::TranslateSFXID(splashSfx3));
SetCalculateLighting(true);
if (lightmapId != kInvalidResId)
x90_actorLights->DisableAreaLights();
x90_actorLights->SetMaxDynamicLights(4);
x90_actorLights->SetCastShadows(false);
x90_actorLights->SetAmbientChannelOverflow(false);
x90_actorLights->SetFindNearestDynamicLights(true);
x148_24_playerInside = true;
CalculateRenderBounds();
xe6_27_ = u8(b1 ? 2 : 1);
if (!x30_24_active)
{
x2bc_alpha = 0.f;
x214_ = 0.f;
x218_ = 0.f;
}
SetupGrid(true);
}
void CScriptWater::SetupGrid(bool b)
{
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);
x2dc_.reset();
if (!x2d8_gridFlags || dimX != x2c4_gridDimX || dimY != x2c8_gridDimY)
x2d8_gridFlags.reset(new bool[dimX * dimY]);
x2c4_gridDimX = dimX;
x2c8_gridDimY = dimY;
for (int i=0 ; i<x2c8_gridDimY ; ++i)
for (int j=0 ; j<x2c4_gridDimX ; ++j)
x2d8_gridFlags[i * x2c4_gridDimX + j] = true;
if (!x2e0_patchFlags || x2d0_patchDimX != 0 || x2d4_patchDimY != 0)
x2e0_patchFlags.reset(new bool[32]);
for (int i=0 ; i<32 ; ++i)
x2e0_patchFlags[i] = true;
x2d4_patchDimY = 0;
x2d0_patchDimX = 0;
x2e8_28 = b;
} }
void CScriptWater::Think(float dt, CStateManager& mgr) { CScriptTrigger::Think(dt, mgr); } void CScriptWater::Think(float dt, CStateManager& mgr) { CScriptTrigger::Think(dt, mgr); }
@ -50,7 +134,13 @@ void CScriptWater::Touch(CActor&, CStateManager&)
void CScriptWater::CalculateRenderBounds() void CScriptWater::CalculateRenderBounds()
{ {
zeus::CVector3f aabbMin = x130_bounds.min;
aabbMin.z = x130_bounds.max.z - 1.f;
zeus::CVector3f aabbMax = x130_bounds.max;
aabbMax.z += 1.f;
zeus::CVector3f transAABBMin = aabbMin + GetTranslation();
zeus::CVector3f transAABBMax = aabbMax + GetTranslation();
x9c_renderBounds = zeus::CAABox(transAABBMin, transAABBMax);
} }
zeus::CAABox CScriptWater::GetSortingBounds(const CStateManager&) const zeus::CAABox CScriptWater::GetSortingBounds(const CStateManager&) const
@ -65,12 +155,12 @@ EWeaponCollisionResponseTypes CScriptWater::GetCollisionResponseType(const zeus:
s16 CScriptWater::GetSplashSound(float dt) const s16 CScriptWater::GetSplashSound(float dt) const
{ {
return x29c_splashSounds[GetSplashIndex(dt)]; return x298_splashSounds[GetSplashIndex(dt)];
} }
const TLockedToken<CParticleGen>& CScriptWater::GetSplashEffect(float dt) const const std::experimental::optional<TLockedToken<CGenDescription>>& CScriptWater::GetSplashEffect(float dt) const
{ {
return x268_splashEffects[GetSplashIndex(dt)]; return x264_splashEffects[GetSplashIndex(dt)];
} }
float CScriptWater::GetSplashEffectScale(float dt) const float CScriptWater::GetSplashEffectScale(float dt) const

View File

@ -13,12 +13,17 @@ class CScriptWater : public CScriptTrigger
{ {
private: private:
static const float kSplashScales[6]; static const float kSplashScales[6];
u32 x150_ = 0; zeus::CFrustum x150_frustum;
std::unique_ptr<CFluidPlaneCPU> x1b4_fluidPlane; std::unique_ptr<CFluidPlaneCPU> x1b4_fluidPlane;
zeus::CVector3f x1b8_; zeus::CVector3f x1b8_position;
zeus::CVector3f x1c4_extent;
float x1d0_f2;
zeus::CVector3f x1d4_position2;
zeus::CVector3f x1e0_extent2;
float x1ec_damage;
float x1f0_damage2;
float x1f4_; float x1f4_;
float x1f8_lightmapDoubleBlendFactor = 0.f; float x1f8_lightmapDoubleBlendFactor = 0.f;
zeus::CVector3f x1d4_;
std::list<std::pair<TUniqueId, bool>> x1fc_waterInhabitants; std::list<std::pair<TUniqueId, bool>> x1fc_waterInhabitants;
u32 x210_; u32 x210_;
float x214_; float x214_;
@ -27,46 +32,65 @@ private:
float x220_; float x220_;
float x224_; float x224_;
zeus::CColor x228_; zeus::CColor x228_;
u32 x22c_; ResId x22c_splashParticle1Id;
u32 x230_; ResId x230_splashParticle2Id;
u32 x234_; ResId x234_splashParticle3Id;
u32 x238_; ResId x238_particle4Id;
u32 x248_; std::experimental::optional<TLockedToken<CGenDescription>> x23c_;
u32 x24c_; ResId x24c_particle5Id;
std::experimental::optional<TLockedToken<CGenDescription>> x250_visorRunoffEffect; std::experimental::optional<TLockedToken<CGenDescription>> x250_visorRunoffEffect;
u16 x260_; u16 x260_;
u16 x262_visorRunoffSfx; u16 x262_visorRunoffSfx;
u32 x264_ = 0; rstl::reserved_vector<std::experimental::optional<TLockedToken<CGenDescription>>, 3> x264_splashEffects;
TLockedToken<CParticleGen> x268_splashEffects[5]; rstl::reserved_vector<u16, 3> x298_splashSounds;
u16 x29c_splashSounds[5]; zeus::CColor x2a4_c1;
u32 x2c0_tesselationSize; zeus::CColor x2a8_c2;
float x2ac_lf2;
float x2b0_lf3;
float x2b4_;
float x2b8_;
float x2bc_alpha;
float x2c0_tileSize;
u32 x2c4_gridDimX = 0; u32 x2c4_gridDimX = 0;
u32 x2c8_gridDimY = 0; u32 x2c8_gridDimY = 0;
u32 x2cc_gridCellCount = 0; u32 x2cc_gridCellCount = 0;
u32 x2d0_patchDimX = 0;
u32 x2d4_patchDimY = 0;
std::unique_ptr<bool[]> x2d8_gridFlags; std::unique_ptr<bool[]> x2d8_gridFlags;
std::unique_ptr<bool[]> x2e0_; std::unique_ptr<bool[]> x2dc_;
std::unique_ptr<bool[]> x2e0_patchFlags;
u32 x2e4_gridCellCount2 = 0; u32 x2e4_gridCellCount2 = 0;
union union
{ {
struct struct
{ {
bool x2e8_24 : 1; bool x2e8_24_b4 : 1;
bool x2e8_25 : 1; bool x2e8_25 : 1;
bool x2e8_26 : 1; bool x2e8_26 : 1;
bool x2e8_27 : 1; bool x2e8_27_b2 : 1;
bool x2e8_28 : 1; bool x2e8_28 : 1;
bool x2e8_29 : 1;
bool x2e8_30 : 1;
}; };
u32 _dummy = 0; u32 _dummy = 0;
}; };
void SetupGrid(bool b); void SetupGrid(bool b);
public: public:
CScriptWater(CStateManager&, TUniqueId, const std::string& name, const CEntityInfo&, const zeus::CVector3f&, CScriptWater(CStateManager& mgr, TUniqueId uid, const std::string& name, const CEntityInfo& info,
const zeus::CAABox&, CDamageInfo const&, zeus::CVector3f&, ETriggerFlags, bool, bool, ResId, ResId, ResId, ResId, const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo,
ResId, ResId, ResId, const zeus::CVector3f&, float, float, float, bool, CFluidPlane::EFluidType, bool, zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool b1, bool b2,
float, const CFluidUVMotion&, float, float, float, float, float, float, float, float, ResId patternMap1, ResId patternMap2, ResId colorMap, ResId bumpMap, ResId envMap,
const zeus::CColor&, const zeus::CColor&, ResId, ResId, ResId, ResId, ResId, s32, s32, s32, s32, s32, ResId envBumpMap, ResId unusedMap, const zeus::CVector3f& bumpLightDir, float bumpScale,
float, u32, float, float, float, float, float, float, float, float, const zeus::CColor&, ResId, float, float f2, float f3, bool active, CFluidPlane::EFluidType fluidType, bool b4, float alpha,
float, float, u32, u32, bool, s32, s32, const u32*); const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax,
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
float turbAmplitudeMin, const zeus::CColor& c1, const zeus::CColor& c2, ResId splashParticle1,
ResId splashParticle2, ResId splashParticle3, ResId particle4, ResId particle5, s32 i1,
s32 visorRunoffSfx, s32 splashSfx1, s32 splashSfx2, s32 splashSfx3, float tileSize,
u32 tileSubdivisions, float specularMin, float specularMax, float reflectionSize,
float fluidPlaneF2, float reflectionBlend, float slF6, float slF7, float slF8,
const zeus::CColor& c3, ResId lightmapId, float unitsPerLightmapTexel, float lF2, float lF3,
u32, u32, bool, s32, s32, std::unique_ptr<u32[]>&& u32Arr);
void Think(float, CStateManager&); void Think(float, CStateManager&);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
@ -82,7 +106,7 @@ public:
void UpdateSplashInhabitants(CStateManager&); void UpdateSplashInhabitants(CStateManager&);
s16 GetSplashSound(float) const; s16 GetSplashSound(float) const;
const TLockedToken<CParticleGen>& GetSplashEffect(float) const; const std::experimental::optional<TLockedToken<CGenDescription>>& GetSplashEffect(float) const;
float GetSplashEffectScale(float) const; float GetSplashEffectScale(float) const;
u32 GetSplashIndex(float) const; u32 GetSplashIndex(float) const;
void FluidPlane(); void FluidPlane();
@ -99,6 +123,9 @@ public:
u16 GetVisorRunoffSfx() const { return x262_visorRunoffSfx; } u16 GetVisorRunoffSfx() const { return x262_visorRunoffSfx; }
const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const; const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const;
float GetLightmapDoubleBlendFactor() const { return x1f8_lightmapDoubleBlendFactor; } float GetLightmapDoubleBlendFactor() const { return x1f8_lightmapDoubleBlendFactor; }
bool CanRenderPatch(int x, int y) const { return x2e0_patchFlags[y * x2d0_patchDimX + x]; }
u32 GetPatchDimensionX() const { return x2d0_patchDimX; }
u32 GetPatchDimensionY() const { return x2d4_patchDimY; }
}; };
} }

View File

@ -1271,7 +1271,7 @@ CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propC
u32 w22 = in.readUint32Big(); u32 w22 = in.readUint32Big();
bool b5 = in.readBool(); bool b5 = in.readBool();
u32* bitset = nullptr; std::unique_ptr<u32[]> bitset;
u32 bitVal0 = 0; u32 bitVal0 = 0;
u32 bitVal1 = 0; u32 bitVal1 = 0;
@ -1280,8 +1280,8 @@ CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propC
bitVal0 = in.readUint16Big(); bitVal0 = in.readUint16Big();
bitVal1 = in.readUint16Big(); bitVal1 = in.readUint16Big();
u32 len = ((bitVal0 * bitVal1) + 31) / 31; u32 len = ((bitVal0 * bitVal1) + 31) / 31;
bitset = new u32[len]; bitset.reset(new u32[len]);
in.readBytesToBuf(&bitset, len * 4); in.readBytesToBuf(bitset.get(), len * 4);
} }
zeus::CAABox box(-extent * 0.5f, extent * 0.5f); zeus::CAABox box(-extent * 0.5f, extent * 0.5f);
@ -1299,7 +1299,8 @@ CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propC
textureId1, textureId2, textureId3, textureId4, realTextureId5, realTextureId6, -1, otherV2, f1, f2, f3, active, textureId1, textureId2, textureId3, textureId4, realTextureId5, realTextureId6, -1, otherV2, f1, f2, f3, active,
fluidType, b4, f4, fluidMotion, f5, f6, f7, f8, f9, f10, f11, f12, c1, c2, enterParticle, partId2, partId3, fluidType, b4, f4, fluidMotion, f5, f6, f7, f8, f9, f10, f11, f12, c1, c2, enterParticle, partId2, partId3,
partId4, partId5, soundId1, soundId2, soundId3, soundId4, soundId5, f13, w19, f14, f15, f16, f17, f18, f19, partId4, partId5, soundId1, soundId2, soundId3, soundId4, soundId5, f13, w19, f14, f15, f16, f17, f18, f19,
heatWaveHeight, heatWaveSpeed, heatWaveColor, lightmap, f22, f23, f24, w21, w22, b5, bitVal0, bitVal1, bitset); heatWaveHeight, heatWaveSpeed, heatWaveColor, lightmap, f22, f23, f24, w21, w22, b5, bitVal0, bitVal1,
std::move(bitset));
} }
CEntity* ScriptLoader::LoadWarWasp(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) CEntity* ScriptLoader::LoadWarWasp(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)