mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-12-15 23:37:02 +00:00
Initial CFluidPlane implementation
This commit is contained in:
@@ -170,6 +170,7 @@ public:
|
||||
bool translateId);
|
||||
SAdvancementDeltas UpdateAnimation(float, CStateManager&, bool);
|
||||
void SetActorLights(std::unique_ptr<CActorLights>);
|
||||
const CActorLights* GetActorLights() const { return x90_actorLights.get(); }
|
||||
bool CanDrawStatic() const;
|
||||
bool GetE7_29() const { return xe7_29_; }
|
||||
const CScannableObjectInfo* GetScannableObjectInfo() const;
|
||||
|
||||
@@ -19,15 +19,15 @@ class CFluidPlane
|
||||
public:
|
||||
enum class EFluidType
|
||||
{
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
NormalWater,
|
||||
PoisonWater,
|
||||
Lava,
|
||||
Three,
|
||||
Four,
|
||||
Five
|
||||
};
|
||||
|
||||
private:
|
||||
protected:
|
||||
ResId x4_texPattern1Id;
|
||||
ResId x8_texPattern2Id;
|
||||
ResId xc_texColorId;
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
virtual void Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos,
|
||||
CScriptWater& water, CStateManager& mgr);
|
||||
virtual void Update();
|
||||
virtual void Render(const CStateManager& mgr, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
virtual void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum,
|
||||
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
||||
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const {}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#include "CFluidPlaneCPU.hpp"
|
||||
#include "CSimplePool.hpp"
|
||||
#include "GameGlobalObjects.hpp"
|
||||
#include "CFluidPlaneManager.hpp"
|
||||
#include "CStateManager.hpp"
|
||||
#include "CWorld.hpp"
|
||||
#include "World/CScriptWater.hpp"
|
||||
#include "TCastTo.hpp"
|
||||
|
||||
#define kTableSize 2048
|
||||
|
||||
@@ -38,19 +43,20 @@ CFluidPlaneCPU::CTurbulence::CTurbulence(float speed, float distance, float freq
|
||||
}
|
||||
|
||||
CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texColor, ResId bumpMap, ResId envMap,
|
||||
ResId envBumpMap, ResId unkMap, float f1, float tileSize, u32 tileSubdivisions,
|
||||
EFluidType fluidType, float alpha, const zeus::CVector3f& bumpLightDir, float bumpScale,
|
||||
const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax,
|
||||
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
|
||||
float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend,
|
||||
float reflectionSize, float fluidPlaneF2)
|
||||
ResId envBumpMap, ResId unkMap, float unitsPerLightmapTexel, float tileSize,
|
||||
u32 tileSubdivisions, EFluidType fluidType, float alpha,
|
||||
const zeus::CVector3f& bumpLightDir, float bumpScale, const CFluidUVMotion& mot,
|
||||
float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin,
|
||||
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),
|
||||
xa0_texIdBumpMap(bumpMap), xa4_texIdEnvMap(envMap), xa8_texIdEnvBumpMap(envBumpMap), xac_texId4(unkMap),
|
||||
xf0_bumpLightDir(bumpLightDir), xfc_bumpScale(bumpScale), x100_tileSize(tileSize),
|
||||
x104_tileSubdivisions(tileSubdivisions & ~0x1),
|
||||
x108_rippleResolution(x100_tileSize / float(x104_tileSubdivisions)),
|
||||
x10c_specularMin(specularMin), x110_specularMax(specularMax), x114_reflectionBlend(reflectionBlend),
|
||||
x118_reflectionSize(reflectionSize), x11c_f1(f1),
|
||||
x118_reflectionSize(reflectionSize), x11c_unitsPerLightmapTexel(unitsPerLightmapTexel),
|
||||
x120_turbulence(turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax,
|
||||
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin)
|
||||
{
|
||||
@@ -61,7 +67,7 @@ CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texCo
|
||||
if (g_ResFactory->GetResourceTypeById(xa8_texIdEnvBumpMap) == FOURCC('TXTR'))
|
||||
xd0_envBumpMap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa8_texIdEnvBumpMap}));
|
||||
if (g_ResFactory->GetResourceTypeById(xac_texId4) == FOURCC('TXTR'))
|
||||
xe0_tex4.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xac_texId4}));
|
||||
xe0_lightmap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xac_texId4}));
|
||||
}
|
||||
|
||||
void CFluidPlaneCPU::CreateRipple(const CRipple& ripple, CStateManager& mgr)
|
||||
@@ -69,18 +75,228 @@ void CFluidPlaneCPU::CreateRipple(const CRipple& ripple, CStateManager& mgr)
|
||||
|
||||
}
|
||||
|
||||
void CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, const zeus::CAABox& aabb, CScriptWater* water) const
|
||||
void CFluidPlaneCPU::CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf,
|
||||
const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const
|
||||
{
|
||||
int width = GetLightMap().GetWidth();
|
||||
int height = GetLightMap().GetHeight();
|
||||
|
||||
zeus::CTransform toLocal = areaXf.getRotation().inverse();
|
||||
zeus::CAABox areaLocalAABB = aabb.getTransformedAABox(toLocal);
|
||||
float f26 = (areaLocalAABB.max.x - areaLocalAABB.min.x) / (width * x11c_unitsPerLightmapTexel);
|
||||
float f25 = (areaLocalAABB.max.y - areaLocalAABB.min.y) / (height * x11c_unitsPerLightmapTexel);
|
||||
float f24 = (1.f + std::fmod(areaLocalAABB.min.x + xf.origin.x, x11c_unitsPerLightmapTexel)) / width;
|
||||
float f23 = (2.f - std::fmod(areaLocalAABB.max.x + xf.origin.x, x11c_unitsPerLightmapTexel)) / width;
|
||||
float f29 = (1.f + std::fmod(areaLocalAABB.min.y + xf.origin.y, x11c_unitsPerLightmapTexel)) / height;
|
||||
float f6 = (2.f - std::fmod(areaLocalAABB.max.y + xf.origin.y, x11c_unitsPerLightmapTexel)) / height;
|
||||
|
||||
float scaleX = (f26 - f24 - f23) / (areaLocalAABB.max.x - areaLocalAABB.min.x);
|
||||
float scaleY = -(f25 - f29 - f6) / (areaLocalAABB.max.y - areaLocalAABB.min.y);
|
||||
float offX = f24 + f26 * -areaLocalAABB.min.x / (areaLocalAABB.max.x - areaLocalAABB.min.x);
|
||||
float offY = f25 * areaLocalAABB.min.y / (areaLocalAABB.max.y - areaLocalAABB.min.y) - f6;
|
||||
mtxOut = (zeus::CTransform(zeus::CMatrix3f(zeus::CVector3f(scaleX, scaleY, 0.f)),
|
||||
zeus::CVector3f(offX, offY, 0.f)) * toLocal).toMatrix4f();
|
||||
}
|
||||
|
||||
void CFluidPlaneCPU::Render(const CStateManager& mgr, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
#define kEnableWaterBumpMaps true
|
||||
|
||||
CFluidPlaneCPU::RenderSetupInfo
|
||||
CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, const zeus::CAABox& aabb, const CScriptWater* water) const
|
||||
{
|
||||
RenderSetupInfo out;
|
||||
|
||||
float uvT = mgr.GetFluidPlaneManager()->GetUVT();
|
||||
bool hasBumpMap = HasBumpMap() && kEnableWaterBumpMaps;
|
||||
bool doubleLightmapBlend = false;
|
||||
bool hasEnvMap = mgr.GetCameraManager()->GetFluidCounter() == 0 && HasEnvMap();
|
||||
bool hasEnvBumpMap = HasEnvBumpMap();
|
||||
CGraphics::SetModelMatrix(xf);
|
||||
|
||||
if (hasBumpMap)
|
||||
{
|
||||
// Build 50% grey directional light with xf0_bumpLightDir and load into LIGHT_3
|
||||
// Light 3 in channel 1
|
||||
// Vertex colors in channel 0
|
||||
}
|
||||
else
|
||||
{
|
||||
// Normal light mask in channel 1
|
||||
// Vertex colors in channel 0
|
||||
}
|
||||
|
||||
if (x10_texPattern1)
|
||||
{
|
||||
// Load into 0
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load black tex into 0
|
||||
}
|
||||
|
||||
if (x20_texPattern2)
|
||||
{
|
||||
// Load into 1
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load black tex into 1
|
||||
}
|
||||
|
||||
if (x30_texColor)
|
||||
{
|
||||
// Load into 2
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load black tex into 2
|
||||
}
|
||||
|
||||
int curTex = 3;
|
||||
int bumpMapId;
|
||||
int envMapId;
|
||||
int envBumpMapId;
|
||||
int lightmapId;
|
||||
|
||||
if (hasBumpMap)
|
||||
{
|
||||
// Load into next
|
||||
bumpMapId = curTex++;
|
||||
}
|
||||
|
||||
if (hasEnvMap)
|
||||
{
|
||||
// Load into next
|
||||
envMapId = curTex++;
|
||||
}
|
||||
|
||||
if (hasEnvBumpMap)
|
||||
{
|
||||
// Load into next
|
||||
envBumpMapId = curTex++;
|
||||
}
|
||||
|
||||
float fluidUVs[3][2];
|
||||
x4c_uvMotion.CalculateFluidTextureOffset(uvT, fluidUVs);
|
||||
|
||||
out.texMtxs[0][0][0] = out.texMtxs[0][1][1] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale();
|
||||
out.texMtxs[0][3][0] = fluidUVs[1][0];
|
||||
out.texMtxs[0][3][1] = fluidUVs[1][1];
|
||||
|
||||
out.texMtxs[1][0][0] = out.texMtxs[1][1][1] = x4c_uvMotion.GetFluidLayers()[2].GetUVScale();
|
||||
out.texMtxs[1][3][0] = fluidUVs[2][0];
|
||||
out.texMtxs[1][3][1] = fluidUVs[2][1];
|
||||
|
||||
out.texMtxs[2][0][0] = out.texMtxs[2][1][1] = x4c_uvMotion.GetFluidLayers()[0].GetUVScale();
|
||||
out.texMtxs[2][3][0] = fluidUVs[0][0];
|
||||
out.texMtxs[2][3][1] = fluidUVs[0][1];
|
||||
|
||||
// Load normal mtx 0 with
|
||||
out.normMtx =
|
||||
(zeus::CTransform::Scale(xfc_bumpScale) * CGraphics::g_ViewMatrix.getRotation().inverse()).toMatrix4f();
|
||||
|
||||
// Setup TCGs
|
||||
int nextTexMtx = 3;
|
||||
|
||||
if (hasEnvBumpMap)
|
||||
{
|
||||
float pttScale;
|
||||
if (hasEnvMap)
|
||||
pttScale = 0.5f * (1.f - x118_reflectionSize);
|
||||
else
|
||||
pttScale = g_tweakGame->GetFluidEnvBumpScale() * x4c_uvMotion.GetFluidLayers()[0].GetUVScale();
|
||||
|
||||
// Load GX_TEXMTX3 with identity
|
||||
zeus::CMatrix4f& texMtx = out.texMtxs[nextTexMtx++];
|
||||
// Load GX_PTTEXMTX0 with scale of pttScale
|
||||
// Next: GX_TG_MTX2x4 GX_TG_NRM, GX_TEXMTX3, true, GX_PTTEXMTX0
|
||||
|
||||
out.indScale = 0.5f * (hasEnvMap ? x118_reflectionSize : 1.f);
|
||||
// Load ind mtx with scale of (indScale, -indScale)
|
||||
// Load envBumpMap into ind stage 0 with previous TCG
|
||||
}
|
||||
|
||||
if (hasEnvMap)
|
||||
{
|
||||
float scale = std::max(aabb.max.x - aabb.min.x, aabb.max.y - aabb.min.y);
|
||||
zeus::CMatrix4f& texMtx = out.texMtxs[nextTexMtx++];
|
||||
texMtx[0][0] = texMtx[1][1] = 1.f / scale;
|
||||
zeus::CVector3f center = aabb.center();
|
||||
texMtx[3][0] = 0.5f + -center.x / scale;
|
||||
texMtx[3][1] = 0.5f + -center.y / scale;
|
||||
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
|
||||
}
|
||||
|
||||
if (HasLightMap())
|
||||
{
|
||||
float lowLightBlend = 1.f;
|
||||
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 ||
|
||||
!nextWater->GetFluidPlane().HasLightMap())
|
||||
{
|
||||
lightmapId = curTex;
|
||||
// Load lightmap
|
||||
CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]);
|
||||
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
|
||||
}
|
||||
else if (nextWater && nextWater->GetFluidPlane().HasLightMap())
|
||||
{
|
||||
if (std::fabs(water->GetLightmapDoubleBlendFactor() - 1.f) < 0.00001f)
|
||||
{
|
||||
lightmapId = curTex;
|
||||
// Load lightmap
|
||||
CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]);
|
||||
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
|
||||
}
|
||||
else
|
||||
{
|
||||
lightmapId = curTex;
|
||||
// Load lightmap
|
||||
CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]);
|
||||
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
|
||||
// Load lightmap
|
||||
CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]);
|
||||
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
|
||||
|
||||
float lum = lightLevel * water->GetLightmapDoubleBlendFactor();
|
||||
out.kColors[3] = zeus::CColor(lum, 1.f);
|
||||
lowLightBlend = (1.f - water->GetLightmapDoubleBlendFactor()) / (1.f - lum);
|
||||
doubleLightmapBlend = true;
|
||||
}
|
||||
}
|
||||
|
||||
out.kColors[2] = zeus::CColor(lowLightBlend * lightLevel, 1.f);
|
||||
}
|
||||
|
||||
float waterPlaneOrthoDot = xf.transposeRotate(zeus::CVector3f::skUp).
|
||||
dot(CGraphics::g_ViewMatrix.inverse().transposeRotate(zeus::CVector3f::skForward));
|
||||
if (waterPlaneOrthoDot < 0.f)
|
||||
waterPlaneOrthoDot = -waterPlaneOrthoDot;
|
||||
|
||||
out.kColors[0] =
|
||||
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)
|
||||
m_shader.emplace(x44_fluidType,
|
||||
x10_texPattern1, x20_texPattern2, x30_texColor, xb0_bumpMap, xc0_envMap, xd0_envBumpMap,
|
||||
xe0_lightmap, doubleLightmapBlend, mgr.GetParticleFlags() == 0);
|
||||
out.lights = water->GetActorLights()->BuildLightVector();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum,
|
||||
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
||||
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const
|
||||
{
|
||||
|
||||
TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(waterId);
|
||||
RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr());
|
||||
m_shader->draw(setupInfo.texMtxs, setupInfo.normMtx, setupInfo.indScale, setupInfo.lights, setupInfo.kColors);
|
||||
}
|
||||
|
||||
void CFluidPlaneCPU::RenderCleanup() const
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "CFluidPlane.hpp"
|
||||
#include "CRipple.hpp"
|
||||
#include "Graphics/Shaders/CFluidPlaneShader.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
@@ -41,7 +42,7 @@ class CFluidPlaneCPU : public CFluidPlane
|
||||
std::experimental::optional<TLockedToken<CTexture>> xb0_bumpMap;
|
||||
std::experimental::optional<TLockedToken<CTexture>> xc0_envMap;
|
||||
std::experimental::optional<TLockedToken<CTexture>> xd0_envBumpMap;
|
||||
std::experimental::optional<TLockedToken<CTexture>> xe0_tex4;
|
||||
std::experimental::optional<TLockedToken<CTexture>> xe0_lightmap;
|
||||
zeus::CVector3f xf0_bumpLightDir;
|
||||
float xfc_bumpScale;
|
||||
float x100_tileSize;
|
||||
@@ -51,19 +52,32 @@ class CFluidPlaneCPU : public CFluidPlane
|
||||
float x110_specularMax;
|
||||
float x114_reflectionBlend;
|
||||
float x118_reflectionSize;
|
||||
float x11c_f1;
|
||||
float x11c_unitsPerLightmapTexel;
|
||||
CTurbulence x120_turbulence;
|
||||
mutable std::experimental::optional<CFluidPlaneShader> m_shader;
|
||||
|
||||
struct RenderSetupInfo
|
||||
{
|
||||
zeus::CMatrix4f texMtxs[6];
|
||||
zeus::CMatrix4f normMtx;
|
||||
float indScale = 1.f;
|
||||
zeus::CColor kColors[4];
|
||||
std::vector<CLight> lights;
|
||||
};
|
||||
public:
|
||||
CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texColor, ResId bumpMap, ResId envMap, ResId envBumpMap,
|
||||
ResId unkMap, float f1, float tileSize, u32 tileSubdivisions, EFluidType fluidType, float alpha,
|
||||
ResId unkMap, float unitsPerLightmapTexel, float tileSize, u32 tileSubdivisions, EFluidType fluidType, float alpha,
|
||||
const zeus::CVector3f& bumpLightDir, float bumpScale, const CFluidUVMotion& mot, float turbSpeed,
|
||||
float turbDistance, float turbFreqMax, float turbFreqMin, float turbPhaseMax, float turbPhaseMin,
|
||||
float turbAmplitudeMax, float turbAmplitudeMin, float specularMin, float specularMax,
|
||||
float reflectionBlend, float reflectionSize, float fluidPlaneF2);
|
||||
void CreateRipple(const CRipple& ripple, CStateManager& mgr);
|
||||
void RenderSetup(const CStateManager& mgr, float, const zeus::CTransform& xf, const zeus::CTransform& areaXf,
|
||||
const zeus::CAABox& aabb, CScriptWater* water) const;
|
||||
void Render(const CStateManager& mgr, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
void CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf,
|
||||
const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const;
|
||||
RenderSetupInfo RenderSetup(const CStateManager& mgr, float, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, const zeus::CAABox& aabb,
|
||||
const CScriptWater* water) const;
|
||||
void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum,
|
||||
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
||||
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const;
|
||||
@@ -79,6 +93,8 @@ public:
|
||||
const CTexture& GetEnvMap() const { return **xc0_envMap; }
|
||||
bool HasEnvBumpMap() const { return xd0_envBumpMap.operator bool(); }
|
||||
const CTexture& GetEnvBumpMap() const { return **xd0_envBumpMap; }
|
||||
bool HasLightMap() const { return xe0_lightmap.operator bool(); }
|
||||
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; }
|
||||
|
||||
@@ -8,7 +8,8 @@ CFluidPlaneManager::CFluidProfile CFluidPlaneManager::sProfile = {};
|
||||
CFluidPlaneManager::CFluidPlaneManager()
|
||||
: x0_rippleManager(20, 0.5f)
|
||||
{
|
||||
|
||||
sProfile.Clear();
|
||||
SetupRippleMap();
|
||||
}
|
||||
|
||||
void CFluidPlaneManager::CFluidProfile::Clear()
|
||||
@@ -43,4 +44,56 @@ void CFluidPlaneManager::CreateSplash(TUniqueId splasher, CStateManager& mgr, co
|
||||
|
||||
}
|
||||
|
||||
u8 CFluidPlaneManager::RippleValues[64][64] = {};
|
||||
u8 CFluidPlaneManager::RippleMins[64] = {};
|
||||
u8 CFluidPlaneManager::RippleMaxs[64] = {};
|
||||
|
||||
void CFluidPlaneManager::SetupRippleMap()
|
||||
{
|
||||
float curX = 0.f;
|
||||
for (int i=0 ; i<64 ; ++i)
|
||||
{
|
||||
float curY = 0.f;
|
||||
float minY = 1.f;
|
||||
float maxY = 0.f;
|
||||
for (int j=0 ; j<64 ; ++j)
|
||||
{
|
||||
float rVal = 1.f - curY;
|
||||
float minX = curY;
|
||||
float maxX = 1.25f * (0.25f * rVal + 0.1f) + curY;
|
||||
if (curY < 0.f)
|
||||
minX = 0.f;
|
||||
else if (maxX > 1.f)
|
||||
maxX = 1.f;
|
||||
|
||||
float val = 0.f;
|
||||
if (curX >= minX && curX <= maxX)
|
||||
{
|
||||
float t = (curX - minX) / (maxX - minX);
|
||||
if (t < 0.4f)
|
||||
val = 2.5f * t;
|
||||
else if (t > 0.75f)
|
||||
val = 4.f * (1.f - t);
|
||||
else
|
||||
val = 1.f;
|
||||
}
|
||||
|
||||
auto valA = u8(std::max(int(255.f * val * rVal * rVal) - 1, 0));
|
||||
RippleValues[i][j] = valA;
|
||||
if (valA != 0 && curY < minY)
|
||||
minY = curY;
|
||||
if (valA != 0 && curY > maxY)
|
||||
maxY = curY;
|
||||
|
||||
curY += (1.f / 63.f);
|
||||
}
|
||||
|
||||
auto valB = u8(std::max(int(255.f * minY) - 1, 0));
|
||||
auto valC = u8(std::min(int(255.f * maxY) + 1, 255));
|
||||
RippleMins[i] = valB;
|
||||
RippleMaxs[i] = valC;
|
||||
curX += (1.f / 63.f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,23 +11,43 @@ class CScriptWater;
|
||||
|
||||
class CFluidPlaneManager
|
||||
{
|
||||
class CSplashRecord
|
||||
{
|
||||
public:
|
||||
CSplashRecord(TUniqueId id);
|
||||
void SetTime(float t);
|
||||
float GetTime() const;
|
||||
TUniqueId GetUniqueId() const;
|
||||
};
|
||||
|
||||
CRippleManager x0_rippleManager;
|
||||
bool x121_;
|
||||
rstl::reserved_vector<CSplashRecord, 32> x18_splashes;
|
||||
float x11c_uvT = 0.f;
|
||||
bool x120_ = false;
|
||||
bool x121_ = false;
|
||||
|
||||
class CFluidProfile
|
||||
{
|
||||
public:
|
||||
void Clear();
|
||||
};
|
||||
static CFluidProfile sProfile;
|
||||
static void SetupRippleMap();
|
||||
public:
|
||||
static u8 RippleValues[64][64];
|
||||
static u8 RippleMins[64];
|
||||
static u8 RippleMaxs[64];
|
||||
|
||||
CFluidPlaneManager();
|
||||
void StartFrame(bool);
|
||||
void EndFrame() { x121_ = false; }
|
||||
void Update(float dt);
|
||||
float GetUVT() const { return x11c_uvT; }
|
||||
float GetLastRippleDeltaTime(TUniqueId rippler) const;
|
||||
float GetLastSplashDeltaTime(TUniqueId splasher) const;
|
||||
void CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water,
|
||||
const zeus::CVector3f& pos, float factor, bool);
|
||||
rstl::reserved_vector<CSplashRecord, 32>& SplashRecords() { return x18_splashes; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ CFluidUVMotion::CFluidUVMotion(float a, float b, const CFluidUVMotion::SFluidLay
|
||||
CFluidUVMotion::CFluidUVMotion(float, float)
|
||||
{}
|
||||
|
||||
void CFluidUVMotion::CalculateFluidTextureOffset(float f31, float offsets[3][2])
|
||||
void CFluidUVMotion::CalculateFluidTextureOffset(float f31, float offsets[3][2]) const
|
||||
{
|
||||
float f28 = (f31 * x4c_) * zeus::fastCosF(x50_);
|
||||
float f29 = (f31 * x4c_) / zeus::fastSinF(x50_);
|
||||
|
||||
@@ -22,14 +22,16 @@ public:
|
||||
float x4_a = 0.16666667f;
|
||||
float x8_b = 0.f;
|
||||
float xc_c = 1.f;
|
||||
float x10_d = 5.f;
|
||||
float x14_envNormalScale = 0.2f;
|
||||
float x10_uvMul = 5.f;
|
||||
float x14_uvScale = 0.2f;
|
||||
|
||||
SFluidLayerMotion() = default;
|
||||
SFluidLayerMotion(EFluidUVMotion motion, float a, float b, float c, float d)
|
||||
: x0_motion(motion), x4_a(1.f / a), x8_b(b), xc_c(c), x10_d(d), x14_envNormalScale(1.f / d)
|
||||
SFluidLayerMotion(EFluidUVMotion motion, float a, float b, float c, float uvMul)
|
||||
: x0_motion(motion), x4_a(1.f / a), x8_b(b), xc_c(c), x10_uvMul(uvMul), x14_uvScale(1.f / uvMul)
|
||||
{
|
||||
}
|
||||
|
||||
float GetUVScale() const { return x14_uvScale; }
|
||||
};
|
||||
|
||||
private:
|
||||
@@ -43,7 +45,7 @@ public:
|
||||
const rstl::reserved_vector<SFluidLayerMotion, 3>& GetFluidLayers() const { return x0_fluidLayers; }
|
||||
void GetOrientation() const;
|
||||
void GetOOTimeToWrapTexPage() const;
|
||||
void CalculateFluidTextureOffset(float, float[3][2]);
|
||||
void CalculateFluidTextureOffset(float, float[3][2]) const;
|
||||
};
|
||||
}
|
||||
#endif // __URDE_CFLUIDUVMOTION_HPP__
|
||||
|
||||
@@ -252,7 +252,7 @@ void CPlayer::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager
|
||||
zeus::CVector3f position = x34_transform.origin + posOffset;
|
||||
position.z = water.GetTriggerBoundsWR().max.z;
|
||||
mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.3f, true);
|
||||
if (water.GetFluidPlane().GetFluidType() == CFluidPlane::EFluidType::Zero)
|
||||
if (water.GetFluidPlane().GetFluidType() == CFluidPlane::EFluidType::NormalWater)
|
||||
{
|
||||
float velMag = mgr.GetPlayer().GetVelocity().magnitude() / 10.f;
|
||||
mgr.GetEnvFxManager()->SetXB54(10.f * std::max(1.f, velMag));
|
||||
@@ -1710,14 +1710,14 @@ void CPlayer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CState
|
||||
{
|
||||
switch (water->GetFluidPlane().GetFluidType())
|
||||
{
|
||||
case CFluidPlane::EFluidType::Zero:
|
||||
case CFluidPlane::EFluidType::NormalWater:
|
||||
x2b0_ = 0;
|
||||
break;
|
||||
case CFluidPlane::EFluidType::Two:
|
||||
case CFluidPlane::EFluidType::Lava:
|
||||
case CFluidPlane::EFluidType::Five:
|
||||
x2ac_surfaceRestraint = ESurfaceRestraints::Fluid2Or5;
|
||||
break;
|
||||
case CFluidPlane::EFluidType::One:
|
||||
case CFluidPlane::EFluidType::PoisonWater:
|
||||
x2b0_ = 0;
|
||||
break;
|
||||
case CFluidPlane::EFluidType::Three:
|
||||
@@ -4399,7 +4399,7 @@ void CPlayer::UpdateSubmerged(CStateManager& mgr)
|
||||
x828_waterLevelOnPlayer =
|
||||
-(zeus::CVector3f::skUp.dot(x34_transform.origin) - water->GetTriggerBoundsWR().max.z);
|
||||
CFluidPlane::EFluidType fluidType = water->GetFluidPlane().GetFluidType();
|
||||
x82c_inLava = (fluidType == CFluidPlane::EFluidType::Two || fluidType == CFluidPlane::EFluidType::Five);
|
||||
x82c_inLava = (fluidType == CFluidPlane::EFluidType::Lava || fluidType == CFluidPlane::EFluidType::Five);
|
||||
CheckSubmerged();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "CScriptWater.hpp"
|
||||
#include "CStateManager.hpp"
|
||||
#include "TCastTo.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
@@ -87,4 +88,18 @@ u32 CScriptWater::GetSplashIndex(float dt) const
|
||||
u32 idx = dt * 3.f;
|
||||
return (idx < 3 ? idx : idx - 1);
|
||||
}
|
||||
|
||||
const CScriptWater* CScriptWater::GetNextConnectedWater(const CStateManager& mgr) const
|
||||
{
|
||||
for (const SConnection& conn : x20_conns)
|
||||
{
|
||||
if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate)
|
||||
continue;
|
||||
auto its = mgr.GetIdListForScript(conn.x8_objId);
|
||||
if (its.first != mgr.GetIdListEnd())
|
||||
if (TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(its.first->second))
|
||||
return water.GetPtr();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ private:
|
||||
std::unique_ptr<CFluidPlaneCPU> x1b4_fluidPlane;
|
||||
zeus::CVector3f x1b8_;
|
||||
float x1f4_;
|
||||
float x1f8_ = 0.f;
|
||||
float x1f8_lightmapDoubleBlendFactor = 0.f;
|
||||
zeus::CVector3f x1d4_;
|
||||
std::list<std::pair<TUniqueId, bool>> x1fc_waterInhabitants;
|
||||
u32 x210_;
|
||||
@@ -97,6 +97,8 @@ public:
|
||||
const std::experimental::optional<TLockedToken<CGenDescription>>& GetVisorRunoffEffect() const
|
||||
{ return x250_visorRunoffEffect; }
|
||||
u16 GetVisorRunoffSfx() const { return x262_visorRunoffSfx; }
|
||||
const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const;
|
||||
float GetLightmapDoubleBlendFactor() const { return x1f8_lightmapDoubleBlendFactor; }
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user