ksys/phys: Implement ContactMgr functions used by ContactListener

This commit is contained in:
Léo Lam 2022-03-05 17:22:12 +01:00
parent 88a0a9eb69
commit ba2d81b7b8
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
12 changed files with 261 additions and 93 deletions

View File

@ -83747,8 +83747,8 @@ Address,Quality,Size,Name
0x0000007100fb2474,O,000116,_ZN4ksys4phys10ContactMgr20freeContactPointPoolEv
0x0000007100fb24e8,O,000316,_ZN4ksys4phys10ContactMgr20loadContactInfoTableEPN4sead4HeapEN3agl3utl19ResParameterArchiveENS0_16ContactLayerTypeE
0x0000007100fb2624,O,000688,_ZN4ksys4phys10ContactMgr22doLoadContactInfoTableEN3agl3utl19ResParameterArchiveENS0_16ContactLayerTypeEb
0x0000007100fb28d4,O,000136,_ZN4ksys4phys10ContactMgr18allocContactPointsEPN4sead4HeapEiRKNS2_14SafeStringBaseIcEEiii
0x0000007100fb295c,O,000220,_ZN4ksys4phys10ContactMgr20allocContactPointsExEPN4sead4HeapEiiRKNS2_14SafeStringBaseIcEEiii
0x0000007100fb28d4,O,000136,_ZN4ksys4phys10ContactMgr20makeContactPointInfoEPN4sead4HeapEiRKNS2_14SafeStringBaseIcEEiii
0x0000007100fb295c,O,000220,_ZN4ksys4phys10ContactMgr25makeLayerContactPointInfoEPN4sead4HeapEiiRKNS2_14SafeStringBaseIcEEiii
0x0000007100fb2a38,O,000100,_ZN4ksys4phys10ContactMgr24registerContactPointInfoEPNS0_20ContactPointInfoBaseE
0x0000007100fb2a9c,U,000056,phys::ContactInfoTable::allocCollisionInfo
0x0000007100fb2ad4,U,000156,phys::ContactInfoTable::x_2
@ -83761,14 +83761,14 @@ Address,Quality,Size,Name
0x0000007100fb2fa4,U,000152,phys::ContactInfoTable::x_10
0x0000007100fb303c,U,000380,phys::ContactInfoTable::x_11
0x0000007100fb31b8,U,000204,phys::ContactInfoTable::x_12
0x0000007100fb3284,U,000500,phys::ContactInfoTable::x_13
0x0000007100fb3478,U,000340,phys::ContactInfoTable::x_15
0x0000007100fb3284,O,000500,_ZN4ksys4phys10ContactMgr20registerContactPointEPNS0_16ContactPointInfoERKNS0_12ContactPointERKNS0_23RigidBodyCollisionMasksEb
0x0000007100fb3478,O,000340,_ZN4ksys4phys10ContactMgr20registerContactPointEPNS0_21LayerContactPointInfoERKNS0_12ContactPointEb
0x0000007100fb35cc,U,000376,phys::ContactInfoTable::x_16
0x0000007100fb3744,U,000144,phys::ContactInfoTable::x_17
0x0000007100fb37d4,U,000128,phys::ContactInfoTable::x_18
0x0000007100fb3854,U,000228,phys::ContactInfoTable::x_19
0x0000007100fb3938,U,000244,phys::ContactInfoTable::x_20
0x0000007100fb3a2c,U,000292,phys::ContactInfoTable::x_21
0x0000007100fb3744,O,000144,_ZN4ksys4phys10ContactMgr17registerCollisionEPNS0_13CollisionInfoEPNS0_9RigidBodyES5_
0x0000007100fb37d4,O,000128,_ZN4ksys4phys10ContactMgr17registerCollisionEPNS0_25ContactLayerCollisionInfoEPNS0_9RigidBodyES5_
0x0000007100fb3854,O,000228,_ZN4ksys4phys10ContactMgr19unregisterCollisionEPNS0_13CollisionInfoEPNS0_9RigidBodyES5_
0x0000007100fb3938,O,000244,_ZN4ksys4phys10ContactMgr19unregisterCollisionEPNS0_25ContactLayerCollisionInfoEPNS0_9RigidBodyES5_
0x0000007100fb3a2c,O,000292,_ZN4ksys4phys10ContactMgr27unregisterCollisionWithBodyEPNS0_25ContactLayerCollisionInfoEPNS0_9RigidBodyE
0x0000007100fb3b50,U,000100,phys::ContactInfoTable::x_22
0x0000007100fb3bb4,U,000652,phys::ContactInfoTable::getLayerMaskForContactPoints
0x0000007100fb3e40,U,000644,phys::ContactInfoTable::getLayerMaskForCollisionInfoStuff

