From e25d2a423d963c21f604d074476fbb9f0f099fd7 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sat, 12 Aug 2017 21:56:35 -1000 Subject: [PATCH] Nearly finish CScriptWater --- DataSpec/DNAMP1/ScriptObjects/Water.hpp | 207 ++++---- Runtime/CStateManager.cpp | 19 +- Runtime/CStateManager.hpp | 1 + Runtime/Camera/CFirstPersonCamera.cpp | 4 +- Runtime/Character/CActorLights.hpp | 2 + Runtime/Graphics/CBooRenderer.cpp | 5 +- .../Graphics/Shaders/CFluidPlaneShader.cpp | 4 +- .../Graphics/Shaders/CFluidPlaneShader.hpp | 2 +- Runtime/Weapon/CEnergyProjectile.cpp | 2 +- Runtime/World/CActor.cpp | 6 +- Runtime/World/CActor.hpp | 8 +- Runtime/World/CExplosion.cpp | 2 +- Runtime/World/CFluidPlane.cpp | 4 +- Runtime/World/CFluidPlane.hpp | 4 +- Runtime/World/CFluidPlaneCPU.cpp | 302 +++++++++++- Runtime/World/CFluidPlaneCPU.hpp | 10 +- Runtime/World/CFluidPlaneManager.hpp | 1 + Runtime/World/CFluidUVMotion.cpp | 65 ++- Runtime/World/CFluidUVMotion.hpp | 24 +- Runtime/World/CPhysicsActor.cpp | 6 +- Runtime/World/CPlayer.cpp | 4 +- Runtime/World/CScriptActor.cpp | 8 +- Runtime/World/CScriptDoor.cpp | 2 +- Runtime/World/CScriptTrigger.cpp | 2 +- Runtime/World/CScriptTrigger.hpp | 3 +- Runtime/World/CScriptVisorFlare.cpp | 2 +- Runtime/World/CScriptWater.cpp | 462 ++++++++++++++++-- Runtime/World/CScriptWater.hpp | 117 +++-- Runtime/World/ScriptLoader.cpp | 153 +++--- 29 files changed, 1059 insertions(+), 372 deletions(-) diff --git a/DataSpec/DNAMP1/ScriptObjects/Water.hpp b/DataSpec/DNAMP1/ScriptObjects/Water.hpp index 8aa5f87fc..914820f44 100644 --- a/DataSpec/DNAMP1/ScriptObjects/Water.hpp +++ b/DataSpec/DNAMP1/ScriptObjects/Water.hpp @@ -16,134 +16,151 @@ struct Water : IScriptObject Value location; Value volume; DamageInfo damageInfo; - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - UniqueID32 texture1; - UniqueID32 texture2; - UniqueID32 texture3; - UniqueID32 texture4; - UniqueID32 texture5; - UniqueID32 texture6; - Value unknown5; - Value unknown6; - Value unknown7; - Value unknown8; - Value unknown9; - Value unknown10; - Value unknown11; - Value unknown12; + Value orientedForce; + Value triggerFlags; + Value thermalCold; + Value displaySurface; + UniqueID32 patternMap1; + UniqueID32 patternMap2; + UniqueID32 colorMap; + UniqueID32 bumpMap; + UniqueID32 envMap; + UniqueID32 envBumpMap; + Value bumpLightDir; + Value bumpScale; + Value morphInTime; + Value morphOutTime; + Value active; + Value fluidType; + Value unknownBool; + Value alpha; struct FluidUVMotion : BigYAML { DECL_YAML struct FluidLayerMotion : BigYAML { DECL_YAML - Value unknown1; - Value unknown2; - Value unknown3; - Value unknown4; - Value unknown5; + Value motionType; + Value timeToWrap; + Value orientation; + Value magnitude; + Value uvMul; }; - /* BIG FAT WARNING: Do NOT re-order these, even if they seem incorrect */ - FluidLayerMotion layer2; - FluidLayerMotion layer3; - FluidLayerMotion layer1; - Value unknown1; - Value unknown2; + FluidLayerMotion pattern1Layer; + FluidLayerMotion pattern2Layer; + FluidLayerMotion colorLayer; + Value timeToWrap; + Value orientation; } fluidUVMotion; - Value unknown13; - Value unknown14; - Value unknown15; - Value unknown16; - Value unknown17; - Value unknown18; - Value unknown19; - Value unknown20; - Value unknown21; - Value unknown22; - UniqueID32 particle1; - UniqueID32 particle2; - UniqueID32 particle3; + Value turbulenceSpeed; + Value turbulenceDistance; + Value turbulenceFrequencyMax; + Value turbulenceFrequencyMin; + Value turbulencePhaseMax; + Value turbulencePhaseMin; + Value turbulenceAmplitudeMax; + Value turbulenceAmplitudeMin; + Value splashColor; + Value unkColor; + UniqueID32 splashParticle1; + UniqueID32 splashParticle2; + UniqueID32 splashParticle3; UniqueID32 particle4; UniqueID32 particle5; - Value soundID1; // needs verification - Value soundID2; // needs verification - Value soundID3; // needs verification - Value soundID4; // needs verification - Value soundID5; // needs verification - Value unknown23; - Value unknown24; - Value unknown25; - Value unknown26; - Value unknown27; - Value unknown28; - Value unknown29; - Value unknown30; - Value unknown31; - Value unknown32; - Value unknown33; // CColor - UniqueID32 texture34; - Value unknown35; - Value unknown36; - Value unknown37; - Value unknown38; - Value unknown39; - Value unknown40; + Value unkSfx; + Value visorRunoffSfx; + Value splashSfx1; + Value splashSfx2; + Value splashSfx3; + Value tileSize; + Value tileSubdivisions; + Value specularMin; + Value specularMax; + Value reflectionSize; + Value rippleIntensity; + Value reflectionBlend; + Value fogBias; + Value fogMagnitude; + Value fogSpeed; + Value fogColor; // CColor + UniqueID32 lightmap; + Value unitsPerLightmapTexel; + Value alphaInTime; + Value alphaOutTime; + Value unusedInt1; + Value unusedInt2; + + struct UnusedBitset : BigYAML + { + Delete _d; + void read(athena::io::IStreamReader& in) + { + if (in.readBool()) + { + atUint32 bitVal0 = in.readUint16Big(); + atUint32 bitVal1 = in.readUint16Big(); + atUint32 len = ((bitVal0 * bitVal1) + 31) / 31; + in.seek(len * 4); + } + } + void write(athena::io::IStreamWriter& out) const { out.writeBool(false); } + void read(athena::io::YAMLDocReader& reader) {} + void write(athena::io::YAMLDocWriter& writer) const {} + size_t binarySize(size_t __isz) const { return __isz + 1; } + } unusedBitset; void nameIDs(PAKRouter& pakRouter) const { - if (texture1) + if (patternMap1) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1); + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternMap1); ent->name = name + "_tex1"; } - if (texture2) + if (patternMap2) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2); + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternMap2); ent->name = name + "_tex2"; } - if (texture3) + if (colorMap) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture3); + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(colorMap); ent->name = name + "_tex3"; } - if (texture4) + if (bumpMap) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture4); + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(bumpMap); ent->name = name + "_tex4"; } - if (texture5) + if (envMap) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture5); + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(envMap); ent->name = name + "_tex5"; } - if (texture6) + if (envBumpMap) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture6); + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(envBumpMap); ent->name = name + "_tex6"; } - if (texture34) + if (lightmap) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture34); + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(lightmap); ent->name = name + "_tex34"; } - if (particle1) + if (splashParticle1) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle1); + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle1); ent->name = name + "_part1"; } - if (particle2) + if (splashParticle2) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle2); + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle2); ent->name = name + "_part2"; } - if (particle3) + if (splashParticle3) { - PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(particle3); + PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle3); ent->name = name + "_part3"; } if (particle4) @@ -160,16 +177,16 @@ struct Water : IScriptObject void gatherDependencies(std::vector& pathsOut) const { - g_curSpec->flattenDependencies(texture1, pathsOut); - g_curSpec->flattenDependencies(texture2, pathsOut); - g_curSpec->flattenDependencies(texture3, pathsOut); - g_curSpec->flattenDependencies(texture4, pathsOut); - g_curSpec->flattenDependencies(texture5, pathsOut); - g_curSpec->flattenDependencies(texture6, pathsOut); - g_curSpec->flattenDependencies(texture34, pathsOut); - g_curSpec->flattenDependencies(particle1, pathsOut); - g_curSpec->flattenDependencies(particle2, pathsOut); - g_curSpec->flattenDependencies(particle3, pathsOut); + g_curSpec->flattenDependencies(patternMap1, pathsOut); + g_curSpec->flattenDependencies(patternMap2, pathsOut); + g_curSpec->flattenDependencies(colorMap, pathsOut); + g_curSpec->flattenDependencies(bumpMap, pathsOut); + g_curSpec->flattenDependencies(envMap, pathsOut); + g_curSpec->flattenDependencies(envBumpMap, pathsOut); + g_curSpec->flattenDependencies(lightmap, pathsOut); + g_curSpec->flattenDependencies(splashParticle1, pathsOut); + g_curSpec->flattenDependencies(splashParticle2, pathsOut); + g_curSpec->flattenDependencies(splashParticle3, pathsOut); g_curSpec->flattenDependencies(particle4, pathsOut); g_curSpec->flattenDependencies(particle5, pathsOut); } diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp index 3d46e70b8..8cb042939 100644 --- a/Runtime/CStateManager.cpp +++ b/Runtime/CStateManager.cpp @@ -709,7 +709,7 @@ void CStateManager::DrawWorld() const for (TUniqueId id : x86c_stateManagerContainer->xf370_) if (const CActor* ent = static_cast(GetObjectById(id))) - if (!thermal || ent->xe6_27_ & 0x2) + if (!thermal || ent->xe6_27_renderVisorFlags & 0x2) ent->Render(*this); bool morphingPlayerVisible = false; @@ -747,9 +747,9 @@ void CStateManager::DrawWorld() const continue; } } - if (!thermal || actor->xe6_27_ & 0x2) + if (!thermal || actor->xe6_27_renderVisorFlags & 0x2) actor->AddToRenderer(frustum, *this); - if (thermal && actor->xe6_27_ & 0x4) + if (thermal && actor->xe6_27_renderVisorFlags & 0x4) thermalActorArr[thermalActorCount++] = actor.GetPtr(); } } @@ -785,7 +785,7 @@ void CStateManager::DrawWorld() const CGraphics::SetDepthRange(0.015625f, 0.03125f); for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) if (const CActor* actor = static_cast(GetObjectById(id))) - if (actor->xe6_27_ & 0x2) + if (actor->xe6_27_renderVisorFlags & 0x2) actor->Render(*this); CGraphics::SetDepthRange(0.125f, 1.f); } @@ -793,7 +793,7 @@ void CStateManager::DrawWorld() const for (TUniqueId id : x86c_stateManagerContainer->xf370_) if (const CActor* actor = static_cast(GetObjectById(id))) - if (actor->xe6_27_ & 0x4) + if (actor->xe6_27_renderVisorFlags & 0x4) actor->Render(*this); for (int i=areaCount-1 ; i>=0 ; --i) @@ -856,7 +856,7 @@ void CStateManager::DrawWorld() const CGraphics::SetDepthRange(0.015625f, 0.03125f); for (TUniqueId id : x86c_stateManagerContainer->xf39c_renderLast) if (const CActor* actor = static_cast(GetObjectById(id))) - if (actor->xe6_27_ & 0x4) + if (actor->xe6_27_renderVisorFlags & 0x4) actor->Render(*this); CGraphics::SetDepthRange(0.125f, 1.f); } @@ -2560,6 +2560,13 @@ void CStateManager::SetBossParams(TUniqueId bossId, float maxEnergy, u32 stringI xf20_bossStringIdx = stringIdx; } +float CStateManager::IntegrateVisorFog(float f) const +{ + if (x8b8_playerState->GetActiveVisor(*this) == CPlayerState::EPlayerVisor::Scan) + return (1.f - x8b8_playerState->GetVisorTransitionFactor()) * f; + return f; +} + float CStateManager::g_EscapeShakeCountdown; bool CStateManager::g_EscapeShakeCountdownInit = false; } diff --git a/Runtime/CStateManager.hpp b/Runtime/CStateManager.hpp index 63a8ca235..adf77d754 100644 --- a/Runtime/CStateManager.hpp +++ b/Runtime/CStateManager.hpp @@ -461,6 +461,7 @@ public: void SetViewportScale(const zeus::CVector2f& scale) { xf2c_viewportScale = scale; } float GetThermalColdScale2() const { return xf28_thermColdScale2; } void SetThermalColdScale2(float s) { xf28_thermColdScale2 = s; } + float IntegrateVisorFog(float f) const; static float g_EscapeShakeCountdown; static bool g_EscapeShakeCountdownInit; diff --git a/Runtime/Camera/CFirstPersonCamera.cpp b/Runtime/Camera/CFirstPersonCamera.cpp index 283b521b0..4b46a8950 100644 --- a/Runtime/Camera/CFirstPersonCamera.cpp +++ b/Runtime/Camera/CFirstPersonCamera.cpp @@ -77,7 +77,7 @@ void CFirstPersonCamera::UpdateTransform(CStateManager& mgr, float dt) x34_transform = zeus::CTransform::Identity(); xe4_27_ = true; xe4_28_ = true; - xe4_29_ = true; + xe4_29_actorLightsDirty = true; return; } @@ -262,7 +262,7 @@ void CFirstPersonCamera::UpdateTransform(CStateManager& mgr, float dt) xe4_27_ = true; xe4_28_ = true; xe4_28_ = true; - xe4_29_ = true; + xe4_29_actorLightsDirty = true; CActor::SetTranslation(x190_gunFollowXf.origin + player->GetTransform().rotate(bobXf.origin)); x190_gunFollowXf.orthonormalize(); diff --git a/Runtime/Character/CActorLights.hpp b/Runtime/Character/CActorLights.hpp index eef3865d9..729d0b07c 100644 --- a/Runtime/Character/CActorLights.hpp +++ b/Runtime/Character/CActorLights.hpp @@ -84,8 +84,10 @@ public: const zeus::CColor& GetAmbientColor() const { return x288_ambientColor; } const CLight& GetLight(u32 idx) const; u32 GetActiveLightCount() const; + int GetMaxAreaLights() const { return x2b8_maxAreaLights; } const std::vector& GetAreaLights() const { return x0_areaLights; } const std::vector& GetDynamicLights() const { return x144_dynamicLights; } + bool GetIsDirty() const { return x298_24_dirty; } }; } diff --git a/Runtime/Graphics/CBooRenderer.cpp b/Runtime/Graphics/CBooRenderer.cpp index 0b2c8d85b..4c5c3455c 100644 --- a/Runtime/Graphics/CBooRenderer.cpp +++ b/Runtime/Graphics/CBooRenderer.cpp @@ -1146,8 +1146,11 @@ void CBooRenderer::SetWorldFog(ERglFogMode mode, float startz, float endz, const CGraphics::SetFog(mode, startz, endz, color); } -void CBooRenderer::RenderFogVolume(const zeus::CColor&, const zeus::CAABox&, const TLockedToken*, const CSkinnedModel*) +void CBooRenderer::RenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, + const TLockedToken* model, const CSkinnedModel* sModel) { + if (!x318_28_disableFog) + x2ac_fogVolumes.emplace_back(CGraphics::g_GXModelMatrix, color, aabb, model, sModel); } void CBooRenderer::SetThermal(bool thermal, float level, const zeus::CColor& color) diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp index 063313cdb..2fa2023a6 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShader.cpp @@ -124,7 +124,7 @@ CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type, const std::experimental::optional>& envMap, const std::experimental::optional>& envBumpMap, const std::experimental::optional>& lightmap, - bool doubleLightmapBlend, bool additive) + bool doubleLightmapBlend, bool additive, u32 maxVertCount) : m_patternTex1(patternTex1), m_patternTex2(patternTex2), m_colorTex(colorTex), @@ -147,7 +147,7 @@ CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type, m_gfxTok = CGraphics::CommitResources( [&](boo::IGraphicsDataFactory::Context& ctx) { - m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), 999); // TODO: Figure out how many + m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount); m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, 1024, 1); switch (ctx.platform()) diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp b/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp index 742e3b53e..eb62a6ced 100644 --- a/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp +++ b/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp @@ -114,7 +114,7 @@ public: const std::experimental::optional>& envMap, const std::experimental::optional>& envBumpMap, const std::experimental::optional>& lightmap, - bool doubleLightmapBlend, bool additive); + bool doubleLightmapBlend, bool additive, u32 maxVertCount); void prepareDraw(const zeus::CMatrix4f* texMtxs, const zeus::CMatrix4f& normMtx, float indScale, const std::vector& lights, const zeus::CColor* kColors); void loadVerts(const std::vector& verts); diff --git a/Runtime/Weapon/CEnergyProjectile.cpp b/Runtime/Weapon/CEnergyProjectile.cpp index ea12df16d..1ee8d0d0d 100644 --- a/Runtime/Weapon/CEnergyProjectile.cpp +++ b/Runtime/Weapon/CEnergyProjectile.cpp @@ -14,7 +14,7 @@ CEnergyProjectile::CEnergyProjectile(bool active, const TToken& particle, TUniqueId xf4_24_ = flags & 0x4; xf4_25_ = true; xf4_26_ = flags & 0x8; - xe6_27_ = flags & 0x1 ? 1 : 2; + xe6_27_renderVisorFlags = flags & 0x1 ? 1 : 2; xe8_particleGen->SetGlobalTranslation(xf.origin); xe8_particleGen->SetOrientation(xf.getRotation()); xe8_particleGen->SetGlobalScale(scale); diff --git a/Runtime/World/CFluidPlane.cpp b/Runtime/World/CFluidPlane.cpp index 2827eacfe..d73f9b913 100644 --- a/Runtime/World/CFluidPlane.cpp +++ b/Runtime/World/CFluidPlane.cpp @@ -6,9 +6,9 @@ namespace urde { CFluidPlane::CFluidPlane(ResId texPattern1, ResId texPattern2, ResId texColor, float alpha, EFluidType fluidType, - float f2, const CFluidUVMotion& motion) + float rippleIntensity, const CFluidUVMotion& motion) : x4_texPattern1Id(texPattern1), x8_texPattern2Id(texPattern2), xc_texColorId(texColor), x40_alpha(alpha), - x44_fluidType(fluidType), x48_f2(f2), x4c_uvMotion(motion) + x44_fluidType(fluidType), x48_rippleIntensity(rippleIntensity), x4c_uvMotion(motion) { if (g_ResFactory->GetResourceTypeById(texPattern1) == FOURCC('TXTR')) x10_texPattern1.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern1})); diff --git a/Runtime/World/CFluidPlane.hpp b/Runtime/World/CFluidPlane.hpp index 886e0a655..4052e0111 100644 --- a/Runtime/World/CFluidPlane.hpp +++ b/Runtime/World/CFluidPlane.hpp @@ -36,11 +36,11 @@ protected: std::experimental::optional> x30_texColor; float x40_alpha; EFluidType x44_fluidType; - float x48_f2; + float x48_rippleIntensity; CFluidUVMotion x4c_uvMotion; public: CFluidPlane(ResId texPattern1, ResId texPattern2, ResId texColor, float alpha, EFluidType fluidType, - float f2, const CFluidUVMotion& motion); + float rippleIntensity, const CFluidUVMotion& motion); virtual void Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos, CScriptWater& water, CStateManager& mgr); diff --git a/Runtime/World/CFluidPlaneCPU.cpp b/Runtime/World/CFluidPlaneCPU.cpp index a1c0e3a31..23b0a7fe1 100644 --- a/Runtime/World/CFluidPlaneCPU.cpp +++ b/Runtime/World/CFluidPlaneCPU.cpp @@ -50,8 +50,8 @@ CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texCo float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend, float reflectionSize, - float fluidPlaneF2) -: CFluidPlane(texPattern1, texPattern2, texColor, alpha, fluidType, fluidPlaneF2, mot), + float rippleIntensity, u32 maxVertCount) +: CFluidPlane(texPattern1, texPattern2, texColor, alpha, fluidType, rippleIntensity, mot), 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), @@ -59,7 +59,8 @@ CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texCo x10c_specularMin(specularMin), x110_specularMax(specularMax), x114_reflectionBlend(reflectionBlend), x118_reflectionSize(reflectionSize), x11c_unitsPerLightmapTexel(unitsPerLightmapTexel), x120_turbulence(turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax, - turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin) + turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin), + m_maxVertCount(maxVertCount) { if (g_ResFactory->GetResourceTypeById(xa0_texIdBumpMap) == FOURCC('TXTR')) xb0_bumpMap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa0_texIdBumpMap})); @@ -223,7 +224,7 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C const CGameArea* area = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()); float lightLevel = area->GetPostConstructed()->x1128_worldLightingLevel; const CScriptWater* nextWater = water->GetNextConnectedWater(mgr); - if (std::fabs(water->GetLightmapDoubleBlendFactor()) < 0.00001f || !nextWater || + if (std::fabs(water->GetMorphFactor()) < 0.00001f || !nextWater || !nextWater->GetFluidPlane().HasLightMap()) { lightmapId = curTex; @@ -233,7 +234,7 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C } else if (nextWater && nextWater->GetFluidPlane().HasLightMap()) { - if (std::fabs(water->GetLightmapDoubleBlendFactor() - 1.f) < 0.00001f) + if (std::fabs(water->GetMorphFactor() - 1.f) < 0.00001f) { lightmapId = curTex; // Load lightmap @@ -250,9 +251,9 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]); // Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY - float lum = lightLevel * water->GetLightmapDoubleBlendFactor(); + float lum = lightLevel * water->GetMorphFactor(); out.kColors[3] = zeus::CColor(lum, 1.f); - lowLightBlend = (1.f - water->GetLightmapDoubleBlendFactor()) / (1.f - lum); + lowLightBlend = (1.f - water->GetMorphFactor()) / (1.f - lum); doubleLightmapBlend = true; } } @@ -269,11 +270,15 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C zeus::CColor((1.f - waterPlaneOrthoDot) * (x110_specularMax - x10c_specularMin) + x10c_specularMin, alpha); out.kColors[1] = zeus::CColor(x114_reflectionBlend, 1.f); - // TODO: Detect parameter changes and rebuild if needed - if (!m_shader) + if (!m_shader || m_cachedDoubleLightmapBlend != doubleLightmapBlend || + m_cachedAdditive != (mgr.GetParticleFlags() == 0)) + { + m_cachedDoubleLightmapBlend = doubleLightmapBlend; + m_cachedAdditive = mgr.GetParticleFlags() == 0; m_shader.emplace(x44_fluidType, x10_texPattern1, x20_texPattern2, x30_texColor, xb0_bumpMap, xc0_envMap, xd0_envBumpMap, - xe0_lightmap, doubleLightmapBlend, mgr.GetParticleFlags() == 0); + xe0_lightmap, m_cachedDoubleLightmapBlend, m_cachedAdditive, m_maxVertCount); + } return out; } @@ -369,6 +374,16 @@ public: s8 ny; s8 nz; u8 wavecapIntensity; + + zeus::CVector3f MakeNormal() const { return {nx / 63.f, ny / 63.f, nz / 63.f}; } + zeus::CVector3f MakeBinormal() const { return {nx / 63.f, nz / 63.f, -ny / 63.f}; } + zeus::CVector3f MakeTangent() const { return {nz / 63.f, ny / 63.f, -nx / 63.f}; } + zeus::CColor MakeColor(const CFluidPlaneCPURender::SPatchInfo& info) const + { + return {(wavecapIntensity >> info.x34_redShift) / 255.f, + (wavecapIntensity >> info.x35_greenShift) / 255.f, + (wavecapIntensity >> info.x36_blueShift) / 255.f}; + } }; }; @@ -427,7 +442,8 @@ static void ApplyTurbulence(float t, CFluidPlaneCPURender::SHFieldSample (&heigh float distFac = curX * curX + curYSq; if (distFac != 0.f) distFac = std::sqrt(distFac); - heights[i][j].height = fluidPane.GetTurbulenceHeight(fluidPane.GetOOTurbulenceDistance() * distFac + scaledT); + heights[i][j].height = + fluidPane.GetTurbulenceHeight(fluidPane.GetOOTurbulenceDistance() * distFac + scaledT); curX += info.x18_rippleResolution; } curY += info.x18_rippleResolution; @@ -561,7 +577,8 @@ 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)]; } else { @@ -581,7 +598,6 @@ static void ApplyRipple(const CFluidPlaneCPURender::SRippleInfo& rippleInfo, curYDiv = nextYDiv; curGridY += info.x2a_gridDimX; } - } static void ApplyRipples(const rstl::reserved_vector& rippleInfos, @@ -600,7 +616,7 @@ static void ApplyRipples(const rstl::reserved_vector& vOut) { + int yTile = (startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile - 1) / + CFluidPlaneCPURender::numSubdivisionsInTile; + int endXTile = (info.x0_xSubdivs + CFluidPlaneCPURender::numSubdivisionsInTile - 4) / + CFluidPlaneCPURender::numSubdivisionsInTile; + int midDiv = CFluidPlaneCPURender::numSubdivisionsInTile / 2; + 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); + int xTile = 1; + int tileSpan; + for (int i = 1 ; i < info.x0_xSubdivs - 2 ; + i += CFluidPlaneCPURender::numSubdivisionsInTile * tileSpan, gridCell += tileSpan, + xTile += tileSpan, curX += info.x14_tileSize * tileSpan) + { + tileSpan = 1; + if (info.x30_gridFlags && !info.x30_gridFlags[gridCell]) + continue; + + if ((flags[yTile][xTile] & 0x1f) == 0x1f) + { + for (; xTile+tileSpan<=endXTile ; ++tileSpan) + { + if ((flags[yTile][xTile+tileSpan] & 0x1f) != 0x1f) + break; + if (info.x30_gridFlags && !info.x30_gridFlags[gridCell+tileSpan]) + break; + } + + int stripDivCount = tileSpan * CFluidPlaneCPURender::numSubdivisionsInTile + 1; + int remSubdivs = CFluidPlaneCPURender::numSubdivisionsInTile; + std::function func; + + switch (info.x37_normalMode) + { + case CFluidPlaneCPURender::NormalMode::None: + func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp) + { + vOut.emplace_back(zeus::CVector3f(x, y, samp.height)); + }; + break; + case CFluidPlaneCPURender::NormalMode::NoNormals: + func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp) + { + vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeColor(info)); + }; + break; + case CFluidPlaneCPURender::NormalMode::Normals: + func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp) + { + vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), + samp.MakeColor(info)); + }; + break; + case CFluidPlaneCPURender::NormalMode::NBT: + func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp) + { + vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), + samp.MakeBinormal(), samp.MakeTangent(), samp.MakeColor(info)); + }; + break; + } + + float curTileY = yMin; + int curYDiv = startYDiv; + for (; remSubdivs>0 ; --remSubdivs, ++curYDiv, curTileY+=info.x18_rippleResolution) + { + size_t start = vOut.size(); + float curTileX = xMin; + for (int v=0 ; v toStrip(vOut); + std::function func; + + switch (info.x37_normalMode) + { + case CFluidPlaneCPURender::NormalMode::None: + func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp) + { + toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height)); + }; + break; + case CFluidPlaneCPURender::NormalMode::NoNormals: + func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp) + { + toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeColor(info)); + }; + break; + case CFluidPlaneCPURender::NormalMode::Normals: + func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp) + { + toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), + samp.MakeColor(info)); + }; + break; + case CFluidPlaneCPURender::NormalMode::NBT: + func = [&](float x, float y, const CFluidPlaneCPURender::SHFieldSample& samp) + { + toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(), + samp.MakeBinormal(), samp.MakeTangent(), samp.MakeColor(info)); + }; + break; + } + + func(tileMid + xMin, yMid, heights[startYDiv+midDiv][i+midDiv]); + + int curXDiv = i; + int curYDiv = startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile; + float curTileX = xMin; + float curTileY = yMin + info.x14_tileSize; + for (int v=0 ; v<(r19 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v) + { + const CFluidPlaneCPURender::SHFieldSample& samp = heights[curYDiv][curXDiv+v]; + func(curTileX, curTileY, samp); + curTileX += info.x18_rippleResolution; + } + + curXDiv = i + CFluidPlaneCPURender::numSubdivisionsInTile; + curYDiv = startYDiv + CFluidPlaneCPURender::numSubdivisionsInTile; + curTileX = xMin + info.x14_tileSize; + curTileY = yMin + info.x14_tileSize; + for (int v=0 ; v<(r18 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v) + { + const CFluidPlaneCPURender::SHFieldSample& samp = heights[curYDiv-v][curXDiv]; + func(curTileX, curTileY, samp); + curTileY -= info.x18_rippleResolution; + } + + curXDiv = i + CFluidPlaneCPURender::numSubdivisionsInTile; + curYDiv = startYDiv; + curTileX = xMin + info.x14_tileSize; + curTileY = yMin; + for (int v=0 ; v<(r17 ? CFluidPlaneCPURender::numSubdivisionsInTile : 1) ; ++v) + { + const CFluidPlaneCPURender::SHFieldSample& samp = heights[curYDiv][curXDiv-v]; + func(curTileX, curTileY, samp); + curTileX -= info.x18_rippleResolution; + } + + curXDiv = i; + curYDiv = startYDiv; + curTileX = xMin; + curTileY = yMin; + if (r16) + { + for (int v=0 ; v m_verts; mutable std::experimental::optional m_shader; + mutable bool m_cachedDoubleLightmapBlend; + mutable bool m_cachedAdditive; struct RenderSetupInfo { @@ -73,7 +77,7 @@ public: const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend, - float reflectionSize, float fluidPlaneF2); + float reflectionSize, float rippleIntensity, u32 maxVertCount); void CreateRipple(const CRipple& ripple, CStateManager& mgr); void CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf, const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const; @@ -100,7 +104,7 @@ public: const CTexture& GetLightMap() const { return **xe0_lightmap; } const zeus::CVector3f& GetBumpLightDir() const { return xf0_bumpLightDir; } float GetTileSize() const { return x100_tileSize; } - u32 GetTileSubdivisions() const { return x104_tileSubdivisions; } + int GetTileSubdivisions() const { return x104_tileSubdivisions; } float GetRippleResolution() const { return x108_rippleResolution; } float GetTurbulenceHeight(float sel) const { return x120_turbulence.GetHeight(sel); } float GetOOTurbulenceDistance() const { return x120_turbulence.GetOODistance(); } diff --git a/Runtime/World/CFluidPlaneManager.hpp b/Runtime/World/CFluidPlaneManager.hpp index c65664fff..3ece15dcc 100644 --- a/Runtime/World/CFluidPlaneManager.hpp +++ b/Runtime/World/CFluidPlaneManager.hpp @@ -48,6 +48,7 @@ public: void CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water, const zeus::CVector3f& pos, float factor, bool); rstl::reserved_vector& SplashRecords() { return x18_splashes; } + const CRippleManager& GetRippleManager() const { return x0_rippleManager; } }; } diff --git a/Runtime/World/CFluidUVMotion.cpp b/Runtime/World/CFluidUVMotion.cpp index fca804907..2b941a858 100644 --- a/Runtime/World/CFluidUVMotion.cpp +++ b/Runtime/World/CFluidUVMotion.cpp @@ -4,58 +4,69 @@ namespace urde { -CFluidUVMotion::CFluidUVMotion(float a, float b, const CFluidUVMotion::SFluidLayerMotion& c, - const CFluidUVMotion::SFluidLayerMotion& d, const CFluidUVMotion::SFluidLayerMotion& e) -: x4c_(1.f/a) -, x50_(b) +CFluidUVMotion::CFluidUVMotion(float timeToWrap, float orientation, + const CFluidUVMotion::SFluidLayerMotion& colorLayer, + const CFluidUVMotion::SFluidLayerMotion& pattern1Layer, + const CFluidUVMotion::SFluidLayerMotion& pattern2Layer) +: x4c_ooTimeToWrap(1.f / timeToWrap) +, x50_orientation(orientation) { x0_fluidLayers.resize(3); - x0_fluidLayers[0] = c; - x0_fluidLayers[1] = d; - x0_fluidLayers[2] = e; + x0_fluidLayers[0] = colorLayer; + x0_fluidLayers[1] = pattern1Layer; + x0_fluidLayers[2] = pattern2Layer; } -CFluidUVMotion::CFluidUVMotion(float, float) -{} - -void CFluidUVMotion::CalculateFluidTextureOffset(float f31, float offsets[3][2]) const +CFluidUVMotion::CFluidUVMotion(float timeToWrap, float orientation) +: x4c_ooTimeToWrap(1.f / timeToWrap), x50_orientation(orientation) { - float f28 = (f31 * x4c_) * zeus::fastCosF(x50_); - float f29 = (f31 * x4c_) / zeus::fastSinF(x50_); + x0_fluidLayers.resize(3); + x0_fluidLayers[0].x4_ooTimeToWrap = 0.001f; + x0_fluidLayers[1].x4_ooTimeToWrap = 0.33333334f; + x0_fluidLayers[2].x4_ooTimeToWrap = 0.2f; + x0_fluidLayers[2].x8_orientation = 0.78539819f; +} + +void CFluidUVMotion::CalculateFluidTextureOffset(float t, float offsets[3][2]) const +{ + float totalYOffset = (t * x4c_ooTimeToWrap) * zeus::fastCosF(x50_orientation); + float totalXOffset = (t * x4c_ooTimeToWrap) * zeus::fastSinF(x50_orientation); for (u32 i = 0 ; i x0_fluidLayers; - float x4c_; - float x50_; + float x4c_ooTimeToWrap; + float x50_orientation; public: - CFluidUVMotion(float a, float b, const SFluidLayerMotion& c, const SFluidLayerMotion& d, const SFluidLayerMotion& e); - CFluidUVMotion(float, float); + CFluidUVMotion(float timeToWrap, float orientation, const SFluidLayerMotion& colorLayer, + const SFluidLayerMotion& pattern1Layer, const SFluidLayerMotion& pattern2Layer); + CFluidUVMotion(float timeToWrap, float orientation); const rstl::reserved_vector& GetFluidLayers() const { return x0_fluidLayers; } - void GetOrientation() const; - void GetOOTimeToWrapTexPage() const; + float GetOrientation() const { return x50_orientation; } + float GetOOTimeToWrapTexPage() const { return x4c_ooTimeToWrap; } void CalculateFluidTextureOffset(float, float[3][2]) const; }; } diff --git a/Runtime/World/CPhysicsActor.cpp b/Runtime/World/CPhysicsActor.cpp index 4005c2f17..194b8b289 100644 --- a/Runtime/World/CPhysicsActor.cpp +++ b/Runtime/World/CPhysicsActor.cpp @@ -103,7 +103,7 @@ void CPhysicsActor::AddMotionState(const CMotionState& mst) xe4_27_ = true; xe4_28_ = true; - xe4_29_ = true; + xe4_29_actorLightsDirty = true; SetTranslation(x34_transform.origin + mst.x0_translation); @@ -123,7 +123,7 @@ void CPhysicsActor::SetMotionState(const CMotionState& mst) xe4_27_ = true; xe4_28_ = true; - xe4_29_ = true; + xe4_29_actorLightsDirty = true; SetTranslation(mst.x0_translation); xfc_constantForce = mst.x1c_velocity; @@ -268,7 +268,7 @@ void CPhysicsActor::SetPhysicsState(const CPhysicsState& state) x34_transform = zeus::CTransform(state.GetOrientation(), x34_transform.origin); xe4_27_ = true; xe4_28_ = true; - xe4_29_ = true; + xe4_29_actorLightsDirty = true; xfc_constantForce = state.GetConstantForceWR(); x108_angularMomentum = state.GetAngularMomentumWR(); diff --git a/Runtime/World/CPlayer.cpp b/Runtime/World/CPlayer.cpp index cfbdb611e..d52429964 100644 --- a/Runtime/World/CPlayer.cpp +++ b/Runtime/World/CPlayer.cpp @@ -2554,7 +2554,7 @@ void CPlayer::ApplyGrappleForces(const CFinalInput& input, CStateManager& mgr, f zeus::CTransform(x3c0_grappleSwingAxis, swingForward, zeus::CVector3f::skUp, GetTranslation()); xe4_27_ = true; xe4_28_ = true; - xe4_29_ = true; + xe4_29_actorLightsDirty = true; SetVelocityWR(pullVec); if (!ValidateFPPosition(GetTranslation(), mgr)) @@ -2563,7 +2563,7 @@ void CPlayer::ApplyGrappleForces(const CFinalInput& input, CStateManager& mgr, f x34_transform = backupXf; xe4_27_ = true; xe4_28_ = true; - xe4_29_ = true; + xe4_29_actorLightsDirty = true; SetVelocityWR(backupVel); } } diff --git a/Runtime/World/CScriptActor.cpp b/Runtime/World/CScriptActor.cpp index 8db1ab787..22bf8e9e3 100644 --- a/Runtime/World/CScriptActor.cpp +++ b/Runtime/World/CScriptActor.cpp @@ -127,10 +127,10 @@ void CScriptActor::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { CActor::PreRender(mgr, frustum); - if (xe4_30_ && TCastToPtr(mgr.GetCameraManager()->GetCurrentCamera(mgr))) - xe4_30_ = false; + if (xe4_30_outOfFrustum && TCastToPtr(mgr.GetCameraManager()->GetCurrentCamera(mgr))) + xe4_30_outOfFrustum = false; - if (xe4_30_ && !x2e2_29_ && !x2e2_27_) + if (xe4_30_outOfFrustum && !x2e2_29_ && !x2e2_27_) { zeus::CColor col(1.f, 1.f, x2dc_xrayAlpha); if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) @@ -154,7 +154,7 @@ void CScriptActor::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) } } - if (!x2e2_24_ && xe6_27_ == 2 && + if (!x2e2_24_ && xe6_27_renderVisorFlags == 2 && mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) { xb4_drawFlags.x2_flags &= ~3; diff --git a/Runtime/World/CScriptDoor.cpp b/Runtime/World/CScriptDoor.cpp index 91c346608..ce6b3ab48 100644 --- a/Runtime/World/CScriptDoor.cpp +++ b/Runtime/World/CScriptDoor.cpp @@ -79,7 +79,7 @@ void CScriptDoor::Think(float dt, CStateManager& mgr) void CScriptDoor::AddToRenderer(const zeus::CFrustum& /*frustum*/, CStateManager &mgr) { - if (!xe4_30_) + if (!xe4_30_outOfFrustum) CPhysicsActor::Render(mgr); } diff --git a/Runtime/World/CScriptTrigger.cpp b/Runtime/World/CScriptTrigger.cpp index 67af517c6..249ca64c4 100644 --- a/Runtime/World/CScriptTrigger.cpp +++ b/Runtime/World/CScriptTrigger.cpp @@ -44,7 +44,7 @@ void CScriptTrigger::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CS if (msg == EScriptObjectMessage::Deactivate) { xe8_inhabitants.clear(); - x148_25_ = false; + x148_25_camSubmerged = false; } if (x148_28_) diff --git a/Runtime/World/CScriptTrigger.hpp b/Runtime/World/CScriptTrigger.hpp index 8898994c8..e5e56280c 100644 --- a/Runtime/World/CScriptTrigger.hpp +++ b/Runtime/World/CScriptTrigger.hpp @@ -58,7 +58,7 @@ protected: struct { bool x148_24_playerInside : 1; - bool x148_25_ : 1; + bool x148_25_camSubmerged : 1; bool x148_26_deactivateOnEntered : 1; bool x148_27_deactivateOnExited : 1; bool x148_28_ : 1; @@ -84,6 +84,7 @@ public: std::list& GetInhabitants(); rstl::optional_object GetTouchBounds() const; void Touch(CActor &, CStateManager &); + const zeus::CAABox& GetTriggerBoundsOR() const { return x130_bounds; } zeus::CAABox GetTriggerBoundsWR() const; const CDamageInfo& GetDamageInfo() const { return x100_damageInfo; } ETriggerFlags GetTriggerFlags() const { return x12c_flags; } diff --git a/Runtime/World/CScriptVisorFlare.cpp b/Runtime/World/CScriptVisorFlare.cpp index 5477b9354..91e894f94 100644 --- a/Runtime/World/CScriptVisorFlare.cpp +++ b/Runtime/World/CScriptVisorFlare.cpp @@ -16,7 +16,7 @@ CScriptVisorFlare::CScriptVisorFlare(TUniqueId uid, const std::string& name, con CMaterialList(EMaterialTypes::Unknown), CActorParameters::None(), kInvalidUniqueId), xe8_flare(blendMode, b1, f1, f2, f3, w1, w2, flares) { - xe6_27_ = 2; + xe6_27_renderVisorFlags = 2; } void CScriptVisorFlare::Accept(IVisitor& visitor) diff --git a/Runtime/World/CScriptWater.cpp b/Runtime/World/CScriptWater.cpp index f64acb291..818d6136c 100644 --- a/Runtime/World/CScriptWater.cpp +++ b/Runtime/World/CScriptWater.cpp @@ -3,6 +3,9 @@ #include "TCastTo.hpp" #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" +#include "World/CWorld.hpp" +#include "Graphics/CBooRenderer.hpp" +#include "Camera/CGameCamera.hpp" namespace urde { @@ -15,42 +18,49 @@ const float CScriptWater::kSplashScales[6] = 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, - zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool b1, bool b2, - ResId patternMap1, ResId patternMap2, ResId colorMap, ResId bumpMap, ResId envMap, - ResId envBumpMap, ResId unusedMap, const zeus::CVector3f& bumpLightDir, float bumpScale, - float f2, float f3, bool active, CFluidPlane::EFluidType fluidType, bool b4, float alpha, - 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, + zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool thermalCold, + bool allowRender, ResId patternMap1, ResId patternMap2, ResId colorMap, ResId bumpMap, + ResId envMap, ResId envBumpMap, ResId unusedMap, const zeus::CVector3f& bumpLightDir, + float bumpScale, float morphInTime, float morphOutTime, bool active, + CFluidPlane::EFluidType fluidType, bool b4, float alpha, const CFluidUVMotion& uvMot, + float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin, + float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbAmplitudeMin, + const zeus::CColor& splashColor, const zeus::CColor& unkColor, ResId splashParticle1, + ResId splashParticle2, ResId splashParticle3, ResId particle4, ResId particle5, s32 unkSfx, 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&& u32Arr) + float rippleIntensity, float reflectionBlend, float fogBias, float fogMagnitude, + float fogSpeed, const zeus::CColor& fogColor, ResId lightmapId, float unitsPerLightmapTexel, + float alphaInTime, float alphaOutTime, u32, u32, bool, s32, s32, + std::unique_ptr&& 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), + x1b8_positionMorphed(pos), x1c4_extentMorphed(box.max - box.min), x1d0_morphInTime(morphInTime), x1d4_positionOrig(pos), + x1e0_extentOrig(box.max - box.min), x1ec_damageOrig(dInfo.GetDamage()), x1f0_damageMorphed(dInfo.GetDamage()), + x1f4_morphOutTime(morphOutTime), x214_fogBias(fogBias), x218_fogMagnitude(fogMagnitude), x21c_origFogBias(fogBias), + x220_origFogMagnitude(fogMagnitude), x224_fogSpeed(fogSpeed), x228_fogColor(fogColor), + 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) + x260_unkSfx(CSfxManager::TranslateSFXID(unkSfx)), x262_visorRunoffSfx(CSfxManager::TranslateSFXID(visorRunoffSfx)), + x2a4_splashColor(splashColor), x2a8_unkColor(unkColor), x2ac_alphaInTime(alphaInTime), x2b0_alphaOutTime(alphaOutTime), + x2b4_alphaInRecip((alphaInTime != 0.f) ? 1.f / alphaInTime : 0.f), + x2b8_alphaOutRecip((alphaOutTime != 0.f) ? 1.f / alphaOutTime : 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; + x2e8_27_allowRender = allowRender; + x2e8_28_recomputeClipping = true; x1b4_fluidPlane = std::make_unique(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); + specularMax, reflectionBlend, reflectionSize, rippleIntensity, + x2cc_gridCellCount * + ((std::max(u32(2), tileSubdivisions) * 4 + 2) * 4)); u32Arr.reset(); x264_splashEffects.resize(3); if (x22c_splashParticle1Id != kInvalidResId) @@ -75,61 +85,410 @@ CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, const std::string& x90_actorLights->SetFindNearestDynamicLights(true); x148_24_playerInside = true; CalculateRenderBounds(); - xe6_27_ = u8(b1 ? 2 : 1); + xe6_27_renderVisorFlags = u8(thermalCold ? 2 : 1); if (!x30_24_active) { x2bc_alpha = 0.f; - x214_ = 0.f; - x218_ = 0.f; + x214_fogBias = 0.f; + x218_fogMagnitude = 0.f; } SetupGrid(true); } -void CScriptWater::SetupGrid(bool b) +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); - x2dc_.reset(); - if (!x2d8_gridFlags || dimX != x2c4_gridDimX || dimY != x2c8_gridDimY) - x2d8_gridFlags.reset(new bool[dimX * dimY]); + x2dc_vertIntersects.reset(); + if (!x2d8_tileIntersects || dimX != x2c4_gridDimX || dimY != x2c8_gridDimY) + x2d8_tileIntersects.reset(new bool[dimX * dimY]); x2c4_gridDimX = dimX; x2c8_gridDimY = dimY; for (int i=0 ; i= x2cc_gridCellCount) + return; + + if (!x2dc_vertIntersects) + x2dc_vertIntersects.reset(new bool[(x2c4_gridDimX + 1) * (x2c8_gridDimY + 1)]); + 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)); + 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) + { + zeus::CVector3f pos = basePos; + pos.x += xOffset; + pos.y += yOffset; + x2dc_vertIntersects[i] = mgr.RayStaticIntersection(pos, zeus::CVector3f::skDown, mag, SolidFilter).IsValid(); + gridDiv.rem += 1; + xOffset += x2c0_tileSize; + if (gridDiv.rem > x2c4_gridDimX) + { + yOffset += x2c0_tileSize; + xOffset = 0.f; + gridDiv.rem = 0; + } + } + x2e4_gridCellCount2 += computeVerts; + if (x2e4_gridCellCount2 < x2cc_gridCellCount) + return; + + x2e4_gridCellCount2 = x2cc_gridCellCount; + x2d8_tileIntersects.reset(new bool[x2c4_gridDimX * x2c8_gridDimY]); + + for (int i = 0; i < x2c8_gridDimY; ++i) + { + int rowBase = x2c4_gridDimX * i; + int nextRowBase = (x2c4_gridDimX + 1) * i; + for (int j = 0; j < x2c4_gridDimX; ++j) + { + x2d8_tileIntersects[rowBase + j] = + x2dc_vertIntersects[nextRowBase + j] || + x2dc_vertIntersects[nextRowBase + j + 1] || + x2dc_vertIntersects[nextRowBase + j + x2c4_gridDimX + 1] || + x2dc_vertIntersects[nextRowBase + j + x2c4_gridDimX + 2]; + } + } + + int tilesPerPatch = std::min(42 / x1b4_fluidPlane->GetTileSubdivisions(), 7); + x2d0_patchDimX = (tilesPerPatch + x2c4_gridDimX - 1) / tilesPerPatch; + x2d4_patchDimY = (tilesPerPatch + x2c8_gridDimY - 1) / tilesPerPatch; + x2e0_patchIntersects.reset(new u8[x2d0_patchDimX * x2d4_patchDimY]); + int curTileY = 0; + int nextTileY; + for (int i=0 ; iGetCurrentCamera(mgr); + if (x148_25_camSubmerged && !oldCamSubmerged) + mgr.SendScriptMsg(curCam, x8_uid, EScriptObjectMessage::AddSplashInhabitant); + else if (!x148_25_camSubmerged && oldCamSubmerged) + mgr.SendScriptMsg(curCam, x8_uid, EScriptObjectMessage::RemoveSplashInhabitant); + + UpdateSplashInhabitants(mgr); + + if (x2e8_30_alphaOut) + { + x2bc_alpha -= x2b8_alphaOutRecip * dt * x1b4_fluidPlane->GetAlpha(); + x214_fogBias -= x2b8_alphaOutRecip * dt * x21c_origFogBias; + x218_fogMagnitude -= x2b8_alphaOutRecip * dt * x220_origFogMagnitude; + if (x2bc_alpha <= 0.f) + { + x218_fogMagnitude = 0.f; + x214_fogBias = 0.f; + x2bc_alpha = 0.f; + x2e8_30_alphaOut = false; + } + } + else if (x2e8_29_alphaIn) + { + x2bc_alpha += x2b4_alphaInRecip * dt * x1b4_fluidPlane->GetAlpha(); + x214_fogBias -= x2b4_alphaInRecip * dt * x21c_origFogBias; + x218_fogMagnitude -= x2b4_alphaInRecip * dt * x220_origFogMagnitude; + if (x2bc_alpha > x1b4_fluidPlane->GetAlpha()) + { + x2bc_alpha = x1b4_fluidPlane->GetAlpha(); + x214_fogBias = x21c_origFogBias; + x218_fogMagnitude = x220_origFogMagnitude; + x2e8_29_alphaIn = false; + } + } + + if (x2e8_26_morphing) + { + bool stillMorphing = true; + if (x2e8_25_morphIn) + { + x1f8_morphFactor += dt / x1d0_morphInTime; + if (x1f8_morphFactor > 1.f) + { + x1f8_morphFactor = 1.f; + stillMorphing = false; + } + } + else + { + x1f8_morphFactor -= dt / x1f4_morphOutTime; + if (x1f8_morphFactor < 0.f) + { + x1f8_morphFactor = 0.f; + stillMorphing = false; + } + } + + SetTranslation(zeus::CVector3f::lerp(x1d4_positionOrig, x1b8_positionMorphed, x1f8_morphFactor)); + zeus::CVector3f lerpExtent = zeus::CVector3f::lerp(x1e0_extentOrig, x1c4_extentMorphed, x1f8_morphFactor); + x130_bounds = zeus::CAABox(lerpExtent * -0.5f, lerpExtent * 0.5f); + CalculateRenderBounds(); + + if (!stillMorphing) + SetMorphing(false); + else + SetupGrid(false); + } + + SetupGridClipping(mgr, 4); +} void CScriptWater::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr) { + switch (msg) + { + case EScriptObjectMessage::Next: + if (!x30_24_active) + break; + x2e8_25_morphIn = !x2e8_25_morphIn; + if (x2e8_25_morphIn) + { + for (const SConnection& conn : x20_conns) + { + if (conn.x0_state != EScriptObjectState::Play || + conn.x4_msg != EScriptObjectMessage::Activate) + continue; + auto list = mgr.GetIdListForScript(conn.x8_objId); + if (list.first == mgr.GetIdListEnd()) + continue; + if (TCastToConstPtr trig = mgr.GetObjectById(list.first->second)) + { + x1b8_positionMorphed = trig->GetTranslation(); + x1c4_extentMorphed = trig->GetTriggerBoundsOR().max - trig->GetTriggerBoundsOR().min; + x1f0_damageMorphed = trig->GetDamageInfo().GetDamage(); + x1d4_positionOrig = GetTranslation(); + x1e0_extentOrig = x130_bounds.max - x130_bounds.min; + x1ec_damageOrig = x100_damageInfo.GetDamage(); + break; + } + } + } + SetMorphing(true); + break; + case EScriptObjectMessage::Activate: + x2e8_30_alphaOut = false; + if (std::fabs(x2ac_alphaInTime) < 0.00001f) + { + x2bc_alpha = x1b4_fluidPlane->GetAlpha(); + x214_fogBias = x21c_origFogBias; + x218_fogMagnitude = x220_origFogMagnitude; + } + else + { + x2e8_29_alphaIn = true; + } + break; + case EScriptObjectMessage::Action: + x2e8_29_alphaIn = false; + if (std::fabs(x2b0_alphaOutTime) < 0.00001f) + { + x2bc_alpha = 0.f; + x214_fogBias = 0.f; + x218_fogMagnitude = 0.f; + } + else + { + x2e8_30_alphaOut = true; + } + break; + default: + break; + } + CScriptTrigger::AcceptScriptMsg(msg, other, mgr); } -void CScriptWater::PreRender(CStateManager &, const zeus::CFrustum &) {} +void CScriptWater::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) +{ + if (x2e8_27_allowRender) + { + zeus::CAABox aabb = GetSortingBounds(mgr); + xe4_30_outOfFrustum = !frustum.aabbFrustumTest(aabb); + if (!xe4_30_outOfFrustum) + { + if (x4_areaId != kInvalidAreaId) + { + if (x90_actorLights->GetMaxAreaLights() && + (xe4_29_actorLightsDirty || x90_actorLights->GetIsDirty())) + { + const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId); + if (area->IsPostConstructed()) + { + x90_actorLights->BuildAreaLightList(mgr, *area, GetTriggerBoundsWR()); + xe4_29_actorLightsDirty = false; + } + } + x90_actorLights->BuildDynamicLightList(mgr, GetTriggerBoundsWR()); + } + x150_frustum = frustum; + } + } + else + { + xe4_30_outOfFrustum = true; + } +} void CScriptWater::AddToRenderer(const zeus::CFrustum& /*frustum*/, const CStateManager& mgr) const { - zeus::CPlane plane; - plane.vec = x34_transform.origin.normalized(); - plane.d = x34_transform.origin.z + x130_bounds.max.z; - zeus::CAABox renderBounds = GetSortingBounds(mgr); - mgr.AddDrawableActorPlane(*this, plane, renderBounds); + if (!xe4_30_outOfFrustum) + { + zeus::CPlane plane; + plane.vec = x34_transform.origin.normalized(); + plane.d = x34_transform.origin.z + x130_bounds.max.z; + zeus::CAABox renderBounds = GetSortingBounds(mgr); + mgr.AddDrawableActorPlane(*this, plane, renderBounds); + } } -void CScriptWater::Render(const CStateManager&) const {} - -void CScriptWater::Touch(CActor&, CStateManager&) +void CScriptWater::Render(const CStateManager& mgr) const { + if (x30_24_active && !xe4_30_outOfFrustum) + { + float zOffset = 0.5f * (x9c_renderBounds.max.z + x9c_renderBounds.min.z) - x34_transform.origin.z; + zeus::CAABox aabb = x9c_renderBounds.getTransformedAABox( + zeus::CTransform::Translate(-x34_transform.origin.x, -x34_transform.origin.y, + -x34_transform.origin.z - zOffset)); + zeus::CTransform xf = x34_transform; + xf.origin.z += zOffset; + zeus::CVector3f areaCenter = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId())->GetAABB().center(); + std::experimental::optional rippleMan(mgr.GetFluidPlaneManager()->GetRippleManager()); + x1b4_fluidPlane->Render(mgr, x2bc_alpha, aabb, xf, + mgr.GetWorld()->GetAreaAlways(x4_areaId)->GetTransform(), false, + x150_frustum, rippleMan, x8_uid, x2d8_tileIntersects.get(), + x2c4_gridDimX, x2c8_gridDimY, areaCenter); + if (x214_fogBias != 0.f) + { + if (mgr.GetPlayerState()->CanVisorSeeFog(mgr)) + { + float fogLevel = mgr.IntegrateVisorFog(x218_fogMagnitude * + std::sin(x224_fogSpeed * CGraphics::GetSecondsMod900()) + + x214_fogBias); + if (fogLevel > 0.f) + { + zeus::CAABox fogBox = GetTriggerBoundsWR(); + fogBox.min.z = fogBox.max.z; + fogBox.max.z += fogLevel; + zeus::CTransform modelXf = zeus::CTransform::Translate(fogBox.center()) * + zeus::CTransform::Scale((fogBox.max - fogBox.min) * 0.5f); + zeus::CAABox renderAABB(zeus::CVector3f::skNegOne, zeus::CVector3f::skOne); + CGraphics::SetModelMatrix(modelXf); + g_Renderer->SetAmbientColor(zeus::CColor::skWhite); + g_Renderer->RenderFogVolume(x228_fogColor, renderAABB, nullptr, nullptr); + } + } + } + CGraphics::DisableAllLights(); + } + CActor::Render(mgr); +} + +void CScriptWater::Touch(CActor& otherAct, CStateManager& mgr) +{ + if (!x30_24_active) + return; + + CScriptTrigger::Touch(otherAct, mgr); + if (otherAct.GetMaterialList().HasMaterial(EMaterialTypes::Trigger)) + return; + + for (auto& inhab : x1fc_waterInhabitants) + if (inhab.first == otherAct.GetUniqueId()) + { + inhab.second = true; + return; + } + + auto touchBounds = otherAct.GetTouchBounds(); + if (!touchBounds) + return; + + x1fc_waterInhabitants.emplace_back(otherAct.GetUniqueId(), true); + float triggerMaxZ = GetTriggerBoundsWR().max.z; + if (touchBounds->min.z <= triggerMaxZ && touchBounds->max.z >= triggerMaxZ) + otherAct.FluidFXThink(EFluidState::Zero, *this, mgr); + + mgr.SendScriptMsg(&otherAct, x8_uid, EScriptObjectMessage::AddSplashInhabitant); } void CScriptWater::CalculateRenderBounds() @@ -143,12 +502,15 @@ void CScriptWater::CalculateRenderBounds() x9c_renderBounds = zeus::CAABox(transAABBMin, transAABBMax); } -zeus::CAABox CScriptWater::GetSortingBounds(const CStateManager&) const +zeus::CAABox CScriptWater::GetSortingBounds(const CStateManager& mgr) const { - return {}; + zeus::CVector3f max = x9c_renderBounds.max; + max.z = std::max(max.z, x9c_renderBounds.max.z - 1.f + x214_fogBias + x218_fogMagnitude); + return {x9c_renderBounds.min, max}; } -EWeaponCollisionResponseTypes CScriptWater::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, CWeaponMode&, int) +EWeaponCollisionResponseTypes CScriptWater::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, + CWeaponMode&, int) { return EWeaponCollisionResponseTypes::Water; } @@ -175,10 +537,18 @@ float CScriptWater::GetSplashEffectScale(float dt) const u32 CScriptWater::GetSplashIndex(float dt) const { - u32 idx = dt * 3.f; + auto idx = u32(dt * 3.f); return (idx < 3 ? idx : idx - 1); } +void CScriptWater::SetMorphing(bool m) +{ + if (m == x2e8_26_morphing) + return; + x2e8_26_morphing = m; + SetupGrid(!m); +} + const CScriptWater* CScriptWater::GetNextConnectedWater(const CStateManager& mgr) const { for (const SConnection& conn : x20_conns) diff --git a/Runtime/World/CScriptWater.hpp b/Runtime/World/CScriptWater.hpp index 6e2403b99..6e855e52a 100644 --- a/Runtime/World/CScriptWater.hpp +++ b/Runtime/World/CScriptWater.hpp @@ -15,23 +15,22 @@ private: static const float kSplashScales[6]; zeus::CFrustum x150_frustum; std::unique_ptr x1b4_fluidPlane; - 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 x1f8_lightmapDoubleBlendFactor = 0.f; + zeus::CVector3f x1b8_positionMorphed; + zeus::CVector3f x1c4_extentMorphed; + float x1d0_morphInTime; + zeus::CVector3f x1d4_positionOrig; + zeus::CVector3f x1e0_extentOrig; + float x1ec_damageOrig; + float x1f0_damageMorphed; + float x1f4_morphOutTime; + float x1f8_morphFactor = 0.f; std::list> x1fc_waterInhabitants; - u32 x210_; - float x214_; - float x218_; - float x21c_; - float x220_; - float x224_; - zeus::CColor x228_; + float x214_fogBias; + float x218_fogMagnitude; + float x21c_origFogBias; + float x220_origFogMagnitude; + float x224_fogSpeed; + zeus::CColor x228_fogColor; ResId x22c_splashParticle1Id; ResId x230_splashParticle2Id; ResId x234_splashParticle3Id; @@ -39,58 +38,60 @@ private: std::experimental::optional> x23c_; ResId x24c_particle5Id; std::experimental::optional> x250_visorRunoffEffect; - u16 x260_; + u16 x260_unkSfx; u16 x262_visorRunoffSfx; rstl::reserved_vector>, 3> x264_splashEffects; rstl::reserved_vector x298_splashSounds; - zeus::CColor x2a4_c1; - zeus::CColor x2a8_c2; - float x2ac_lf2; - float x2b0_lf3; - float x2b4_; - float x2b8_; + zeus::CColor x2a4_splashColor; + zeus::CColor x2a8_unkColor; + float x2ac_alphaInTime; + float x2b0_alphaOutTime; + float x2b4_alphaInRecip; + float x2b8_alphaOutRecip; float x2bc_alpha; float x2c0_tileSize; - u32 x2c4_gridDimX = 0; - u32 x2c8_gridDimY = 0; - u32 x2cc_gridCellCount = 0; - u32 x2d0_patchDimX = 0; - u32 x2d4_patchDimY = 0; - std::unique_ptr x2d8_gridFlags; - std::unique_ptr x2dc_; - std::unique_ptr x2e0_patchFlags; - u32 x2e4_gridCellCount2 = 0; + int x2c4_gridDimX = 0; + int x2c8_gridDimY = 0; + int x2cc_gridCellCount = 0; + int x2d0_patchDimX = 0; + int x2d4_patchDimY = 0; + std::unique_ptr x2d8_tileIntersects; + std::unique_ptr x2dc_vertIntersects; + std::unique_ptr x2e0_patchIntersects; // 0: all clear, 1: all intersect, 2: partial intersect + int x2e4_gridCellCount2 = 0; union { struct { bool x2e8_24_b4 : 1; - bool x2e8_25 : 1; - bool x2e8_26 : 1; - bool x2e8_27_b2 : 1; - bool x2e8_28 : 1; - bool x2e8_29 : 1; - bool x2e8_30 : 1; + bool x2e8_25_morphIn : 1; + bool x2e8_26_morphing : 1; + bool x2e8_27_allowRender : 1; + bool x2e8_28_recomputeClipping : 1; + bool x2e8_29_alphaIn : 1; + bool x2e8_30_alphaOut : 1; }; u32 _dummy = 0; }; - void SetupGrid(bool b); + void SetupGrid(bool recomputeClipping); + void SetupGridClipping(CStateManager& mgr, int computeVerts); + void UpdateSplashInhabitants(CStateManager& mgr); public: CScriptWater(CStateManager& mgr, TUniqueId uid, const std::string& name, const CEntityInfo& info, const zeus::CVector3f& pos, const zeus::CAABox& box, const urde::CDamageInfo& dInfo, - zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool b1, bool b2, + zeus::CVector3f& orientedForce, ETriggerFlags triggerFlags, bool thermalCold, bool allowRender, ResId patternMap1, ResId patternMap2, ResId colorMap, ResId bumpMap, ResId envMap, ResId envBumpMap, ResId unusedMap, const zeus::CVector3f& bumpLightDir, float bumpScale, - float f2, float f3, bool active, CFluidPlane::EFluidType fluidType, bool b4, float alpha, - const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax, + float morphInTime, float morphOutTime, bool active, CFluidPlane::EFluidType fluidType, bool b4, + float alpha, 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, + float turbAmplitudeMin, const zeus::CColor& splashColor, const zeus::CColor& unkColor, + ResId splashParticle1, ResId splashParticle2, ResId splashParticle3, ResId particle4, ResId particle5, + s32 unkSfx, 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&& u32Arr); + float rippleIntensity, float reflectionBlend, float fogBias, float fogMagnitude, float fogSpeed, + const zeus::CColor& fogColor, ResId lightmapId, float unitsPerLightmapTexel, float alphaInTime, + float alphaOutTime, u32, u32, bool, s32, s32, std::unique_ptr&& u32Arr); void Think(float, CStateManager&); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); @@ -100,32 +101,30 @@ public: void Touch(CActor &, CStateManager &); void CalculateRenderBounds(); zeus::CAABox GetSortingBounds(const CStateManager&) const; - void RenderSurface(); EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, CWeaponMode&, int); - void UpdateSplashInhabitants(CStateManager&); s16 GetSplashSound(float) const; const std::experimental::optional>& GetSplashEffect(float) const; float GetSplashEffectScale(float) const; u32 GetSplashIndex(float) const; - void FluidPlane(); + CFluidPlaneCPU& FluidPlane() { return *x1b4_fluidPlane; } zeus::CPlane GetWRSurfacePlane() const; float GetSurfaceZ() const; - bool IsMorphing() const; + bool IsMorphing() const { return x2e8_26_morphing; } void SetMorphing(bool); - zeus::CColor GetSplashColor() const; - void SetFrustumPlanes(const zeus::CFrustum& frustum); - const zeus::CFrustum& GetFrustumPlanes() const; + float GetMorphFactor() const { return x1f8_morphFactor; } + zeus::CColor GetSplashColor() const { return x2a4_splashColor; } + void SetFrustumPlanes(const zeus::CFrustum& frustum) { x150_frustum = frustum; } + const zeus::CFrustum& GetFrustumPlanes() const { return x150_frustum; } CFluidPlaneCPU& GetFluidPlane() const { return *x1b4_fluidPlane; } const std::experimental::optional>& GetVisorRunoffEffect() const { return x250_visorRunoffEffect; } u16 GetVisorRunoffSfx() const { return x262_visorRunoffSfx; } const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const; - float GetLightmapDoubleBlendFactor() const { return x1f8_lightmapDoubleBlendFactor; } - u8 GetPatchRenderFlags(int x, int y) const { return x2e0_patchFlags[y * x2d0_patchDimX + x]; } - u32 GetPatchDimensionX() const { return x2d0_patchDimX; } - u32 GetPatchDimensionY() const { return x2d4_patchDimY; } + u8 GetPatchRenderFlags(int x, int y) const { return x2e0_patchIntersects[y * x2d0_patchDimX + x]; } + int GetPatchDimensionX() const { return x2d0_patchDimX; } + int GetPatchDimensionY() const { return x2d4_patchDimY; } }; } diff --git a/Runtime/World/ScriptLoader.cpp b/Runtime/World/ScriptLoader.cpp index 5b6828dc5..dd26601d3 100644 --- a/Runtime/World/ScriptLoader.cpp +++ b/Runtime/World/ScriptLoader.cpp @@ -327,20 +327,13 @@ CAnimationParameters ScriptLoader::LoadAnimationParameters(CInputStream& in) CFluidUVMotion ScriptLoader::LoadFluidUVMotion(CInputStream& in) { - /* NOTE: DO NOT RE-ORDER THIS FUNCTION - * For some inexplicable reason Retro stores the layers in this order. - * Changing it will change the behavior of CFluidUVMotion, - * which is something we don't want. - * - Phil - * P.S: If you do change it, I'll hunt you down and put pink lipstick on your dog. - */ - CFluidUVMotion::EFluidUVMotion motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); + auto motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); float a = in.readFloatBig(); float b = in.readFloatBig(); b = zeus::degToRad(b) - M_PIF; float c = in.readFloatBig(); float d = in.readFloatBig(); - CFluidUVMotion::SFluidLayerMotion layerMotion2(motion, a, b, c, d); + CFluidUVMotion::SFluidLayerMotion pattern1Layer(motion, a, b, c, d); motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); a = in.readFloatBig(); @@ -348,7 +341,7 @@ CFluidUVMotion ScriptLoader::LoadFluidUVMotion(CInputStream& in) b = zeus::degToRad(b) - M_PIF; c = in.readFloatBig(); d = in.readFloatBig(); - CFluidUVMotion::SFluidLayerMotion layerMotion3(motion, a, b, c, d); + CFluidUVMotion::SFluidLayerMotion pattern2Layer(motion, a, b, c, d); motion = CFluidUVMotion::EFluidUVMotion(in.readUint32Big()); a = in.readFloatBig(); @@ -356,14 +349,14 @@ CFluidUVMotion ScriptLoader::LoadFluidUVMotion(CInputStream& in) b = zeus::degToRad(b) - M_PIF; c = in.readFloatBig(); d = in.readFloatBig(); - CFluidUVMotion::SFluidLayerMotion layerMotion1(motion, a, b, c, d); + CFluidUVMotion::SFluidLayerMotion colorLayer(motion, a, b, c, d); a = in.readFloatBig(); b = in.readFloatBig(); b = zeus::degToRad(b) - M_PIF; - return CFluidUVMotion(a, b, layerMotion1, layerMotion2, layerMotion3); + return CFluidUVMotion(a, b, colorLayer, pattern1Layer, pattern2Layer); } zeus::CTransform ScriptLoader::ConvertEditorEulerToTransform4f(const zeus::CVector3f& orientation, @@ -1206,68 +1199,68 @@ CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propC ETriggerFlags::DetectProjectiles4 | ETriggerFlags::DetectBombs | ETriggerFlags::DetectPowerBombs | ETriggerFlags::DetectProjectiles5 | ETriggerFlags::DetectProjectiles6 | ETriggerFlags::DetectProjectiles7; - bool b1 = in.readBool(); + bool thermalCold = in.readBool(); bool displaySurface = in.readBool(); - ResId textureId1 = in.readUint32Big(); - ResId textureId2 = in.readUint32Big(); - ResId textureId3 = in.readUint32Big(); - ResId textureId4 = in.readUint32Big(); - ResId textureId5 = in.readUint32Big(); - ResId textureId6 = in.readUint32Big(); - zeus::CVector3f v2; - v2.readBig(in); + ResId patternMap1 = in.readUint32Big(); + ResId patternMap2 = in.readUint32Big(); + ResId colorMap = in.readUint32Big(); + ResId bumpMap = in.readUint32Big(); + ResId _envMap = in.readUint32Big(); + ResId _envBumpMap = in.readUint32Big(); + zeus::CVector3f _bumpLightDir; + _bumpLightDir.readBig(in); - zeus::CVector3f otherV2 = v2; - if (otherV2.canBeNormalized()) - otherV2.assign(0.f, 0.f, -1.f); + zeus::CVector3f bumpLightDir = _bumpLightDir; + if (!bumpLightDir.canBeNormalized()) + bumpLightDir.assign(0.f, 0.f, -1.f); - float f1 = 1.f / in.readFloatBig(); - float f2 = in.readFloatBig(); - float f3 = in.readFloatBig(); + float bumpScale = 1.f / in.readFloatBig(); + float morphInTime = in.readFloatBig(); + float morphOutTime = in.readFloatBig(); bool active = in.readBool(); - CFluidPlane::EFluidType fluidType = CFluidPlane::EFluidType(in.readUint32Big()); + auto fluidType = CFluidPlane::EFluidType(in.readUint32Big()); bool b4 = in.readBool(); - float f4 = in.readFloatBig(); - CFluidUVMotion fluidMotion = LoadFluidUVMotion(in); + float alpha = in.readFloatBig(); + CFluidUVMotion uvMotion = LoadFluidUVMotion(in); - float f5 = in.readFloatBig(); - float f6 = in.readFloatBig(); - float f7 = in.readFloatBig(); - float f8 = in.readFloatBig(); - float f9 = zeus::degToRad(in.readFloatBig()); - float f10 = zeus::degToRad(in.readFloatBig()); - float f11 = in.readFloatBig(); - float f12 = in.readFloatBig(); - zeus::CColor c1; - c1.readRGBABig(in); - zeus::CColor c2; - c2.readRGBABig(in); - ResId enterParticle = in.readUint32Big(); - ResId partId2 = in.readUint32Big(); - ResId partId3 = in.readUint32Big(); - ResId partId4 = in.readUint32Big(); - ResId partId5 = in.readUint32Big(); - u32 soundId1 = in.readUint32Big(); - u32 soundId2 = in.readUint32Big(); - u32 soundId3 = in.readUint32Big(); - u32 soundId4 = in.readUint32Big(); - u32 soundId5 = in.readUint32Big(); - float f13 = in.readFloatBig(); - u32 w19 = in.readUint32Big(); - float f14 = in.readFloatBig(); - float f15 = in.readFloatBig(); - float f16 = in.readFloatBig(); - float f17 = in.readFloatBig(); - float f18 = in.readFloatBig(); - float f19 = in.readFloatBig(); - float heatWaveHeight = in.readFloatBig(); - float heatWaveSpeed = in.readFloatBig(); - zeus::CColor heatWaveColor; - heatWaveColor.readRGBABig(in); + float turbSpeed = in.readFloatBig(); + float turbDistance = in.readFloatBig(); + float turbFreqMax = in.readFloatBig(); + float turbFreqMin = in.readFloatBig(); + float turbPhaseMax = zeus::degToRad(in.readFloatBig()); + float turbPhaseMin = zeus::degToRad(in.readFloatBig()); + float turbAmplitudeMax = in.readFloatBig(); + float turbAmplitudeMin = in.readFloatBig(); + zeus::CColor splashColor; + splashColor.readRGBABig(in); + zeus::CColor unkColor; + unkColor.readRGBABig(in); + ResId splashParticle1 = in.readUint32Big(); + ResId splashParticle2 = in.readUint32Big(); + ResId splashParticle3 = in.readUint32Big(); + ResId particle4 = in.readUint32Big(); + ResId particle5 = in.readUint32Big(); + u32 unkSfx = in.readUint32Big(); + u32 visorRunoffSfx = in.readUint32Big(); + u32 splashSfx1 = in.readUint32Big(); + u32 splashSfx2 = in.readUint32Big(); + u32 splashSfx3 = in.readUint32Big(); + float tileSize = in.readFloatBig(); + u32 tileSubdivisions = in.readUint32Big(); + float specularMin = in.readFloatBig(); + float specularMax = in.readFloatBig(); + float reflectionSize = in.readFloatBig(); + float rippleIntensity = in.readFloatBig(); + float reflectionBlend = in.readFloatBig(); + float fogBias = in.readFloatBig(); + float fogMagnitude = in.readFloatBig(); + float fogSpeed = in.readFloatBig(); + zeus::CColor fogColor; + fogColor.readRGBABig(in); ResId lightmap = in.readUint32Big(); - float f22 = in.readFloatBig(); - float f23 = in.readFloatBig(); - float f24 = in.readFloatBig(); + float unitsPerLightmapTexel = in.readFloatBig(); + float alphaInTime = in.readFloatBig(); + float alphaOutTime = in.readFloatBig(); u32 w21 = in.readUint32Big(); u32 w22 = in.readUint32Big(); bool b5 = in.readBool(); @@ -1287,21 +1280,23 @@ CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propC zeus::CAABox box(-extent * 0.5f, extent * 0.5f); - ResId realTextureId6 = -1; - if (textureId4 == -1) - realTextureId6 = textureId6; + ResId envBumpMap = -1; + if (bumpMap == -1) + envBumpMap = _envBumpMap; - ResId realTextureId5 = -1; - if (textureId4 == -1) - realTextureId5 = textureId5; + ResId envMap = -1; + if (bumpMap == -1) + envMap = _envMap; return new CScriptWater( - mgr, mgr.AllocateUniqueId(), name, info, position, box, dInfo, orientedForce, triggerFlags, b1, displaySurface, - 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, - 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, - std::move(bitset)); + mgr, mgr.AllocateUniqueId(), name, info, position, box, dInfo, orientedForce, triggerFlags, thermalCold, + displaySurface, patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap, -1, bumpLightDir, bumpScale, + morphInTime, morphOutTime, active, fluidType, b4, alpha, uvMotion, turbSpeed, turbDistance, turbFreqMax, + turbFreqMin, turbPhaseMax, turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, splashColor, unkColor, + splashParticle1, splashParticle2, splashParticle3, particle4, particle5, unkSfx, visorRunoffSfx, splashSfx1, + splashSfx2, splashSfx3, tileSize, tileSubdivisions, specularMin, specularMax, reflectionSize, rippleIntensity, + reflectionBlend, fogBias, fogMagnitude, fogSpeed, fogColor, lightmap, unitsPerLightmapTexel, alphaInTime, + alphaOutTime, w21, w22, b5, bitVal0, bitVal1, std::move(bitset)); } CEntity* ScriptLoader::LoadWarWasp(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)