ksys/phys: Start adding ContactListener

This commit is contained in:
Léo Lam
2022-01-21 12:59:31 +01:00
parent c292675646
commit c36c03c6fb
5 changed files with 163 additions and 13 deletions
+2
View File
@@ -70,6 +70,8 @@ target_sources(uking PRIVATE
System/physConstraint.h
System/physContactInfoParam.cpp
System/physContactInfoParam.h
System/physContactListener.cpp
System/physContactListener.h
System/physContactMgr.cpp
System/physContactMgr.h
System/physDefines.cpp
@@ -365,6 +365,18 @@ public:
virtual void resetPosition();
virtual const char* getName();
// Internal.
void onCollisionAdded() {
if (mCollisionCount.increment() == 0)
clearFlag4000000(false);
}
// Internal.
void onCollisionRemoved() {
if (mCollisionCount.decrement() == 1)
clearFlag4000000(true);
}
private:
void createMotionAccessor(sead::Heap* heap);
void onInvalidParameter(int code = 0);
@@ -385,8 +397,7 @@ private:
f32 _b0 = 1.0f;
Type mType{};
MotionAccessor* mMotionAccessor = nullptr;
u16 _c0 = 0;
u16 _c2 = 0;
sead::Atomic<int> mCollisionCount;
void* _c8 = nullptr;
};
KSYS_CHECK_SIZE_NX150(RigidBody, 0xD0);
@@ -0,0 +1,68 @@
#include "KingSystem/Physics/System/physContactListener.h"
#include <Havok/Physics2012/Dynamics/Collide/ContactListener/hkpCollisionEvent.h>
#include <Havok/Physics2012/Dynamics/Collide/ContactListener/hkpContactPointEvent.h>
#include <math/seadMathCalcCommon.h>
#include <prim/seadMemUtil.h>
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
namespace ksys::phys {
static RigidBody* getRigidBody(hkpRigidBody* hk_body) {
// This needs to be kept in sync with the RigidBody constructor!
return reinterpret_cast<RigidBody*>(hk_body->getUserData());
}
ContactListener::ContactListener(ContactMgr* mgr, ContactLayerType layer_type, int layer_count)
: mMgr(mgr), mLayerType(layer_type), mLayerBase(getContactLayerBase(layer_type)),
mLayerCount(layer_count) {}
ContactListener::~ContactListener() = default;
void ContactListener::init(sead::Heap* heap) {
// NOLINTBEGIN(cppcoreguidelines-narrowing-conversions)
_20.allocBufferAssert(mLayerCount, nullptr);
for (u32 i = 0; i < mLayerCount; ++i) {
_20[i].allocBufferAssert(mLayerCount, nullptr);
}
_30.allocBufferAssert(mLayerCount, nullptr);
for (u32 i = 0; i < mLayerCount; ++i) {
auto& row = _30[i];
row.allocBufferAssert(mLayerCount, nullptr);
for (u32 j = 0; j < mLayerCount; ++j) {
if (j >= i) {
row[j] = new (heap) ContactUnk1(mLayerBase + i);
} else {
row[j] = _30[j][i];
}
}
}
// NOLINTEND(cppcoreguidelines-narrowing-conversions)
_48 = sead::Mathu::roundUpPow2(mLayerCount * mLayerCount, 0x20);
_40 = ::operator new[](_48, heap, 0x20);
clearTable();
}
void ContactListener::clearTable() {
sead::MemUtil::fillZero(_40, _48);
}
void ContactListener::collisionAddedCallback(const hkpCollisionEvent& event) {
auto* bodyA = getRigidBody(event.getBody(0));
auto* bodyB = getRigidBody(event.getBody(1));
handleCollisionAdded(event, bodyA, bodyB);
bodyA->onCollisionAdded();
bodyB->onCollisionAdded();
}
void ContactListener::collisionRemovedCallback(const hkpCollisionEvent& event) {
auto* bodyA = getRigidBody(event.getBody(0));
auto* bodyB = getRigidBody(event.getBody(1));
handleCollisionRemoved(event, bodyA, bodyB);
bodyA->onCollisionRemoved();
bodyB->onCollisionRemoved();
}
} // namespace ksys::phys
@@ -0,0 +1,69 @@
#pragma once
#include <Havok/Physics2012/Dynamics/Collide/ContactListener/hkpContactListener.h>
#include <container/seadBuffer.h>
#include <container/seadObjArray.h>
#include <hostio/seadHostIONode.h>
#include <prim/seadRuntimeTypeInfo.h>
#include <thread/seadCriticalSection.h>
#include "KingSystem/Physics/System/physDefines.h"
namespace ksys::phys {
class ContactMgr;
class RigidBody;
struct ContactUnk1 {
ContactUnk1(u32 layer);
virtual ~ContactUnk1();
u8 _8[0x68];
};
class ContactListener : public hkpContactListener, public sead::hostio::Node {
SEAD_RTTI_BASE(ContactListener)
public:
ContactListener(ContactMgr* mgr, ContactLayerType layer_type, int layer_count);
~ContactListener() override;
void init(sead::Heap* heap);
void clearTable();
void contactPointCallback(const hkpContactPointEvent& event) override;
void collisionAddedCallback(const hkpCollisionEvent& event) override;
void collisionRemovedCallback(const hkpCollisionEvent& event) override;
void contactPointAddedCallback(hkpContactPointAddedEvent& event) override;
void contactPointRemovedCallback(hkpContactPointRemovedEvent& event) override;
void contactProcessCallback(hkpContactProcessEvent& event) override;
virtual void m10();
virtual void m11() {}
virtual void handleCollisionAdded(const hkpCollisionEvent& event, RigidBody* bodyA,
RigidBody* bodyB);
virtual void m13();
virtual void m14();
virtual u32 m15() { return 0; }
protected:
void handleCollisionRemoved(const hkpCollisionEvent& event, RigidBody* bodyA, RigidBody* bodyB);
private:
struct Unk1 {
void* _0;
void* _8;
};
ContactMgr* mMgr{};
ContactLayerType mLayerType{};
u32 mLayerBase{};
sead::Buffer<sead::Buffer<sead::FixedObjArray<Unk1, 8>>> _20;
sead::Buffer<sead::Buffer<ContactUnk1*>> _30;
void* _40{};
u32 _48{};
u32 mLayerCount{};
sead::CriticalSection mCS;
u16 _90{};
bool _92{};
};
} // namespace ksys::phys