Can't render this file because it is too large.

View File

@ -12,12 +12,11 @@ void CollisionInfo::free(CollisionInfo* info) {
}
CollisionInfo::CollisionInfo(const sead::SafeString& name) : sead::INamable(name) {
// FIXME: figure out what this is
mList.initOffset(0x10);
mCollidingBodies.initOffset(CollidingBodies::getListNodeOffset());
}
CollisionInfo::~CollisionInfo() {
mList.clear();
mCollidingBodies.clear();
}
} // namespace ksys::phys

View File

@ -10,6 +10,16 @@
namespace ksys::phys {
class RigidBody;
struct CollidingBodies {
RigidBody* body_a;
RigidBody* body_b;
sead::ListNode list_node;
static constexpr size_t getListNodeOffset() { return offsetof(CollidingBodies, list_node); }
};
class CollisionInfoBase {
public:
CollisionInfoBase() = default;
@ -38,12 +48,14 @@ public:
explicit CollisionInfo(const sead::SafeString& name);
~CollisionInfo() override;
sead::OffsetList<CollidingBodies>& getCollidingBodies() { return mCollidingBodies; }
const sead::OffsetList<CollidingBodies>& getCollidingBodies() const { return mCollidingBodies; }
bool isLinked() const { return mListNode.isLinked(); }
static constexpr size_t getListNodeOffset() { return offsetof(CollisionInfo, mListNode); }
private:
// FIXME: type
sead::OffsetList<void*> mList;
sead::OffsetList<CollidingBodies> mCollidingBodies;
sead::ListNode mListNode;
};

View File

@ -3,8 +3,7 @@
namespace ksys::phys {
ContactLayerCollisionInfo::ContactLayerCollisionInfo(ContactLayer layer) : mLayer(layer) {
// FIXME: figure out what this is
mList.initOffset(0x10);
mCollidingBodies.initOffset(CollidingBodies::getListNodeOffset());
}
ContactLayerCollisionInfo::~ContactLayerCollisionInfo() = default;

View File

@ -14,13 +14,12 @@ public:
ContactLayer getLayer() const { return mLayer; }
auto& getList() { return mList; }
const auto& getList() const { return mList; }
sead::OffsetList<CollidingBodies>& getCollidingBodies() { return mCollidingBodies; }
const sead::OffsetList<CollidingBodies>& getCollidingBodies() const { return mCollidingBodies; }
private:
ContactLayer mLayer;
// FIXME: type
sead::OffsetList<void*> mList;
sead::OffsetList<CollidingBodies> mCollidingBodies;
};
} // namespace ksys::phys

View File

