From 57db4303eb4904043e48fee2620f5aed7cbd2bf9 Mon Sep 17 00:00:00 2001 From: MonsterDruide1 <5958456@gmail.com> Date: Sat, 1 Feb 2025 11:54:11 +0100 Subject: [PATCH] Library/Nature: Implement `WaterSurfaceFinder` (#317) --- data/odyssey_functions.csv | 14 ++-- lib/al/Library/Nature/NatureUtil.h | 4 ++ lib/al/Library/Nature/WaterSurfaceFinder.cpp | 75 ++++++++++++++++++++ lib/al/Library/Nature/WaterSurfaceFinder.h | 35 +++++++++ 4 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 lib/al/Library/Nature/WaterSurfaceFinder.cpp create mode 100644 lib/al/Library/Nature/WaterSurfaceFinder.h diff --git a/data/odyssey_functions.csv b/data/odyssey_functions.csv index f58a1678c..87df11851 100644 --- a/data/odyssey_functions.csv +++ b/data/odyssey_functions.csv @@ -60031,13 +60031,13 @@ Address,Quality,Size,Name 0x0000007100958b08,U,000096,_ZN2al39calcMatrixFromActorPoseAndWaterSurfaceHEPN4sead8Matrix34IfEEPKNS_18WaterSurfaceFinderEPKNS_9LiveActorE 0x0000007100958b68,U,000248,_ZN12alNatureUtil36calcFindDistanceWaterSurfaceToGroundEPfPKN2al9LiveActorERKN4sead7Vector3IfEEf 0x0000007100958c60,U,000548, -0x0000007100958e84,U,000032,_ZN2al18WaterSurfaceFinderC2EPKNS_9LiveActorE -0x0000007100958ea4,U,000232,_ZN2al18WaterSurfaceFinder6updateERKN4sead7Vector3IfEES5_f -0x0000007100958f8c,U,000280,_ZN2al18WaterSurfaceFinder11updateLocalERKN4sead7Vector3IfEES5_fbbb -0x00000071009590a4,U,000232,_ZN2al18WaterSurfaceFinder22updateForSurfaceShadowERKN4sead7Vector3IfEES5_f -0x000000710095918c,U,000232,_ZN2al18WaterSurfaceFinder21updateForDisplacementERKN4sead7Vector3IfEES5_f -0x0000007100959274,U,000232,_ZN2al18WaterSurfaceFinder20updateConsiderGroundERKN4sead7Vector3IfEES5_f -0x000000710095935c,U,000044,_ZNK2al18WaterSurfaceFinder13isNearSurfaceEf +0x0000007100958e84,O,000032,_ZN2al18WaterSurfaceFinderC2EPKNS_9LiveActorE +0x0000007100958ea4,M,000232,_ZN2al18WaterSurfaceFinder6updateERKN4sead7Vector3IfEES5_f +0x0000007100958f8c,M,000280,_ZN2al18WaterSurfaceFinder11updateLocalERKN4sead7Vector3IfEES5_fbbb +0x00000071009590a4,M,000232,_ZN2al18WaterSurfaceFinder22updateForSurfaceShadowERKN4sead7Vector3IfEES5_f +0x000000710095918c,M,000232,_ZN2al18WaterSurfaceFinder21updateForDisplacementERKN4sead7Vector3IfEES5_f +0x0000007100959274,M,000232,_ZN2al18WaterSurfaceFinder20updateConsiderGroundERKN4sead7Vector3IfEES5_f +0x000000710095935c,O,000044,_ZNK2al18WaterSurfaceFinder13isNearSurfaceEf 0x0000007100959388,O,000072,_ZN2al11NerveActionC2Ev 0x00000071009593d0,O,000044,_ZN15alNerveFunction20NerveActionCollector8addNerveEPN2al11NerveActionE 0x00000071009593fc,O,000024,_ZN15alNerveFunction20NerveActionCollectorC2Ev diff --git a/lib/al/Library/Nature/NatureUtil.h b/lib/al/Library/Nature/NatureUtil.h index a8f3f1b0b..bd3933729 100644 --- a/lib/al/Library/Nature/NatureUtil.h +++ b/lib/al/Library/Nature/NatureUtil.h @@ -15,5 +15,9 @@ bool calcFindWaterSurface(sead::Vector3f*, sead::Vector3f*, const LiveActor*, co const sead::Vector3f&, f32); bool calcFindWaterSurfaceFlat(sead::Vector3f*, sead::Vector3f*, const LiveActor*, const sead::Vector3f&, const sead::Vector3f&, f32); +bool calcFindWaterSurfaceDisplacement(sead::Vector3f*, sead::Vector3f*, const LiveActor*, + const sead::Vector3f&, const sead::Vector3f&, f32); +bool calcFindWaterSurfaceOverGround(sead::Vector3f*, sead::Vector3f*, const LiveActor*, + const sead::Vector3f&, const sead::Vector3f&, f32); } // namespace al diff --git a/lib/al/Library/Nature/WaterSurfaceFinder.cpp b/lib/al/Library/Nature/WaterSurfaceFinder.cpp new file mode 100644 index 000000000..47dd817b2 --- /dev/null +++ b/lib/al/Library/Nature/WaterSurfaceFinder.cpp @@ -0,0 +1,75 @@ +#include "Library/Nature/WaterSurfaceFinder.h" + +#include "Library/Nature/NatureUtil.h" + +namespace al { + +WaterSurfaceFinder::WaterSurfaceFinder(const LiveActor* actor) : mActor(actor) {} + +// NON_MATCHING: inlined updateLocal +void WaterSurfaceFinder::update(const sead::Vector3f& position, const sead::Vector3f& gravity, + f32 distance) { + updateLocal(position, gravity, distance, false, false, false); +} + +// NON_MATCHING: storing {0,0,0} if no surface was found (https://decomp.me/scratch/zHEdm) +void WaterSurfaceFinder::updateLocal(const sead::Vector3f& position, const sead::Vector3f& gravity, + f32 maxDistance, bool isFlat, bool isDisplacement, + bool isOverGround) { + sead::Vector3f surfacePos = {0.0f, 0.0f, 0.0f}; + sead::Vector3f surfaceNormal = {0.0f, 0.0f, 0.0f}; + mIsFoundSurface = false; + + if (isFlat) + mIsFoundSurface = calcFindWaterSurfaceFlat(&surfacePos, &surfaceNormal, mActor, position, + gravity, maxDistance); + else if (isDisplacement) + mIsFoundSurface = calcFindWaterSurfaceDisplacement(&surfacePos, &surfaceNormal, mActor, + position, gravity, maxDistance); + else if (isOverGround) + mIsFoundSurface = calcFindWaterSurfaceOverGround(&surfacePos, &surfaceNormal, mActor, + position, gravity, maxDistance); + else + mIsFoundSurface = calcFindWaterSurface(&surfacePos, &surfaceNormal, mActor, position, + gravity, maxDistance); + + if (mIsFoundSurface) { + // requires this manual dot product calculation to match + mDistance = gravity.x * (surfacePos.x - position.x) + + gravity.y * (surfacePos.y - position.y) + + gravity.z * (surfacePos.z - position.z); + // mDistance = gravity.dot(surfacePos - position); + mSurfacePosition.set(surfacePos); + mSurfaceNormal.set(surfaceNormal); + } else { + mDistance = 0.0f; + mSurfacePosition = {0.0f, 0.0f, 0.0f}; + mSurfaceNormal = {0.0f, 0.0f, 0.0f}; + } + + _28 = {0.0f, 0.0f, 0.0f}; +} + +// NON_MATCHING: inlined updateLocal +void WaterSurfaceFinder::updateForSurfaceShadow(const sead::Vector3f& position, + const sead::Vector3f& gravity, f32 distance) { + updateLocal(position, gravity, distance, true, false, false); +} + +// NON_MATCHING: inlined updateLocal +void WaterSurfaceFinder::updateForDisplacement(const sead::Vector3f& position, + const sead::Vector3f& gravity, f32 distance) { + updateLocal(position, gravity, distance, false, true, false); +} + +// NON_MATCHING: inlined updateLocal +void WaterSurfaceFinder::updateConsiderGround(const sead::Vector3f& position, + const sead::Vector3f& gravity, f32 distance) { + updateLocal(position, gravity, distance, false, false, true); +} + +bool WaterSurfaceFinder::isNearSurface(f32 distance) const { + return mIsFoundSurface && sead::Mathf::abs(mDistance) < distance; +} + +} // namespace al diff --git a/lib/al/Library/Nature/WaterSurfaceFinder.h b/lib/al/Library/Nature/WaterSurfaceFinder.h new file mode 100644 index 000000000..3ccff570c --- /dev/null +++ b/lib/al/Library/Nature/WaterSurfaceFinder.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +namespace al { +class LiveActor; + +class WaterSurfaceFinder { +public: + WaterSurfaceFinder(const LiveActor* player); + + void update(const sead::Vector3f& position, const sead::Vector3f& gravity, f32 distance); + void updateLocal(const sead::Vector3f& position, const sead::Vector3f& gravity, f32 maxDistance, + bool isFlat, bool isDisplacement, bool isOverGround); + void updateForSurfaceShadow(const sead::Vector3f& position, const sead::Vector3f& gravity, + f32 distance); + void updateForDisplacement(const sead::Vector3f& position, const sead::Vector3f& gravity, + f32 distance); + void updateConsiderGround(const sead::Vector3f& position, const sead::Vector3f& gravity, + f32 distance); + + bool isNearSurface(f32 distance) const; + +private: + const LiveActor* mActor; + bool mIsFoundSurface = false; + f32 mDistance = 0.0f; + sead::Vector3f mSurfacePosition = {0.0f, 0.0f, 0.0f}; + sead::Vector3f mSurfaceNormal = {0.0f, 0.0f, 0.0f}; + sead::Vector3f _28 = {0.0f, 0.0f, 0.0f}; +}; + +static_assert(sizeof(WaterSurfaceFinder) == 0x38); + +} // namespace al