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