mirror of https://github.com/zeldaret/botw.git
ksys/phys: Implement ContactMgr functions used by ContactListener
This commit is contained in:
parent
88a0a9eb69
commit
ba2d81b7b8
|
|
@ -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.
|
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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{};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in New Issue