diff --git a/.idea/misc.xml b/.idea/misc.xml
index 79b3c9483..674375dd3 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/DataSpec/DNACommon/Tweaks/ITweakBall.hpp b/DataSpec/DNACommon/Tweaks/ITweakBall.hpp
index 83ecc2c7b..17f64287b 100644
--- a/DataSpec/DNACommon/Tweaks/ITweakBall.hpp
+++ b/DataSpec/DNACommon/Tweaks/ITweakBall.hpp
@@ -7,6 +7,9 @@ namespace DataSpec
{
struct ITweakBall : ITweak
{
+ virtual float GetMaxBallTranslationAcceleration(int s) const=0;
+ virtual float GetBallTranslationFriction(int s) const=0;
+ virtual float GetBallTranslationMaxSpeed(int s) const=0;
virtual float GetBallCameraControlDistance() const=0;
virtual float GetLeftStickDivisor() const=0;
virtual float GetRightStickDivisor() const=0;
diff --git a/DataSpec/DNACommon/Tweaks/ITweakGame.hpp b/DataSpec/DNACommon/Tweaks/ITweakGame.hpp
index 8f6dc8b80..4dae5ce70 100644
--- a/DataSpec/DNACommon/Tweaks/ITweakGame.hpp
+++ b/DataSpec/DNACommon/Tweaks/ITweakGame.hpp
@@ -12,6 +12,7 @@ struct ITweakGame : ITweak
virtual bool GetSplashScreensDisabled() const = 0;
virtual float GetFirstPersonFOV() const = 0;
virtual float GetPressStartDelay() const = 0;
+ virtual float GetFluidEnvBumpScale() const = 0;
virtual float GetHardModeDamageMultiplier() const = 0;
virtual float GetHardModeWeaponMultiplier() const = 0;
};
diff --git a/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp b/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp
index 9c58af6c2..9f960cda8 100644
--- a/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp
+++ b/DataSpec/DNACommon/Tweaks/ITweakPlayer.hpp
@@ -9,14 +9,14 @@ namespace DataSpec
struct ITweakPlayer : ITweak
{
- virtual float GetX50() const=0;
- virtual float GetX54() const=0;
- virtual float GetX58() const=0;
- virtual float GetX5C() const=0;
+ virtual float GetMaxTranslationalAcceleration(int s) const=0;
+ virtual float GetPlayerTranslationFriction(int s) const=0;
+ virtual float GetPlayerTranslationMaxSpeed(int s) const=0;
virtual float GetNormalGravAccel() const=0;
virtual float GetFluidGravAccel() const=0;
virtual float GetEyeOffset() const=0;
- virtual float GetHudLagAmount() const=0;
+ virtual float GetFreeLookSpeed() const=0;
+ virtual float GetFreeLookSnapSpeed() const=0;
virtual float GetFreeLookCenteredThresholdAngle() const=0;
virtual float GetFreeLookCenteredTime() const=0;
virtual float GetOrbitNormalDistance() const=0;
@@ -56,7 +56,7 @@ struct ITweakPlayer : ITweak
virtual bool GetGunNotFiringHolstersGun() const=0;
virtual float GetPlayerHeight() const=0; // x26c
virtual float GetPlayerXYHalfExtent() const=0; // x270
- virtual bool GetX228_24() const=0; // x228_24
+ virtual bool GetFreeLookTurnsPlayer() const=0; // x228_24
virtual float GetX274() const=0; // x274
virtual float GetX278() const=0; // x278
virtual float GetPlayerBallHalfExtent() const=0; // x27c
@@ -85,7 +85,6 @@ struct ITweakPlayer : ITweak
virtual float GetX29C() const=0; // x29c
virtual float GetX280() const=0; // x280
virtual float GetX2B0() const=0; // x2b0
- virtual float GetX138() const=0; // x138
virtual float GetX14C() const=0; // x14c
virtual float GetLeftLogicalThreshold() const=0;
virtual float GetRightLogicalThreshold() const=0;
diff --git a/DataSpec/DNAMP1/Tweaks/CTweakBall.cpp b/DataSpec/DNAMP1/Tweaks/CTweakBall.cpp
index 983b1cb44..05f438d24 100644
--- a/DataSpec/DNAMP1/Tweaks/CTweakBall.cpp
+++ b/DataSpec/DNAMP1/Tweaks/CTweakBall.cpp
@@ -8,53 +8,53 @@ namespace DNAMP1
void CTweakBall::read(athena::io::IStreamReader& __dna_reader)
{
/* x4_[0] */
- x4_[0] = __dna_reader.readFloatBig();
+ x4_maxTranslationAcceleration[0] = __dna_reader.readFloatBig();
/* x4_[1] */
- x4_[1] = __dna_reader.readFloatBig();
+ x4_maxTranslationAcceleration[1] = __dna_reader.readFloatBig();
/* x4_[2] */
- x4_[2] = __dna_reader.readFloatBig();
+ x4_maxTranslationAcceleration[2] = __dna_reader.readFloatBig();
/* x4_[3] */
- x4_[3] = __dna_reader.readFloatBig();
+ x4_maxTranslationAcceleration[3] = __dna_reader.readFloatBig();
/* x4_[4] */
- x4_[4] = __dna_reader.readFloatBig();
+ x4_maxTranslationAcceleration[4] = __dna_reader.readFloatBig();
/* x4_[5] */
- x4_[5] = __dna_reader.readFloatBig();
+ x4_maxTranslationAcceleration[5] = __dna_reader.readFloatBig();
/* x4_[6] */
- x4_[6] = __dna_reader.readFloatBig();
+ x4_maxTranslationAcceleration[6] = __dna_reader.readFloatBig();
/* x4_[7] */
- x4_[7] = __dna_reader.readFloatBig();
+ x4_maxTranslationAcceleration[7] = __dna_reader.readFloatBig();
/* x24_[0] */
- x24_[0] = __dna_reader.readFloatBig();
+ x24_translationFriction[0] = __dna_reader.readFloatBig();
/* x24_[1] */
- x24_[1] = __dna_reader.readFloatBig();
+ x24_translationFriction[1] = __dna_reader.readFloatBig();
/* x24_[2] */
- x24_[2] = __dna_reader.readFloatBig();
+ x24_translationFriction[2] = __dna_reader.readFloatBig();
/* x24_[3] */
- x24_[3] = __dna_reader.readFloatBig();
+ x24_translationFriction[3] = __dna_reader.readFloatBig();
/* x24_[4] */
- x24_[4] = __dna_reader.readFloatBig();
+ x24_translationFriction[4] = __dna_reader.readFloatBig();
/* x24_[5] */
- x24_[5] = __dna_reader.readFloatBig();
+ x24_translationFriction[5] = __dna_reader.readFloatBig();
/* x24_[6] */
- x24_[6] = __dna_reader.readFloatBig();
+ x24_translationFriction[6] = __dna_reader.readFloatBig();
/* x24_[7] */
- x24_[7] = __dna_reader.readFloatBig();
+ x24_translationFriction[7] = __dna_reader.readFloatBig();
/* x44_[0] */
- x44_[0] = __dna_reader.readFloatBig();
+ x44_translationMaxSpeed[0] = __dna_reader.readFloatBig();
/* x44_[1] */
- x44_[1] = __dna_reader.readFloatBig();
+ x44_translationMaxSpeed[1] = __dna_reader.readFloatBig();
/* x44_[2] */
- x44_[2] = __dna_reader.readFloatBig();
+ x44_translationMaxSpeed[2] = __dna_reader.readFloatBig();
/* x44_[3] */
- x44_[3] = __dna_reader.readFloatBig();
+ x44_translationMaxSpeed[3] = __dna_reader.readFloatBig();
/* x44_[4] */
- x44_[4] = __dna_reader.readFloatBig();
+ x44_translationMaxSpeed[4] = __dna_reader.readFloatBig();
/* x44_[5] */
- x44_[5] = __dna_reader.readFloatBig();
+ x44_translationMaxSpeed[5] = __dna_reader.readFloatBig();
/* x44_[6] */
- x44_[6] = __dna_reader.readFloatBig();
+ x44_translationMaxSpeed[6] = __dna_reader.readFloatBig();
/* x44_[7] */
- x44_[7] = __dna_reader.readFloatBig();
+ x44_translationMaxSpeed[7] = __dna_reader.readFloatBig();
/* x64_ */
x64_ = __dna_reader.readFloatBig();
/* x68_ */
@@ -228,53 +228,53 @@ void CTweakBall::read(athena::io::IStreamReader& __dna_reader)
void CTweakBall::write(athena::io::IStreamWriter& __dna_writer) const
{
/* x4_[0] */
- __dna_writer.writeFloatBig(x4_[0]);
+ __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[0]);
/* x4_[1] */
- __dna_writer.writeFloatBig(x4_[1]);
+ __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[1]);
/* x4_[2] */
- __dna_writer.writeFloatBig(x4_[2]);
+ __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[2]);
/* x4_[3] */
- __dna_writer.writeFloatBig(x4_[3]);
+ __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[3]);
/* x4_[4] */
- __dna_writer.writeFloatBig(x4_[4]);
+ __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[4]);
/* x4_[5] */
- __dna_writer.writeFloatBig(x4_[5]);
+ __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[5]);
/* x4_[6] */
- __dna_writer.writeFloatBig(x4_[6]);
+ __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[6]);
/* x4_[7] */
- __dna_writer.writeFloatBig(x4_[7]);
+ __dna_writer.writeFloatBig(x4_maxTranslationAcceleration[7]);
/* x24_[0] */
- __dna_writer.writeFloatBig(x24_[0]);
+ __dna_writer.writeFloatBig(x24_translationFriction[0]);
/* x24_[1] */
- __dna_writer.writeFloatBig(x24_[1]);
+ __dna_writer.writeFloatBig(x24_translationFriction[1]);
/* x24_[2] */
- __dna_writer.writeFloatBig(x24_[2]);
+ __dna_writer.writeFloatBig(x24_translationFriction[2]);
/* x24_[3] */
- __dna_writer.writeFloatBig(x24_[3]);
+ __dna_writer.writeFloatBig(x24_translationFriction[3]);
/* x24_[4] */
- __dna_writer.writeFloatBig(x24_[4]);
+ __dna_writer.writeFloatBig(x24_translationFriction[4]);
/* x24_[5] */
- __dna_writer.writeFloatBig(x24_[5]);
+ __dna_writer.writeFloatBig(x24_translationFriction[5]);
/* x24_[6] */
- __dna_writer.writeFloatBig(x24_[6]);
+ __dna_writer.writeFloatBig(x24_translationFriction[6]);
/* x24_[7] */
- __dna_writer.writeFloatBig(x24_[7]);
+ __dna_writer.writeFloatBig(x24_translationFriction[7]);
/* x44_[0] */
- __dna_writer.writeFloatBig(x44_[0]);
+ __dna_writer.writeFloatBig(x44_translationMaxSpeed[0]);
/* x44_[1] */
- __dna_writer.writeFloatBig(x44_[1]);
+ __dna_writer.writeFloatBig(x44_translationMaxSpeed[1]);
/* x44_[2] */
- __dna_writer.writeFloatBig(x44_[2]);
+ __dna_writer.writeFloatBig(x44_translationMaxSpeed[2]);
/* x44_[3] */
- __dna_writer.writeFloatBig(x44_[3]);
+ __dna_writer.writeFloatBig(x44_translationMaxSpeed[3]);
/* x44_[4] */
- __dna_writer.writeFloatBig(x44_[4]);
+ __dna_writer.writeFloatBig(x44_translationMaxSpeed[4]);
/* x44_[5] */
- __dna_writer.writeFloatBig(x44_[5]);
+ __dna_writer.writeFloatBig(x44_translationMaxSpeed[5]);
/* x44_[6] */
- __dna_writer.writeFloatBig(x44_[6]);
+ __dna_writer.writeFloatBig(x44_translationMaxSpeed[6]);
/* x44_[7] */
- __dna_writer.writeFloatBig(x44_[7]);
+ __dna_writer.writeFloatBig(x44_translationMaxSpeed[7]);
/* x64_ */
__dna_writer.writeFloatBig(x64_);
/* x68_ */
@@ -452,63 +452,63 @@ void CTweakBall::read(athena::io::YAMLDocReader& __dna_docin)
if (auto v = __dna_docin.enterSubVector("x4_", __x4_Count))
{
/* x4_[0] */
- x4_[0] = __dna_docin.readFloat("x4_");
+ x4_maxTranslationAcceleration[0] = __dna_docin.readFloat("x4_");
/* x4_[1] */
- x4_[1] = __dna_docin.readFloat("x4_");
+ x4_maxTranslationAcceleration[1] = __dna_docin.readFloat("x4_");
/* x4_[2] */
- x4_[2] = __dna_docin.readFloat("x4_");
+ x4_maxTranslationAcceleration[2] = __dna_docin.readFloat("x4_");
/* x4_[3] */
- x4_[3] = __dna_docin.readFloat("x4_");
+ x4_maxTranslationAcceleration[3] = __dna_docin.readFloat("x4_");
/* x4_[4] */
- x4_[4] = __dna_docin.readFloat("x4_");
+ x4_maxTranslationAcceleration[4] = __dna_docin.readFloat("x4_");
/* x4_[5] */
- x4_[5] = __dna_docin.readFloat("x4_");
+ x4_maxTranslationAcceleration[5] = __dna_docin.readFloat("x4_");
/* x4_[6] */
- x4_[6] = __dna_docin.readFloat("x4_");
+ x4_maxTranslationAcceleration[6] = __dna_docin.readFloat("x4_");
/* x4_[7] */
- x4_[7] = __dna_docin.readFloat("x4_");
+ x4_maxTranslationAcceleration[7] = __dna_docin.readFloat("x4_");
}
/* x24_ */
size_t __x24_Count;
if (auto v = __dna_docin.enterSubVector("x24_", __x24_Count))
{
/* x24_[0] */
- x24_[0] = __dna_docin.readFloat("x24_");
+ x24_translationFriction[0] = __dna_docin.readFloat("x24_");
/* x24_[1] */
- x24_[1] = __dna_docin.readFloat("x24_");
+ x24_translationFriction[1] = __dna_docin.readFloat("x24_");
/* x24_[2] */
- x24_[2] = __dna_docin.readFloat("x24_");
+ x24_translationFriction[2] = __dna_docin.readFloat("x24_");
/* x24_[3] */
- x24_[3] = __dna_docin.readFloat("x24_");
+ x24_translationFriction[3] = __dna_docin.readFloat("x24_");
/* x24_[4] */
- x24_[4] = __dna_docin.readFloat("x24_");
+ x24_translationFriction[4] = __dna_docin.readFloat("x24_");
/* x24_[5] */
- x24_[5] = __dna_docin.readFloat("x24_");
+ x24_translationFriction[5] = __dna_docin.readFloat("x24_");
/* x24_[6] */
- x24_[6] = __dna_docin.readFloat("x24_");
+ x24_translationFriction[6] = __dna_docin.readFloat("x24_");
/* x24_[7] */
- x24_[7] = __dna_docin.readFloat("x24_");
+ x24_translationFriction[7] = __dna_docin.readFloat("x24_");
}
/* x44_ */
size_t __x44_Count;
if (auto v = __dna_docin.enterSubVector("x44_", __x44_Count))
{
/* x44_[0] */
- x44_[0] = __dna_docin.readFloat("x44_");
+ x44_translationMaxSpeed[0] = __dna_docin.readFloat("x44_");
/* x44_[1] */
- x44_[1] = __dna_docin.readFloat("x44_");
+ x44_translationMaxSpeed[1] = __dna_docin.readFloat("x44_");
/* x44_[2] */
- x44_[2] = __dna_docin.readFloat("x44_");
+ x44_translationMaxSpeed[2] = __dna_docin.readFloat("x44_");
/* x44_[3] */
- x44_[3] = __dna_docin.readFloat("x44_");
+ x44_translationMaxSpeed[3] = __dna_docin.readFloat("x44_");
/* x44_[4] */
- x44_[4] = __dna_docin.readFloat("x44_");
+ x44_translationMaxSpeed[4] = __dna_docin.readFloat("x44_");
/* x44_[5] */
- x44_[5] = __dna_docin.readFloat("x44_");
+ x44_translationMaxSpeed[5] = __dna_docin.readFloat("x44_");
/* x44_[6] */
- x44_[6] = __dna_docin.readFloat("x44_");
+ x44_translationMaxSpeed[6] = __dna_docin.readFloat("x44_");
/* x44_[7] */
- x44_[7] = __dna_docin.readFloat("x44_");
+ x44_translationMaxSpeed[7] = __dna_docin.readFloat("x44_");
}
/* x64_ */
x64_ = __dna_docin.readFloat("x64_");
@@ -691,61 +691,61 @@ void CTweakBall::write(athena::io::YAMLDocWriter& __dna_docout) const
if (auto v = __dna_docout.enterSubVector("x4_"))
{
/* x4_[0] */
- __dna_docout.writeFloat("x4_", x4_[0]);
+ __dna_docout.writeFloat("x4_", x4_maxTranslationAcceleration[0]);
/* x4_[1] */
- __dna_docout.writeFloat("x4_", x4_[1]);
+ __dna_docout.writeFloat("x4_", x4_maxTranslationAcceleration[1]);
/* x4_[2] */
- __dna_docout.writeFloat("x4_", x4_[2]);
+ __dna_docout.writeFloat("x4_", x4_maxTranslationAcceleration[2]);
/* x4_[3] */
- __dna_docout.writeFloat("x4_", x4_[3]);
+ __dna_docout.writeFloat("x4_", x4_maxTranslationAcceleration[3]);
/* x4_[4] */
- __dna_docout.writeFloat("x4_", x4_[4]);
+ __dna_docout.writeFloat("x4_", x4_maxTranslationAcceleration[4]);
/* x4_[5] */
- __dna_docout.writeFloat("x4_", x4_[5]);
+ __dna_docout.writeFloat("x4_", x4_maxTranslationAcceleration[5]);
/* x4_[6] */
- __dna_docout.writeFloat("x4_", x4_[6]);
+ __dna_docout.writeFloat("x4_", x4_maxTranslationAcceleration[6]);
/* x4_[7] */
- __dna_docout.writeFloat("x4_", x4_[7]);
+ __dna_docout.writeFloat("x4_", x4_maxTranslationAcceleration[7]);
}
/* x24_ */
if (auto v = __dna_docout.enterSubVector("x24_"))
{
/* x24_[0] */
- __dna_docout.writeFloat("x24_", x24_[0]);
+ __dna_docout.writeFloat("x24_", x24_translationFriction[0]);
/* x24_[1] */
- __dna_docout.writeFloat("x24_", x24_[1]);
+ __dna_docout.writeFloat("x24_", x24_translationFriction[1]);
/* x24_[2] */
- __dna_docout.writeFloat("x24_", x24_[2]);
+ __dna_docout.writeFloat("x24_", x24_translationFriction[2]);
/* x24_[3] */
- __dna_docout.writeFloat("x24_", x24_[3]);
+ __dna_docout.writeFloat("x24_", x24_translationFriction[3]);
/* x24_[4] */
- __dna_docout.writeFloat("x24_", x24_[4]);
+ __dna_docout.writeFloat("x24_", x24_translationFriction[4]);
/* x24_[5] */
- __dna_docout.writeFloat("x24_", x24_[5]);
+ __dna_docout.writeFloat("x24_", x24_translationFriction[5]);
/* x24_[6] */
- __dna_docout.writeFloat("x24_", x24_[6]);
+ __dna_docout.writeFloat("x24_", x24_translationFriction[6]);
/* x24_[7] */
- __dna_docout.writeFloat("x24_", x24_[7]);
+ __dna_docout.writeFloat("x24_", x24_translationFriction[7]);
}
/* x44_ */
if (auto v = __dna_docout.enterSubVector("x44_"))
{
/* x44_[0] */
- __dna_docout.writeFloat("x44_", x44_[0]);
+ __dna_docout.writeFloat("x44_", x44_translationMaxSpeed[0]);
/* x44_[1] */
- __dna_docout.writeFloat("x44_", x44_[1]);
+ __dna_docout.writeFloat("x44_", x44_translationMaxSpeed[1]);
/* x44_[2] */
- __dna_docout.writeFloat("x44_", x44_[2]);
+ __dna_docout.writeFloat("x44_", x44_translationMaxSpeed[2]);
/* x44_[3] */
- __dna_docout.writeFloat("x44_", x44_[3]);
+ __dna_docout.writeFloat("x44_", x44_translationMaxSpeed[3]);
/* x44_[4] */
- __dna_docout.writeFloat("x44_", x44_[4]);
+ __dna_docout.writeFloat("x44_", x44_translationMaxSpeed[4]);
/* x44_[5] */
- __dna_docout.writeFloat("x44_", x44_[5]);
+ __dna_docout.writeFloat("x44_", x44_translationMaxSpeed[5]);
/* x44_[6] */
- __dna_docout.writeFloat("x44_", x44_[6]);
+ __dna_docout.writeFloat("x44_", x44_translationMaxSpeed[6]);
/* x44_[7] */
- __dna_docout.writeFloat("x44_", x44_[7]);
+ __dna_docout.writeFloat("x44_", x44_translationMaxSpeed[7]);
}
/* x64_ */
__dna_docout.writeFloat("x64_", x64_);
diff --git a/DataSpec/DNAMP1/Tweaks/CTweakBall.hpp b/DataSpec/DNAMP1/Tweaks/CTweakBall.hpp
index 29cec4864..c2e020a12 100644
--- a/DataSpec/DNAMP1/Tweaks/CTweakBall.hpp
+++ b/DataSpec/DNAMP1/Tweaks/CTweakBall.hpp
@@ -12,9 +12,9 @@ struct CTweakBall : public ITweakBall
{
DECL_YAML
Delete __d;
- Value x4_[8];
- Value x24_[8];
- Value x44_[8];
+ Value x4_maxTranslationAcceleration[8];
+ Value x24_translationFriction[8];
+ Value x44_translationMaxSpeed[8];
Value x64_;
Value x68_;
Value x6c_;
@@ -137,6 +137,9 @@ struct CTweakBall : public ITweakBall
x1ec_ = zeus::degToRad(x1ec_);
}
+ float GetMaxBallTranslationAcceleration(int s) const { return x4_maxTranslationAcceleration[s]; }
+ float GetBallTranslationFriction(int s) const { return x24_translationFriction[s]; }
+ float GetBallTranslationMaxSpeed(int s) const { return x44_translationMaxSpeed[s]; }
float GetBallCameraControlDistance() const { return x1d0_ballCameraControlDistance; }
float GetLeftStickDivisor() const { return x1e4_leftStickDivisor; }
float GetRightStickDivisor() const { return x1e8_rightStickDivisor; }
diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp b/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp
index 31268c17f..dac212252 100644
--- a/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp
+++ b/DataSpec/DNAMP1/Tweaks/CTweakGame.hpp
@@ -26,7 +26,7 @@ struct CTweakGame : ITweakGame
Value x40_unknown10;
Value x44_unknown11;
Value x48_unknown12;
- Value x4c_unknown13;
+ Value x4c_fluidEnvBumpScale;
Value x50_unknown14;
Value x54_unknown15;
Value x58_unknown16;
@@ -38,6 +38,7 @@ struct CTweakGame : ITweakGame
virtual bool GetSplashScreensDisabled() const { return x2b_splashScreensDisabled; }
virtual float GetFirstPersonFOV() const { return x24_fov; }
virtual float GetPressStartDelay() const { return x30_presStartDelay; }
+ virtual float GetFluidEnvBumpScale() const { return x4c_fluidEnvBumpScale; }
virtual float GetHardModeDamageMultiplier() const { return x60_hardmodeDamageMult; }
virtual float GetHardModeWeaponMultiplier() const { return x64_hardmodeWeaponMult; }
CTweakGame() = default;
diff --git a/DataSpec/DNAMP1/Tweaks/CTweakPlayer.cpp b/DataSpec/DNAMP1/Tweaks/CTweakPlayer.cpp
index ba801703f..00015b301 100644
--- a/DataSpec/DNAMP1/Tweaks/CTweakPlayer.cpp
+++ b/DataSpec/DNAMP1/Tweaks/CTweakPlayer.cpp
@@ -7,22 +7,22 @@ namespace DNAMP1
{
void CTweakPlayer::read(athena::io::IStreamReader& __dna_reader)
{
- /* x4_[0] */
- x4_[0] = __dna_reader.readFloatBig();
- /* x4_[1] */
- x4_[1] = __dna_reader.readFloatBig();
- /* x4_[2] */
- x4_[2] = __dna_reader.readFloatBig();
- /* x4_[3] */
- x4_[3] = __dna_reader.readFloatBig();
- /* x4_[4] */
- x4_[4] = __dna_reader.readFloatBig();
- /* x4_[5] */
- x4_[5] = __dna_reader.readFloatBig();
- /* x4_[6] */
- x4_[6] = __dna_reader.readFloatBig();
- /* x4_[7] */
- x4_[7] = __dna_reader.readFloatBig();
+ /* x4_maxTranslationalAcceleration[0] */
+ x4_maxTranslationalAcceleration[0] = __dna_reader.readFloatBig();
+ /* x4_maxTranslationalAcceleration[1] */
+ x4_maxTranslationalAcceleration[1] = __dna_reader.readFloatBig();
+ /* x4_maxTranslationalAcceleration[2] */
+ x4_maxTranslationalAcceleration[2] = __dna_reader.readFloatBig();
+ /* x4_maxTranslationalAcceleration[3] */
+ x4_maxTranslationalAcceleration[3] = __dna_reader.readFloatBig();
+ /* x4_maxTranslationalAcceleration[4] */
+ x4_maxTranslationalAcceleration[4] = __dna_reader.readFloatBig();
+ /* x4_maxTranslationalAcceleration[5] */
+ x4_maxTranslationalAcceleration[5] = __dna_reader.readFloatBig();
+ /* x4_maxTranslationalAcceleration[6] */
+ x4_maxTranslationalAcceleration[6] = __dna_reader.readFloatBig();
+ /* x4_maxTranslationalAcceleration[7] */
+ x4_maxTranslationalAcceleration[7] = __dna_reader.readFloatBig();
/* x24_[0] */
x24_[0] = __dna_reader.readFloatBig();
/* x24_[1] */
@@ -39,22 +39,22 @@ void CTweakPlayer::read(athena::io::IStreamReader& __dna_reader)
x24_[6] = __dna_reader.readFloatBig();
/* x24_[7] */
x24_[7] = __dna_reader.readFloatBig();
- /* x44_[0] */
- x44_[0] = __dna_reader.readFloatBig();
- /* x44_[1] */
- x44_[1] = __dna_reader.readFloatBig();
- /* x44_[2] */
- x44_[2] = __dna_reader.readFloatBig();
- /* x44_[3] */
- x44_[3] = __dna_reader.readFloatBig();
- /* x44_[4] */
- x44_[4] = __dna_reader.readFloatBig();
- /* x44_[5] */
- x44_[5] = __dna_reader.readFloatBig();
- /* x44_[6] */
- x44_[6] = __dna_reader.readFloatBig();
- /* x44_[7] */
- x44_[7] = __dna_reader.readFloatBig();
+ /* x44_translationFriction[0] */
+ x44_translationFriction[0] = __dna_reader.readFloatBig();
+ /* x44_translationFriction[1] */
+ x44_translationFriction[1] = __dna_reader.readFloatBig();
+ /* x44_translationFriction[2] */
+ x44_translationFriction[2] = __dna_reader.readFloatBig();
+ /* x44_translationFriction[3] */
+ x44_translationFriction[3] = __dna_reader.readFloatBig();
+ /* x44_translationFriction[4] */
+ x44_translationFriction[4] = __dna_reader.readFloatBig();
+ /* x44_translationFriction[5] */
+ x44_translationFriction[5] = __dna_reader.readFloatBig();
+ /* x44_translationFriction[6] */
+ x44_translationFriction[6] = __dna_reader.readFloatBig();
+ /* x44_translationFriction[7] */
+ x44_translationFriction[7] = __dna_reader.readFloatBig();
/* x64_[0] */
x64_[0] = __dna_reader.readFloatBig();
/* x64_[1] */
@@ -87,22 +87,22 @@ void CTweakPlayer::read(athena::io::IStreamReader& __dna_reader)
x84_[6] = __dna_reader.readFloatBig();
/* x84_[7] */
x84_[7] = __dna_reader.readFloatBig();
- /* xa4_[0] */
- xa4_[0] = __dna_reader.readFloatBig();
- /* xa4_[1] */
- xa4_[1] = __dna_reader.readFloatBig();
- /* xa4_[2] */
- xa4_[2] = __dna_reader.readFloatBig();
- /* xa4_[3] */
- xa4_[3] = __dna_reader.readFloatBig();
- /* xa4_[4] */
- xa4_[4] = __dna_reader.readFloatBig();
- /* xa4_[5] */
- xa4_[5] = __dna_reader.readFloatBig();
- /* xa4_[6] */
- xa4_[6] = __dna_reader.readFloatBig();
- /* xa4_[7] */
- xa4_[7] = __dna_reader.readFloatBig();
+ /* xa4_translationMaxSpeed[0] */
+ xa4_translationMaxSpeed[0] = __dna_reader.readFloatBig();
+ /* xa4_translationMaxSpeed[1] */
+ xa4_translationMaxSpeed[1] = __dna_reader.readFloatBig();
+ /* xa4_translationMaxSpeed[2] */
+ xa4_translationMaxSpeed[2] = __dna_reader.readFloatBig();
+ /* xa4_translationMaxSpeed[3] */
+ xa4_translationMaxSpeed[3] = __dna_reader.readFloatBig();
+ /* xa4_translationMaxSpeed[4] */
+ xa4_translationMaxSpeed[4] = __dna_reader.readFloatBig();
+ /* xa4_translationMaxSpeed[5] */
+ xa4_translationMaxSpeed[5] = __dna_reader.readFloatBig();
+ /* xa4_translationMaxSpeed[6] */
+ xa4_translationMaxSpeed[6] = __dna_reader.readFloatBig();
+ /* xa4_translationMaxSpeed[7] */
+ xa4_translationMaxSpeed[7] = __dna_reader.readFloatBig();
/* xc4_normalGravAccel */
xc4_normalGravAccel = __dna_reader.readFloatBig();
/* xc8_fluidGravAccel */
@@ -161,10 +161,10 @@ void CTweakPlayer::read(athena::io::IStreamReader& __dna_reader)
x130_horizontalFreeLookAngleVel = __dna_reader.readFloatBig();
/* x134_verticalFreeLookAngleVel */
x134_verticalFreeLookAngleVel = __dna_reader.readFloatBig();
- /* x138_hudLagAmount */
- x138_hudLagAmount = __dna_reader.readFloatBig();
- /* x13c_ */
- x13c_ = __dna_reader.readFloatBig();
+ /* x138_freeLookSpeed */
+ x138_freeLookSpeed = __dna_reader.readFloatBig();
+ /* x13c_freeLookSnapSpeed */
+ x13c_freeLookSnapSpeed = __dna_reader.readFloatBig();
/* x140_ */
x140_ = __dna_reader.readFloatBig();
/* x144_freeLookCenteredThresholdAngle */
@@ -177,8 +177,8 @@ void CTweakPlayer::read(athena::io::IStreamReader& __dna_reader)
x150_leftDiv = __dna_reader.readFloatBig();
/* x154_rightDiv */
x154_rightDiv = __dna_reader.readFloatBig();
- /* x228_24_ */
- x228_24_ = __dna_reader.readBool();
+ /* x228_24_freelookTurnsPlayer */
+ x228_24_freelookTurnsPlayer = __dna_reader.readBool();
/* x228_25_ */
x228_25_ = __dna_reader.readBool();
/* x228_26_ */
@@ -447,22 +447,22 @@ void CTweakPlayer::read(athena::io::IStreamReader& __dna_reader)
void CTweakPlayer::write(athena::io::IStreamWriter& __dna_writer) const
{
- /* x4_[0] */
- __dna_writer.writeFloatBig(x4_[0]);
- /* x4_[1] */
- __dna_writer.writeFloatBig(x4_[1]);
- /* x4_[2] */
- __dna_writer.writeFloatBig(x4_[2]);
- /* x4_[3] */
- __dna_writer.writeFloatBig(x4_[3]);
- /* x4_[4] */
- __dna_writer.writeFloatBig(x4_[4]);
- /* x4_[5] */
- __dna_writer.writeFloatBig(x4_[5]);
- /* x4_[6] */
- __dna_writer.writeFloatBig(x4_[6]);
- /* x4_[7] */
- __dna_writer.writeFloatBig(x4_[7]);
+ /* x4_maxTranslationalAcceleration[0] */
+ __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[0]);
+ /* x4_maxTranslationalAcceleration[1] */
+ __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[1]);
+ /* x4_maxTranslationalAcceleration[2] */
+ __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[2]);
+ /* x4_maxTranslationalAcceleration[3] */
+ __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[3]);
+ /* x4_maxTranslationalAcceleration[4] */
+ __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[4]);
+ /* x4_maxTranslationalAcceleration[5] */
+ __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[5]);
+ /* x4_maxTranslationalAcceleration[6] */
+ __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[6]);
+ /* x4_maxTranslationalAcceleration[7] */
+ __dna_writer.writeFloatBig(x4_maxTranslationalAcceleration[7]);
/* x24_[0] */
__dna_writer.writeFloatBig(x24_[0]);
/* x24_[1] */
@@ -479,22 +479,22 @@ void CTweakPlayer::write(athena::io::IStreamWriter& __dna_writer) const
__dna_writer.writeFloatBig(x24_[6]);
/* x24_[7] */
__dna_writer.writeFloatBig(x24_[7]);
- /* x44_[0] */
- __dna_writer.writeFloatBig(x44_[0]);
- /* x44_[1] */
- __dna_writer.writeFloatBig(x44_[1]);
- /* x44_[2] */
- __dna_writer.writeFloatBig(x44_[2]);
- /* x44_[3] */
- __dna_writer.writeFloatBig(x44_[3]);
- /* x44_[4] */
- __dna_writer.writeFloatBig(x44_[4]);
- /* x44_[5] */
- __dna_writer.writeFloatBig(x44_[5]);
- /* x44_[6] */
- __dna_writer.writeFloatBig(x44_[6]);
- /* x44_[7] */
- __dna_writer.writeFloatBig(x44_[7]);
+ /* x44_translationFriction[0] */
+ __dna_writer.writeFloatBig(x44_translationFriction[0]);
+ /* x44_translationFriction[1] */
+ __dna_writer.writeFloatBig(x44_translationFriction[1]);
+ /* x44_translationFriction[2] */
+ __dna_writer.writeFloatBig(x44_translationFriction[2]);
+ /* x44_translationFriction[3] */
+ __dna_writer.writeFloatBig(x44_translationFriction[3]);
+ /* x44_translationFriction[4] */
+ __dna_writer.writeFloatBig(x44_translationFriction[4]);
+ /* x44_translationFriction[5] */
+ __dna_writer.writeFloatBig(x44_translationFriction[5]);
+ /* x44_translationFriction[6] */
+ __dna_writer.writeFloatBig(x44_translationFriction[6]);
+ /* x44_translationFriction[7] */
+ __dna_writer.writeFloatBig(x44_translationFriction[7]);
/* x64_[0] */
__dna_writer.writeFloatBig(x64_[0]);
/* x64_[1] */
@@ -527,22 +527,22 @@ void CTweakPlayer::write(athena::io::IStreamWriter& __dna_writer) const
__dna_writer.writeFloatBig(x84_[6]);
/* x84_[7] */
__dna_writer.writeFloatBig(x84_[7]);
- /* xa4_[0] */
- __dna_writer.writeFloatBig(xa4_[0]);
- /* xa4_[1] */
- __dna_writer.writeFloatBig(xa4_[1]);
- /* xa4_[2] */
- __dna_writer.writeFloatBig(xa4_[2]);
- /* xa4_[3] */
- __dna_writer.writeFloatBig(xa4_[3]);
- /* xa4_[4] */
- __dna_writer.writeFloatBig(xa4_[4]);
- /* xa4_[5] */
- __dna_writer.writeFloatBig(xa4_[5]);
- /* xa4_[6] */
- __dna_writer.writeFloatBig(xa4_[6]);
- /* xa4_[7] */
- __dna_writer.writeFloatBig(xa4_[7]);
+ /* xa4_translationMaxSpeed[0] */
+ __dna_writer.writeFloatBig(xa4_translationMaxSpeed[0]);
+ /* xa4_translationMaxSpeed[1] */
+ __dna_writer.writeFloatBig(xa4_translationMaxSpeed[1]);
+ /* xa4_translationMaxSpeed[2] */
+ __dna_writer.writeFloatBig(xa4_translationMaxSpeed[2]);
+ /* xa4_translationMaxSpeed[3] */
+ __dna_writer.writeFloatBig(xa4_translationMaxSpeed[3]);
+ /* xa4_translationMaxSpeed[4] */
+ __dna_writer.writeFloatBig(xa4_translationMaxSpeed[4]);
+ /* xa4_translationMaxSpeed[5] */
+ __dna_writer.writeFloatBig(xa4_translationMaxSpeed[5]);
+ /* xa4_translationMaxSpeed[6] */
+ __dna_writer.writeFloatBig(xa4_translationMaxSpeed[6]);
+ /* xa4_translationMaxSpeed[7] */
+ __dna_writer.writeFloatBig(xa4_translationMaxSpeed[7]);
/* xc4_normalGravAccel */
__dna_writer.writeFloatBig(xc4_normalGravAccel);
/* xc8_fluidGravAccel */
@@ -601,10 +601,10 @@ void CTweakPlayer::write(athena::io::IStreamWriter& __dna_writer) const
__dna_writer.writeFloatBig(x130_horizontalFreeLookAngleVel);
/* x134_verticalFreeLookAngleVel */
__dna_writer.writeFloatBig(x134_verticalFreeLookAngleVel);
- /* x138_ */
- __dna_writer.writeFloatBig(x138_hudLagAmount);
- /* x13c_ */
- __dna_writer.writeFloatBig(x13c_);
+ /* x138_freeLookSpeed */
+ __dna_writer.writeFloatBig(x138_freeLookSpeed);
+ /* x13c_freeLookSnapSpeed */
+ __dna_writer.writeFloatBig(x13c_freeLookSnapSpeed);
/* x140_ */
__dna_writer.writeFloatBig(x140_);
/* x144_freeLookCenteredThresholdAngle */
@@ -617,8 +617,8 @@ void CTweakPlayer::write(athena::io::IStreamWriter& __dna_writer) const
__dna_writer.writeFloatBig(x150_leftDiv);
/* x154_rightDiv */
__dna_writer.writeFloatBig(x154_rightDiv);
- /* x228_24_ */
- __dna_writer.writeBool(x228_24_);
+ /* x228_24_freelookTurnsPlayer */
+ __dna_writer.writeBool(x228_24_freelookTurnsPlayer);
/* x228_25_ */
__dna_writer.writeBool(x228_25_);
/* x228_26_ */
@@ -887,26 +887,26 @@ void CTweakPlayer::write(athena::io::IStreamWriter& __dna_writer) const
void CTweakPlayer::read(athena::io::YAMLDocReader& __dna_docin)
{
- /* x4_ */
+ /* x4_maxTranslationalAcceleration */
size_t __x4_Count;
- if (auto v = __dna_docin.enterSubVector("x4_", __x4_Count))
+ if (auto v = __dna_docin.enterSubVector("x4_maxTranslationalAcceleration", __x4_Count))
{
- /* x4_[0] */
- x4_[0] = __dna_docin.readFloat("x4_");
- /* x4_[1] */
- x4_[1] = __dna_docin.readFloat("x4_");
- /* x4_[2] */
- x4_[2] = __dna_docin.readFloat("x4_");
- /* x4_[3] */
- x4_[3] = __dna_docin.readFloat("x4_");
- /* x4_[4] */
- x4_[4] = __dna_docin.readFloat("x4_");
- /* x4_[5] */
- x4_[5] = __dna_docin.readFloat("x4_");
- /* x4_[6] */
- x4_[6] = __dna_docin.readFloat("x4_");
- /* x4_[7] */
- x4_[7] = __dna_docin.readFloat("x4_");
+ /* x4_maxTranslationalAcceleration[0] */
+ x4_maxTranslationalAcceleration[0] = __dna_docin.readFloat("x4_maxTranslationalAcceleration");
+ /* x4_maxTranslationalAcceleration[1] */
+ x4_maxTranslationalAcceleration[1] = __dna_docin.readFloat("x4_maxTranslationalAcceleration");
+ /* x4_maxTranslationalAcceleration[2] */
+ x4_maxTranslationalAcceleration[2] = __dna_docin.readFloat("x4_maxTranslationalAcceleration");
+ /* x4_maxTranslationalAcceleration[3] */
+ x4_maxTranslationalAcceleration[3] = __dna_docin.readFloat("x4_maxTranslationalAcceleration");
+ /* x4_maxTranslationalAcceleration[4] */
+ x4_maxTranslationalAcceleration[4] = __dna_docin.readFloat("x4_maxTranslationalAcceleration");
+ /* x4_maxTranslationalAcceleration[5] */
+ x4_maxTranslationalAcceleration[5] = __dna_docin.readFloat("x4_maxTranslationalAcceleration");
+ /* x4_maxTranslationalAcceleration[6] */
+ x4_maxTranslationalAcceleration[6] = __dna_docin.readFloat("x4_maxTranslationalAcceleration");
+ /* x4_maxTranslationalAcceleration[7] */
+ x4_maxTranslationalAcceleration[7] = __dna_docin.readFloat("x4_maxTranslationalAcceleration");
}
/* x24_ */
size_t __x24_Count;
@@ -929,26 +929,26 @@ void CTweakPlayer::read(athena::io::YAMLDocReader& __dna_docin)
/* x24_[7] */
x24_[7] = __dna_docin.readFloat("x24_");
}
- /* x44_ */
+ /* x44_translationFriction */
size_t __x44_Count;
- if (auto v = __dna_docin.enterSubVector("x44_", __x44_Count))
+ if (auto v = __dna_docin.enterSubVector("x44_translationFriction", __x44_Count))
{
- /* x44_[0] */
- x44_[0] = __dna_docin.readFloat("x44_");
- /* x44_[1] */
- x44_[1] = __dna_docin.readFloat("x44_");
- /* x44_[2] */
- x44_[2] = __dna_docin.readFloat("x44_");
- /* x44_[3] */
- x44_[3] = __dna_docin.readFloat("x44_");
- /* x44_[4] */
- x44_[4] = __dna_docin.readFloat("x44_");
- /* x44_[5] */
- x44_[5] = __dna_docin.readFloat("x44_");
- /* x44_[6] */
- x44_[6] = __dna_docin.readFloat("x44_");
- /* x44_[7] */
- x44_[7] = __dna_docin.readFloat("x44_");
+ /* x44_translationFriction[0] */
+ x44_translationFriction[0] = __dna_docin.readFloat("x44_translationFriction");
+ /* x44_translationFriction[1] */
+ x44_translationFriction[1] = __dna_docin.readFloat("x44_translationFriction");
+ /* x44_translationFriction[2] */
+ x44_translationFriction[2] = __dna_docin.readFloat("x44_translationFriction");
+ /* x44_translationFriction[3] */
+ x44_translationFriction[3] = __dna_docin.readFloat("x44_translationFriction");
+ /* x44_translationFriction[4] */
+ x44_translationFriction[4] = __dna_docin.readFloat("x44_translationFriction");
+ /* x44_translationFriction[5] */
+ x44_translationFriction[5] = __dna_docin.readFloat("x44_translationFriction");
+ /* x44_translationFriction[6] */
+ x44_translationFriction[6] = __dna_docin.readFloat("x44_translationFriction");
+ /* x44_translationFriction[7] */
+ x44_translationFriction[7] = __dna_docin.readFloat("x44_translationFriction");
}
/* x64_ */
size_t __x64_Count;
@@ -992,26 +992,26 @@ void CTweakPlayer::read(athena::io::YAMLDocReader& __dna_docin)
/* x84_[7] */
x84_[7] = __dna_docin.readFloat("x84_");
}
- /* xa4_ */
+ /* xa4_translationMaxSpeed */
size_t __xa4_Count;
- if (auto v = __dna_docin.enterSubVector("xa4_", __xa4_Count))
+ if (auto v = __dna_docin.enterSubVector("xa4_translationMaxSpeed", __xa4_Count))
{
- /* xa4_[0] */
- xa4_[0] = __dna_docin.readFloat("xa4_");
- /* xa4_[1] */
- xa4_[1] = __dna_docin.readFloat("xa4_");
- /* xa4_[2] */
- xa4_[2] = __dna_docin.readFloat("xa4_");
- /* xa4_[3] */
- xa4_[3] = __dna_docin.readFloat("xa4_");
- /* xa4_[4] */
- xa4_[4] = __dna_docin.readFloat("xa4_");
- /* xa4_[5] */
- xa4_[5] = __dna_docin.readFloat("xa4_");
- /* xa4_[6] */
- xa4_[6] = __dna_docin.readFloat("xa4_");
- /* xa4_[7] */
- xa4_[7] = __dna_docin.readFloat("xa4_");
+ /* xa4_translationMaxSpeed[0] */
+ xa4_translationMaxSpeed[0] = __dna_docin.readFloat("xa4_translationMaxSpeed");
+ /* xa4_translationMaxSpeed[1] */
+ xa4_translationMaxSpeed[1] = __dna_docin.readFloat("xa4_translationMaxSpeed");
+ /* xa4_translationMaxSpeed[2] */
+ xa4_translationMaxSpeed[2] = __dna_docin.readFloat("xa4_translationMaxSpeed");
+ /* xa4_translationMaxSpeed[3] */
+ xa4_translationMaxSpeed[3] = __dna_docin.readFloat("xa4_translationMaxSpeed");
+ /* xa4_translationMaxSpeed[4] */
+ xa4_translationMaxSpeed[4] = __dna_docin.readFloat("xa4_translationMaxSpeed");
+ /* xa4_translationMaxSpeed[5] */
+ xa4_translationMaxSpeed[5] = __dna_docin.readFloat("xa4_translationMaxSpeed");
+ /* xa4_translationMaxSpeed[6] */
+ xa4_translationMaxSpeed[6] = __dna_docin.readFloat("xa4_translationMaxSpeed");
+ /* xa4_translationMaxSpeed[7] */
+ xa4_translationMaxSpeed[7] = __dna_docin.readFloat("xa4_translationMaxSpeed");
}
/* xc4_normalGravAccel */
xc4_normalGravAccel = __dna_docin.readFloat("xc4_normalGravAccel");
@@ -1071,10 +1071,10 @@ void CTweakPlayer::read(athena::io::YAMLDocReader& __dna_docin)
x130_horizontalFreeLookAngleVel = __dna_docin.readFloat("x130_horizontalFreeLookAngleVel");
/* x134_verticalFreeLookAngleVel */
x134_verticalFreeLookAngleVel = __dna_docin.readFloat("x134_verticalFreeLookAngleVel");
- /* x138_hudLagAmount */
- x138_hudLagAmount = __dna_docin.readFloat("x138_hudLagAmount");
- /* x13c_ */
- x13c_ = __dna_docin.readFloat("x13c_");
+ /* x138_freeLookSpeed */
+ x138_freeLookSpeed = __dna_docin.readFloat("x138_freeLookSpeed");
+ /* x13c_freeLookSnapSpeed */
+ x13c_freeLookSnapSpeed = __dna_docin.readFloat("x13c_freeLookSnapSpeed");
/* x140_ */
x140_ = __dna_docin.readFloat("x140_");
/* x144_freeLookCenteredThresholdAngle */
@@ -1087,8 +1087,8 @@ void CTweakPlayer::read(athena::io::YAMLDocReader& __dna_docin)
x150_leftDiv = __dna_docin.readFloat("x150_leftDiv");
/* x154_rightDiv */
x154_rightDiv = __dna_docin.readFloat("x154_rightDiv");
- /* x228_24_ */
- x228_24_ = __dna_docin.readBool("x228_24_");
+ /* x228_24_freelookTurnsPlayer */
+ x228_24_freelookTurnsPlayer = __dna_docin.readBool("x228_24_freelookTurnsPlayer");
/* x228_25_ */
x228_25_ = __dna_docin.readBool("x228_25_");
/* x228_26_ */
@@ -1402,25 +1402,25 @@ void CTweakPlayer::read(athena::io::YAMLDocReader& __dna_docin)
void CTweakPlayer::write(athena::io::YAMLDocWriter& __dna_docout) const
{
- /* x4_ */
- if (auto v = __dna_docout.enterSubVector("x4_"))
+ /* x4_maxTranslationalAcceleration */
+ if (auto v = __dna_docout.enterSubVector("x4_maxTranslationalAcceleration"))
{
- /* x4_[0] */
- __dna_docout.writeFloat("x4_", x4_[0]);
- /* x4_[1] */
- __dna_docout.writeFloat("x4_", x4_[1]);
- /* x4_[2] */
- __dna_docout.writeFloat("x4_", x4_[2]);
- /* x4_[3] */
- __dna_docout.writeFloat("x4_", x4_[3]);
- /* x4_[4] */
- __dna_docout.writeFloat("x4_", x4_[4]);
- /* x4_[5] */
- __dna_docout.writeFloat("x4_", x4_[5]);
- /* x4_[6] */
- __dna_docout.writeFloat("x4_", x4_[6]);
- /* x4_[7] */
- __dna_docout.writeFloat("x4_", x4_[7]);
+ /* x4_maxTranslationalAcceleration[0] */
+ __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[0]);
+ /* x4_maxTranslationalAcceleration[1] */
+ __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[1]);
+ /* x4_maxTranslationalAcceleration[2] */
+ __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[2]);
+ /* x4_maxTranslationalAcceleration[3] */
+ __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[3]);
+ /* x4_maxTranslationalAcceleration[4] */
+ __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[4]);
+ /* x4_maxTranslationalAcceleration[5] */
+ __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[5]);
+ /* x4_maxTranslationalAcceleration[6] */
+ __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[6]);
+ /* x4_maxTranslationalAcceleration[7] */
+ __dna_docout.writeFloat("x4_maxTranslationalAcceleration", x4_maxTranslationalAcceleration[7]);
}
/* x24_ */
if (auto v = __dna_docout.enterSubVector("x24_"))
@@ -1442,25 +1442,25 @@ void CTweakPlayer::write(athena::io::YAMLDocWriter& __dna_docout) const
/* x24_[7] */
__dna_docout.writeFloat("x24_", x24_[7]);
}
- /* x44_ */
- if (auto v = __dna_docout.enterSubVector("x44_"))
+ /* x44_translationFriction */
+ if (auto v = __dna_docout.enterSubVector("x44_translationFriction"))
{
- /* x44_[0] */
- __dna_docout.writeFloat("x44_", x44_[0]);
- /* x44_[1] */
- __dna_docout.writeFloat("x44_", x44_[1]);
- /* x44_[2] */
- __dna_docout.writeFloat("x44_", x44_[2]);
- /* x44_[3] */
- __dna_docout.writeFloat("x44_", x44_[3]);
- /* x44_[4] */
- __dna_docout.writeFloat("x44_", x44_[4]);
- /* x44_[5] */
- __dna_docout.writeFloat("x44_", x44_[5]);
- /* x44_[6] */
- __dna_docout.writeFloat("x44_", x44_[6]);
- /* x44_[7] */
- __dna_docout.writeFloat("x44_", x44_[7]);
+ /* x44_translationFriction[0] */
+ __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[0]);
+ /* x44_translationFriction[1] */
+ __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[1]);
+ /* x44_translationFriction[2] */
+ __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[2]);
+ /* x44_translationFriction[3] */
+ __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[3]);
+ /* x44_translationFriction[4] */
+ __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[4]);
+ /* x44_translationFriction[5] */
+ __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[5]);
+ /* x44_translationFriction[6] */
+ __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[6]);
+ /* x44_translationFriction[7] */
+ __dna_docout.writeFloat("x44_translationFriction", x44_translationFriction[7]);
}
/* x64_ */
if (auto v = __dna_docout.enterSubVector("x64_"))
@@ -1502,25 +1502,25 @@ void CTweakPlayer::write(athena::io::YAMLDocWriter& __dna_docout) const
/* x84_[7] */
__dna_docout.writeFloat("x84_", x84_[7]);
}
- /* xa4_ */
- if (auto v = __dna_docout.enterSubVector("xa4_"))
+ /* xa4_translationMaxSpeed */
+ if (auto v = __dna_docout.enterSubVector("xa4_translationMaxSpeed"))
{
- /* xa4_[0] */
- __dna_docout.writeFloat("xa4_", xa4_[0]);
- /* xa4_[1] */
- __dna_docout.writeFloat("xa4_", xa4_[1]);
- /* xa4_[2] */
- __dna_docout.writeFloat("xa4_", xa4_[2]);
- /* xa4_[3] */
- __dna_docout.writeFloat("xa4_", xa4_[3]);
- /* xa4_[4] */
- __dna_docout.writeFloat("xa4_", xa4_[4]);
- /* xa4_[5] */
- __dna_docout.writeFloat("xa4_", xa4_[5]);
- /* xa4_[6] */
- __dna_docout.writeFloat("xa4_", xa4_[6]);
- /* xa4_[7] */
- __dna_docout.writeFloat("xa4_", xa4_[7]);
+ /* xa4_translationMaxSpeed[0] */
+ __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[0]);
+ /* xa4_translationMaxSpeed[1] */
+ __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[1]);
+ /* xa4_translationMaxSpeed[2] */
+ __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[2]);
+ /* xa4_translationMaxSpeed[3] */
+ __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[3]);
+ /* xa4_translationMaxSpeed[4] */
+ __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[4]);
+ /* xa4_translationMaxSpeed[5] */
+ __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[5]);
+ /* xa4_translationMaxSpeed[6] */
+ __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[6]);
+ /* xa4_translationMaxSpeed[7] */
+ __dna_docout.writeFloat("xa4_translationMaxSpeed", xa4_translationMaxSpeed[7]);
}
/* xc4_normalGravAccel */
__dna_docout.writeFloat("xc4_normalGravAccel", xc4_normalGravAccel);
@@ -1580,10 +1580,10 @@ void CTweakPlayer::write(athena::io::YAMLDocWriter& __dna_docout) const
__dna_docout.writeFloat("x130_horizontalFreeLookAngleVel", x130_horizontalFreeLookAngleVel);
/* x134_verticalFreeLookAngleVel */
__dna_docout.writeFloat("x134_verticalFreeLookAngleVel", x134_verticalFreeLookAngleVel);
- /* x138_hudLagAmount */
- __dna_docout.writeFloat("x138_hudLagAmount", x138_hudLagAmount);
- /* x13c_ */
- __dna_docout.writeFloat("x13c_", x13c_);
+ /* x138_freeLookSpeed */
+ __dna_docout.writeFloat("x138_freeLookSpeed", x138_freeLookSpeed);
+ /* x13c_freeLookSnapSpeed */
+ __dna_docout.writeFloat("x13c_freeLookSnapSpeed", x13c_freeLookSnapSpeed);
/* x140_ */
__dna_docout.writeFloat("x140_", x140_);
/* x144_freeLookCenteredThresholdAngle */
@@ -1596,8 +1596,8 @@ void CTweakPlayer::write(athena::io::YAMLDocWriter& __dna_docout) const
__dna_docout.writeFloat("x150_leftDiv", x150_leftDiv);
/* x154_rightDiv */
__dna_docout.writeFloat("x154_rightDiv", x154_rightDiv);
- /* x228_24_ */
- __dna_docout.writeBool("x228_24_", x228_24_);
+ /* x228_24_freelookTurnsPlayer */
+ __dna_docout.writeBool("x228_24_freelookTurnsPlayer", x228_24_freelookTurnsPlayer);
/* x228_25_ */
__dna_docout.writeBool("x228_25_", x228_25_);
/* x228_26_ */
@@ -1904,8 +1904,8 @@ void CTweakPlayer::FixupValues()
{
x130_horizontalFreeLookAngleVel = zeus::degToRad(x130_horizontalFreeLookAngleVel);
x134_verticalFreeLookAngleVel = zeus::degToRad(x134_verticalFreeLookAngleVel);
- x138_hudLagAmount = zeus::degToRad(x138_hudLagAmount);
- x13c_ = zeus::degToRad(x13c_);
+ x138_freeLookSpeed = zeus::degToRad(x138_freeLookSpeed);
+ x13c_freeLookSnapSpeed = zeus::degToRad(x13c_freeLookSnapSpeed);
x140_ = zeus::degToRad(x140_);
x144_freeLookCenteredThresholdAngle = zeus::degToRad(x144_freeLookCenteredThresholdAngle);
x23c_ = zeus::degToRad(x23c_);
diff --git a/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp b/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp
index e7af7cb32..7980fbad5 100644
--- a/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp
+++ b/DataSpec/DNAMP1/Tweaks/CTweakPlayer.hpp
@@ -11,12 +11,12 @@ namespace DNAMP1
struct CTweakPlayer : ITweakPlayer
{
Delete _d;
- Value x4_[8];
+ Value x4_maxTranslationalAcceleration[8];
Value x24_[8];
- Value x44_[8];
+ Value x44_translationFriction[8];
Value x64_[8];
Value x84_[8];
- Value xa4_[8];
+ Value xa4_translationMaxSpeed[8];
Value xc4_normalGravAccel;
Value xc8_fluidGravAccel;
Value xcc_;
@@ -46,8 +46,8 @@ struct CTweakPlayer : ITweakPlayer
Value x12c_;
Value x130_horizontalFreeLookAngleVel;
Value x134_verticalFreeLookAngleVel;
- Value x138_hudLagAmount;
- Value x13c_;
+ Value x138_freeLookSpeed;
+ Value x13c_freeLookSnapSpeed;
Value x140_;
Value x144_freeLookCenteredThresholdAngle;
Value x148_freeLookCenteredTime;
@@ -97,7 +97,7 @@ struct CTweakPlayer : ITweakPlayer
Value x21c_26_orbitWhileScanning : 1;
Value x220_;
Value x224_scanningFrameSenseRange;
- Value x228_24_ : 1;
+ Value x228_24_freelookTurnsPlayer : 1;
Value x228_25_ : 1;
Value x228_26_ : 1;
Value x228_27_ : 1;
@@ -175,14 +175,14 @@ struct CTweakPlayer : ITweakPlayer
Value x300_variaDamageReduction;
Value x304_gravityDamageReduction;
Value x308_phazonDamageReduction;
- float GetX50() const { return x44_[3]; }
- float GetX54() const { return x44_[4]; }
- float GetX58() const { return x44_[5]; }
- float GetX5C() const { return x44_[6]; }
+ float GetMaxTranslationalAcceleration(int s) const { return x4_maxTranslationalAcceleration[s]; }
+ float GetPlayerTranslationFriction(int s) const { return x44_translationFriction[s]; }
+ float GetPlayerTranslationMaxSpeed(int s) const { return xa4_translationMaxSpeed[s]; }
float GetNormalGravAccel() const { return xc4_normalGravAccel; }
float GetFluidGravAccel() const { return xc8_fluidGravAccel; }
float GetEyeOffset() const { return x124_eyeOffset; }
- float GetHudLagAmount() const { return x138_hudLagAmount; }
+ float GetFreeLookSpeed() const { return x138_freeLookSpeed; }
+ float GetFreeLookSnapSpeed() const { return x13c_freeLookSnapSpeed; }
float GetFreeLookCenteredThresholdAngle() const { return x144_freeLookCenteredThresholdAngle; }
float GetFreeLookCenteredTime() const { return x148_freeLookCenteredTime; }
float GetOrbitNormalDistance() const { return x180_orbitNormalDistance; }
@@ -242,7 +242,7 @@ struct CTweakPlayer : ITweakPlayer
float GetVerticalFreeLookAngleVel() const { return x134_verticalFreeLookAngleVel; }
float GetX184() const { return x184_; }
float GetX1fc() const { return x1fc_; }
- bool GetX228_24() const { return x228_24_; }
+ bool GetFreeLookTurnsPlayer() const { return x228_24_freelookTurnsPlayer; }
float GetX288() const { return x288_; }
float GetX28c() const { return x28c_; }
float GetX290() const { return x290_; }
@@ -251,7 +251,6 @@ struct CTweakPlayer : ITweakPlayer
float GetX29C() const { return x29c_; }
float GetX280() const { return x280_; }
float GetX2B0() const { return x2b0_; }
- float GetX138() const { return x138_hudLagAmount; }
float GetX14C() const { return x14c_; }
float GetLeftLogicalThreshold() const { return x150_leftDiv; }
float GetRightLogicalThreshold() const { return x154_rightDiv; }
diff --git a/Runtime/CStateManager.cpp b/Runtime/CStateManager.cpp
index 791d73c01..5d36ac46d 100644
--- a/Runtime/CStateManager.cpp
+++ b/Runtime/CStateManager.cpp
@@ -1055,7 +1055,7 @@ void CStateManager::SendScriptMsg(TUniqueId src, TEditorId dest, EScriptObjectMe
{
CEntity* ent = ObjectById(src);
auto search = GetIdListForScript(dest);
- if (ent && search.first != x890_scriptIdMap.cend() && search.second != x890_scriptIdMap.cend())
+ if (ent && search.first != x890_scriptIdMap.cend())
{
for (auto it = search.first; it != search.second; ++it)
{
@@ -1137,7 +1137,10 @@ TUniqueId CStateManager::GetIdForScript(TEditorId id) const
std::pair::const_iterator, std::multimap::const_iterator>
CStateManager::GetIdListForScript(TEditorId id) const
{
- return x890_scriptIdMap.equal_range(id);
+ auto ret = x890_scriptIdMap.equal_range(id);
+ if (ret.first->first != id)
+ ret.first = x890_scriptIdMap.cend();
+ return ret;
}
void CStateManager::LoadScriptObjects(TAreaId aid, CInputStream& in, std::vector& idsOut)
@@ -1310,9 +1313,9 @@ void CStateManager::KnockBackPlayer(CPlayer& player, const zeus::CVector3f& pos,
if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed)
{
usePower = power * 1000.f;
- CPlayer::EPlayerMovementSurface surface =
- player.x2b0_ == 2 ? player.x2ac_movementSurface : CPlayer::EPlayerMovementSurface::Four;
- if (surface != CPlayer::EPlayerMovementSurface::Normal &&
+ CPlayer::ESurfaceRestraints surface =
+ player.x2b0_ == 2 ? player.x2ac_surfaceRestraint : CPlayer::ESurfaceRestraints::Four;
+ if (surface != CPlayer::ESurfaceRestraints::Normal &&
player.GetOrbitState() == CPlayer::EPlayerOrbitState::Zero)
usePower /= 7.f;
}
diff --git a/Runtime/CStateManager.hpp b/Runtime/CStateManager.hpp
index 873f36d60..b5f494781 100644
--- a/Runtime/CStateManager.hpp
+++ b/Runtime/CStateManager.hpp
@@ -315,6 +315,7 @@ public:
std::pair::const_iterator,
std::multimap::const_iterator>
GetIdListForScript(TEditorId) const;
+ std::multimap::const_iterator GetIdListEnd() const { return x890_scriptIdMap.cend(); };
void LoadScriptObjects(TAreaId, CInputStream& in, std::vector& idsOut);
void InitializeScriptObjects(const std::vector& objIds);
std::pair LoadScriptObject(TAreaId, EScriptObjectType, u32, CInputStream& in);
diff --git a/Runtime/Camera/CCameraManager.cpp b/Runtime/Camera/CCameraManager.cpp
index 660539cec..5704f0e12 100644
--- a/Runtime/Camera/CCameraManager.cpp
+++ b/Runtime/Camera/CCameraManager.cpp
@@ -262,12 +262,12 @@ void CCameraManager::UpdateListener(CStateManager& mgr)
float CCameraManager::CalculateFogDensity(CStateManager& mgr, const CScriptWater* water)
{
- float f31 = 1.f /* 1.f - water->x1b4_->x40_; */;
+ float f31 = water->GetFluidPlane().GetAlpha();
float f1 = 0;
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GravitySuit))
- f1 = (g_tweakPlayer->GetX54() * g_tweakPlayer->GetX50()) + f31;
+ f1 = (g_tweakPlayer->GetPlayerTranslationFriction(4) * g_tweakPlayer->GetPlayerTranslationFriction(3)) + f31;
else
- f1 = (g_tweakPlayer->GetX5C() * g_tweakPlayer->GetX58()) + f31;
+ f1 = (g_tweakPlayer->GetPlayerTranslationFriction(6) * g_tweakPlayer->GetPlayerTranslationFriction(5)) + f31;
return f1 * x94_;
}
diff --git a/Runtime/Camera/CFirstPersonCamera.cpp b/Runtime/Camera/CFirstPersonCamera.cpp
index 878b3d1ee..283b521b0 100644
--- a/Runtime/Camera/CFirstPersonCamera.cpp
+++ b/Runtime/Camera/CFirstPersonCamera.cpp
@@ -91,9 +91,9 @@ void CFirstPersonCamera::UpdateTransform(CStateManager& mgr, float dt)
angle = (player->x3ec_freeLookPitchAngle > -0.f ? -1.f : 1.f);
zeus::CVector3f vec;
vec.z = std::sin(angle);
- vec.y = std::cos(-player->x3e4_) * std::cos(angle);
- vec.x = std::sin(-player->x3e4_) * std::cos(angle);
- if (g_tweakPlayer->GetX228_24() && !zeus::close_enough(vec, zeus::CVector3f::skZero))
+ vec.y = std::cos(-player->x3e4_freeLookYawAngle) * std::cos(angle);
+ vec.x = std::sin(-player->x3e4_freeLookYawAngle) * std::cos(angle);
+ if (g_tweakPlayer->GetFreeLookTurnsPlayer() && !zeus::close_enough(vec, zeus::CVector3f::skZero))
vec.normalize();
rVec = zeus::CQuaternion::lookAt({0.f, 1.f, 0.f}, rVec, zeus::CRelAngle::FromDegrees(360.f)).transform(vec);
@@ -240,7 +240,7 @@ void CFirstPersonCamera::UpdateTransform(CStateManager& mgr, float dt)
float angle = gunFront.dot(rVec);
if (std::fabs(angle) > 1.f)
angle = (angle > -0.f ? -1.f : 1.f);
- float sdt = dt * g_tweakPlayer->GetX138();
+ float sdt = dt * g_tweakPlayer->GetFreeLookSpeed();
qGun = zeus::CQuaternion::lookAt(
rVec, gunFront, sdt * zeus::clamp(0.f, g_tweakPlayer->GetX14C() * (std::acos(angle) / sdt), 1.f));
}
diff --git a/Runtime/Character/CActorLights.cpp b/Runtime/Character/CActorLights.cpp
index c1c328145..8215bdd58 100644
--- a/Runtime/Character/CActorLights.cpp
+++ b/Runtime/Character/CActorLights.cpp
@@ -503,19 +503,9 @@ void CActorLights::BuildDynamicLightList(const CStateManager& mgr, const zeus::C
}
}
-void CActorLights::ActivateLights(CBooModel& model) const
+std::vector CActorLights::BuildLightVector() const
{
std::vector lights;
- if (x298_28_inArea)
- {
- if (!x298_26_hasAreaLights || !x299_26_)
- {
- g_Renderer->SetAmbientColor(zeus::CColor::skWhite);
- model.ActivateLights(lights);
- return;
- }
- }
-
lights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, x288_ambientColor));
if (x0_areaLights.size())
@@ -538,6 +528,24 @@ void CActorLights::ActivateLights(CBooModel& model) const
for (const CLight& light : x144_dynamicLights)
lights.push_back(light);
+ return lights;
+}
+
+void CActorLights::ActivateLights(CBooModel& model) const
+{
+ std::vector lights;
+
+ if (x298_28_inArea)
+ {
+ if (!x298_26_hasAreaLights || !x299_26_)
+ {
+ g_Renderer->SetAmbientColor(zeus::CColor::skWhite);
+ model.ActivateLights(lights);
+ return;
+ }
+ }
+
+ lights = BuildLightVector();
model.ActivateLights(lights);
if (x298_31_disableWorldLights)
diff --git a/Runtime/Character/CActorLights.hpp b/Runtime/Character/CActorLights.hpp
index b831fd474..48770efc5 100644
--- a/Runtime/Character/CActorLights.hpp
+++ b/Runtime/Character/CActorLights.hpp
@@ -71,6 +71,7 @@ public:
void BuildFaceLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb);
bool BuildAreaLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb);
void BuildDynamicLightList(const CStateManager& mgr, const zeus::CAABox& aabb);
+ std::vector BuildLightVector() const;
void ActivateLights(CBooModel& model) const;
void SetCastShadows(bool v) { x298_25_castShadows = v; }
void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; }
diff --git a/Runtime/Graphics/CMakeLists.txt b/Runtime/Graphics/CMakeLists.txt
index 8da2d0b47..d29a791ce 100644
--- a/Runtime/Graphics/CMakeLists.txt
+++ b/Runtime/Graphics/CMakeLists.txt
@@ -19,7 +19,8 @@ if(WIN32)
Shaders/CScanLinesFilterHLSL.cpp
Shaders/CRandomStaticFilterHLSL.cpp
Shaders/CElementGenShadersHLSL.cpp
- Shaders/CParticleSwooshShadersHLSL.cpp)
+ Shaders/CParticleSwooshShadersHLSL.cpp
+ Shaders/CFluidPlaneShaderHLSL.cpp)
elseif(BOO_HAS_METAL)
set(PLAT_SRCS
Shaders/CLineRendererShadersMetal.cpp
@@ -41,7 +42,8 @@ elseif(BOO_HAS_METAL)
Shaders/CScanLinesFilterMetal.cpp
Shaders/CRandomStaticFilterMetal.cpp
Shaders/CElementGenShadersMetal.cpp
- Shaders/CParticleSwooshShadersMetal.cpp)
+ Shaders/CParticleSwooshShadersMetal.cpp
+ Shaders/CFluidPlaneShaderMetal.cpp)
endif()
set(GRAPHICS_SOURCES
@@ -85,6 +87,7 @@ set(GRAPHICS_SOURCES
Shaders/CRandomStaticFilter.hpp Shaders/CRandomStaticFilter.cpp Shaders/CRandomStaticFilterGLSL.cpp
Shaders/CElementGenShaders.hpp Shaders/CElementGenShaders.cpp Shaders/CElementGenShadersGLSL.cpp
Shaders/CParticleSwooshShaders.hpp Shaders/CParticleSwooshShaders.cpp Shaders/CParticleSwooshShadersGLSL.cpp
+ Shaders/CFluidPlaneShader.hpp Shaders/CFluidPlaneShader.cpp Shaders/CFluidPlaneShaderGLSL.cpp
${PLAT_SRCS})
runtime_add_list(Graphics GRAPHICS_SOURCES)
diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp
index e96a3d8ac..86bab39bd 100644
--- a/Runtime/Graphics/CModelBoo.cpp
+++ b/Runtime/Graphics/CModelBoo.cpp
@@ -390,50 +390,7 @@ void CBooModel::MakeTexturesFromMats(std::vector>& toksOu
void CBooModel::ActivateLights(const std::vector& lights)
{
- m_lightingData.ambient = zeus::CColor::skBlack;
- size_t curLight = 0;
-
- for (const CLight& light : lights)
- {
- switch (light.x1c_type)
- {
- case ELightType::LocalAmbient:
- m_lightingData.ambient += light.x18_color;
- break;
- case ELightType::Point:
- case ELightType::Spot:
- case ELightType::Custom:
- case ELightType::Directional:
- {
- if (curLight >= URDE_MAX_LIGHTS)
- continue;
- CModelShaders::Light& lightOut = m_lightingData.lights[curLight++];
- lightOut.pos = CGraphics::g_CameraMatrix * light.x0_pos;
- lightOut.dir = CGraphics::g_CameraMatrix.basis * light.xc_dir;
- lightOut.dir.normalize();
- lightOut.color = light.x18_color;
- lightOut.linAtt[0] = light.x24_distC;
- lightOut.linAtt[1] = light.x28_distL;
- lightOut.linAtt[2] = light.x2c_distQ;
- lightOut.angAtt[0] = light.x30_angleC;
- lightOut.angAtt[1] = light.x34_angleL;
- lightOut.angAtt[2] = light.x38_angleQ;
-
- if (light.x1c_type == ELightType::Directional)
- lightOut.pos = (-lightOut.dir) * 1048576.f;
- break;
- }
- default: break;
- }
- }
-
- for (; curLight(ctx), info);
+ break;
+#if _WIN32
+ case boo::IGraphicsDataFactory::Platform::D3D11:
+ case boo::IGraphicsDataFactory::Platform::D3D12:
+ slot.second = BuildShader(static_cast(ctx), info);
+ break;
+#endif
+#if BOO_HAS_METAL
+ case boo::IGraphicsDataFactory::Platform::Metal:
+ slot.second = BuildShader(static_cast(ctx), info);
+ break;
+#endif
+#if BOO_HAS_VULKAN
+ case boo::IGraphicsDataFactory::Platform::Vulkan:
+ slot.second = BuildShader(static_cast(ctx), info);
+ break;
+#endif
+ default: break;
+ }
+ return true;
+ });
+
+ return slot.second;
+}
+
+CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type,
+ const std::experimental::optional>& patternTex1,
+ const std::experimental::optional>& patternTex2,
+ const std::experimental::optional>& colorTex,
+ const std::experimental::optional>& bumpMap,
+ const std::experimental::optional>& envMap,
+ const std::experimental::optional>& envBumpMap,
+ const std::experimental::optional>& lightmap,
+ bool doubleLightmapBlend, bool additive)
+: m_patternTex1(patternTex1),
+ m_patternTex2(patternTex2),
+ m_colorTex(colorTex),
+ m_bumpMap(bumpMap),
+ m_envMap(envMap),
+ m_envBumpMap(envBumpMap),
+ m_lightmap(lightmap)
+{
+ SFluidPlaneShaderInfo shaderInfo(type,
+ m_patternTex1.operator bool(),
+ m_patternTex2.operator bool(),
+ m_colorTex.operator bool(),
+ m_bumpMap.operator bool(),
+ m_envMap.operator bool(),
+ m_envBumpMap.operator bool(),
+ m_lightmap.operator bool(),
+ doubleLightmapBlend, additive);
+ boo::IShaderPipeline* pipeline = _cache.GetOrBuildShader(shaderInfo);
+
+ m_gfxTok = CGraphics::CommitResources(
+ [&](boo::IGraphicsDataFactory::Context& ctx)
+ {
+ m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), 999); // TODO: Figure out how many
+ m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, 1024, 1);
+
+ switch (ctx.platform())
+ {
+ case boo::IGraphicsDataFactory::Platform::OpenGL:
+ m_dataBind = BuildBinding(static_cast(ctx), pipeline);
+ break;
+#if _WIN32
+ case boo::IGraphicsDataFactory::Platform::D3D11:
+ case boo::IGraphicsDataFactory::Platform::D3D12:
+ m_dataBind = BuildBinding(static_cast(ctx), pipeline);
+ break;
+#endif
+#if BOO_HAS_METAL
+ case boo::IGraphicsDataFactory::Platform::Metal:
+ m_dataBind = BuildBinding(static_cast(ctx), pipeline);
+ break;
+#endif
+#if BOO_HAS_VULKAN
+ case boo::IGraphicsDataFactory::Platform::Vulkan:
+ m_dataBind = BuildBinding(static_cast(ctx), pipeline);
+ break;
+#endif
+ default: break;
+ }
+ return true;
+ });
+}
+
+void CFluidPlaneShader::draw(const zeus::CMatrix4f texMtxs[6], const zeus::CMatrix4f& normMtx, float indScale,
+ const std::vector& lights, const zeus::CColor kColors[4])
+{
+ Uniform& uni = *reinterpret_cast(m_uniBuf->map(sizeof(Uniform)));
+ uni.m_mv = CGraphics::g_GXModelView.toMatrix4f();
+ uni.m_mvNorm = normMtx;
+ uni.m_proj = CGraphics::GetPerspectiveProjectionMatrix(true);
+ for (int i=0 ; i<6 ; ++i)
+ uni.m_texMtxs[i] = texMtxs[i];
+ uni.m_lighting.ActivateLights(lights);
+ for (int i=0 ; i<3 ; ++i)
+ uni.m_lighting.colorRegs[i] = kColors[i];
+ uni.m_lighting.mulColor = kColors[3];
+ uni.m_lighting.fog.m_rangeScale = indScale;
+ m_uniBuf->unmap();
+ CGraphics::SetShaderDataBinding(m_dataBind);
+ CGraphics::DrawArray(0, 0);
+}
+
+}
diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp b/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp
new file mode 100644
index 000000000..9f5b9fc34
--- /dev/null
+++ b/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp
@@ -0,0 +1,110 @@
+#ifndef CFLUIDPLANESHADER_HPP
+#define CFLUIDPLANESHADER_HPP
+
+#include "RetroTypes.hpp"
+#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
+#include "Runtime/World/CFluidPlane.hpp"
+#include "CModelShaders.hpp"
+#include "boo/graphicsdev/GL.hpp"
+#include "boo/graphicsdev/D3D.hpp"
+#include "boo/graphicsdev/Metal.hpp"
+#include "boo/graphicsdev/Vulkan.hpp"
+
+namespace urde
+{
+
+struct SFluidPlaneShaderInfo
+{
+ CFluidPlane::EFluidType m_type;
+ bool m_hasPatternTex1;
+ bool m_hasPatternTex2;
+ bool m_hasColorTex;
+ bool m_hasBumpMap;
+ bool m_hasEnvMap;
+ bool m_hasEnvBumpMap;
+ bool m_hasLightmap;
+ bool m_doubleLightmapBlend;
+ bool m_additive;
+
+ SFluidPlaneShaderInfo(CFluidPlane::EFluidType type, bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex,
+ bool hasBumpMap, bool hasEnvMap, bool hasEnvBumpMap, bool hasLightmap,
+ bool doubleLightmapBlend, bool additive)
+ : m_type(type), m_hasPatternTex1(hasPatternTex1), m_hasPatternTex2(hasPatternTex2), m_hasColorTex(hasColorTex),
+ m_hasBumpMap(hasBumpMap), m_hasEnvMap(hasEnvMap), m_hasEnvBumpMap(hasEnvBumpMap), m_hasLightmap(hasLightmap),
+ m_doubleLightmapBlend(doubleLightmapBlend), m_additive(additive)
+ {}
+};
+
+class CFluidPlaneShader
+{
+ class Cache
+ {
+ std::pair m_cache[1024] = {};
+ static u16 MakeCacheKey(const SFluidPlaneShaderInfo& info);
+ public:
+ boo::IShaderPipeline* GetOrBuildShader(const SFluidPlaneShaderInfo& info);
+ };
+ static Cache _cache;
+
+ struct Vertex
+ {
+ zeus::CVector3f m_pos;
+ zeus::CVector3f m_norm;
+ zeus::CVector3f m_binorm;
+ zeus::CVector3f m_tangent;
+ zeus::CColor m_color;
+ };
+
+ struct Uniform
+ {
+ zeus::CMatrix4f m_mv;
+ zeus::CMatrix4f m_mvNorm;
+ zeus::CMatrix4f m_proj;
+ zeus::CMatrix4f m_texMtxs[9]; // Pad out to 768 bytes
+ CModelShaders::LightingUniform m_lighting;
+ };
+
+ std::experimental::optional> m_patternTex1;
+ std::experimental::optional> m_patternTex2;
+ std::experimental::optional> m_colorTex;
+ std::experimental::optional> m_bumpMap;
+ std::experimental::optional> m_envMap;
+ std::experimental::optional> m_envBumpMap;
+ std::experimental::optional> m_lightmap;
+ boo::GraphicsDataToken m_gfxTok;
+ boo::IGraphicsBufferD* m_vbo;
+ boo::IGraphicsBufferD* m_uniBuf;
+ boo::IShaderDataBinding* m_dataBind;
+
+ static boo::IShaderPipeline* BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info);
+ boo::IShaderDataBinding* BuildBinding(boo::GLDataFactory::Context& ctx, boo::IShaderPipeline* pipeline);
+#if _WIN32
+ static boo::IShaderPipeline* BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info);
+ boo::IShaderDataBinding* BuildBinding(boo::ID3DDataFactory::Context& ctx, boo::IShaderPipeline* pipeline);
+#endif
+#if BOO_HAS_METAL
+ static boo::IShaderPipeline* BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info);
+ boo::IShaderDataBinding* BuildBinding(boo::MetalDataFactory::Context& ctx, boo::IShaderPipeline* pipeline);
+#endif
+#if BOO_HAS_VULKAN
+ static boo::IShaderPipeline* BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info);
+ boo::IShaderDataBinding* BuildBinding(boo::VulkanDataFactory::Context& ctx, boo::IShaderPipeline* pipeline);
+#endif
+
+public:
+ CFluidPlaneShader(CFluidPlane::EFluidType type,
+ const std::experimental::optional>& patternTex1,
+ const std::experimental::optional>& patternTex2,
+ const std::experimental::optional>& colorTex,
+ const std::experimental::optional>& bumpMap,
+ const std::experimental::optional>& envMap,
+ const std::experimental::optional>& envBumpMap,
+ const std::experimental::optional>& lightmap,
+ bool doubleLightmapBlend, bool additive);
+ void draw(const zeus::CMatrix4f texMtxs[6], const zeus::CMatrix4f& normMtx, float indScale,
+ const std::vector& lights, const zeus::CColor kColors[4]);
+};
+
+}
+
+#endif // CFLUIDPLANESHADER_HPP
diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShaderGLSL.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShaderGLSL.cpp
new file mode 100644
index 000000000..fbb652f6a
--- /dev/null
+++ b/Runtime/Graphics/Shaders/CFluidPlaneShaderGLSL.cpp
@@ -0,0 +1,558 @@
+#include "CFluidPlaneShader.hpp"
+
+namespace urde
+{
+
+static const char* VS =
+"#version 330\n"
+BOO_GLSL_BINDING_HEAD
+"layout(location=0) in vec4 posIn;\n"
+"layout(location=1) in vec4 normalIn;\n"
+"layout(location=2) in vec4 binormalIn;\n"
+"layout(location=3) in vec4 tangentIn;\n"
+"layout(location=4) in vec4 colorIn;\n"
+"\n"
+"UBINDING0 uniform FluidPlaneUniform\n"
+"{\n"
+" mat4 mv;\n"
+" mat4 mvNorm;\n"
+" mat4 proj;\n"
+" mat4 texMtxs[6];\n"
+"};\n"
+"\n"
+"struct VertToFrag\n"
+"{\n"
+" vec4 mvPos;\n"
+" vec4 mvNorm;\n"
+" vec4 mvBinorm;\n"
+" vec4 mvTangent;\n"
+" vec4 color;\n"
+" vec2 uvs[7];\n"
+"};\n"
+"\n"
+"SBINDING(0) out VertToFrag vtf;\n"
+"void main()\n"
+"{\n"
+" vtf.mvPos = mv * vec4(posIn.xyz, 1.0);\n"
+" gl_Position = proj * vtf.mvPos;\n"
+" vtf.mvNorm = mvNorm * normalIn;\n"
+" vtf.mvBinorm = mvNorm * binormalIn;\n"
+" vtf.mvTangent = mvNorm * tangentIn;\n"
+" vtf.color = colorIn;\n"
+" vtf.uvs[0] = (texMtxs[0] * posIn).xy;\n"
+" vtf.uvs[1] = (texMtxs[1] * posIn).xy;\n"
+" vtf.uvs[2] = (texMtxs[2] * posIn).xy;\n"
+"%s" // Additional TCGs here
+"}\n";
+
+static const char* FS =
+"#version 330\n"
+BOO_GLSL_BINDING_HEAD
+"\n"
+"struct Light\n"
+"{\n"
+" vec4 pos;\n"
+" vec4 dir;\n"
+" vec4 color;\n"
+" vec4 linAtt;\n"
+" vec4 angAtt;\n"
+"};\n"
+"struct Fog\n" // Reappropriated for indirect texture scaling
+"{\n"
+" vec4 color;\n"
+" float indScale;\n"
+" float start;\n"
+"};\n"
+"\n"
+"UBINDING2 uniform LightingUniform\n"
+"{\n"
+" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n"
+" vec4 ambient;\n"
+" vec4 kColor0;\n"
+" vec4 kColor1;\n"
+" vec4 kColor2;\n"
+" vec4 kColor3;\n"
+" Fog fog;\n"
+"};\n"
+"\n"
+"vec4 LightingFunc(vec4 mvPosIn, vec4 mvNormIn)\n"
+"{\n"
+" vec4 ret = ambient;\n"
+" \n"
+" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
+" {\n"
+" vec3 delta = mvPosIn.xyz - lights[i].pos.xyz;\n"
+" float dist = length(delta);\n"
+" float angDot = clamp(dot(normalize(delta), lights[i].dir.xyz), 0.0, 1.0);\n"
+" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n"
+" lights[i].linAtt[1] * dist +\n"
+" lights[i].linAtt[0]);\n"
+" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n"
+" lights[i].angAtt[1] * angDot +\n"
+" lights[i].angAtt[0];\n"
+" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn.xyz), 0.0, 1.0);\n"
+" }\n"
+" \n"
+" return clamp(ret, vec4(0.0,0.0,0.0,0.0), vec4(1.0,1.0,1.0,1.0));\n"
+"}\n"
+"\n"
+"struct VertToFrag\n"
+"{\n"
+" vec4 mvPos;\n"
+" vec4 mvNorm;\n"
+" vec4 mvBinorm;\n"
+" vec4 mvTangent;\n"
+" vec4 color;\n"
+" vec2 uvs[7];\n"
+"};\n"
+"\n"
+"SBINDING(0) in VertToFrag vtf;\n"
+"layout(location=0) out vec4 colorOut;\n"
+"%s" // Textures here
+"void main()\n"
+"{\n"
+" vec4 lighting = LightingFunc(vtf.mvPos, normalize(vtf.mvNorm));\n"
+"%s" // Combiner expression here
+"}\n";
+
+static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTex, const char* texNames[7],
+ const SFluidPlaneShaderInfo& info)
+{
+ std::string additionalTCGs;
+ std::string textures;
+ std::string combiner;
+ int nextTCG = 3;
+ int nextMtx = 4;
+ int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv;
+
+ if (info.m_hasPatternTex1)
+ {
+ texNames[nextTex] = "patternTex1";
+ textures += hecl::Format("TBINDING%d uniform sampler2D patternTex1;\n", nextTex++);
+ }
+ if (info.m_hasPatternTex2)
+ {
+ texNames[nextTex] = "patternTex2";
+ textures += hecl::Format("TBINDING%d uniform sampler2D patternTex2;\n", nextTex++);
+ }
+ if (info.m_hasColorTex)
+ {
+ texNames[nextTex] = "colorTex";
+ textures += hecl::Format("TBINDING%d uniform sampler2D colorTex;\n", nextTex++);
+ }
+ if (info.m_hasBumpMap)
+ {
+ texNames[nextTex] = "bumpMap";
+ textures += hecl::Format("TBINDING%d uniform sampler2D bumpMap;\n", nextTex++);
+ }
+ if (info.m_hasEnvMap)
+ {
+ texNames[nextTex] = "envMap";
+ textures += hecl::Format("TBINDING%d uniform sampler2D envMap;\n", nextTex++);
+ }
+ if (info.m_hasEnvBumpMap)
+ {
+ texNames[nextTex] = "envBumpMap";
+ textures += hecl::Format("TBINDING%d uniform sampler2D envBumpMap;\n", nextTex++);
+ }
+ if (info.m_hasLightmap)
+ {
+ texNames[nextTex] = "lightMap";
+ textures += hecl::Format("TBINDING%d uniform sampler2D lightMap;\n", nextTex++);
+ }
+
+ if (info.m_hasBumpMap)
+ {
+ bumpMapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[0] * posIn).xy;\n", nextTCG++);
+ }
+ if (info.m_hasEnvBumpMap)
+ {
+ envBumpMapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[3] * posIn).xy;\n", nextTCG++);
+ }
+ if (info.m_hasEnvMap)
+ {
+ envMapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * posIn).xy;\n", nextTCG++, nextMtx++);
+ }
+ if (info.m_hasLightmap)
+ {
+ lightmapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * posIn).xy;\n", nextTCG++, nextMtx++);
+ }
+
+ switch (info.m_type)
+ {
+ case CFluidPlane::EFluidType::NormalWater:
+ case CFluidPlane::EFluidType::Three:
+ case CFluidPlane::EFluidType::Four:
+ if (info.m_hasLightmap)
+ {
+ combiner += hecl::Format(" vec4 lightMapTexel = texture(lightMap, vtf.uvs[%d]);\n", lightmapUv);
+ // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
+ // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
+ // Output reg 2
+ // KColor 2
+ if (info.m_doubleLightmapBlend)
+ {
+ // 1: Tex4TCG2, Tex4, GX_COLOR1A1
+ // C2, TEX, KONST, RAS
+ // Output reg 2
+ // KColor 3
+ // Tex * K2 + Lighting
+ combiner += " lighting += mix(lightMapTexel * kColor2, lightMapTexel, kColor3);\n";
+ }
+ else
+ {
+ // mix(Tex * K2, Tex, K3) + Lighting
+ combiner += " lighting += lightMapTexel * kColor2;\n";
+ }
+ }
+
+ // Next: Tex0TCG, Tex0, GX_COLOR1A1
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // Next: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // Next: Tex2TCG, Tex2, GX_COLOR1A1
+ // ZERO, TEX, hasTex4 ? C2 : RAS, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + lighting) *\n"
+ " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = lighting * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+
+ if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap)
+ {
+ // Make previous stage indirect, mtx0
+ combiner += hecl::Format(" vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n"
+ " vec2(fog.indScale, -fog.indScale);", envBumpMapUv);
+ combiner += " colorOut += texture(colorTex, indUvs + vtf.uvs[2]) * lighting;\n";
+ }
+ else if (info.m_hasEnvMap)
+ {
+ // Next: envTCG, envTex, NULL
+ // PREV, TEX, KONST, ZERO
+ // Output reg prev
+ // KColor 1
+
+ // Make previous stage indirect, mtx0
+ if (info.m_hasColorTex)
+ combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n";
+ combiner += hecl::Format(" vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n"
+ " vec2(fog.indScale, -fog.indScale);", envBumpMapUv);
+ combiner += hecl::Format(" colorOut = mix(colorOut, texture(envMap, indUvs + vtf.uvs[%d]), kColor1);\n",
+ envMapUv);
+ }
+ else if (info.m_hasColorTex)
+ {
+ combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n";
+ }
+
+ break;
+
+ case CFluidPlane::EFluidType::PoisonWater:
+ if (info.m_hasLightmap)
+ {
+ combiner += hecl::Format(" vec4 lightMapTexel = texture(lightMap, vtf.uvs[%d]);\n", lightmapUv);
+ // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
+ // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
+ // Output reg 2
+ // KColor 2
+ if (info.m_doubleLightmapBlend)
+ {
+ // 1: Tex4TCG2, Tex4, GX_COLOR1A1
+ // C2, TEX, KONST, RAS
+ // Output reg 2
+ // KColor 3
+ // Tex * K2 + Lighting
+ combiner += " lighting += mix(lightMapTexel * kColor2, lightMapTexel, kColor3);\n";
+ }
+ else
+ {
+ // mix(Tex * K2, Tex, K3) + Lighting
+ combiner += " lighting += lightMapTexel * kColor2;\n";
+ }
+ }
+
+ // Next: Tex0TCG, Tex0, GX_COLOR1A1
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // Next: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // Next: Tex2TCG, Tex2, GX_COLOR1A1
+ // ZERO, TEX, hasTex4 ? C2 : RAS, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + lighting) *\n"
+ " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = lighting * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+ if (info.m_hasColorTex)
+ {
+ if (info.m_hasEnvBumpMap)
+ {
+ // Make previous stage indirect, mtx0
+ combiner += hecl::Format(" vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n"
+ " vec2(fog.indScale, -fog.indScale);", envBumpMapUv);
+ combiner += " colorOut += texture(colorTex, indUvs + vtf.uvs[2]) * lighting;\n";
+ }
+ else
+ {
+ combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n";
+ }
+ }
+
+ break;
+
+ case CFluidPlane::EFluidType::Lava:
+ // 0: Tex0TCG, Tex0, GX_COLOR0A0
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // 1: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // 2: Tex2TCG, Tex2, NULL
+ // ZERO, TEX, ONE, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + vtf.color) *\n"
+ " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = vtf.color * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+ if (info.m_hasColorTex)
+ combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n";
+
+ if (info.m_hasBumpMap)
+ {
+ // 3: bumpMapTCG, bumpMap, NULL
+ // ZERO, TEX, ONE, HALF
+ // Output reg 0, no clamp, no bias
+
+ // 4: bumpMapTCG2, bumpMap, NULL
+ // ZERO, TEX, ONE, C0
+ // Output reg 0, subtract, clamp, no bias
+
+ combiner += " vec3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n"
+ " float lx = dot(vtf.mvTangent, lightVec);\n"
+ " float ly = dot(vtf.mvBinorm, lightVec);\n";
+ combiner += hecl::Format(" vec4 emboss1 = texture(bumpMap, vtf.uvs[%d]) + vec4(0.5);\n"
+ " vec4 emboss2 = texture(bumpMap, vtf.uvs[%d] + vec2(lx, ly));\n",
+ bumpMapUv, bumpMapUv);
+
+ // 5: NULL, NULL, NULL
+ // ZERO, PREV, C0, ZERO
+ // Output reg prev, scale 2, clamp
+
+ // colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0
+ combiner += "colorOut *= clamp((emboss1 + vec4(0.5) - emboss2) * vec4(2.0), vec4(0.0), vec4(1.0));\n";
+ }
+
+ break;
+
+ case CFluidPlane::EFluidType::Five:
+ // 0: Tex0TCG, Tex0, GX_COLOR0A0
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // 1: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // 2: Tex2TCG, Tex2, NULL
+ // ZERO, TEX, ONE, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + vtf.color) *\n"
+ " texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = vtf.color * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+ if (info.m_hasColorTex)
+ combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n";
+
+ if (info.m_hasBumpMap)
+ {
+ // 3: bumpMapTCG, bumpMap, NULL
+ // ZERO, TEX, PREV, ZERO
+ // Output reg prev, scale 2
+ combiner += hecl::Format(" vec4 emboss1 = texture(bumpMap, vtf.uvs[%d]) + vec4(0.5);\n", bumpMapUv);
+ combiner += "colorOut *= emboss1 * vec4(2.0);\n";
+ }
+
+ break;
+ }
+
+ combiner += " colorOut.a = kColor0.a;\n";
+
+ finalVS = hecl::Format(VS, additionalTCGs.c_str());
+ finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str());
+}
+
+boo::IShaderPipeline*
+CFluidPlaneShader::BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info)
+{
+ int nextTex = 0;
+ const char* texNames[7] = {};
+ std::string finalVS, finalFS;
+ _BuildShader(finalVS, finalFS, nextTex, texNames, info);
+ const char* uniNames[] = {"FluidPlaneUniform", "FluidPlaneUniform", "LightingUniform"};
+ return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), size_t(nextTex), texNames, 3, uniNames,
+ info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
+ info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
+ boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
+ boo::CullMode::None);
+}
+
+#if BOO_HAS_VULKAN
+static boo::IVertexFormat* s_vtxFmt = nullptr;
+
+boo::IShaderPipeline*
+CFluidPlaneShader::BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info)
+{
+ if (s_vtxFmt == nullptr)
+ {
+ boo::VertexElementDescriptor elements[] =
+ {
+ {nullptr, nullptr, boo::VertexSemantic::Position4},
+ {nullptr, nullptr, boo::VertexSemantic::Normal4, 0},
+ {nullptr, nullptr, boo::VertexSemantic::Normal4, 1},
+ {nullptr, nullptr, boo::VertexSemantic::Normal4, 2},
+ {nullptr, nullptr, boo::VertexSemantic::Color}
+ };
+ s_vtxFmt = ctx.newVertexFormat(5, elements);
+ }
+
+ int nextTex = 0;
+ const char* texNames[7] = {};
+ std::string finalVS, finalFS;
+ _BuildShader(finalVS, finalFS, nextTex, texNames, info);
+ return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), s_vtxFmt,
+ info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
+ info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
+ boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
+ boo::CullMode::None);
+}
+#endif
+
+boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::GLDataFactory::Context& ctx,
+ boo::IShaderPipeline* pipeline)
+{
+ boo::VertexElementDescriptor elements[] =
+ {
+ {m_vbo, nullptr, boo::VertexSemantic::Position4},
+ {m_vbo, nullptr, boo::VertexSemantic::Normal4, 0},
+ {m_vbo, nullptr, boo::VertexSemantic::Normal4, 1},
+ {m_vbo, nullptr, boo::VertexSemantic::Normal4, 2},
+ {m_vbo, nullptr, boo::VertexSemantic::Color}
+ };
+ boo::IVertexFormat* vtxFmt = ctx.newVertexFormat(5, elements);
+ boo::IGraphicsBuffer* ubufs[] = { m_uniBuf, m_uniBuf, m_uniBuf };
+ boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
+ boo::PipelineStage::Fragment };
+ size_t ubufOffs[] = {0, 0, 768};
+ size_t ubufSizes[] = {768, 768, 256};
+ size_t texCount = 0;
+ boo::ITexture* texs[7] = {};
+ if (m_patternTex1)
+ texs[texCount++] = (*m_patternTex1)->GetBooTexture();
+ if (m_patternTex2)
+ texs[texCount++] = (*m_patternTex2)->GetBooTexture();
+ if (m_colorTex)
+ texs[texCount++] = (*m_colorTex)->GetBooTexture();
+ if (m_bumpMap)
+ texs[texCount++] = (*m_bumpMap)->GetBooTexture();
+ if (m_envMap)
+ texs[texCount++] = (*m_envMap)->GetBooTexture();
+ if (m_envBumpMap)
+ texs[texCount++] = (*m_envBumpMap)->GetBooTexture();
+ if (m_lightmap)
+ texs[texCount++] = (*m_lightmap)->GetBooTexture();
+ return ctx.newShaderDataBinding(pipeline, vtxFmt, m_vbo, nullptr, nullptr, 1, ubufs, ubufStages, ubufOffs,
+ ubufSizes, texCount, texs, nullptr, nullptr);
+}
+
+#if BOO_HAS_VULKAN
+boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::VulkanDataFactory::Context& ctx,
+ boo::IShaderPipeline* pipeline)
+{
+ boo::IGraphicsBuffer* ubufs[] = { m_uniBuf, m_uniBuf, m_uniBuf };
+ boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
+ boo::PipelineStage::Fragment };
+ size_t ubufOffs[] = {0, 0, 768};
+ size_t ubufSizes[] = {768, 768, 256};
+ size_t texCount = 0;
+ boo::ITexture* texs[7] = {};
+ if (m_patternTex1)
+ texs[texCount++] = (*m_patternTex1)->GetBooTexture();
+ if (m_patternTex2)
+ texs[texCount++] = (*m_patternTex2)->GetBooTexture();
+ if (m_colorTex)
+ texs[texCount++] = (*m_colorTex)->GetBooTexture();
+ if (m_bumpMap)
+ texs[texCount++] = (*m_bumpMap)->GetBooTexture();
+ if (m_envMap)
+ texs[texCount++] = (*m_envMap)->GetBooTexture();
+ if (m_envBumpMap)
+ texs[texCount++] = (*m_envBumpMap)->GetBooTexture();
+ if (m_lightmap)
+ texs[texCount++] = (*m_lightmap)->GetBooTexture();
+ return ctx.newShaderDataBinding(pipeline, s_vtxFmt, m_vbo, nullptr, nullptr, 1, ubufs, ubufStages, ubufOffs,
+ ubufSizes, texCount, texs, nullptr, nullptr);
+}
+#endif
+
+}
diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShaderHLSL.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShaderHLSL.cpp
new file mode 100644
index 000000000..f84010322
--- /dev/null
+++ b/Runtime/Graphics/Shaders/CFluidPlaneShaderHLSL.cpp
@@ -0,0 +1,476 @@
+#include "CFluidPlaneShader.hpp"
+
+namespace urde
+{
+
+static boo::IVertexFormat* s_vtxFmt = nullptr;
+
+static const char* VS =
+"struct VertData\n"
+"{\n"
+" float4 posIn : POSITION;\n"
+" float4 normalIn : NORMAL0;\n"
+" float4 binormalIn : NORMAL1;\n"
+" float4 tangentIn : NORMAL2;\n"
+" float4 colorIn : COLOR;\n"
+"};\n"
+"\n"
+"cbuffer FluidPlaneUniform : register(b0)\n"
+"{\n"
+" float4x4 mv;\n"
+" float4x4 mvNorm;\n"
+" float4x4 proj;\n"
+" float4x4 texMtxs[6];\n"
+"};\n"
+"\n"
+"struct VertToFrag\n"
+"{\n"
+" float4 pos : SV_Position;\n"
+" float4 mvPos : POSITION;\n"
+" float4 mvNorm : NORMAL;\n"
+" float4 mvBinorm : BINORMAL;\n"
+" float4 mvTangent : TANGENT;\n"
+" float4 color : COLOR;\n"
+" float2 uvs[7] : UV;\n"
+"};\n"
+"\n"
+"VertToFrag main(in VertData v)\n"
+"{\n"
+" VertToFrag vtf;\n"
+" vtf.mvPos = mul(mv, float4(v.posIn.xyz, 1.0));\n"
+" vtf.pos = mul(proj, vtf.mvPos);\n"
+" vtf.mvNorm = mul(mvNorm, v.normalIn);\n"
+" vtf.mvBinorm = mul(mvNorm, v.binormalIn);\n"
+" vtf.mvTangent = mul(mvNorm, v.tangentIn);\n"
+" vtf.color = v.colorIn;\n"
+" vtf.uvs[0] = mul(texMtxs[0], v.posIn).xy;\n"
+" vtf.uvs[1] = mul(texMtxs[1], v.posIn).xy;\n"
+" vtf.uvs[2] = mul(texMtxs[2], v.posIn).xy;\n"
+"%s" // Additional TCGs here
+" return vtf;\n"
+"}\n";
+
+static const char* FS =
+"struct Light\n"
+"{\n"
+" float4 pos;\n"
+" float4 dir;\n"
+" float4 color;\n"
+" float4 linAtt;\n"
+" float4 angAtt;\n"
+"};\n"
+"struct Fog\n" // Reappropriated for indirect texture scaling
+"{\n"
+" float4 color;\n"
+" float indScale;\n"
+" float start;\n"
+"};\n"
+"\n"
+"struct LightingUniform\n"
+"{\n"
+" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n"
+" float4 ambient;\n"
+" float4 kColor0;\n"
+" float4 kColor1;\n"
+" float4 kColor2;\n"
+" float4 kColor3;\n"
+" Fog fog;\n"
+"};\n"
+"\n"
+"static float4 LightingFunc(float4 mvPosIn, float4 mvNormIn)\n"
+"{\n"
+" float4 ret = ambient;\n"
+" \n"
+" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
+" {\n"
+" float3 delta = mvPosIn.xyz - lights[i].pos.xyz;\n"
+" float dist = length(delta);\n"
+" float angDot = clamp(dot(normalize(delta), lights[i].dir.xyz), 0.0, 1.0);\n"
+" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n"
+" lights[i].linAtt[1] * dist +\n"
+" lights[i].linAtt[0]);\n"
+" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n"
+" lights[i].angAtt[1] * angDot +\n"
+" lights[i].angAtt[0];\n"
+" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn.xyz), 0.0, 1.0);\n"
+" }\n"
+" \n"
+" return clamp(ret, float4(0.0,0.0,0.0,0.0), float4(1.0,1.0,1.0,1.0));\n"
+"}\n"
+"\n"
+"struct VertToFrag\n"
+"{\n"
+" float4 pos : SV_Position;\n"
+" float4 mvPos : POSITION;\n"
+" float4 mvNorm : NORMAL;\n"
+" float4 mvBinorm : BINORMAL;\n"
+" float4 mvTangent : TANGENT;\n"
+" float4 color : COLOR;\n"
+" float2 uvs[7] : UV;\n"
+"};\n"
+"\n"
+"SamplerState samp : register(s0);\n"
+"%s" // Textures here
+"float4 main(in VertToFrag vtf)\n"
+"{\n"
+" float4 lighting = LightingFunc(vtf.mvPos, normalize(vtf.mvNorm));\n"
+" float4 colorOut;\n"
+"%s" // Combiner expression here
+" return colorOut;\n"
+"}\n";
+
+boo::IShaderPipeline*
+CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info)
+{
+ if (s_vtxFmt == nullptr)
+ {
+ boo::VertexElementDescriptor elements[] =
+ {
+ {nullptr, nullptr, boo::VertexSemantic::Position4},
+ {nullptr, nullptr, boo::VertexSemantic::Normal4, 0},
+ {nullptr, nullptr, boo::VertexSemantic::Normal4, 1},
+ {nullptr, nullptr, boo::VertexSemantic::Normal4, 2},
+ {nullptr, nullptr, boo::VertexSemantic::Color}
+ };
+ s_vtxFmt = ctx.newVertexFormat(5, elements);
+ }
+
+ std::string additionalTCGs;
+ std::string textures;
+ std::string combiner;
+ int nextTex = 0;
+ int nextTCG = 3;
+ int nextMtx = 4;
+ int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv;
+
+ if (info.m_hasPatternTex1)
+ textures += hecl::Format("Texture2D patternTex1 : register(t%d)\n", nextTex++);
+ if (info.m_hasPatternTex2)
+ textures += hecl::Format("Texture2D patternTex2 : register(t%d)\n", nextTex++);
+ if (info.m_hasColorTex)
+ textures += hecl::Format("Texture2D colorTex : register(t%d)\n", nextTex++);
+ if (info.m_hasBumpMap)
+ textures += hecl::Format("Texture2D bumpMap : register(t%d)\n", nextTex++);
+ if (info.m_hasEnvMap)
+ textures += hecl::Format("Texture2D envMap : register(t%d)\n", nextTex++);
+ if (info.m_hasEnvBumpMap)
+ textures += hecl::Format("Texture2D envBumpMap : register(t%d)\n", nextTex++);
+ if (info.m_hasLightmap)
+ textures += hecl::Format("Texture2D lightMap : register(t%d)\n", nextTex++);
+
+ if (info.m_hasBumpMap)
+ {
+ bumpMapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[0], v.posIn).xy;\n", nextTCG++);
+ }
+ if (info.m_hasEnvBumpMap)
+ {
+ envBumpMapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[3], v.posIn).xy;\n", nextTCG++);
+ }
+ if (info.m_hasEnvMap)
+ {
+ envMapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[%d], v.posIn).xy;\n", nextTCG++, nextMtx++);
+ }
+ if (info.m_hasLightmap)
+ {
+ lightmapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[%d], v.posIn).xy;\n", nextTCG++, nextMtx++);
+ }
+
+ switch (info.m_type)
+ {
+ case CFluidPlane::EFluidType::NormalWater:
+ case CFluidPlane::EFluidType::Three:
+ case CFluidPlane::EFluidType::Four:
+ if (info.m_hasLightmap)
+ {
+ combiner += hecl::Format(" float4 lightMapTexel = lightMap.Sample(samp, vtf.uvs[%d]);\n", lightmapUv);
+ // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
+ // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
+ // Output reg 2
+ // KColor 2
+ if (info.m_doubleLightmapBlend)
+ {
+ // 1: Tex4TCG2, Tex4, GX_COLOR1A1
+ // C2, TEX, KONST, RAS
+ // Output reg 2
+ // KColor 3
+ // Tex * K2 + Lighting
+ combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n";
+ }
+ else
+ {
+ // mix(Tex * K2, Tex, K3) + Lighting
+ combiner += " lighting += lightMapTexel * lu.kColor2;\n";
+ }
+ }
+
+ // Next: Tex0TCG, Tex0, GX_COLOR1A1
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // Next: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // Next: Tex2TCG, Tex2, GX_COLOR1A1
+ // ZERO, TEX, hasTex4 ? C2 : RAS, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * lu.kColor0 + lighting) *\n"
+ " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = lighting * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+
+ if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap)
+ {
+ // Make previous stage indirect, mtx0
+ combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
+ " float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
+ combiner += " colorOut += colorTex.Sample(samp, indUvs + vtf.uvs[2]) * lighting;\n";
+ }
+ else if (info.m_hasEnvMap)
+ {
+ // Next: envTCG, envTex, NULL
+ // PREV, TEX, KONST, ZERO
+ // Output reg prev
+ // KColor 1
+
+ // Make previous stage indirect, mtx0
+ if (info.m_hasColorTex)
+ combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;\n";
+ combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
+ " float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
+ combiner += hecl::Format(" colorOut = mix(colorOut, envMap.Sample(samp, indUvs + vtf.uvs[%d]), lu.kColor1);\n",
+ envMapUv);
+ }
+ else if (info.m_hasColorTex)
+ {
+ combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;\n";
+ }
+
+ break;
+
+ case CFluidPlane::EFluidType::PoisonWater:
+ if (info.m_hasLightmap)
+ {
+ combiner += hecl::Format(" float4 lightMapTexel = lightMap.Sample(samp, vtf.uvs[%d]);\n", lightmapUv);
+ // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
+ // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
+ // Output reg 2
+ // KColor 2
+ if (info.m_doubleLightmapBlend)
+ {
+ // 1: Tex4TCG2, Tex4, GX_COLOR1A1
+ // C2, TEX, KONST, RAS
+ // Output reg 2
+ // KColor 3
+ // Tex * K2 + Lighting
+ combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n";
+ }
+ else
+ {
+ // mix(Tex * K2, Tex, K3) + Lighting
+ combiner += " lighting += lightMapTexel * lu.kColor2;\n";
+ }
+ }
+
+ // Next: Tex0TCG, Tex0, GX_COLOR1A1
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // Next: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // Next: Tex2TCG, Tex2, GX_COLOR1A1
+ // ZERO, TEX, hasTex4 ? C2 : RAS, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * lu.kColor0 + lighting) *\n"
+ " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = lighting * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+ if (info.m_hasColorTex)
+ {
+ if (info.m_hasEnvBumpMap)
+ {
+ // Make previous stage indirect, mtx0
+ combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
+ " float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
+ combiner += " colorOut += colorTex.Sample(samp, indUvs + vtf.uvs[2]) * lighting;\n";
+ }
+ else
+ {
+ combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;\n";
+ }
+ }
+
+ break;
+
+ case CFluidPlane::EFluidType::Lava:
+ // 0: Tex0TCG, Tex0, GX_COLOR0A0
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // 1: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // 2: Tex2TCG, Tex2, NULL
+ // ZERO, TEX, ONE, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * lu.kColor0 + vtf.color) *\n"
+ " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = vtf.color * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+ if (info.m_hasColorTex)
+ combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]);\n";
+
+ if (info.m_hasBumpMap)
+ {
+ // 3: bumpMapTCG, bumpMap, NULL
+ // ZERO, TEX, ONE, HALF
+ // Output reg 0, no clamp, no bias
+
+ // 4: bumpMapTCG2, bumpMap, NULL
+ // ZERO, TEX, ONE, C0
+ // Output reg 0, subtract, clamp, no bias
+
+ combiner += " float3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n"
+ " float lx = dot(vtf.mvTangent.xyz, lightVec);\n"
+ " float ly = dot(vtf.mvBinorm.xyz, lightVec);\n";
+ combiner += hecl::Format(" float4 emboss1 = bumpMap.Sample(samp, vtf.uvs[%d]) + float4(0.5);\n"
+ " float4 emboss2 = bumpMap.Sample(samp, vtf.uvs[%d] + float2(lx, ly));\n",
+ bumpMapUv, bumpMapUv);
+
+ // 5: NULL, NULL, NULL
+ // ZERO, PREV, C0, ZERO
+ // Output reg prev, scale 2, clamp
+
+ // colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0
+ combiner += "colorOut *= clamp((emboss1 + float4(0.5) - emboss2) * float4(2.0), float4(0.0), float4(1.0));\n";
+ }
+
+ break;
+
+ case CFluidPlane::EFluidType::Five:
+ // 0: Tex0TCG, Tex0, GX_COLOR0A0
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // 1: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // 2: Tex2TCG, Tex2, NULL
+ // ZERO, TEX, ONE, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * lu.kColor0 + vtf.color) *\n"
+ " patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = vtf.color * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+ if (info.m_hasColorTex)
+ combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]);\n";
+
+ if (info.m_hasBumpMap)
+ {
+ // 3: bumpMapTCG, bumpMap, NULL
+ // ZERO, TEX, PREV, ZERO
+ // Output reg prev, scale 2
+ combiner += hecl::Format(" float4 emboss1 = bumpMap.Sample(samp, vtf.uvs[%d]) + float4(0.5);\n", bumpMapUv);
+ combiner += "colorOut *= emboss1 * float4(2.0);\n";
+ }
+
+ break;
+ }
+
+ combiner += " colorOut.a = kColor0.a;\n";
+
+ std::string finalVS = hecl::Format(VS, additionalTCGs.c_str());
+ std::string finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str());
+
+ return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), nullptr, nullptr, nullptr, s_vtxFmt,
+ info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
+ info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
+ boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
+ boo::CullMode::None);
+}
+
+boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::ID3DDataFactory::Context& ctx,
+ boo::IShaderPipeline* pipeline)
+{
+ boo::IGraphicsBuffer* ubufs[] = { m_uniBuf, m_uniBuf, m_uniBuf };
+ boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
+ boo::PipelineStage::Fragment };
+ size_t ubufOffs[] = {0, 0, 768};
+ size_t ubufSizes[] = {768, 768, 256};
+ size_t texCount = 0;
+ boo::ITexture* texs[7] = {};
+ if (m_patternTex1)
+ texs[texCount++] = (*m_patternTex1)->GetBooTexture();
+ if (m_patternTex2)
+ texs[texCount++] = (*m_patternTex2)->GetBooTexture();
+ if (m_colorTex)
+ texs[texCount++] = (*m_colorTex)->GetBooTexture();
+ if (m_bumpMap)
+ texs[texCount++] = (*m_bumpMap)->GetBooTexture();
+ if (m_envMap)
+ texs[texCount++] = (*m_envMap)->GetBooTexture();
+ if (m_envBumpMap)
+ texs[texCount++] = (*m_envBumpMap)->GetBooTexture();
+ if (m_lightmap)
+ texs[texCount++] = (*m_lightmap)->GetBooTexture();
+ return ctx.newShaderDataBinding(pipeline, s_vtxFmt, m_vbo, nullptr, nullptr, 1, ubufs, ubufStages, ubufOffs,
+ ubufSizes, texCount, texs, nullptr, nullptr);
+}
+
+}
diff --git a/Runtime/Graphics/Shaders/CFluidPlaneShaderMetal.cpp b/Runtime/Graphics/Shaders/CFluidPlaneShaderMetal.cpp
new file mode 100644
index 000000000..78708bf9d
--- /dev/null
+++ b/Runtime/Graphics/Shaders/CFluidPlaneShaderMetal.cpp
@@ -0,0 +1,482 @@
+#include "CFluidPlaneShader.hpp"
+
+namespace urde
+{
+
+static boo::IVertexFormat* s_vtxFmt = nullptr;
+
+static const char* VS =
+"#include \n"
+"using namespace metal;\n"
+"struct VertData\n"
+"{\n"
+" float4 posIn [[ attribute(0) ]];\n"
+" float4 normalIn [[ attribute(1) ]];\n"
+" float4 binormalIn [[ attribute(2) ]];\n"
+" float4 tangentIn [[ attribute(3) ]];\n"
+" float4 colorIn [[ attribute(4) ]];\n"
+"};\n"
+"\n"
+"UBINDING0 uniform FluidPlaneUniform\n"
+"{\n"
+" float4x4 mv;\n"
+" float4x4 mvNorm;\n"
+" float4x4 proj;\n"
+" float4x4 texMtxs[6];\n"
+"};\n"
+"\n"
+"struct VertToFrag\n"
+"{\n"
+" float4 pos : [[ position ]];\n"
+" float4 mvPos;\n"
+" float4 mvNorm;\n"
+" float4 mvBinorm;\n"
+" float4 mvTangent;\n"
+" float4 color;\n"
+" float2 uvs[7];\n"
+"};\n"
+"\n"
+"vertex VertToFrag vmain(VertData v [[ stage_in ]],\n"
+" constant FluidPlaneUniform& fu [[ buffer(2) ]])\n"
+"{\n"
+" VertToFrag vtf;\n"
+" vtf.mvPos = fu.mv * float4(v.posIn.xyz, 1.0);\n"
+" vtf.pos = fu.proj * vtf.mvPos;\n"
+" vtf.mvNorm = fu.mvNorm * v.normalIn;\n"
+" vtf.mvBinorm = fu.mvNorm * v.binormalIn;\n"
+" vtf.mvTangent = fu.mvNorm * v.tangentIn;\n"
+" vtf.color = v.colorIn;\n"
+" vtf.uvs[0] = (fu.texMtxs[0] * v.posIn).xy;\n"
+" vtf.uvs[1] = (fu.texMtxs[1] * v.posIn).xy;\n"
+" vtf.uvs[2] = (fu.texMtxs[2] * v.posIn).xy;\n"
+"%s" // Additional TCGs here
+" return vtf;\n"
+"}\n";
+
+static const char* FS =
+"#include \n"
+"using namespace metal;\n"
+"constexpr sampler samp(address::repeat, filter::linear);\n"
+"\n"
+"struct Light\n"
+"{\n"
+" float4 pos;\n"
+" float4 dir;\n"
+" float4 color;\n"
+" float4 linAtt;\n"
+" float4 angAtt;\n"
+"};\n"
+"struct Fog\n" // Reappropriated for indirect texture scaling
+"{\n"
+" float4 color;\n"
+" float indScale;\n"
+" float start;\n"
+"};\n"
+"\n"
+"struct LightingUniform\n"
+"{\n"
+" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n"
+" float4 ambient;\n"
+" float4 kColor0;\n"
+" float4 kColor1;\n"
+" float4 kColor2;\n"
+" float4 kColor3;\n"
+" Fog fog;\n"
+"};\n"
+"\n"
+"static float4 LightingFunc(float4 mvPosIn, float4 mvNormIn)\n"
+"{\n"
+" float4 ret = ambient;\n"
+" \n"
+" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
+" {\n"
+" float3 delta = mvPosIn.xyz - lights[i].pos.xyz;\n"
+" float dist = length(delta);\n"
+" float angDot = clamp(dot(normalize(delta), lights[i].dir.xyz), 0.0, 1.0);\n"
+" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n"
+" lights[i].linAtt[1] * dist +\n"
+" lights[i].linAtt[0]);\n"
+" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n"
+" lights[i].angAtt[1] * angDot +\n"
+" lights[i].angAtt[0];\n"
+" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn.xyz), 0.0, 1.0);\n"
+" }\n"
+" \n"
+" return clamp(ret, float4(0.0,0.0,0.0,0.0), float4(1.0,1.0,1.0,1.0));\n"
+"}\n"
+"\n"
+"struct VertToFrag\n"
+"{\n"
+" float4 pos : [[ position ]];\n"
+" float4 mvPos;\n"
+" float4 mvNorm;\n"
+" float4 mvBinorm;\n"
+" float4 mvTangent;\n"
+" float4 color;\n"
+" float2 uvs[7];\n"
+"};\n"
+"\n"
+"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n"
+" constant LightingUniform& lu [[ buffer(4) ]]%s)\n" // Textures here
+"{\n"
+" float4 lighting = LightingFunc(vtf.mvPos, normalize(vtf.mvNorm));\n"
+" float4 colorOut;\n"
+"%s" // Combiner expression here
+" return colorOut;\n"
+"}\n";
+
+boo::IShaderPipeline*
+CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info)
+{
+ if (s_vtxFmt == nullptr)
+ {
+ boo::VertexElementDescriptor elements[] =
+ {
+ {nullptr, nullptr, boo::VertexSemantic::Position4},
+ {nullptr, nullptr, boo::VertexSemantic::Normal4, 0},
+ {nullptr, nullptr, boo::VertexSemantic::Normal4, 1},
+ {nullptr, nullptr, boo::VertexSemantic::Normal4, 2},
+ {nullptr, nullptr, boo::VertexSemantic::Color}
+ };
+ s_vtxFmt = ctx.newVertexFormat(5, elements);
+ }
+
+ std::string additionalTCGs;
+ std::string textures;
+ std::string combiner;
+ int nextTex = 0;
+ int nextTCG = 3;
+ int nextMtx = 4;
+ int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv;
+
+ if (info.m_hasPatternTex1)
+ textures += hecl::Format(",\ntexture2d patternTex1 [[ texture(%d) ]]", nextTex++);
+ if (info.m_hasPatternTex2)
+ textures += hecl::Format(",\ntexture2d patternTex2 [[ texture(%d) ]]", nextTex++);
+ if (info.m_hasColorTex)
+ textures += hecl::Format(",\ntexture2d colorTex [[ texture(%d) ]]", nextTex++);
+ if (info.m_hasBumpMap)
+ textures += hecl::Format(",\ntexture2d bumpMap [[ texture(%d) ]]", nextTex++);
+ if (info.m_hasEnvMap)
+ textures += hecl::Format(",\ntexture2d envMap [[ texture(%d) ]]", nextTex++);
+ if (info.m_hasEnvBumpMap)
+ textures += hecl::Format(",\ntexture2d envBumpMap [[ texture(%d) ]]", nextTex++);
+ if (info.m_hasLightmap)
+ textures += hecl::Format(",\ntexture2d lightMap [[ texture(%d) ]]", nextTex++);
+
+ if (info.m_hasBumpMap)
+ {
+ bumpMapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[0] * v.posIn).xy;\n", nextTCG++);
+ }
+ if (info.m_hasEnvBumpMap)
+ {
+ envBumpMapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[3] * v.posIn).xy;\n", nextTCG++);
+ }
+ if (info.m_hasEnvMap)
+ {
+ envMapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[%d] * v.posIn).xy;\n", nextTCG++, nextMtx++);
+ }
+ if (info.m_hasLightmap)
+ {
+ lightmapUv = nextTCG;
+ additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[%d] * v.posIn).xy;\n", nextTCG++, nextMtx++);
+ }
+
+ switch (info.m_type)
+ {
+ case CFluidPlane::EFluidType::NormalWater:
+ case CFluidPlane::EFluidType::Three:
+ case CFluidPlane::EFluidType::Four:
+ if (info.m_hasLightmap)
+ {
+ combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uvs[%d]);\n", lightmapUv);
+ // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
+ // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
+ // Output reg 2
+ // KColor 2
+ if (info.m_doubleLightmapBlend)
+ {
+ // 1: Tex4TCG2, Tex4, GX_COLOR1A1
+ // C2, TEX, KONST, RAS
+ // Output reg 2
+ // KColor 3
+ // Tex * K2 + Lighting
+ combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n";
+ }
+ else
+ {
+ // mix(Tex * K2, Tex, K3) + Lighting
+ combiner += " lighting += lightMapTexel * lu.kColor2;\n";
+ }
+ }
+
+ // Next: Tex0TCG, Tex0, GX_COLOR1A1
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // Next: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // Next: Tex2TCG, Tex2, GX_COLOR1A1
+ // ZERO, TEX, hasTex4 ? C2 : RAS, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + lighting) *\n"
+ " patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = lighting * patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+
+ if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap)
+ {
+ // Make previous stage indirect, mtx0
+ combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
+ " float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
+ combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uvs[2]) * lighting;\n";
+ }
+ else if (info.m_hasEnvMap)
+ {
+ // Next: envTCG, envTex, NULL
+ // PREV, TEX, KONST, ZERO
+ // Output reg prev
+ // KColor 1
+
+ // Make previous stage indirect, mtx0
+ if (info.m_hasColorTex)
+ combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]) * lighting;\n";
+ combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
+ " float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
+ combiner += hecl::Format(" colorOut = mix(colorOut, envMap.sample(samp, indUvs + vtf.uvs[%d]), lu.kColor1);\n",
+ envMapUv);
+ }
+ else if (info.m_hasColorTex)
+ {
+ combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]) * lighting;\n";
+ }
+
+ break;
+
+ case CFluidPlane::EFluidType::PoisonWater:
+ if (info.m_hasLightmap)
+ {
+ combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uvs[%d]);\n", lightmapUv);
+ // 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
+ // ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
+ // Output reg 2
+ // KColor 2
+ if (info.m_doubleLightmapBlend)
+ {
+ // 1: Tex4TCG2, Tex4, GX_COLOR1A1
+ // C2, TEX, KONST, RAS
+ // Output reg 2
+ // KColor 3
+ // Tex * K2 + Lighting
+ combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n";
+ }
+ else
+ {
+ // mix(Tex * K2, Tex, K3) + Lighting
+ combiner += " lighting += lightMapTexel * lu.kColor2;\n";
+ }
+ }
+
+ // Next: Tex0TCG, Tex0, GX_COLOR1A1
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // Next: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // Next: Tex2TCG, Tex2, GX_COLOR1A1
+ // ZERO, TEX, hasTex4 ? C2 : RAS, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + lighting) *\n"
+ " patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = lighting * patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+ if (info.m_hasColorTex)
+ {
+ if (info.m_hasEnvBumpMap)
+ {
+ // Make previous stage indirect, mtx0
+ combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
+ " float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
+ combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uvs[2]) * lighting;\n";
+ }
+ else
+ {
+ combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]) * lighting;\n";
+ }
+ }
+
+ break;
+
+ case CFluidPlane::EFluidType::Lava:
+ // 0: Tex0TCG, Tex0, GX_COLOR0A0
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // 1: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // 2: Tex2TCG, Tex2, NULL
+ // ZERO, TEX, ONE, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + vtf.color) *\n"
+ " patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = vtf.color * patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+ if (info.m_hasColorTex)
+ combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]);\n";
+
+ if (info.m_hasBumpMap)
+ {
+ // 3: bumpMapTCG, bumpMap, NULL
+ // ZERO, TEX, ONE, HALF
+ // Output reg 0, no clamp, no bias
+
+ // 4: bumpMapTCG2, bumpMap, NULL
+ // ZERO, TEX, ONE, C0
+ // Output reg 0, subtract, clamp, no bias
+
+ combiner += " float3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n"
+ " float lx = dot(vtf.mvTangent.xyz, lightVec);\n"
+ " float ly = dot(vtf.mvBinorm.xyz, lightVec);\n";
+ combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uvs[%d]) + float4(0.5);\n"
+ " float4 emboss2 = bumpMap.sample(samp, vtf.uvs[%d] + float2(lx, ly));\n",
+ bumpMapUv, bumpMapUv);
+
+ // 5: NULL, NULL, NULL
+ // ZERO, PREV, C0, ZERO
+ // Output reg prev, scale 2, clamp
+
+ // colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0
+ combiner += "colorOut *= clamp((emboss1 + float4(0.5) - emboss2) * float4(2.0), float4(0.0), float4(1.0));\n";
+ }
+
+ break;
+
+ case CFluidPlane::EFluidType::Five:
+ // 0: Tex0TCG, Tex0, GX_COLOR0A0
+ // ZERO, TEX, KONST, RAS
+ // Output reg prev
+ // KColor 0
+
+ // 1: Tex1TCG, Tex1, GX_COLOR0A0
+ // ZERO, TEX, PREV, RAS
+ // Output reg prev
+
+ // 2: Tex2TCG, Tex2, NULL
+ // ZERO, TEX, ONE, PREV
+ // Output reg prev
+
+ // (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2
+ if (info.m_hasPatternTex2)
+ {
+ if (info.m_hasPatternTex1)
+ combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 + vtf.color) *\n"
+ " patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ else
+ combiner += " colorOut = vtf.color * patternTex2.sample(samp, vtf.uvs[1]) + vtf.color;\n";
+ }
+ else
+ {
+ combiner += " colorOut = vtf.color;\n";
+ }
+
+ if (info.m_hasColorTex)
+ combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]);\n";
+
+ if (info.m_hasBumpMap)
+ {
+ // 3: bumpMapTCG, bumpMap, NULL
+ // ZERO, TEX, PREV, ZERO
+ // Output reg prev, scale 2
+ combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uvs[%d]) + float4(0.5);\n", bumpMapUv);
+ combiner += "colorOut *= emboss1 * float4(2.0);\n";
+ }
+
+ break;
+ }
+
+ combiner += " colorOut.a = kColor0.a;\n";
+
+ std::string finalVS = hecl::Format(VS, additionalTCGs.c_str());
+ std::string finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str());
+
+ return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), s_vtxFmt, CGraphics::g_ViewportSamples,
+ info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
+ info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
+ boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
+ boo::CullMode::None);
+}
+
+boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::MetalDataFactory::Context& ctx,
+ boo::IShaderPipeline* pipeline)
+{
+ boo::IGraphicsBuffer* ubufs[] = { m_uniBuf, m_uniBuf, m_uniBuf };
+ boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
+ boo::PipelineStage::Fragment };
+ size_t ubufOffs[] = {0, 0, 768};
+ size_t ubufSizes[] = {768, 768, 256};
+ size_t texCount = 0;
+ boo::ITexture* texs[7] = {};
+ if (m_patternTex1)
+ texs[texCount++] = (*m_patternTex1)->GetBooTexture();
+ if (m_patternTex2)
+ texs[texCount++] = (*m_patternTex2)->GetBooTexture();
+ if (m_colorTex)
+ texs[texCount++] = (*m_colorTex)->GetBooTexture();
+ if (m_bumpMap)
+ texs[texCount++] = (*m_bumpMap)->GetBooTexture();
+ if (m_envMap)
+ texs[texCount++] = (*m_envMap)->GetBooTexture();
+ if (m_envBumpMap)
+ texs[texCount++] = (*m_envBumpMap)->GetBooTexture();
+ if (m_lightmap)
+ texs[texCount++] = (*m_lightmap)->GetBooTexture();
+ return ctx.newShaderDataBinding(pipeline, s_vtxFmt, m_vbo, nullptr, nullptr, 1, ubufs, ubufStages, ubufOffs,
+ ubufSizes, texCount, texs, nullptr, nullptr);
+}
+
+}
diff --git a/Runtime/Graphics/Shaders/CModelShaders.cpp b/Runtime/Graphics/Shaders/CModelShaders.cpp
index d9b225c44..54cb7e761 100644
--- a/Runtime/Graphics/Shaders/CModelShaders.cpp
+++ b/Runtime/Graphics/Shaders/CModelShaders.cpp
@@ -1,10 +1,58 @@
#include "CModelShaders.hpp"
+#include "Graphics/CLight.hpp"
namespace urde
{
std::experimental::optional CModelShaders::g_ModelShaders;
+void CModelShaders::LightingUniform::ActivateLights(const std::vector& lts)
+{
+ ambient = zeus::CColor::skBlack;
+ size_t curLight = 0;
+
+ for (const CLight& light : lts)
+ {
+ switch (light.GetType())
+ {
+ case ELightType::LocalAmbient:
+ ambient += light.GetColor();
+ break;
+ case ELightType::Point:
+ case ELightType::Spot:
+ case ELightType::Custom:
+ case ELightType::Directional:
+ {
+ if (curLight >= URDE_MAX_LIGHTS)
+ continue;
+ CModelShaders::Light& lightOut = lights[curLight++];
+ lightOut.pos = CGraphics::g_CameraMatrix * light.GetPosition();
+ lightOut.dir = CGraphics::g_CameraMatrix.basis * light.GetDirection();
+ lightOut.dir.normalize();
+ lightOut.color = light.GetColor();
+ lightOut.linAtt[0] = light.GetAttenuationConstant();
+ lightOut.linAtt[1] = light.GetAttenuationLinear();
+ lightOut.linAtt[2] = light.GetAttenuationQuadratic();
+ lightOut.angAtt[0] = light.GetAngleAttenuationConstant();
+ lightOut.angAtt[1] = light.GetAngleAttenuationLinear();
+ lightOut.angAtt[2] = light.GetAngleAttenuationQuadratic();
+
+ if (light.GetType() == ELightType::Directional)
+ lightOut.pos = (-lightOut.dir) * 1048576.f;
+ break;
+ }
+ }
+ }
+
+ for (; curLight& lts);
};
struct ThermalUniform
diff --git a/Runtime/MP1/CSamusFaceReflection.cpp b/Runtime/MP1/CSamusFaceReflection.cpp
index ad0ed4efb..33eb0909c 100644
--- a/Runtime/MP1/CSamusFaceReflection.cpp
+++ b/Runtime/MP1/CSamusFaceReflection.cpp
@@ -110,7 +110,7 @@ void CSamusFaceReflection::Update(float dt, const CStateManager& mgr, CRandom16&
lookDot = lookDot > 0.f ? 1.f : -1.f;
float lookAng = std::acos(lookDot);
x50_lookRot = zeus::CQuaternion::slerp(x50_lookRot, xfLook2,
- zeus::clamp(0.f, 18.f * dt * ((lookAng > 0.f) ? 0.5f * dt * g_tweakPlayer->GetHudLagAmount() / lookAng : 0.f), 1.f));
+ zeus::clamp(0.f, 18.f * dt * ((lookAng > 0.f) ? 0.5f * dt * g_tweakPlayer->GetFreeLookSpeed() / lookAng : 0.f), 1.f));
x60_lookDir = lookDir;
}
}
diff --git a/Runtime/MP1/CSamusHud.cpp b/Runtime/MP1/CSamusHud.cpp
index 9dd0ac3dc..50ecda6dc 100644
--- a/Runtime/MP1/CSamusHud.cpp
+++ b/Runtime/MP1/CSamusHud.cpp
@@ -690,7 +690,7 @@ void CSamusHud::ApplyClassicLag(const zeus::CUnitVector3f& lookDir, zeus::CQuate
float angle = std::acos(dot);
float tmp = 0.f;
if (angle > 0.f)
- tmp = 0.5f * dt * g_tweakPlayer->GetHudLagAmount() / angle;
+ tmp = 0.5f * dt * g_tweakPlayer->GetFreeLookSpeed() / angle;
float t = zeus::clamp(0.f, 18.f * dt * tmp, 1.f);
rot = zeus::CQuaternion::slerp(rot, doubleRot, t);
diff --git a/Runtime/World/CActor.hpp b/Runtime/World/CActor.hpp
index 150194241..ddaafa6cc 100644
--- a/Runtime/World/CActor.hpp
+++ b/Runtime/World/CActor.hpp
@@ -170,6 +170,7 @@ public:
bool translateId);
SAdvancementDeltas UpdateAnimation(float, CStateManager&, bool);
void SetActorLights(std::unique_ptr);
+ const CActorLights* GetActorLights() const { return x90_actorLights.get(); }
bool CanDrawStatic() const;
bool GetE7_29() const { return xe7_29_; }
const CScannableObjectInfo* GetScannableObjectInfo() const;
diff --git a/Runtime/World/CFluidPlane.cpp b/Runtime/World/CFluidPlane.cpp
index bbce900f3..2827eacfe 100644
--- a/Runtime/World/CFluidPlane.cpp
+++ b/Runtime/World/CFluidPlane.cpp
@@ -1,9 +1,21 @@
+#include
#include "CFluidPlane.hpp"
+#include "CSimplePool.hpp"
namespace urde
{
-CFluidPlane::CFluidPlane(u32, u32, u32, EFluidType, float, const urde::CFluidUVMotion&, float)
+
+CFluidPlane::CFluidPlane(ResId texPattern1, ResId texPattern2, ResId texColor, float alpha, EFluidType fluidType,
+ float f2, const CFluidUVMotion& motion)
+: x4_texPattern1Id(texPattern1), x8_texPattern2Id(texPattern2), xc_texColorId(texColor), x40_alpha(alpha),
+ x44_fluidType(fluidType), x48_f2(f2), x4c_uvMotion(motion)
{
+ if (g_ResFactory->GetResourceTypeById(texPattern1) == FOURCC('TXTR'))
+ x10_texPattern1.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern1}));
+ if (g_ResFactory->GetResourceTypeById(texPattern2) == FOURCC('TXTR'))
+ x20_texPattern2.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern2}));
+ if (g_ResFactory->GetResourceTypeById(texColor) == FOURCC('TXTR'))
+ x30_texColor.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texColor}));
}
void CFluidPlane::Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos,
diff --git a/Runtime/World/CFluidPlane.hpp b/Runtime/World/CFluidPlane.hpp
index 41343a876..074c92572 100644
--- a/Runtime/World/CFluidPlane.hpp
+++ b/Runtime/World/CFluidPlane.hpp
@@ -2,6 +2,12 @@
#define __URDE_CFLUIDPLANE_HPP__
#include "RetroTypes.hpp"
+#include "CToken.hpp"
+#include "Graphics/CTexture.hpp"
+#include "CFluidUVMotion.hpp"
+#include "zeus/CAABox.hpp"
+#include "zeus/CFrustum.hpp"
+
namespace urde
{
class CFluidUVMotion;
@@ -13,37 +19,45 @@ class CFluidPlane
public:
enum class EFluidType
{
- Zero,
- One,
- Two,
+ NormalWater,
+ PoisonWater,
+ Lava,
Three,
Four,
Five
};
-private:
- u32 x4_;
- u32 x8_;
- u32 xc_;
- float x40_;
+protected:
+ ResId x4_texPattern1Id;
+ ResId x8_texPattern2Id;
+ ResId xc_texColorId;
+ std::experimental::optional> x10_texPattern1;
+ std::experimental::optional> x20_texPattern2;
+ std::experimental::optional> x30_texColor;
+ float x40_alpha;
EFluidType x44_fluidType;
- float x48_;
+ float x48_f2;
+ CFluidUVMotion x4c_uvMotion;
public:
- CFluidPlane() = default;
- CFluidPlane(u32, u32, u32, EFluidType, float, const CFluidUVMotion&, float);
+ CFluidPlane(ResId texPattern1, ResId texPattern2, ResId texColor, float alpha, EFluidType fluidType,
+ float f2, const CFluidUVMotion& motion);
virtual void Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos,
CScriptWater& water, CStateManager& mgr);
virtual void Update();
- float GetAlpha() const;
+ 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& rippleManager, TUniqueId waterId,
+ const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const {}
+ float GetAlpha() const { return x40_alpha; }
EFluidType GetFluidType() const { return x44_fluidType; }
- const CFluidUVMotion& GetUVMotion() const;
- void GetColorTexture() const;
- bool HasColorTexture() const;
- void GetTexturePattern1() const;
- bool HasTexturePattern1() const;
- void GetTexturePattern2() const;
- bool HasTexturePattern2() const;
+ const CFluidUVMotion& GetUVMotion() const { return x4c_uvMotion; }
+ const CTexture& GetColorTexture() const { return **x30_texColor; }
+ bool HasColorTexture() const { return x30_texColor.operator bool(); }
+ const CTexture& GetTexturePattern1() const { return **x10_texPattern1; }
+ bool HasTexturePattern1() const { return x10_texPattern1.operator bool(); }
+ const CTexture& GetTexturePattern2() const { return **x20_texPattern2; }
+ bool HasTexturePattern2() const { return x20_texPattern2.operator bool(); }
};
}
diff --git a/Runtime/World/CFluidPlaneCPU.cpp b/Runtime/World/CFluidPlaneCPU.cpp
index fa0085c76..48d120254 100644
--- a/Runtime/World/CFluidPlaneCPU.cpp
+++ b/Runtime/World/CFluidPlaneCPU.cpp
@@ -1,13 +1,307 @@
#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
namespace urde
{
-CFluidPlaneCPU::CFluidPlaneCPU(u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, u32 w6, float f1, u32 w7, u32 w8,
- EFluidType fluidType, float f2, const zeus::CVector3f& v1, float f3,
- const urde::CFluidUVMotion& motion, float f4, float f5, float f6, float f7, float f8,
- float f9, float f10, float f11, float f12, float f13, float f14, float f15, float f16,
- float f17)
-: CFluidPlane(w1, w2, w3, fluidType, f3, motion, f17)
+CFluidPlaneCPU::CTurbulence::CTurbulence(float speed, float distance, float freqMax, float freqMin,
+ float phaseMax, float phaseMin, float amplitudeMax, float amplitudeMin)
+: x0_speed(speed), x4_distance(distance), x8_freqMax(freqMax), xc_freqMin(freqMin),
+ x10_phaseMax(phaseMax), x14_phaseMin(phaseMin), x18_amplitudeMax(amplitudeMax), x1c_amplitudeMin(amplitudeMin),
+ x2c_ooTurbSpeed(1.f / x0_speed), x30_ooTurbDistance(1.f / x4_distance)
{
+ if (x18_amplitudeMax != 0.f || x1c_amplitudeMin != 0.f)
+ {
+ x24_tableCount = kTableSize;
+ x28_heightSelPitch = x24_tableCount;
+ x20_table.reset(new float[x24_tableCount]);
+ float anglePitch = 2.f * M_PIF / x28_heightSelPitch;
+ float freqConstant = 0.5f * (x8_freqMax + xc_freqMin);
+ float freqLinear = 0.5f * (x8_freqMax - xc_freqMin);
+ float phaseConstant = 0.5f * (x10_phaseMax + x14_phaseMin);
+ float phaseLinear = 0.5f * (x10_phaseMax - x14_phaseMin);
+ float amplitudeConstant = 0.5f * (x18_amplitudeMax + x1c_amplitudeMin);
+ float amplitudeLinear = 0.5f * (x18_amplitudeMax - x1c_amplitudeMin);
+
+ float curAng = 0.f;
+ for (int i=0 ; iGetResourceTypeById(xa0_texIdBumpMap) == FOURCC('TXTR'))
+ xb0_bumpMap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa0_texIdBumpMap}));
+ if (g_ResFactory->GetResourceTypeById(xa4_texIdEnvMap) == FOURCC('TXTR'))
+ xc0_envMap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa4_texIdEnvMap}));
+ 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_lightmap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xac_texId4}));
+}
+
+void CFluidPlaneCPU::CreateRipple(const CRipple& ripple, CStateManager& mgr)
+{
+
+}
+
+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();
+}
+
+#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& rippleManager, TUniqueId waterId,
+ const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const
+{
+ TCastToConstPtr 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
+{
+
+}
+
}
diff --git a/Runtime/World/CFluidPlaneCPU.hpp b/Runtime/World/CFluidPlaneCPU.hpp
index 8a524a968..4be9c82f7 100644
--- a/Runtime/World/CFluidPlaneCPU.hpp
+++ b/Runtime/World/CFluidPlaneCPU.hpp
@@ -2,16 +2,107 @@
#define __URDE_CFLUIDPLANECPU_HPP__
#include "CFluidPlane.hpp"
+#include "CRipple.hpp"
+#include "Graphics/Shaders/CFluidPlaneShader.hpp"
namespace urde
{
class CFluidUVMotion;
class CFluidPlaneCPU : public CFluidPlane
{
+ class CTurbulence
+ {
+ float x0_speed;
+ float x4_distance;
+ float x8_freqMax;
+ float xc_freqMin;
+ float x10_phaseMax;
+ float x14_phaseMin;
+ float x18_amplitudeMax;
+ float x1c_amplitudeMin;
+ std::unique_ptr x20_table; // x140
+ u32 x24_tableCount = 0; // x144
+ float x28_heightSelPitch = 0.f; // x148
+ float x2c_ooTurbSpeed; // x14c
+ float x30_ooTurbDistance; // x150
+ bool x34_hasTurbulence = false; // x154
+ public:
+ CTurbulence(float speed, float distance, float freqMax, float freqMin,
+ float phaseMax, float phaseMin, float amplitudeMax, float amplitudeMin);
+ float GetHeight(float sel) const { return x20_table[(x24_tableCount - 1) & int(sel * x28_heightSelPitch)]; }
+ float GetOODistance() const { return x30_ooTurbDistance; }
+ float GetOOSpeed() const { return x2c_ooTurbSpeed; }
+ bool HasTurbulence() const { return x34_hasTurbulence; }
+ };
+
+ ResId xa0_texIdBumpMap;
+ ResId xa4_texIdEnvMap;
+ ResId xa8_texIdEnvBumpMap;
+ ResId xac_texId4;
+ std::experimental::optional> xb0_bumpMap;
+ std::experimental::optional> xc0_envMap;
+ std::experimental::optional> xd0_envBumpMap;
+ std::experimental::optional> xe0_lightmap;
+ zeus::CVector3f xf0_bumpLightDir;
+ float xfc_bumpScale;
+ float x100_tileSize;
+ u32 x104_tileSubdivisions;
+ float x108_rippleResolution;
+ float x10c_specularMin;
+ float x110_specularMax;
+ float x114_reflectionBlend;
+ float x118_reflectionSize;
+ float x11c_unitsPerLightmapTexel;
+ CTurbulence x120_turbulence;
+ mutable std::experimental::optional m_shader;
+
+ struct RenderSetupInfo
+ {
+ zeus::CMatrix4f texMtxs[6];
+ zeus::CMatrix4f normMtx;
+ float indScale = 1.f;
+ zeus::CColor kColors[4];
+ std::vector lights;
+ };
public:
- CFluidPlaneCPU(u32, u32, u32, u32, u32, u32, float, u32, u32, EFluidType, float, const zeus::CVector3f&,
- float, const CFluidUVMotion&, float, float, float, float, float, float, float, float, float, float,
- float, float, float, float);
+ CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texColor, ResId bumpMap, ResId envMap, ResId envBumpMap,
+ ResId unkMap, float unitsPerLightmapTexel, float tileSize, u32 tileSubdivisions, EFluidType fluidType, float alpha,
+ 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 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& rippleManager, TUniqueId waterId,
+ const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const;
+ void RenderCleanup() const;
+ float GetReflectionBlend() const { return x114_reflectionBlend; }
+ float GetSpecularMax() const { return x110_specularMax; }
+ float GetSpecularMin() const { return x10c_specularMin; }
+ float GetReflectionSize() const { return x118_reflectionSize; }
+ float GetBumpScale() const { return xfc_bumpScale; }
+ bool HasBumpMap() const { return xb0_bumpMap.operator bool(); }
+ const CTexture& GetBumpMap() const { return **xb0_bumpMap; }
+ bool HasEnvMap() const { return xc0_envMap.operator bool(); }
+ 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; }
+ float GetRippleResolution() const { return x108_rippleResolution; }
+ float GetTurbulenceHeight(float sel) const { return x120_turbulence.GetHeight(sel); }
+ float GetOOTurbulenceDistance() const { return x120_turbulence.GetOODistance(); }
+ float GetOOTurbulenceSpeed() const { return x120_turbulence.GetOOSpeed(); }
+ bool HasTurbulence() const { return x120_turbulence.HasTurbulence(); }
};
}
diff --git a/Runtime/World/CFluidPlaneManager.cpp b/Runtime/World/CFluidPlaneManager.cpp
index b29e55514..48eeea9ac 100644
--- a/Runtime/World/CFluidPlaneManager.cpp
+++ b/Runtime/World/CFluidPlaneManager.cpp
@@ -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);
+ }
+}
+
}
diff --git a/Runtime/World/CFluidPlaneManager.hpp b/Runtime/World/CFluidPlaneManager.hpp
index 19ca2b1de..c65664fff 100644
--- a/Runtime/World/CFluidPlaneManager.hpp
+++ b/Runtime/World/CFluidPlaneManager.hpp
@@ -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 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& SplashRecords() { return x18_splashes; }
};
}
diff --git a/Runtime/World/CFluidUVMotion.cpp b/Runtime/World/CFluidUVMotion.cpp
index a5fd37711..fca804907 100644
--- a/Runtime/World/CFluidUVMotion.cpp
+++ b/Runtime/World/CFluidUVMotion.cpp
@@ -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_);
diff --git a/Runtime/World/CFluidUVMotion.hpp b/Runtime/World/CFluidUVMotion.hpp
index 5cca35500..6a3568937 100644
--- a/Runtime/World/CFluidUVMotion.hpp
+++ b/Runtime/World/CFluidUVMotion.hpp
@@ -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_e = 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_e(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& 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__
diff --git a/Runtime/World/CMorphBall.hpp b/Runtime/World/CMorphBall.hpp
index 6db492c96..dcd3ded15 100644
--- a/Runtime/World/CMorphBall.hpp
+++ b/Runtime/World/CMorphBall.hpp
@@ -128,7 +128,7 @@ public:
void SetTouchedHalfPipeRecently(bool) {}
void DisableHalfPipeStatus() {}
void BallCloseToCollision(const CStateManager&, float) const {}
- void CollidedWith(const TUniqueId&, const CCollisionInfoList&, CStateManager&) {}
+ void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager&) {}
bool IsInFrustum(const zeus::CFrustum&) const { return false; }
void ComputeLiftForces(const zeus::CVector3f&, const zeus::CVector3f&, const CStateManager&) {}
void CalculateSurfaceFriction() const {}
diff --git a/Runtime/World/CPlayer.cpp b/Runtime/World/CPlayer.cpp
index 5fdf28cd1..4719914e7 100644
--- a/Runtime/World/CPlayer.cpp
+++ b/Runtime/World/CPlayer.cpp
@@ -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));
@@ -346,7 +346,7 @@ void CPlayer::TakeDamage(bool significant, const zeus::CVector3f& location,
doRumble = true;
}
- if (damageLoopSfx && !x9c7_24_ && x2ac_movementSurface >= EPlayerMovementSurface::Ice)
+ if (damageLoopSfx && !x9c7_24_ && x2ac_surfaceRestraint >= ESurfaceRestraints::Ice)
{
if (!x770_damageLoopSfx || x788_damageLoopSfxId != damageLoopSfx)
{
@@ -987,7 +987,7 @@ void CPlayer::UpdateFreeLookState(const CFinalInput& input, float dt, CStateMana
zeus::CVector3f lookDir = mgr.GetCameraManager()->GetFirstPersonCamera()->GetTransform().basis[1];
zeus::CVector3f lookDirFlat = lookDir;
lookDirFlat.z = 0.f;
- x3e4_ = 0.f;
+ x3e4_freeLookYawAngle = 0.f;
if (lookDirFlat.canBeNormalized())
{
lookDirFlat.normalize();
@@ -1022,7 +1022,7 @@ void CPlayer::UpdateFreeLookState(const CFinalInput& input, float dt, CStateMana
ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookDown, input) >= 0.1f ||
ControlMapper::GetAnalogInput(ControlMapper::ECommands::LookUp, input) >= 0.1f);
x3dd_freeLookPitchAngleCalculated = false;
- if (std::fabs(x3e4_) < g_tweakPlayer->GetFreeLookCenteredThresholdAngle() &&
+ if (std::fabs(x3e4_freeLookYawAngle) < g_tweakPlayer->GetFreeLookCenteredThresholdAngle() &&
std::fabs(x3ec_freeLookPitchAngle) < g_tweakPlayer->GetFreeLookCenteredThresholdAngle())
{
if (x3e0_curFreeLookCenteredTime > g_tweakPlayer->GetFreeLookCenteredTime())
@@ -1046,9 +1046,34 @@ void CPlayer::UpdateFreeLookState(const CFinalInput& input, float dt, CStateMana
UpdateCrosshairsState(input);
}
-void CPlayer::UpdateFreeLook(float dt) {}
+void CPlayer::UpdateFreeLook(float dt)
+{
+ if (GetFrozenState())
+ return;
+ float lookDeltaAngle = dt * g_tweakPlayer->GetFreeLookSpeed();
+ if (!x3de_lookControlHeld)
+ lookDeltaAngle = dt * g_tweakPlayer->GetFreeLookSnapSpeed();
+ float angleVelP = x3f0_vertFreeLookAngleVel - x3ec_freeLookPitchAngle;
+ float vertLookDamp = zeus::clamp(0.f, std::fabs(angleVelP / 1.0471976f), 1.f);
+ float dx = lookDeltaAngle * (2.f * vertLookDamp - std::sin((M_PIF / 2.f) * vertLookDamp));
+ if (0.f <= angleVelP)
+ x3ec_freeLookPitchAngle += dx;
+ else
+ x3ec_freeLookPitchAngle -= dx;
+ angleVelP = x3e8_horizFreeLookAngleVel - x3e4_freeLookYawAngle;
+ dx = lookDeltaAngle * zeus::clamp(0.f, std::fabs(angleVelP / g_tweakPlayer->GetHorizontalFreeLookAngleVel()), 1.f);
+ if (0.f <= angleVelP)
+ x3e4_freeLookYawAngle += dx;
+ else
+ x3e4_freeLookYawAngle -= dx;
+ if (g_tweakPlayer->GetFreeLookTurnsPlayer())
+ x3e4_freeLookYawAngle = 0.f;
+}
-float CPlayer::GetMaximumPlayerPositiveVerticalVelocity(CStateManager&) const { return 0.f; }
+float CPlayer::GetMaximumPlayerPositiveVerticalVelocity(CStateManager& mgr) const
+{
+ return mgr.GetPlayerState()->GetItemAmount(CPlayerState::EItemType::SpaceJumpBoots) ? 14.f : 11.666666f;
+}
void CPlayer::StartLandingControlFreeze()
{
@@ -1652,16 +1677,16 @@ void CPlayer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CState
SetMoveState(EPlayerMovementState::StartingJump, mgr);
break;
case EScriptObjectMessage::OnIceSurface:
- x2ac_movementSurface = EPlayerMovementSurface::Ice;
+ x2ac_surfaceRestraint = ESurfaceRestraints::Ice;
break;
case EScriptObjectMessage::OnMudSlowSurface:
- x2ac_movementSurface = EPlayerMovementSurface::MudSlow;
+ x2ac_surfaceRestraint = ESurfaceRestraints::MudSlow;
break;
case EScriptObjectMessage::OnNormalSurface:
- x2ac_movementSurface = EPlayerMovementSurface::Normal;
+ x2ac_surfaceRestraint = ESurfaceRestraints::Normal;
break;
case EScriptObjectMessage::InSnakeWeed:
- x2ac_movementSurface = EPlayerMovementSurface::SnakeWeed;
+ x2ac_surfaceRestraint = ESurfaceRestraints::SnakeWeed;
break;
case EScriptObjectMessage::AddSplashInhabitant:
{
@@ -1685,18 +1710,18 @@ 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_movementSurface = EPlayerMovementSurface::Fluid2Or5;
+ x2ac_surfaceRestraint = ESurfaceRestraints::Fluid2Or5;
break;
- case CFluidPlane::EFluidType::One:
+ case CFluidPlane::EFluidType::PoisonWater:
x2b0_ = 0;
break;
case CFluidPlane::EFluidType::Three:
- x2ac_movementSurface = EPlayerMovementSurface::Fluid3;
+ x2ac_surfaceRestraint = ESurfaceRestraints::Fluid3;
break;
default: break;
}
@@ -1775,7 +1800,7 @@ void CPlayer::UpdateFootstepSounds(const CFinalInput& input, CStateManager& mgr,
float sfxDelay = 0.f;
if (forward > 0.05f || x304_orbitState != EPlayerOrbitState::Zero)
{
- float vel = std::min(1.f, x138_velocity.magnitude() / GetActualFirstPersonMaxVelocity());
+ float vel = std::min(1.f, x138_velocity.magnitude() / GetActualFirstPersonMaxVelocity(dt));
if (vel > 0.05f)
{
sfxDelay = -0.475f * vel + 0.85f;
@@ -3830,6 +3855,11 @@ float CPlayer::GetEyeHeight() const
return x9c8_eyeZBias + (x2d8_fpBounds.max.z - g_tweakPlayer->GetEyeOffset());
}
+float CPlayer::GetUnbiasedEyeHeight() const
+{
+ return x2d8_fpBounds.max.z - g_tweakPlayer->GetEyeOffset();
+}
+
float CPlayer::GetStepUpHeight() const
{
if (x258_movementState == EPlayerMovementState::Jump ||
@@ -3878,11 +3908,34 @@ const CCollidableSphere* CPlayer::GetCollidableSphere() const
return x768_morphball->GetCollidableSphere();
}
-zeus::CTransform CPlayer::GetPrimitiveTransform() const { return {}; }
+zeus::CTransform CPlayer::GetPrimitiveTransform() const
+{
+ return CPhysicsActor::GetPrimitiveTransform();
+}
-void CPlayer::CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager& mgr) {}
+void CPlayer::CollidedWith(TUniqueId id, const CCollisionInfoList& list, CStateManager& mgr)
+{
+ if (x2f8_morphTransState != EPlayerMorphBallState::Unmorphed)
+ x768_morphball->CollidedWith(id, list, mgr);
+}
-float CPlayer::GetActualFirstPersonMaxVelocity() const { return 0.f; }
+float CPlayer::GetActualBallMaxVelocity(float dt) const
+{
+ ESurfaceRestraints surf = x2b0_ == 2 ? x2ac_surfaceRestraint : ESurfaceRestraints::Four;
+ float friction = g_tweakBall->GetBallTranslationFriction(int(surf));
+ float maxSpeed = g_tweakBall->GetBallTranslationMaxSpeed(int(surf));
+ float acceleration = g_tweakBall->GetMaxBallTranslationAcceleration(int(surf));
+ return -(friction * xe8_mass * maxSpeed / (acceleration * dt) - maxSpeed - friction);
+}
+
+float CPlayer::GetActualFirstPersonMaxVelocity(float dt) const
+{
+ ESurfaceRestraints surf = x2b0_ == 2 ? x2ac_surfaceRestraint : ESurfaceRestraints::Four;
+ float friction = g_tweakPlayer->GetPlayerTranslationFriction(int(surf));
+ float maxSpeed = g_tweakPlayer->GetPlayerTranslationMaxSpeed(int(surf));
+ float acceleration = g_tweakPlayer->GetMaxTranslationalAcceleration(int(surf));
+ return -(friction * xe8_mass * maxSpeed / (acceleration * dt) - maxSpeed - friction);
+}
void CPlayer::SetMoveState(EPlayerMovementState, CStateManager& mgr) {}
@@ -4004,7 +4057,7 @@ void CPlayer::LeaveMorphBallState(CStateManager& mgr)
SetHudDisable(FLT_EPSILON, 0.f, 2.f);
SetIntoBallReadyAnimation(mgr);
CPhysicsActor::Stop();
- x3e4_ = 0.f;
+ x3e4_freeLookYawAngle = 0.f;
x3e8_horizFreeLookAngleVel = 0.f;
x3ec_freeLookPitchAngle = 0.f;
x3f0_vertFreeLookAngleVel = 0.f;
@@ -4346,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();
}
}
diff --git a/Runtime/World/CPlayer.hpp b/Runtime/World/CPlayer.hpp
index 0d79f686e..74d8779db 100644
--- a/Runtime/World/CPlayer.hpp
+++ b/Runtime/World/CPlayer.hpp
@@ -122,7 +122,7 @@ public:
Four
};
- enum class EPlayerMovementSurface
+ enum class ESurfaceRestraints
{
Normal,
One,
@@ -217,7 +217,7 @@ private:
float x2a0_ = 0.f;
bool x2a4_cancelCameraPitch = false;
float x2a8_ = 1000.f;
- EPlayerMovementSurface x2ac_movementSurface = EPlayerMovementSurface::Normal;
+ ESurfaceRestraints x2ac_surfaceRestraint = ESurfaceRestraints::Normal;
u32 x2b0_ = 2;
rstl::reserved_vector x2b4_;
u32 x2d0_ = 3;
@@ -271,7 +271,7 @@ private:
bool x3dd_freeLookPitchAngleCalculated = false;
bool x3de_lookControlHeld = false;
float x3e0_curFreeLookCenteredTime = 0.f;
- float x3e4_ = 0.f;
+ float x3e4_freeLookYawAngle = 0.f;
float x3e8_horizFreeLookAngleVel = 0.f;
float x3ec_freeLookPitchAngle = 0.f;
float x3f0_vertFreeLookAngleVel = 0.f;
@@ -554,6 +554,7 @@ public:
zeus::CVector3f GetBallPosition() const;
zeus::CVector3f GetEyePosition() const;
float GetEyeHeight() const;
+ float GetUnbiasedEyeHeight() const;
float GetStepUpHeight() const;
float GetStepDownHeight() const;
void Teleport(const zeus::CTransform& xf, CStateManager& mgr, bool);
@@ -563,7 +564,8 @@ public:
const CCollidableSphere* GetCollidableSphere() const;
zeus::CTransform GetPrimitiveTransform() const;
void CollidedWith(TUniqueId, const CCollisionInfoList&, CStateManager& mgr);
- float GetActualFirstPersonMaxVelocity() const;
+ float GetActualBallMaxVelocity(float dt) const;
+ float GetActualFirstPersonMaxVelocity(float dt) const;
void SetMoveState(EPlayerMovementState, CStateManager& mgr);
float JumpInput(const CFinalInput& input, CStateManager& mgr);
float TurnInput(const CFinalInput& input) const;
diff --git a/Runtime/World/CScriptWater.cpp b/Runtime/World/CScriptWater.cpp
index 2ada1b486..ce9dfa3fb 100644
--- a/Runtime/World/CScriptWater.cpp
+++ b/Runtime/World/CScriptWater.cpp
@@ -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 water = mgr.GetObjectById(its.first->second))
+ return water.GetPtr();
+ }
+ return nullptr;
+}
}
diff --git a/Runtime/World/CScriptWater.hpp b/Runtime/World/CScriptWater.hpp
index 0690aa1a7..833100e6c 100644
--- a/Runtime/World/CScriptWater.hpp
+++ b/Runtime/World/CScriptWater.hpp
@@ -17,7 +17,7 @@ private:
std::unique_ptr x1b4_fluidPlane;
zeus::CVector3f x1b8_;
float x1f4_;
- float x1f8_ = 0.f;
+ float x1f8_lightmapDoubleBlendFactor = 0.f;
zeus::CVector3f x1d4_;
std::list> x1fc_waterInhabitants;
u32 x210_;
@@ -39,6 +39,26 @@ private:
u32 x264_ = 0;
TLockedToken x268_splashEffects[5];
u16 x29c_splashSounds[5];
+ u32 x2c0_tesselationSize;
+ u32 x2c4_gridDimX = 0;
+ u32 x2c8_gridDimY = 0;
+ u32 x2cc_gridCellCount = 0;
+ std::unique_ptr x2d8_gridFlags;
+ std::unique_ptr x2e0_;
+ u32 x2e4_gridCellCount2 = 0;
+ union
+ {
+ struct
+ {
+ bool x2e8_24 : 1;
+ bool x2e8_25 : 1;
+ bool x2e8_26 : 1;
+ bool x2e8_27 : 1;
+ bool x2e8_28 : 1;
+ };
+ u32 _dummy = 0;
+ };
+ void SetupGrid(bool b);
public:
CScriptWater(CStateManager&, TUniqueId, const std::string& name, const CEntityInfo&, const zeus::CVector3f&,
const zeus::CAABox&, CDamageInfo const&, zeus::CVector3f&, ETriggerFlags, bool, bool, ResId, ResId, ResId, ResId,
@@ -77,6 +97,8 @@ public:
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; }
};
}