2
0
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:
Jack Andersen
2017-08-07 20:03:57 -10:00
parent 5590e2f27a
commit 3650a58a1e
27 changed files with 1801 additions and 99 deletions

View File

@@ -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;

View File

@@ -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 {}

View File

@@ -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

View File

@@ -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; }

View File

@@ -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);
}
}
}

View File

@@ -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; }
};
}

View File

@@ -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_);

View File

@@ -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__

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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; }
};
}