mirror of https://github.com/zeldaret/botw.git
ksys/phys: Add ContactLayerCollisionInfoGroup
This commit is contained in:
parent
335a5a201a
commit
a9d5f88968
|
@ -84282,18 +84282,18 @@ Address,Quality,Size,Name
|
|||
0x0000007100fcd7d0,O,000104,_ZN4ksys4phys25ContactLayerCollisionInfoC1ENS0_12ContactLayerE
|
||||
0x0000007100fcd838,O,000020,_ZN4ksys4phys25ContactLayerCollisionInfoD1Ev
|
||||
0x0000007100fcd84c,O,000052,_ZN4ksys4phys25ContactLayerCollisionInfoD0Ev
|
||||
0x0000007100fcd880,U,000064,
|
||||
0x0000007100fcd8c0,U,000004,nullsub_4256
|
||||
0x0000007100fcd8c4,U,000004,j__ZdlPv_1012
|
||||
0x0000007100fcd8c8,U,000044,
|
||||
0x0000007100fcd8f4,U,000024,
|
||||
0x0000007100fcd90c,U,000236,
|
||||
0x0000007100fcd9f8,U,000056,
|
||||
0x0000007100fcda30,U,000144,
|
||||
0x0000007100fcdac0,U,000120,
|
||||
0x0000007100fcdb38,U,000224,
|
||||
0x0000007100fcdc18,U,000020,
|
||||
0x0000007100fcdc2c,U,000204,
|
||||
0x0000007100fcd880,O,000064,_ZN4ksys4phys30ContactLayerCollisionInfoGroupC1ENS0_12ContactLayerERKN4sead14SafeStringBaseIcEE
|
||||
0x0000007100fcd8c0,O,000004,_ZN4ksys4phys30ContactLayerCollisionInfoGroupD1Ev
|
||||
0x0000007100fcd8c4,O,000004,_ZN4ksys4phys30ContactLayerCollisionInfoGroupD0Ev
|
||||
0x0000007100fcd8c8,O,000044,_ZN4ksys4phys30ContactLayerCollisionInfoGroup4makeEPN4sead4HeapENS0_12ContactLayerEiRKNS2_14SafeStringBaseIcEE
|
||||
0x0000007100fcd8f4,O,000024,_ZN4ksys4phys30ContactLayerCollisionInfoGroup4freeEPS1_
|
||||
0x0000007100fcd90c,O,000236,_ZN4ksys4phys30ContactLayerCollisionInfoGroup4initEPN4sead4HeapEi
|
||||
0x0000007100fcd9f8,O,000056,_ZN4ksys4phys30ContactLayerCollisionInfoGroup8finalizeEv
|
||||
0x0000007100fcda30,m,000144,_ZN4ksys4phys30ContactLayerCollisionInfoGroup8addLayerENS0_12ContactLayerE
|
||||
0x0000007100fcdac0,O,000120,_ZN4ksys4phys30ContactLayerCollisionInfoGroup22ensureLayersAreTrackedEv
|
||||
0x0000007100fcdb38,O,000224,_ZN4ksys4phys30ContactLayerCollisionInfoGroup23CollidingBodiesIteratorC1EPKS1_iNS2_7IsStartE
|
||||
0x0000007100fcdc18,O,000020,_ZN4ksys4phys30ContactLayerCollisionInfoGroup23CollidingBodiesIteratorD1Ev
|
||||
0x0000007100fcdc2c,O,000204,_ZN4ksys4phys30ContactLayerCollisionInfoGroup23CollidingBodiesIteratorppEv
|
||||
0x0000007100fcdcf8,O,000104,_ZN4ksys4phys15ContactListenerC1EPNS0_10ContactMgrENS0_16ContactLayerTypeEi
|
||||
0x0000007100fcdd60,O,000024,_ZN4ksys4phys15ContactListenerD1Ev
|
||||
0x0000007100fcdd78,O,000060,_ZN4ksys4phys15ContactListenerD0Ev
|
||||
|
|
Can't render this file because it is too large.
|
|
@ -115,6 +115,8 @@ target_sources(uking PRIVATE
|
|||
System/physContactInfoParam.h
|
||||
System/physContactLayerCollisionInfo.cpp
|
||||
System/physContactLayerCollisionInfo.h
|
||||
System/physContactLayerCollisionInfoGroup.cpp
|
||||
System/physContactLayerCollisionInfoGroup.h
|
||||
System/physContactListener.cpp
|
||||
System/physContactListener.h
|
||||
System/physContactMgr.cpp
|
||||
|
|
|
@ -477,7 +477,7 @@ void RigidBody::x_10() {
|
|||
void RigidBody::setCollisionInfo(CollisionInfo* info) {
|
||||
if (mCollisionInfo != info) {
|
||||
if (mCollisionInfo && isFlag8Set())
|
||||
System::instance()->registerRigidBodyForContactSystem(this);
|
||||
System::instance()->removeRigidBodyFromContactSystem(this);
|
||||
mCollisionInfo = info;
|
||||
}
|
||||
|
||||
|
@ -717,7 +717,7 @@ void RigidBody::setCollisionFilterInfo(u32 info) {
|
|||
if (getCollisionFilterInfo() != info) {
|
||||
if (isFlag8Set()) {
|
||||
if (int(current_layer) != getContactLayer(EntityCollisionMask(info)))
|
||||
System::instance()->registerRigidBodyForContactSystem(this);
|
||||
System::instance()->removeRigidBodyFromContactSystem(this);
|
||||
}
|
||||
|
||||
mHkBody->setCollisionFilterInfo(info);
|
||||
|
|
|
@ -13,8 +13,7 @@ namespace ksys::phys {
|
|||
class RigidBody;
|
||||
|
||||
struct CollidingBodies {
|
||||
RigidBody* body_a;
|
||||
RigidBody* body_b;
|
||||
RigidBody* bodies[2];
|
||||
sead::ListNode list_node;
|
||||
|
||||
static constexpr size_t getListNodeOffset() { return offsetof(CollidingBodies, list_node); }
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace ksys::phys {
|
||||
|
||||
/// Tracks contact points for a contact layer.
|
||||
/// Tracks colliding bodies that belong to a specific contact layer.
|
||||
class ContactLayerCollisionInfo : public CollisionInfoBase {
|
||||
public:
|
||||
explicit ContactLayerCollisionInfo(ContactLayer layer);
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
#include "KingSystem/Physics/System/physContactLayerCollisionInfoGroup.h"
|
||||
#include "KingSystem/Physics/System/physContactLayerCollisionInfo.h"
|
||||
#include "KingSystem/Physics/System/physSystem.h"
|
||||
|
||||
namespace ksys::phys {
|
||||
|
||||
ContactLayerCollisionInfoGroup::ContactLayerCollisionInfoGroup(ContactLayer layer,
|
||||
const sead::SafeString& name)
|
||||
: sead::INamable(name), mLayer(layer) {}
|
||||
|
||||
ContactLayerCollisionInfoGroup::~ContactLayerCollisionInfoGroup() = default;
|
||||
|
||||
ContactLayerCollisionInfoGroup* ContactLayerCollisionInfoGroup::make(sead::Heap* heap,
|
||||
ContactLayer layer,
|
||||
int capacity,
|
||||
const sead::SafeString& name) {
|
||||
return System::instance()->makeContactLayerCollisionInfoGroup(heap, layer, capacity, name);
|
||||
}
|
||||
|
||||
void ContactLayerCollisionInfoGroup::free(ContactLayerCollisionInfoGroup* group) {
|
||||
System::instance()->freeContactLayerCollisionInfoGroup(group);
|
||||
}
|
||||
|
||||
void ContactLayerCollisionInfoGroup::init(sead::Heap* heap, int capacity) {
|
||||
mCollisionInfoInstances.allocBuffer(capacity, heap);
|
||||
mLayers.allocBufferAssert(capacity, heap);
|
||||
}
|
||||
|
||||
void ContactLayerCollisionInfoGroup::finalize() {
|
||||
mCollisionInfoInstances.freeBuffer();
|
||||
mLayers.freeBuffer();
|
||||
}
|
||||
|
||||
// NON_MATCHING: trivial reordering
|
||||
void ContactLayerCollisionInfoGroup::addLayer(ContactLayer layer) {
|
||||
auto& info = mLayers[mCollisionInfoInstances.size()];
|
||||
info.layer = layer;
|
||||
info.layer_gt = mLayer > layer;
|
||||
info.layer_le = !info.layer_gt;
|
||||
|
||||
auto* collision_info = System::instance()->trackLayerPair(mLayer, layer);
|
||||
mCollisionInfoInstances.pushBack(collision_info);
|
||||
}
|
||||
|
||||
void ContactLayerCollisionInfoGroup::ensureLayersAreTracked() {
|
||||
for (int i = 0; i < mCollisionInfoInstances.size(); ++i) {
|
||||
System::instance()->trackLayerPair(mLayer, mLayers[i].layer);
|
||||
}
|
||||
}
|
||||
|
||||
ContactLayerCollisionInfoGroup::CollidingBodiesIterator::CollidingBodiesIterator(
|
||||
const ContactLayerCollisionInfoGroup* group, int index, IsStart start)
|
||||
: mGroup(group), mInfoIndex(index) {
|
||||
if (!bool(start))
|
||||
return;
|
||||
|
||||
initIterator(group);
|
||||
|
||||
// If there is no colliding body, turn this iterator into an end iterator.
|
||||
if (!mCollidingBodiesEntry) {
|
||||
mInfo = nullptr;
|
||||
mInfoIndex = group->mCollisionInfoInstances.size();
|
||||
}
|
||||
}
|
||||
|
||||
ContactLayerCollisionInfoGroup::CollidingBodiesIterator::~CollidingBodiesIterator() {
|
||||
if (mInfo)
|
||||
mInfo->unlock();
|
||||
}
|
||||
|
||||
void ContactLayerCollisionInfoGroup::CollidingBodiesIterator::initIterator(
|
||||
const ContactLayerCollisionInfoGroup* group) {
|
||||
for (mInfoIndex = 0; mInfoIndex < group->mCollisionInfoInstances.size(); ++mInfoIndex) {
|
||||
mInfo = group->mCollisionInfoInstances[mInfoIndex];
|
||||
if (!mInfo)
|
||||
continue;
|
||||
|
||||
mInfo->lock();
|
||||
mCollidingBodiesEntry = mInfo->getCollidingBodies().front();
|
||||
if (mCollidingBodiesEntry) {
|
||||
// Keep the ContactLayerCollisionInfo locked.
|
||||
break;
|
||||
}
|
||||
// Otherwise, unlock the current ContactLayerCollisionInfo and try the next one.
|
||||
mInfo->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
ContactLayerCollisionInfoGroup::CollidingBodiesIterator&
|
||||
ContactLayerCollisionInfoGroup::CollidingBodiesIterator::operator++() {
|
||||
auto* group = mGroup;
|
||||
|
||||
mCollidingBodiesEntry = mInfo->getCollidingBodies().next(mCollidingBodiesEntry);
|
||||
if (mCollidingBodiesEntry)
|
||||
return *this;
|
||||
|
||||
// If we reached the last entry in the current ContactLayerCollisionInfo,
|
||||
// move on to the next one.
|
||||
|
||||
++mInfoIndex;
|
||||
for (; mInfoIndex < group->mCollisionInfoInstances.size(); ++mInfoIndex) {
|
||||
auto* next_info = group->mCollisionInfoInstances[mInfoIndex];
|
||||
if (!next_info)
|
||||
continue;
|
||||
|
||||
mInfo->unlock();
|
||||
mInfo = next_info;
|
||||
mInfo->lock();
|
||||
mCollidingBodiesEntry = mInfo->getCollidingBodies().front();
|
||||
if (mCollidingBodiesEntry)
|
||||
break;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace ksys::phys
|
|
@ -0,0 +1,114 @@
|
|||
#pragma once
|
||||
|
||||
#include <container/seadBuffer.h>
|
||||
#include <container/seadListImpl.h>
|
||||
#include <container/seadPtrArray.h>
|
||||
#include <prim/seadNamable.h>
|
||||
#include "KingSystem/Physics/physDefines.h"
|
||||
|
||||
namespace ksys::phys {
|
||||
|
||||
struct CollidingBodies;
|
||||
class ContactLayerCollisionInfo;
|
||||
|
||||
/// Container for ContactLayerCollisionInfo instances that pertain to a contact layer
|
||||
/// paired with other layers.
|
||||
class ContactLayerCollisionInfoGroup : public sead::INamable {
|
||||
public:
|
||||
class CollidingBodiesIterator;
|
||||
struct CollidingBodiesRange;
|
||||
|
||||
struct LayerInfo {
|
||||
ContactLayer layer;
|
||||
/// Is `layer` greater than the layer of the group?
|
||||
bool layer_gt;
|
||||
/// Is `layer` lower or equal to the layer of the group?
|
||||
bool layer_le;
|
||||
};
|
||||
|
||||
static ContactLayerCollisionInfoGroup* make(sead::Heap* heap, ContactLayer layer, int capacity,
|
||||
const sead::SafeString& name);
|
||||
static void free(ContactLayerCollisionInfoGroup* group);
|
||||
|
||||
ContactLayerCollisionInfoGroup(ContactLayer layer, const sead::SafeString& name);
|
||||
virtual ~ContactLayerCollisionInfoGroup();
|
||||
|
||||
/// @param capacity The maximum number of layers that can be added to this group.
|
||||
void init(sead::Heap* heap, int capacity);
|
||||
void finalize();
|
||||
|
||||
/// Add (mLayer, layer) to the list of layer pairs in this group.
|
||||
void addLayer(ContactLayer layer);
|
||||
|
||||
/// Call this to ensure that all layer pairs in this group are being tracked by
|
||||
/// the relevant contact listener. This may be necessary if the listener has been reset.
|
||||
void ensureLayersAreTracked();
|
||||
|
||||
CollidingBodiesIterator collidingBodiesBegin() const;
|
||||
CollidingBodiesIterator collidingBodiesEnd() const;
|
||||
CollidingBodiesRange getCollidingBodies() const;
|
||||
|
||||
static constexpr size_t getListNodeOffset() {
|
||||
return offsetof(ContactLayerCollisionInfoGroup, mListNode);
|
||||
}
|
||||
|
||||
private:
|
||||
ContactLayer mLayer;
|
||||
sead::PtrArray<ContactLayerCollisionInfo> mCollisionInfoInstances;
|
||||
sead::Buffer<LayerInfo> mLayers;
|
||||
sead::ListNode mListNode;
|
||||
};
|
||||
|
||||
class ContactLayerCollisionInfoGroup::CollidingBodiesIterator {
|
||||
public:
|
||||
enum class IsStart : bool { Yes = true, No = false };
|
||||
|
||||
CollidingBodiesIterator(const ContactLayerCollisionInfoGroup* group, int index, IsStart start);
|
||||
~CollidingBodiesIterator();
|
||||
|
||||
const LayerInfo& getLayerInfo() const { return mGroup->mLayers[mInfoIndex]; }
|
||||
|
||||
const CollidingBodies& operator*() const { return *mCollidingBodiesEntry; }
|
||||
const CollidingBodies* operator->() const { return mCollidingBodiesEntry; }
|
||||
CollidingBodiesIterator& operator++();
|
||||
|
||||
bool operator==(const CollidingBodiesIterator& other) const {
|
||||
return mInfoIndex == other.mInfoIndex &&
|
||||
mCollidingBodiesEntry == other.mCollidingBodiesEntry;
|
||||
}
|
||||
|
||||
bool operator!=(const CollidingBodiesIterator& other) const { return !operator==(other); }
|
||||
|
||||
private:
|
||||
void initIterator(const ContactLayerCollisionInfoGroup* group);
|
||||
|
||||
const ContactLayerCollisionInfoGroup* mGroup{};
|
||||
ContactLayerCollisionInfo* mInfo{};
|
||||
/// The current CollidingBodies pair within the current ContactLayerCollisionInfo (mInfo).
|
||||
const CollidingBodies* mCollidingBodiesEntry{};
|
||||
int mInfoIndex{};
|
||||
};
|
||||
|
||||
struct ContactLayerCollisionInfoGroup::CollidingBodiesRange {
|
||||
auto begin() const { return group->collidingBodiesBegin(); }
|
||||
auto end() const { return group->collidingBodiesEnd(); }
|
||||
|
||||
const ContactLayerCollisionInfoGroup* group;
|
||||
};
|
||||
|
||||
inline ContactLayerCollisionInfoGroup::CollidingBodiesIterator
|
||||
ContactLayerCollisionInfoGroup::collidingBodiesBegin() const {
|
||||
return {this, 0, CollidingBodiesIterator::IsStart::Yes};
|
||||
}
|
||||
|
||||
inline ContactLayerCollisionInfoGroup::CollidingBodiesIterator
|
||||
ContactLayerCollisionInfoGroup::collidingBodiesEnd() const {
|
||||
return {this, mCollisionInfoInstances.size(), CollidingBodiesIterator::IsStart::No};
|
||||
}
|
||||
|
||||
inline ContactLayerCollisionInfoGroup::CollidingBodiesRange
|
||||
ContactLayerCollisionInfoGroup::getCollidingBodies() const {
|
||||
return {this};
|
||||
}
|
||||
|
||||
} // namespace ksys::phys
|
|
@ -214,7 +214,7 @@ void ContactMgr::removeCollisionEntriesWithBody(RigidBody* body) {
|
|||
continue;
|
||||
|
||||
for (auto& colliding_pair : collision_info.getCollidingBodies().robustRange()) {
|
||||
if (colliding_pair.body_b != body)
|
||||
if (colliding_pair.bodies[1] != body)
|
||||
continue;
|
||||
|
||||
collision_info.getCollidingBodies().erase(&colliding_pair);
|
||||
|
@ -363,8 +363,8 @@ void ContactMgr::registerCollision(CollisionInfo* info, RigidBody* body_a, Rigid
|
|||
|
||||
auto* entry = mCollidingBodiesFreeList.popFront();
|
||||
if (entry) {
|
||||
entry->body_a = body_a;
|
||||
entry->body_b = body_b;
|
||||
entry->bodies[0] = body_a;
|
||||
entry->bodies[1] = body_b;
|
||||
info->getCollidingBodies().pushBack(entry);
|
||||
}
|
||||
}
|
||||
|
@ -375,8 +375,8 @@ void ContactMgr::registerCollision(ContactLayerCollisionInfo* info, RigidBody* b
|
|||
|
||||
auto* entry = mCollidingBodiesFreeList.popFront();
|
||||
if (entry) {
|
||||
entry->body_a = body_a;
|
||||
entry->body_b = body_b;
|
||||
entry->bodies[0] = body_a;
|
||||
entry->bodies[1] = body_b;
|
||||
info->getCollidingBodies().pushBack(entry);
|
||||
}
|
||||
}
|
||||
|
@ -386,7 +386,7 @@ void ContactMgr::unregisterCollision(CollisionInfo* info, RigidBody* body_a, Rig
|
|||
auto info_lock = sead::makeScopedLock(*info);
|
||||
|
||||
for (auto& entry : info->getCollidingBodies()) {
|
||||
if (entry.body_a == body_a && entry.body_b == body_b) {
|
||||
if (entry.bodies[0] == body_a && entry.bodies[1] == body_b) {
|
||||
info->getCollidingBodies().erase(&entry);
|
||||
mCollidingBodiesFreeList.pushBack(&entry);
|
||||
break;
|
||||
|
@ -400,7 +400,7 @@ void ContactMgr::unregisterCollision(ContactLayerCollisionInfo* info, RigidBody*
|
|||
auto info_lock = sead::makeScopedLock(*info);
|
||||
|
||||
for (auto& entry : info->getCollidingBodies()) {
|
||||
if (entry.body_a == body_a && entry.body_b == body_b) {
|
||||
if (entry.bodies[0] == body_a && entry.bodies[1] == body_b) {
|
||||
info->getCollidingBodies().erase(&entry);
|
||||
freeCollidingBodiesEntry(&entry);
|
||||
break;
|
||||
|
@ -415,8 +415,8 @@ void ContactMgr::unregisterCollisionWithBody(ContactLayerCollisionInfo* info, Ri
|
|||
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;
|
||||
auto* body_a = entry.bodies[0];
|
||||
auto* body_b = int(body_a->getContactLayer()) == body_layer ? body_a : entry.bodies[1];
|
||||
if (body_b == body) {
|
||||
info->getCollidingBodies().erase(&entry);
|
||||
freeCollidingBodiesEntry(&entry);
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
namespace ksys::phys {
|
||||
|
||||
class CollisionInfo;
|
||||
class ContactLayerCollisionInfo;
|
||||
class ContactLayerCollisionInfoGroup;
|
||||
class ContactMgr;
|
||||
class GroupFilter;
|
||||
class MaterialTable;
|
||||
|
@ -69,8 +71,17 @@ public:
|
|||
// 0x00000071012169ac
|
||||
void freeCollisionInfo(CollisionInfo* info) const;
|
||||
|
||||
// 0x00000071012169b4
|
||||
ContactLayerCollisionInfoGroup*
|
||||
makeContactLayerCollisionInfoGroup(sead::Heap* heap, ContactLayer layer, int capacity,
|
||||
const sead::SafeString& name);
|
||||
// 0x00000071012169c0
|
||||
void freeContactLayerCollisionInfoGroup(ContactLayerCollisionInfoGroup* group);
|
||||
// 0x00000071012169c8
|
||||
ContactLayerCollisionInfo* trackLayerPair(ContactLayer layer_a, ContactLayer layer_b);
|
||||
|
||||
// 0x0000007101216a20
|
||||
void registerRigidBodyForContactSystem(RigidBody* body);
|
||||
void removeRigidBodyFromContactSystem(RigidBody* body);
|
||||
|
||||
void removeSystemGroupHandler(SystemGroupHandler* handler);
|
||||
|
||||
|
|
Loading…
Reference in New Issue