ksys/phys: Add ContactPointInfo iterator

It's mostly the same thing as LayerContactPointInfo::Iterator.
With some functions inexplicably marked as virtual.
This commit is contained in:
Léo Lam
2022-03-06 01:36:41 +01:00
parent 631a0ab388
commit 5dde8ced89
3 changed files with 92 additions and 4 deletions
@@ -1,4 +1,5 @@
#include "KingSystem/Physics/System/physContactPointInfo.h"
#include "KingSystem/Physics/System/physContactMgr.h"
#include "KingSystem/Physics/System/physSystem.h"
namespace ksys::phys {
@@ -25,4 +26,50 @@ void ContactPointInfo::freePoints() {
mPoints.freeBuffer();
}
ContactPointInfo::Iterator::Iterator(const Points& points, int count)
: mPoints(points.getBufferPtr()), mPointsNum(count), mPointsStart(points.getBufferPtr()) {
for (int i = 0; i != count; ++i) {
if (!mPoints[i]->flags.isOn(ContactPoint::Flag::_1))
break;
++mIdx;
}
}
ContactPointInfo::Iterator::Iterator(const Points& points, int count, IsEnd is_end)
: mIdx(count), mPoints(points.getBufferPtr()), mPointsNum(count),
mPointsStart(points.getBufferPtr()) {}
void ContactPointInfo::Iterator::getPointPosition(sead::Vector3f* out, Point point) const {
const float separating_distance = getPoint()->separating_distance;
out->e = getPoint()->position.e;
switch (point) {
case Point::BodyA: {
if (getPoint()->flags.isOn(ContactPoint::Flag::Penetrating))
return;
*out += getPoint()->separating_normal * -separating_distance;
break;
}
case Point::BodyB: {
if (!getPoint()->flags.isOn(ContactPoint::Flag::Penetrating))
return;
*out += getPoint()->separating_normal * separating_distance;
break;
}
case Point::Midpoint:
default: {
*out += getPoint()->separating_normal * separating_distance * 0.5f;
break;
}
}
}
sead::Vector3f ContactPointInfo::Iterator::getPointPosition(Point point) const {
sead::Vector3f out;
getPointPosition(&out, point);
return out;
}
} // namespace ksys::phys
@@ -81,6 +81,44 @@ public:
const RigidBody::CollisionMasks* collision_masks;
};
class Iterator {
public:
enum class IsEnd : bool { Yes = true };
enum class Point {
BodyA,
BodyB,
Midpoint,
};
Iterator(const Points& points, int count);
Iterator(const Points& points, int count, IsEnd is_end);
Iterator& operator++() {
++mIdx;
return *this;
}
virtual void getPointPosition(sead::Vector3f* out, Point point) const;
virtual sead::Vector3f getPointPosition(Point point) const;
const ContactPoint* getPoint() const { return mPoints[mIdx]; }
const ContactPoint* 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:
int mIdx = 0;
const ContactPoint* const* mPoints = nullptr;
int mPointsNum = 0;
const ContactPoint* const* mPointsStart = nullptr;
};
using ContactCallback = sead::IDelegate2R<ShouldDisableContact*, const Event&, bool>;
static ContactPointInfo* make(sead::Heap* heap, int num, const sead::SafeString& name, int a,
@@ -95,6 +133,9 @@ public:
ContactCallback* getContactCallback() const { return mContactCallback; }
void setContactCallback(ContactCallback* cb) { mContactCallback = cb; }
auto begin() const { return Iterator(mPoints, mNumContactPoints); }
auto end() const { return Iterator(mPoints, mNumContactPoints, Iterator::IsEnd::Yes); }
private:
friend class ContactMgr;