@ -255,7 +255,8 @@ int ContactListener::notifyContactPointInfo(RigidBody* body_a, RigidBody* body_b
storeToVec3(&point.position, event.m_contactPoint->getPosition());
storeToVec3(&point.separating_normal, event.m_contactPoint->getSeparatingNormal());
if (mMgr->x_13(body_b->getContactPointInfo(), point, masks_a, distance < 0)) {
if (mMgr->registerContactPoint(body_b->getContactPointInfo(), point, masks_a,
distance < 0)) {
disableContact(event);
}
@ -281,7 +282,8 @@ int ContactListener::notifyContactPointInfo(RigidBody* body_a, RigidBody* body_b
point.shape_key_b = getShapeKeyOrMinus1(event.getShapeKeys(1));
point.separating_normal *= -1;
if (mMgr->x_13(body_a->getContactPointInfo(), point, masks_b, !(distance < 0))) {
if (mMgr->registerContactPoint(body_a->getContactPointInfo(), point, masks_b,
!(distance < 0))) {
disableContact(event);
}
@ -353,7 +355,7 @@ void ContactListener::notifyLayerContactPointInfo(const TrackedContactPointLayer
point.shape_key_b = getShapeKeyOrMinus1(event.getShapeKeys(1));
point.separating_normal *= -1;
point.separating_distance = distance < 0 ? distance : 0;
mMgr->x_15(tracked_layer.info, point, !(distance < 0));
mMgr->registerContactPoint(tracked_layer.info, point, !(distance < 0));
} else {
point.body_a = body_b;
point.body_b = body_a;
@ -362,7 +364,7 @@ void ContactListener::notifyLayerContactPointInfo(const TrackedContactPointLayer
point.shape_key_a = getShapeKeyOrMinus1(event.getShapeKeys(1));
point.shape_key_b = getShapeKeyOrMinus1(event.getShapeKeys(0));
point.separating_distance = distance < 0 ? distance : 0;
mMgr->x_15(tracked_layer.info, point, distance < 0);
mMgr->registerContactPoint(tracked_layer.info, point, distance < 0);
}
}
@ -374,22 +376,22 @@ void ContactListener::handleCollisionAdded(const hkpCollisionEvent& event, Rigid
const auto layer_b = body_b->getContactLayer();
if (body_a->getCollisionInfo() && body_a->getCollisionInfo()->isLayerEnabled(layer_b))
mMgr->x_17(body_a->getCollisionInfo(), body_a, body_b);
mMgr->registerCollision(body_a->getCollisionInfo(), body_a, body_b);
if (body_b->getCollisionInfo() && body_b->getCollisionInfo()->isLayerEnabled(layer_a))
mMgr->x_17(body_b->getCollisionInfo(), body_b, body_a);
mMgr->registerCollision(body_b->getCollisionInfo(), body_b, body_a);
const auto i = int(layer_a - mLayerBase);
const auto j = int(layer_b - mLayerBase);
if (areContactsTrackedForLayerPair(i, j)) {
auto* info = getContactLayerCollisionInfo(i, j);
auto* layer_col_info = getContactLayerCollisionInfo(i, j);
if (body_a->isFlag8Set() && body_b->isFlag8Set()) {
const auto layer_a_ = int(layer_a);
const auto tracked_layer = info->getLayer();
const auto tracked_layer = layer_col_info->getLayer();
const bool body_a_first = layer_a_ == tracked_layer;
auto* body1 = body_a_first ? body_a : body_b;
auto* body2 = body_a_first ? body_b : body_a;
mMgr->x_18(info, body1, body2);
mMgr->registerCollision(layer_col_info, body1, body2);
}
}
}
@ -402,21 +404,21 @@ void ContactListener::handleCollisionRemoved(const hkpCollisionEvent& event, Rig
const auto layer_b = body_b->getContactLayer();
if (auto* info = body_a->getCollisionInfo())
mMgr->x_19(info, body_a, body_b);
mMgr->unregisterCollision(info, body_a, body_b);
if (auto* info = body_b->getCollisionInfo())
mMgr->x_19(info, body_b, body_a);
mMgr->unregisterCollision(info, body_b, body_a);
const auto i = int(layer_a - mLayerBase);
const auto j = int(layer_b - mLayerBase);
auto* info = getContactLayerCollisionInfo(i, j);
if (!info->getList().isEmpty()) {
if (!info->getCollidingBodies().isEmpty()) {
const auto layer_a_ = int(layer_a);
const auto tracked_layer = info->getLayer();
const bool body_a_first = layer_a_ == tracked_layer;
auto* body1 = body_a_first ? body_a : body_b;
auto* body2 = body_a_first ? body_b : body_a;
mMgr->x_20(info, body1, body2);
mMgr->unregisterCollision(info, body1, body2);
}
}
@ -494,7 +496,7 @@ void ContactListener::registerRigidBody(RigidBody* body) {
auto& column = mCollisionInfoPerLayerPair[int(rlayer)];
for (u32 i = 0; i < mLayerCount; ++i) {
ContactLayerCollisionInfo* info = column[int(i)];
mMgr->x_21(info, body);
mMgr->unregisterCollisionWithBody(info, body);
}
}

View File

@ -1,19 +1,22 @@
#include "KingSystem/Physics/System/physContactMgr.h"
#include <prim/seadScopedLock.h>
#include "KingSystem/Physics/System/physCollisionInfo.h"
#include "KingSystem/Physics/System/physContactLayerCollisionInfo.h"
#include "KingSystem/Physics/System/physContactPointInfo.h"
#include "KingSystem/Physics/System/physEntityGroupFilter.h"
#include "KingSystem/Physics/System/physGroupFilter.h"
#include "KingSystem/Physics/System/physLayerContactPointInfo.h"
#include "KingSystem/Physics/System/physSystem.h"
#include "KingSystem/Utils/Debug.h"
namespace ksys::phys {
ContactMgr::ContactMgr() {
mRigidContactPoints.initOffset(ContactPointInfo::getListNodeOffset());
mContactPointInfoInstances.initOffset(ContactPointInfo::getListNodeOffset());
// FIXME: figure out what these offsets are
mList2.initOffset(0x78);
mList3.initOffset(0x40);
mList0.initOffset(0x10);
mCollidingBodiesFreeList.initOffset(CollidingBodies::getListNodeOffset());
mList4.initOffset(0x48);
mList5.initOffset(0x48);
}
@ -76,42 +79,172 @@ void ContactMgr::doLoadContactInfoTable(agl::utl::ResParameterArchive archive,
table.param_io.applyResParameterArchive(archive);
}
ContactPointInfo* ContactMgr::allocContactPoints(sead::Heap* heap, int num,
const sead::SafeString& name, int a, int b,
int c) {
auto* points = new (heap) ContactPointInfo(name, a, b, c);
points->allocPoints(heap, num);
return points;
ContactPointInfo* ContactMgr::makeContactPointInfo(sead::Heap* heap, int num,
const sead::SafeString& name, int a, int b,
int c) {
auto* info = new (heap) ContactPointInfo(name, a, b, c);
info->allocPoints(heap, num);
return info;
}
LayerContactPointInfo* ContactMgr::allocContactPointsEx(sead::Heap* heap, int num, int num2,
const sead::SafeString& name, int a, int b,
int c) {
auto* points = new (heap) LayerContactPointInfo(name, a, b, c);
points->allocPoints(heap, num, num2);
registerContactPointInfo(points);
return points;
LayerContactPointInfo* ContactMgr::makeLayerContactPointInfo(sead::Heap* heap, int num, int num2,
const sead::SafeString& name, int a,
int b, int c) {
auto* info = new (heap) LayerContactPointInfo(name, a, b, c);
info->allocPoints(heap, num, num2);
registerContactPointInfo(info);
return info;
}
void ContactMgr::registerContactPointInfo(ContactPointInfoBase* info) {
auto lock = sead::makeScopedLock(mMutex1);
auto lock = sead::makeScopedLock(mContactPointInfoMutex);
if (!info->isLinked())
mRigidContactPoints.pushBack(info);
mContactPointInfoInstances.pushBack(info);
}
void ContactMgr::unregisterContactPointInfo(ContactPointInfoBase* info) {
auto lock = sead::makeScopedLock(mContactPointInfoMutex);
if (info->isLinked())
mContactPointInfoInstances.erase(info);
}
void ContactMgr::freeContactPointInfo(ContactPointInfoBase* info) {
if (!info)
return;
{
auto lock = sead::makeScopedLock(mMutex1);
if (info->isLinked())
mRigidContactPoints.erase(info);
}
unregisterContactPointInfo(info);
info->freePoints();
delete info;
}
int ContactMgr::allocateContactPoint() {
if (mContactPointIndex >= mContactPointPool.size() - 1) {
util::PrintDebugFmt("contact point pool exhausted (current index: %d)",
mContactPointIndex.load());
return -1;
}
return mContactPointIndex.increment();
}
bool ContactMgr::registerContactPoint(ContactPointInfo* info, const ContactPoint& point,
const RigidBodyCollisionMasks& colliding_body_masks,
bool penetrating) {
if (!info->isLinked())
return false;
auto disable_contact = ContactPointInfo::ShouldDisableContact::No;
if (auto* callback = info->getContactCallback()) {
ContactPointInfo::Event event;
event.body = point.body_b;
event.position = &point.position;
event.separating_normal = &point.separating_normal;
event.collision_masks = &colliding_body_masks;
if (!callback->invoke(&disable_contact, event))
return disable_contact == ContactPointInfo::ShouldDisableContact::Yes;
}
int pool_index = allocateContactPoint();
if (pool_index != -1) {
auto& point_in_pool = mContactPointPool[pool_index];
point_in_pool = point;
if (info->mContactPointIndex < info->mPoints.size() || info->_2c >= 2) {
int index = info->mContactPointIndex.increment();
info->mPoints[index] = &point_in_pool;
info->mPoints[index]->flags.makeAllZero();
info->mPoints[index]->flags.change(ContactPoint::Flag::Penetrating, penetrating);
}
}
return disable_contact == ContactPointInfo::ShouldDisableContact::Yes;
}
void ContactMgr::registerContactPoint(LayerContactPointInfo* info, const ContactPoint& point,
bool penetrating) {
int pool_index = allocateContactPoint();
if (pool_index == -1)
return;
auto& point_in_pool = mContactPointPool[pool_index];
point_in_pool = point;
if (info->mContactPointIndex < info->mPoints.size()) {
int index = info->mContactPointIndex.increment();
info->mPoints[index] = &point_in_pool;
info->mPoints[index]->flags.makeAllZero();
info->mPoints[index]->flags.change(ContactPoint::Flag::Penetrating, penetrating);
}
}
void ContactMgr::registerCollision(CollisionInfo* info, RigidBody* body_a, RigidBody* body_b) {
auto lock = sead::makeScopedLock(mCollidingBodiesMutex);
if (!info->isLinked())
return;
auto* entry = mCollidingBodiesFreeList.popFront();
if (entry) {
entry->body_a = body_a;
entry->body_b = body_b;
info->getCollidingBodies().pushBack(entry);
}
}
void ContactMgr::registerCollision(ContactLayerCollisionInfo* info, RigidBody* body_a,
RigidBody* body_b) {
auto lock = sead::makeScopedLock(mCollidingBodiesMutex);
auto* entry = mCollidingBodiesFreeList.popFront();
if (entry) {
entry->body_a = body_a;
entry->body_b = body_b;
info->getCollidingBodies().pushBack(entry);
}
}
void ContactMgr::unregisterCollision(CollisionInfo* info, RigidBody* body_a, RigidBody* body_b) {
auto lock = sead::makeScopedLock(mCollidingBodiesMutex);
auto info_lock = sead::makeScopedLock(*info);
for (auto& entry : info->getCollidingBodies()) {
if (entry.body_a == body_a && entry.body_b == body_b) {
info->getCollidingBodies().erase(&entry);
mCollidingBodiesFreeList.pushBack(&entry);
break;
}
}
}
void ContactMgr::unregisterCollision(ContactLayerCollisionInfo* info, RigidBody* body_a,
RigidBody* body_b) {
auto lock = sead::makeScopedLock(mCollidingBodiesMutex);
auto info_lock = sead::makeScopedLock(*info);
for (auto& entry : info->getCollidingBodies()) {
if (entry.body_a == body_a && entry.body_b == body_b) {
info->getCollidingBodies().erase(&entry);
freeCollidingBodiesEntry(&entry);
break;
}
}
}
void ContactMgr::unregisterCollisionWithBody(ContactLayerCollisionInfo* info, RigidBody* body) {
auto lock = sead::makeScopedLock(mCollidingBodiesMutex);
auto info_lock = sead::makeScopedLock(*info);
auto body_layer = body->getContactLayer();
for (auto& entry : info->getCollidingBodies().robustRange()) {
auto* body_a = entry.body_a;
auto* body_b = int(body_a->getContactLayer()) == body_layer ? body_a : entry.body_b;
if (body_b == body) {
info->getCollidingBodies().erase(&entry);
freeCollidingBodiesEntry(&entry);
}
}
}
bool ContactMgr::getSensorLayerMask(SensorCollisionMask* mask,
const sead::SafeString& receiver_type) const {
const auto& receivers = mContactInfoTables[int(ContactLayerType::Sensor)].receivers;

View File

@ -10,6 +10,7 @@
#include <container/seadSafeArray.h>
#include <hostio/seadHostIONode.h>
#include <prim/seadSafeString.h>
#include <prim/seadScopedLock.h>
#include <thread/seadAtomic.h>
#include <thread/seadMutex.h>
#include "KingSystem/Physics/physDefines.h"
@ -24,6 +25,7 @@ namespace ksys::phys {
enum class IsIndoorStage;
struct CollidingBodies;
class CollisionInfo;
class ContactLayerCollisionInfo;
class ContactPointInfoBase;
@ -53,7 +55,7 @@ struct ContactInfoTable {
struct ContactPoint {
enum class Flag {
_1 = 1 << 0,
_2 = 1 << 1,
Penetrating = 1 << 1,
};
RigidBody* body_a;
@ -84,51 +86,61 @@ public:
bool getSensorLayerMask(SensorCollisionMask* mask, const sead::SafeString& receiver_type) const;
ContactPointInfo* allocContactPoints(sead::Heap* heap, int num, const sead::SafeString& name,
int a, int b, int c);
LayerContactPointInfo* allocContactPointsEx(sead::Heap* heap, int num, int num2,
const sead::SafeString& name, int a, int b, int c);
ContactPointInfo* makeContactPointInfo(sead::Heap* heap, int num, const sead::SafeString& name,
int a, int b, int c);
LayerContactPointInfo* makeLayerContactPointInfo(sead::Heap* heap, int num, int num2,
const sead::SafeString& name, int a, int b,
int c);
void registerContactPointInfo(ContactPointInfoBase* info);
void unregisterContactPointInfo(ContactPointInfoBase* info);
void freeContactPointInfo(ContactPointInfoBase* info);
// 0x0000007100fb3284
/// @param colliding_body_masks The collision masks of the colliding rigid bodies.
/// @returns whether contact should be disabled.
bool x_13(ContactPointInfo* info, const ContactPoint& point,
const RigidBodyCollisionMasks& colliding_body_masks, bool penetrating);
bool registerContactPoint(ContactPointInfo* info, const ContactPoint& point,
const RigidBodyCollisionMasks& colliding_body_masks,
bool penetrating);
// 0x0000007100fb3478
void x_15(LayerContactPointInfo* info, const ContactPoint& point, bool penetrating);
void registerContactPoint(LayerContactPointInfo* info, const ContactPoint& point,
bool penetrating);
// 0x0000007100fb3744
void x_17(CollisionInfo* info, RigidBody* body_a, RigidBody* body_b);
// 0x0000007100fb37d4
void x_18(ContactLayerCollisionInfo* info, RigidBody* body_a, RigidBody* body_b);
// 0x0000007100fb3854
void x_19(CollisionInfo* info, RigidBody* body_a, RigidBody* body_b);
// 0x0000007100fb3938
void x_20(ContactLayerCollisionInfo* info, RigidBody* body_a, RigidBody* body_b);
// 0x0000007100fb3a2c
void x_21(ContactLayerCollisionInfo* info, RigidBody* body);
void registerCollision(CollisionInfo* info, RigidBody* body_a, RigidBody* body_b);
void registerCollision(ContactLayerCollisionInfo* info, RigidBody* body_a, RigidBody* body_b);
void unregisterCollision(CollisionInfo* info, RigidBody* body_a, RigidBody* body_b);
void unregisterCollision(ContactLayerCollisionInfo* info, RigidBody* body_a, RigidBody* body_b);
/// Unregister all collision pairs involving the specified rigid body.
void unregisterCollisionWithBody(ContactLayerCollisionInfo* info, RigidBody* body);
private:
void doLoadContactInfoTable(agl::utl::ResParameterArchive archive, ContactLayerType type,
bool skip_params);
// Used to optimise ContactPoint allocations.
/// @return an index into mContactPointPool or -1 if the pool is exhausted.
int allocateContactPoint();
void freeCollidingBodiesEntry(CollidingBodies* entry) {
auto lock = sead::makeScopedLock(mCollidingBodiesMutex);
mCollidingBodiesFreeList.pushBack(entry);
}
/// Used to optimise ContactPoint allocations.
sead::Buffer<ContactPoint> mContactPointPool;
sead::OffsetList<void*> mList0;
sead::OffsetList<CollidingBodies> mCollidingBodiesFreeList;
int mList0Size = 0;
sead::Atomic<int> _34 = 0;
sead::OffsetList<ContactPointInfoBase> mRigidContactPoints;
/// The index of the next free ContactPoint in the pool.
sead::Atomic<int> mContactPointIndex = 0;
sead::OffsetList<ContactPointInfoBase> mContactPointInfoInstances;
sead::OffsetList<void*> mList2;
sead::OffsetList<void*> mList3;
sead::OffsetList<void*> mList4;
sead::OffsetList<void*> mList5;
sead::Mutex mMutex1;
// TODO: rename these members
sead::Mutex mContactPointInfoMutex;
sead::Mutex mMutex2;
sead::Mutex mMutex3;
sead::Mutex mMutex4;
sead::Mutex mCollidingBodiesMutex;
sead::Mutex mMutex5;
sead::SafeArray<ContactInfoTable, 2> mContactInfoTables{};
};

View File

@ -16,8 +16,12 @@
namespace ksys::phys {
struct ContactPoint;
class ContactPointInfoBase : public sead::INamable {
public:
using Points = sead::Buffer<ContactPoint*>;
// FIXME: parameter names
ContactPointInfoBase(const sead::SafeString& name, int a, int b, int c)
: sead::INamable(name), _2c(a), _30(b), _34(c) {}
@ -41,13 +45,19 @@ public:
return mLayerMask2[int(type)].isOnBit(int(getContactLayerBaseRelativeValue(layer)));
}
public:
// For internal use by the physics system.
bool isLinked() const { return mListNode.isLinked(); }
static constexpr size_t getListNodeOffset() {
return offsetof(ContactPointInfoBase, mListNode);
}
protected:
sead::Atomic<int> _18;
friend class ContactMgr;
sead::Atomic<int> mContactPointIndex;
sead::SafeArray<sead::BitFlag32, 2> mSubscribedLayers;
// TODO: rename
sead::SafeArray<sead::BitFlag32, 2> mLayerMask2;
@ -86,7 +96,9 @@ public:
void setContactCallback(ContactCallback* cb) { mContactCallback = cb; }
private:
sead::Buffer<void*> mPoints{};
friend class ContactMgr;
Points mPoints;
ContactCallback* mContactCallback{};
};
KSYS_CHECK_SIZE_NX150(ContactPointInfo, 0x60);

View File

@ -67,14 +67,14 @@ void LayerContactPointInfo::Iterator::getData(sead::Vector3f* out,
switch (mode) {
case Mode::_0: {
if (getPoint()->flags.isOn(ContactPoint::Flag::_2))
if (getPoint()->flags.isOn(ContactPoint::Flag::Penetrating))
return;
*out += getPoint()->separating_normal * -separating_distance;
break;
}
case Mode::_1: {
if (!getPoint()->flags.isOn(ContactPoint::Flag::_2))
if (!getPoint()->flags.isOn(ContactPoint::Flag::Penetrating))
return;
*out += getPoint()->separating_normal * separating_distance;
break;

View File

@ -16,8 +16,6 @@ class RigidBody;
class LayerContactPointInfo : public ContactPointInfoBase {
public:
using Points = sead::Buffer<ContactPoint*>;
struct LayerEntry {
ContactLayer layer1;
ContactLayer layer2;
@ -115,14 +113,16 @@ public:
ContactCallback* getCallback() const { return mCallback; }
void setCallback(ContactCallback* callback) { mCallback = callback; }
auto begin() const { return Iterator(mPoints, _18); }
auto end() const { return IteratorEnd(mPoints, _18); }
auto begin() const { return Iterator(mPoints, mContactPointIndex); }
auto end() const { return IteratorEnd(mPoints, mContactPointIndex); }
sead::ObjArray<LayerEntry>& getLayerEntries() { return mLayerEntries; }
const sead::ObjArray<LayerEntry>& getLayerEntries() const { return mLayerEntries; }
private:
Points mPoints{};
friend class ContactMgr;
Points mPoints;
sead::ObjArray<LayerEntry> mLayerEntries;
ContactLayerType mLayerType = ContactLayerType::Invalid;
ContactCallback* mCallback = nullptr;

View File

@ -50,7 +50,7 @@ void System::initSystemData(sead::Heap* heap) {
ContactPointInfo* System::allocContactPointInfo(sead::Heap* heap, int num,
const sead::SafeString& name, int a, int b,
int c) const {
return mContactMgr->allocContactPoints(heap, num, name, a, b, c);
return mContactMgr->makeContactPointInfo(heap, num, name, a, b, c);
}
void System::freeContactPointInfo(ContactPointInfo* info) const {
@ -60,7 +60,7 @@ void System::freeContactPointInfo(ContactPointInfo* info) const {
LayerContactPointInfo* System::allocLayerContactPointInfo(sead::Heap* heap, int num, int num2,
const sead::SafeString& name, int a,
int b, int c) const {
return mContactMgr->allocContactPointsEx(heap, num, num2, name, a, b, c);
return mContactMgr->makeLayerContactPointInfo(heap, num, num2, name, a, b, c);
}
void System::registerContactPointInfo(ContactPointInfo* info) const {