From 8ba8563775123df0ca253705eeebc70395c616f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Wed, 29 Dec 2021 12:33:07 +0100 Subject: [PATCH] ksys/phys: Add RigidContactPointsEx iterator --- data/uking_functions.csv | 8 +- .../System/physRigidContactPointsEx.cpp | 49 ++++++++++ .../Physics/System/physRigidContactPointsEx.h | 96 ++++++++++++++++++- 3 files changed, 148 insertions(+), 5 deletions(-) diff --git a/data/uking_functions.csv b/data/uking_functions.csv index d581e5b6..ee6349e3 100644 --- a/data/uking_functions.csv +++ b/data/uking_functions.csv @@ -84308,10 +84308,10 @@ Address,Quality,Size,Name 0x0000007100fcfadc,O,000004,_ZN4ksys4phys20RigidContactPointsExD0Ev 0x0000007100fcfae0,O,000300,_ZN4ksys4phys20RigidContactPointsEx11allocPointsEPN4sead4HeapEii 0x0000007100fcfc0c,O,000168,_ZN4ksys4phys20RigidContactPointsEx10freePointsEv -0x0000007100fcfcb4,U,000260, -0x0000007100fcfdb8,U,000048, -0x0000007100fcfde8,U,000068, -0x0000007100fcfe2c,U,000028, +0x0000007100fcfcb4,O,000260,_ZNK4ksys4phys20RigidContactPointsEx8Iterator7getDataEPN4sead7Vector3IfEENS2_4ModeE +0x0000007100fcfdb8,O,000048,_ZNK4ksys4phys20RigidContactPointsEx8Iterator7getDataENS2_4ModeE +0x0000007100fcfde8,O,000068,_ZN4ksys4phys20RigidContactPointsEx8IteratorC1ERKN4sead6BufferIPNS1_5PointEEEi +0x0000007100fcfe2c,O,000028,_ZN4ksys4phys20RigidContactPointsEx11IteratorEndC1ERKN4sead6BufferIPNS1_5PointEEEi 0x0000007100fcfe48,U,000112, 0x0000007100fcfeb8,U,000072, 0x0000007100fcff00,U,000692, diff --git a/src/KingSystem/Physics/System/physRigidContactPointsEx.cpp b/src/KingSystem/Physics/System/physRigidContactPointsEx.cpp index ac836364..fd718ca0 100644 --- a/src/KingSystem/Physics/System/physRigidContactPointsEx.cpp +++ b/src/KingSystem/Physics/System/physRigidContactPointsEx.cpp @@ -49,4 +49,53 @@ void RigidContactPointsEx::freePoints() { mLayerEntries.freeBuffer(); } +void RigidContactPointsEx::Iterator::getData(sead::Vector3f* out, + RigidContactPointsEx::Iterator::Mode mode) const { + const float scale = getPoint()->scale; + out->e = getPoint()->_10.e; + + switch (mode) { + case Mode::_0: { + if (getPoint()->flags.isOn(Point::Flag::_2)) + return; + *out += getPoint()->_1c * -scale; + break; + } + + case Mode::_1: { + if (!getPoint()->flags.isOn(Point::Flag::_2)) + return; + *out += getPoint()->_1c * scale; + break; + } + + case Mode::_2: + default: { + *out += getPoint()->_1c * scale * 0.5f; + break; + } + } +} + +sead::Vector3f +RigidContactPointsEx::Iterator::getData(RigidContactPointsEx::Iterator::Mode mode) const { + sead::Vector3f out; + getData(&out, mode); + return out; +} + +RigidContactPointsEx::Iterator::Iterator(const RigidContactPointsEx::Points& points, int count) + : mPoints(points.getBufferPtr()), mPointsNum(count), mPointsStart(points.getBufferPtr()) { + for (int i = 0; i != count; ++i) { + if (!mPoints[i]->flags.isOn(Point::Flag::_1)) + break; + ++mIdx; + } +} + +RigidContactPointsEx::IteratorEnd::IteratorEnd(const RigidContactPointsEx::Points& points, + int count) + : mIdx(count), mPoints(points.getBufferPtr()), mPointsNum(count), + mPointsStart(points.getBufferPtr()) {} + } // namespace ksys::phys diff --git a/src/KingSystem/Physics/System/physRigidContactPointsEx.h b/src/KingSystem/Physics/System/physRigidContactPointsEx.h index 69954ee1..d399c61a 100644 --- a/src/KingSystem/Physics/System/physRigidContactPointsEx.h +++ b/src/KingSystem/Physics/System/physRigidContactPointsEx.h @@ -1,14 +1,105 @@ #pragma once #include +#include +#include #include "KingSystem/Physics/System/physDefines.h" #include "KingSystem/Physics/System/physRigidContactPoints.h" +#include "KingSystem/Utils/Types.h" namespace ksys::phys { // FIXME: rename. This should be below SensorGroupFilter and StaticCompound stuff class RigidContactPointsEx : public IRigidContactPoints { public: + struct Point { + enum class Flag { + _1 = 1 << 0, + _2 = 1 << 1, + }; + + void* _0; + void* _8; + sead::Vector3f _10; + sead::Vector3f _1c; + float scale; + void* _30; + void* _38; + void* _40; + void* _48; + void* _50; + void* _58; + void* _60; + sead::TypedBitFlag flags; + }; + KSYS_CHECK_SIZE_NX150(Point, 0x70); + + using Points = sead::Buffer; + + class IteratorEnd; + + class Iterator { + public: + enum class Mode { + _0, + _1, + _2, + }; + + Iterator(const Points& points, int count); + + Iterator& operator++() { + ++mIdx; + return *this; + } + + // FIXME: rename + void getData(sead::Vector3f* out, Mode mode) const; + sead::Vector3f getData(Mode mode) const; + + const Point* getPoint() const { return mPoints[mIdx]; } + const Point* operator*() const { return getPoint(); } + + friend bool operator==(const Iterator& lhs, const Iterator& rhs) { + return lhs.mIdx == rhs.mIdx; + } + friend bool operator!=(const Iterator& lhs, const Iterator& rhs) { + return !operator==(lhs, rhs); + } + + private: + friend class IteratorEnd; + + int mIdx = 0; + const Point* const* mPoints = nullptr; + int mPointsNum = 0; + const Point* const* mPointsStart = nullptr; + }; + + class IteratorEnd { + public: + IteratorEnd(const Points& points, int count); + + friend bool operator==(const Iterator& lhs, const IteratorEnd& rhs) { + return lhs.mIdx == rhs.mIdx; + } + friend bool operator==(const IteratorEnd& lhs, const Iterator& rhs) { + return lhs.mIdx == rhs.mIdx; + } + friend bool operator!=(const Iterator& lhs, const IteratorEnd& rhs) { + return !operator==(lhs, rhs); + } + friend bool operator!=(const IteratorEnd& lhs, const Iterator& rhs) { + return !operator==(lhs, rhs); + } + + private: + int mIdx = 0; + const Point* const* mPoints = nullptr; + int mPointsNum = 0; + const Point* const* mPointsStart = nullptr; + }; + static RigidContactPointsEx* make(); static void free(RigidContactPointsEx* instance); @@ -20,6 +111,9 @@ public: bool registerLayerPair(ContactLayer layer1, ContactLayer layer2, bool enabled); bool isPairUnknown(ContactLayer layer1, ContactLayer layer2) const; + auto begin() const { return Iterator(mPoints, _18); } + auto end() const { return IteratorEnd(mPoints, _18); } + private: struct LayerEntry { ContactLayer layer1; @@ -27,7 +121,7 @@ private: bool enabled; }; - sead::Buffer mPoints{}; + Points mPoints{}; sead::ObjArray mLayerEntries; ContactLayerType mLayerType = ContactLayerType::Invalid; void* _80 = nullptr;