ksys/phys: Add impulse related ContactMgr functions

This commit is contained in:
Léo Lam 2022-03-11 21:59:14 +01:00
parent ad6c11f468
commit e27c55361d
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
9 changed files with 286 additions and 53 deletions

View File

@ -79498,7 +79498,7 @@ Address,Quality,Size,Name
0x0000007100e9d4e0,U,000004,nullsub_4024 0x0000007100e9d4e0,U,000004,nullsub_4024
0x0000007100e9d4e4,U,000004,nullsub_4025 0x0000007100e9d4e4,U,000004,nullsub_4025
0x0000007100e9d4e8,O,000028,_ZN4ksys4phys12MaterialMaskC1Ev 0x0000007100e9d4e8,O,000028,_ZN4ksys4phys12MaterialMaskC1Ev
0x0000007100e9d504,O,000028,_ZN4ksys4phys12MaterialMaskC1ENS0_16MaterialMaskDataE 0x0000007100e9d504,O,000028,_ZN4ksys4phys12MaterialMaskC1Ej
0x0000007100e9d520,O,000080,_ZN4ksys4phys12MaterialMaskC1ENS0_8MaterialENS0_9FloorCodeENS0_8WallCodeEb 0x0000007100e9d520,O,000080,_ZN4ksys4phys12MaterialMaskC1ENS0_8MaterialENS0_9FloorCodeENS0_8WallCodeEb
0x0000007100e9d570,O,000176,_ZN4ksys4phys12MaterialMaskC1ENS0_8MaterialEPKcNS0_9FloorCodeENS0_8WallCodeEb 0x0000007100e9d570,O,000176,_ZN4ksys4phys12MaterialMaskC1ENS0_8MaterialEPKcNS0_9FloorCodeENS0_8WallCodeEb
0x0000007100e9d620,O,000032,_ZN4ksys4phys12MaterialMask17getSubMaterialIdxENS0_8MaterialERKN4sead14SafeStringBaseIcEE 0x0000007100e9d620,O,000032,_ZN4ksys4phys12MaterialMask17getSubMaterialIdxENS0_8MaterialERKN4sead14SafeStringBaseIcEE
@ -83740,9 +83740,9 @@ Address,Quality,Size,Name
0x0000007100fb20f4,U,000004,nullsub_4241 0x0000007100fb20f4,U,000004,nullsub_4241
0x0000007100fb20f8,U,000004,j__ZdlPv_1003 0x0000007100fb20f8,U,000004,j__ZdlPv_1003
0x0000007100fb20fc,O,000308,_ZN4ksys4phys10ContactMgrC1Ev 0x0000007100fb20fc,O,000308,_ZN4ksys4phys10ContactMgrC1Ev
0x0000007100fb2230,U,000180,phys::ContactInfoTable::dtor 0x0000007100fb2230,O,000180,_ZN4ksys4phys10ContactMgrD1Ev
0x0000007100fb22e4,U,000036,phys::ContactInfoTable::dtorDelete 0x0000007100fb22e4,O,000036,_ZN4ksys4phys10ContactMgrD0Ev
0x0000007100fb2308,U,000212,phys::ContactMgr::init 0x0000007100fb2308,O,000212,_ZN4ksys4phys10ContactMgr4initEPN4sead4HeapE
0x0000007100fb23dc,O,000152,_ZN4ksys4phys10ContactMgr20initContactPointPoolEPN4sead4HeapENS0_13IsIndoorStageE 0x0000007100fb23dc,O,000152,_ZN4ksys4phys10ContactMgr20initContactPointPoolEPN4sead4HeapENS0_13IsIndoorStageE
0x0000007100fb2474,O,000116,_ZN4ksys4phys10ContactMgr20freeContactPointPoolEv 0x0000007100fb2474,O,000116,_ZN4ksys4phys10ContactMgr20freeContactPointPoolEv
0x0000007100fb24e8,O,000316,_ZN4ksys4phys10ContactMgr20loadContactInfoTableEPN4sead4HeapEN3agl3utl19ResParameterArchiveENS0_16ContactLayerTypeE 0x0000007100fb24e8,O,000316,_ZN4ksys4phys10ContactMgr20loadContactInfoTableEPN4sead4HeapEN3agl3utl19ResParameterArchiveENS0_16ContactLayerTypeE
@ -83760,7 +83760,7 @@ Address,Quality,Size,Name
0x0000007100fb2f2c,m,000120,_ZN4ksys4phys10ContactMgr18clearContactPointsEv 0x0000007100fb2f2c,m,000120,_ZN4ksys4phys10ContactMgr18clearContactPointsEv
0x0000007100fb2fa4,O,000152,_ZN4ksys4phys10ContactMgr27removeContactPointsWithBodyEPNS0_9RigidBodyE 0x0000007100fb2fa4,O,000152,_ZN4ksys4phys10ContactMgr27removeContactPointsWithBodyEPNS0_9RigidBodyE
0x0000007100fb303c,O,000380,_ZN4ksys4phys10ContactMgr30removeCollisionEntriesWithBodyEPNS0_9RigidBodyE 0x0000007100fb303c,O,000380,_ZN4ksys4phys10ContactMgr30removeCollisionEntriesWithBodyEPNS0_9RigidBodyE
0x0000007100fb31b8,U,000204,phys::ContactInfoTable::x_12 0x0000007100fb31b8,O,000204,_ZN4ksys4phys10ContactMgr28removeImpulseEntriesWithBodyEPNS0_9RigidBodyE
0x0000007100fb3284,O,000500,_ZN4ksys4phys10ContactMgr20registerContactPointEPNS0_16ContactPointInfoERKNS0_12ContactPointERKNS0_23RigidBodyCollisionMasksEb 0x0000007100fb3284,O,000500,_ZN4ksys4phys10ContactMgr20registerContactPointEPNS0_16ContactPointInfoERKNS0_12ContactPointERKNS0_23RigidBodyCollisionMasksEb
0x0000007100fb3478,O,000340,_ZN4ksys4phys10ContactMgr20registerContactPointEPNS0_21LayerContactPointInfoERKNS0_12ContactPointEb 0x0000007100fb3478,O,000340,_ZN4ksys4phys10ContactMgr20registerContactPointEPNS0_21LayerContactPointInfoERKNS0_12ContactPointEb
0x0000007100fb35cc,O,000376,_ZN4ksys4phys10ContactMgr20registerContactPointEPNS0_21QueryContactPointInfoERKNS0_12ContactPointEb 0x0000007100fb35cc,O,000376,_ZN4ksys4phys10ContactMgr20registerContactPointEPNS0_21QueryContactPointInfoERKNS0_12ContactPointEb
@ -83773,11 +83773,11 @@ Address,Quality,Size,Name
0x0000007100fb3bb4,O,000652,_ZNK4ksys4phys10ContactMgr14initLayerMasksEPNS0_16ContactPointInfoERKN4sead14SafeStringBaseIcEE 0x0000007100fb3bb4,O,000652,_ZNK4ksys4phys10ContactMgr14initLayerMasksEPNS0_16ContactPointInfoERKN4sead14SafeStringBaseIcEE
0x0000007100fb3e40,O,000644,_ZNK4ksys4phys10ContactMgr14initLayerMasksEPNS0_13CollisionInfoERKN4sead14SafeStringBaseIcEE 0x0000007100fb3e40,O,000644,_ZNK4ksys4phys10ContactMgr14initLayerMasksEPNS0_13CollisionInfoERKN4sead14SafeStringBaseIcEE
0x0000007100fb40c4,O,000356,_ZNK4ksys4phys10ContactMgr18getSensorLayerMaskEPNS0_19SensorCollisionMaskERKN4sead14SafeStringBaseIcEE 0x0000007100fb40c4,O,000356,_ZNK4ksys4phys10ContactMgr18getSensorLayerMaskEPNS0_19SensorCollisionMaskERKN4sead14SafeStringBaseIcEE
0x0000007100fb4228,U,000204,phys::ContactInfoTable::x_26 0x0000007100fb4228,O,000204,_ZN4ksys4phys10ContactMgr15addImpulseEntryEPNS0_9RigidBodyES3_
0x0000007100fb42f4,U,001092,phys::ContactInfoTable::x_27 0x0000007100fb42f4,O,001092,_ZN4ksys4phys10ContactMgr26setImpulseEntryContactInfoEPNS0_9RigidBodyES3_RKN4sead7Vector3IfEES8_jj
0x0000007100fb4738,U,000668,phys::ContactInfoTable::x_28 0x0000007100fb4738,O,000668,_ZN4ksys4phys10ContactMgr19processImpulseEntryERKNS1_12ImpulseEntryE
0x0000007100fb49d4,U,000188,phys::ContactInfoTable::x_14 0x0000007100fb49d4,O,000188,_ZN4ksys4phys10ContactMgr21processImpulseEntriesEv
0x0000007100fb4a90,U,000184,phys::ContactInfoTable::x_29 0x0000007100fb4a90,O,000184,_ZN4ksys4phys10ContactMgr19clearImpulseEntriesEv
0x0000007100fb4b48,O,000104,_ZN4ksys4phys16ContactInfoTable8Receiver9postRead_Ev 0x0000007100fb4b48,O,000104,_ZN4ksys4phys16ContactInfoTable8Receiver9postRead_Ev
0x0000007100fb4bb0,O,000160,_ZN4ksys4phys16ContactInfoTable8ReceiverD2Ev 0x0000007100fb4bb0,O,000160,_ZN4ksys4phys16ContactInfoTable8ReceiverD2Ev
0x0000007100fb4c50,O,000004,_ZN4ksys4phys16ContactInfoTable8ReceiverD0Ev 0x0000007100fb4c50,O,000004,_ZN4ksys4phys16ContactInfoTable8ReceiverD0Ev

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

View File

@ -66,14 +66,14 @@ bool RigidBodyFromResource::isMaterial(Material material) const {
if (!shape) if (!shape)
return false; return false;
MaterialMask shape_material{MaterialMaskData(shape->getUserData())}; MaterialMask shape_material{shape->getUserData()};
if (int(shape_material.getMaterial()) == material) { if (int(shape_material.getMaterial()) == material) {
found_child_shape_with_material = true; found_child_shape_with_material = true;
break; break;
} }
} }
} else { } else {
MaterialMask shape_material{MaterialMaskData(mShape->getUserData())}; MaterialMask shape_material{mShape->getUserData()};
if (int(shape_material.getMaterial()) == material) if (int(shape_material.getMaterial()) == material)
return true; return true;
} }

View File

@ -54,6 +54,9 @@ public:
// 0x0000007100fa6ebc // 0x0000007100fa6ebc
void removeRigidBody(ContactLayerType type, RigidBody* body); void removeRigidBody(ContactLayerType type, RigidBody* body);
// 0x0000007100fa7340
void addImpulse(RigidBody* body_a, RigidBody* body_b, float impulse);
bool registerMotionAccessor(MotionAccessor* accessor); bool registerMotionAccessor(MotionAccessor* accessor);
bool deregisterMotionAccessor(MotionAccessor* accessor); bool deregisterMotionAccessor(MotionAccessor* accessor);

View File

@ -1,5 +1,8 @@
#include "KingSystem/Physics/System/physContactMgr.h" #include "KingSystem/Physics/System/physContactMgr.h"
#include <memory>
#include <prim/seadScopedLock.h> #include <prim/seadScopedLock.h>
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
#include "KingSystem/Physics/RigidBody/physRigidBodyRequestMgr.h"
#include "KingSystem/Physics/System/physCollisionInfo.h" #include "KingSystem/Physics/System/physCollisionInfo.h"
#include "KingSystem/Physics/System/physContactLayerCollisionInfo.h" #include "KingSystem/Physics/System/physContactLayerCollisionInfo.h"
#include "KingSystem/Physics/System/physContactPointInfo.h" #include "KingSystem/Physics/System/physContactPointInfo.h"
@ -9,17 +12,48 @@
#include "KingSystem/Physics/System/physQueryContactPointInfo.h" #include "KingSystem/Physics/System/physQueryContactPointInfo.h"
#include "KingSystem/Physics/System/physSystem.h" #include "KingSystem/Physics/System/physSystem.h"
#include "KingSystem/Utils/Debug.h" #include "KingSystem/Utils/Debug.h"
#include "KingSystem/Utils/MathUtil.h"
namespace ksys::phys { namespace ksys::phys {
struct ContactMgr::ImpulseEntry {
static constexpr size_t getListNodeOffset() { return offsetof(ImpulseEntry, list_node); }
RigidBody* bodies[2];
sead::Vector3f linear_vels[2];
bool is_dynamic_motion[2];
float magnitude;
float impulses[2];
sead::Vector3f contact_point_pos;
bool is_entity_motion_flag_20_off;
bool valid;
sead::ListNode list_node;
};
ContactMgr::ContactMgr() { ContactMgr::ContactMgr() {
mContactPointInfoInstances.initOffset(ContactPointInfo::getListNodeOffset()); mContactPointInfoInstances.initOffset(ContactPointInfo::getListNodeOffset());
// FIXME: figure out what these offsets are
mCollisionInfoInstances.initOffset(CollisionInfo::getListNodeOffset()); mCollisionInfoInstances.initOffset(CollisionInfo::getListNodeOffset());
// FIXME: figure out what this offset is
mList3.initOffset(0x40); mList3.initOffset(0x40);
mCollidingBodiesFreeList.initOffset(CollidingBodies::getListNodeOffset()); mCollidingBodiesFreeList.initOffset(CollidingBodies::getListNodeOffset());
mList4.initOffset(0x48); mImpulseEntriesFreeList.initOffset(ImpulseEntry::getListNodeOffset());
mList5.initOffset(0x48); mImpulseEntries.initOffset(ImpulseEntry::getListNodeOffset());
}
ContactMgr::~ContactMgr() {
for (int i = 0; i < mCollidingBodiesCapacity; ++i)
delete mCollidingBodiesFreeList.popFront();
}
void ContactMgr::init(sead::Heap* heap) {
mCollidingBodiesCapacity = 0x2000;
for (int i = 0; i < mCollidingBodiesCapacity; ++i) {
mCollidingBodiesFreeList.pushBack(new (heap) CollidingBodies());
}
for (int i = 0; i < 0x100; ++i) {
mImpulseEntriesFreeList.pushBack(new (heap) ImpulseEntry());
}
} }
void ContactMgr::initContactPointPool(sead::Heap* heap, IsIndoorStage indoor) { void ContactMgr::initContactPointPool(sead::Heap* heap, IsIndoorStage indoor) {
@ -189,6 +223,17 @@ void ContactMgr::removeCollisionEntriesWithBody(RigidBody* body) {
} }
} }
void ContactMgr::removeImpulseEntriesWithBody(RigidBody* body) {
auto lock = sead::makeScopedLock(mImpulseEntriesMutex);
for (auto& entry : mImpulseEntries.robustRange()) {
if (entry.bodies[0] == body || entry.bodies[1] == body) {
mImpulseEntries.erase(&entry);
mImpulseEntriesFreeList.pushBack(&entry);
}
}
}
int ContactMgr::allocateContactPoint() { int ContactMgr::allocateContactPoint() {
if (mNumContactPoints >= mContactPointPool.size() - 1) { if (mNumContactPoints >= mContactPointPool.size() - 1) {
util::PrintDebugFmt("contact point pool exhausted (current number of points: %d)", util::PrintDebugFmt("contact point pool exhausted (current number of points: %d)",
@ -389,6 +434,171 @@ void ContactMgr::clearCollisionEntries(CollisionInfo* info) {
} }
} }
void ContactMgr::addImpulseEntry(RigidBody* body_a, RigidBody* body_b) {
auto lock = sead::makeScopedLock(mImpulseEntriesMutex);
auto* entry = mImpulseEntriesFreeList.popFront();
if (!entry)
return;
entry->bodies[0] = body_a;
entry->bodies[1] = body_b;
body_a->getLinearVelocity(&entry->linear_vels[0]);
body_b->getLinearVelocity(&entry->linear_vels[1]);
entry->is_dynamic_motion[0] = body_a->getMotionType() == MotionType::Dynamic;
entry->is_dynamic_motion[1] = body_b->getMotionType() == MotionType::Dynamic;
entry->magnitude = 0;
entry->impulses[0] = 0;
entry->impulses[1] = 0;
entry->is_entity_motion_flag_20_off = true;
entry->valid = false;
mImpulseEntries.pushBack(entry);
}
static sead::Vector3f computeLinearVelocity(const RigidBody& body, const sead::Vector3f& linear_vel,
const sead::Vector3f& pos) {
const auto center = body.getCenterOfMassInWorld();
const auto rel_pos = pos - center;
sead::Vector3f correction;
correction.setCross(body.getAngularVelocity(), rel_pos);
return linear_vel + correction;
}
void ContactMgr::setImpulseEntryContactInfo(RigidBody* body_a, RigidBody* body_b,
const sead::Vector3f& contact_point_pos,
const sead::Vector3f& contact_point_normal,
u32 material_a, u32 material_b) {
auto lock = sead::makeScopedLock(mImpulseEntriesMutex);
ImpulseEntry* entry = nullptr;
for (auto& impulse_entry : mImpulseEntries) {
if ((impulse_entry.bodies[0] == body_a && impulse_entry.bodies[1] == body_b) ||
(impulse_entry.bodies[1] == body_a && impulse_entry.bodies[0] == body_b)) {
entry = std::addressof(impulse_entry);
break;
}
}
if (!entry)
return;
const MaterialMask mat_mask_a{material_a};
const MaterialMask mat_mask_b{material_b};
if (mat_mask_a.getData().flag30 || mat_mask_b.getData().flag30)
return;
if (mat_mask_a.getFloorCode() == FloorCode::NoImpulseUpperMove && entry->linear_vels[0].y > 0)
return;
if (mat_mask_b.getFloorCode() == FloorCode::NoImpulseUpperMove && entry->linear_vels[1].y > 0)
return;
/// The velocities of the rigid bodies at the contact point.
const auto linvel_a =
computeLinearVelocity(*entry->bodies[0], entry->linear_vels[0], contact_point_pos);
const auto linvel_b =
computeLinearVelocity(*entry->bodies[1], entry->linear_vels[1], contact_point_pos);
const bool is_flag_off =
entry->bodies[0]->isEntityMotionFlag20Off() && entry->bodies[1]->isEntityMotionFlag20Off();
/// The pre-collision relative velocity.
const auto relative_vel = linvel_a - linvel_b;
const auto dot_neg = [&](const auto& vec) { return vec.dot(-contact_point_normal); };
float magnitude = is_flag_off ? sead::Mathf::max(0.0, relative_vel.dot(-contact_point_normal)) :
sead::Mathf::max(0.0, relative_vel.length());
if (magnitude >= entry->magnitude) {
float i1, i2;
if (is_flag_off) {
i1 = sead::Mathf::min(sead::Mathf::max(0.0, dot_neg(linvel_a)), magnitude);
i2 = sead::Mathf::min(sead::Mathf::max(0.0, linvel_b.dot(contact_point_normal)),
sead::Mathf::max(0.0, dot_neg(relative_vel)));
} else {
i1 = sead::Mathf::min(sead::Mathf::max(0.0, linvel_a.length()), magnitude);
i2 = sead::Mathf::min(sead::Mathf::max(0.0, linvel_b.length()),
sead::Mathf::max(0.0, relative_vel.length()));
}
entry->magnitude = magnitude;
entry->impulses[0] = i1;
entry->impulses[1] = i2;
entry->contact_point_pos = contact_point_pos;
entry->is_entity_motion_flag_20_off = is_flag_off;
entry->valid = true;
}
}
void ContactMgr::processImpulseEntry(const ImpulseEntry& entry) {
if (!entry.valid)
return;
RigidBody* body_a = entry.bodies[0];
RigidBody* body_b = entry.bodies[1];
if (body_a->isEntityMotionFlag40On())
body_a->setEntityMotionFlag40(false);
if (body_b->isEntityMotionFlag40On())
body_b->setEntityMotionFlag40(false);
float impulse_a = 0.0f;
float impulse_b = 0.0f;
const auto compute_impulse = [&entry](int index, RigidBody* body) {
if (!entry.is_dynamic_motion[index])
return 0.0f;
const auto impulse = entry.impulses[index];
if (!(impulse > 5.0f || !entry.is_entity_motion_flag_20_off))
return 0.0f;
const float scaled_impulse = impulse * body->getMass() * body->getColImpulseScale();
float volume_factor = 1.0f;
if (body->getMotionType() == MotionType::Dynamic)
volume_factor += util::clampAndRemapRange(body->getVolume(), 0.2, 1.0, 1.0, 0.0);
return scaled_impulse * volume_factor;
};
impulse_b = compute_impulse(0, body_a);
impulse_a = compute_impulse(1, body_b);
const auto add_impulse = [impulse_a, impulse_b](RigidBody* body1, RigidBody* body2,
float impulse) {
if (body1->isEntityMotionFlag10Off())
impulse = impulse_a + impulse_b;
if (body2->isEntityMotionFlag8On() ||
(body1->getMaxImpulse() >= 0 && impulse > body1->getMaxImpulse())) {
System::instance()->getRigidBodyRequestMgr()->addImpulse(body1, body2, impulse);
}
};
add_impulse(body_a, body_b, impulse_a);
add_impulse(body_b, body_a, impulse_b);
}
void ContactMgr::processImpulseEntries() {
auto lock = sead::makeScopedLock(mImpulseEntriesMutex);
for (auto& entry : mImpulseEntries.robustRange()) {
processImpulseEntry(entry);
mImpulseEntries.erase(&entry);
mImpulseEntriesFreeList.pushBack(&entry);
}
}
void ContactMgr::clearImpulseEntries() {
auto lock = sead::makeScopedLock(mImpulseEntriesMutex);
for (auto& entry : mImpulseEntries.robustRange()) {
mImpulseEntries.erase(&entry);
mImpulseEntriesFreeList.pushBack(&entry);
}
}
void ContactInfoTable::Receiver::postRead_() { void ContactInfoTable::Receiver::postRead_() {
layer_mask = 0; layer_mask = 0;
layer_mask2 = 0; layer_mask2 = 0;

View File

@ -76,6 +76,8 @@ KSYS_CHECK_SIZE_NX150(ContactPoint, 0x70);
class ContactMgr : public sead::hostio::Node { class ContactMgr : public sead::hostio::Node {
public: public:
struct ImpulseEntry;
ContactMgr(); ContactMgr();
virtual ~ContactMgr(); virtual ~ContactMgr();
@ -114,9 +116,7 @@ public:
/// They will be removed at a later stage. /// They will be removed at a later stage.
void removeContactPointsWithBody(RigidBody* body); void removeContactPointsWithBody(RigidBody* body);
void removeCollisionEntriesWithBody(RigidBody* body); void removeCollisionEntriesWithBody(RigidBody* body);
// TODO: figure out what this removes void removeImpulseEntriesWithBody(RigidBody* body);
// 0x0000007100fb31b8
void removeUnkWithBody(RigidBody* body);
/// @param colliding_body_masks The collision masks of the colliding rigid bodies. /// @param colliding_body_masks The collision masks of the colliding rigid bodies.
/// @returns whether contact should be disabled. /// @returns whether contact should be disabled.
@ -143,19 +143,24 @@ public:
bool initLayerMasks(CollisionInfo* info, const sead::SafeString& receiver_name) const; bool initLayerMasks(CollisionInfo* info, const sead::SafeString& receiver_name) const;
bool getSensorLayerMask(SensorCollisionMask* mask, const sead::SafeString& receiver_name) const; bool getSensorLayerMask(SensorCollisionMask* mask, const sead::SafeString& receiver_name) const;
// 0x0000007100fb4228 /// Add a new impulse entry based on contact between the two specified rigid bodies.
void x_26(RigidBody* body_a, RigidBody* body_b); /// After this is called, contact point information must then be specified using
// 0x0000007100fb42f4 /// setImpulseEntryContactInfo.
void x_27(RigidBody* body_a, RigidBody* body_b, const sead::Vector3f& point_position, void addImpulseEntry(RigidBody* body_a, RigidBody* body_b);
const sead::Vector3f& point_separating_normal, u32 material_a, u32 material_b);
// 0x0000007100fb4738 /// Fill in an existing impulse entry with contact information.
void x_28(void* unk); /// This does nothing if there is no impulse entry for the specified rigid bodies.
// 0x0000007100fb49d4 void setImpulseEntryContactInfo(RigidBody* body_a, RigidBody* body_b,
void x_14(); const sead::Vector3f& contact_point_pos,
// 0x0000007100fb4a90 const sead::Vector3f& contact_point_normal, u32 material_a,
void x_29(); u32 material_b);
void processImpulseEntries();
void clearImpulseEntries();
private: private:
void processImpulseEntry(const ImpulseEntry& index);
void doLoadContactInfoTable(agl::utl::ResParameterArchive archive, ContactLayerType type, void doLoadContactInfoTable(agl::utl::ResParameterArchive archive, ContactLayerType type,
bool skip_params); bool skip_params);
@ -170,20 +175,20 @@ private:
/// Used to optimise ContactPoint allocations. /// Used to optimise ContactPoint allocations.
sead::Buffer<ContactPoint> mContactPointPool; sead::Buffer<ContactPoint> mContactPointPool;
sead::OffsetList<CollidingBodies> mCollidingBodiesFreeList; sead::OffsetList<CollidingBodies> mCollidingBodiesFreeList;
int mList0Size = 0; int mCollidingBodiesCapacity = 0;
/// The number of contact points. Also the iindex of the next free ContactPoint in the pool. /// The number of contact points. Also the iindex of the next free ContactPoint in the pool.
sead::Atomic<int> mNumContactPoints = 0; sead::Atomic<int> mNumContactPoints = 0;
sead::OffsetList<ContactPointInfoBase> mContactPointInfoInstances; sead::OffsetList<ContactPointInfoBase> mContactPointInfoInstances;
sead::OffsetList<CollisionInfo> mCollisionInfoInstances; sead::OffsetList<CollisionInfo> mCollisionInfoInstances;
sead::OffsetList<void*> mList3; sead::OffsetList<void*> mList3;
sead::OffsetList<void*> mList4; sead::OffsetList<ImpulseEntry> mImpulseEntriesFreeList;
sead::OffsetList<void*> mList5; sead::OffsetList<ImpulseEntry> mImpulseEntries;
// TODO: rename these members
sead::Mutex mContactPointInfoMutex; sead::Mutex mContactPointInfoMutex;
sead::Mutex mCollisionInfoMutex; sead::Mutex mCollisionInfoMutex;
// TODO: rename mList3 and mMutex3
sead::Mutex mMutex3; sead::Mutex mMutex3;
sead::Mutex mCollidingBodiesMutex; sead::Mutex mCollidingBodiesMutex;
sead::Mutex mMutex5; sead::Mutex mImpulseEntriesMutex;
sead::SafeArray<ContactInfoTable, 2> mContactInfoTables{}; sead::SafeArray<ContactInfoTable, 2> mContactInfoTables{};
}; };

View File

@ -101,7 +101,7 @@ void EntityContactListener::collisionAddedCallback(const hkpCollisionEvent& even
} }
if (!should_process && m15(body_a, body_b)) { if (!should_process && m15(body_a, body_b)) {
mMgr->x_26(body_a, body_b); mMgr->addImpulseEntry(body_a, body_b);
} }
} }
@ -221,8 +221,8 @@ void EntityContactListener::m11(const hkpContactPointEvent& event,
RigidBody* body_b) { RigidBody* body_b) {
auto* hk_point_properties = event.m_contactPointProperties; auto* hk_point_properties = event.m_contactPointProperties;
const MaterialMask mat_mask_a = MaterialMaskData(masks_a.material_mask); const MaterialMask mat_mask_a{masks_a.material_mask};
const MaterialMask mat_mask_b = MaterialMaskData(masks_b.material_mask); const MaterialMask mat_mask_b{masks_b.material_mask};
const auto* material_table = System::instance()->getMaterialTable(); const auto* material_table = System::instance()->getMaterialTable();
const auto mat_a = mat_mask_a.getMaterial(); const auto mat_a = mat_mask_a.getMaterial();
@ -519,10 +519,11 @@ bool EntityContactListener::regularContactPointCallback(const hkpContactPointEve
storeToVec3(&position, event.m_contactPoint->getPosition()); storeToVec3(&position, event.m_contactPoint->getPosition());
storeToVec3(&normal, event.m_contactPoint->getSeparatingNormal()); storeToVec3(&normal, event.m_contactPoint->getSeparatingNormal());
if (body_a->isEntityMotionFlag40On() || body_b->isEntityMotionFlag40On()) { if (body_a->isEntityMotionFlag40On() || body_b->isEntityMotionFlag40On()) {
mMgr->x_26(body_a, body_b); mMgr->addImpulseEntry(body_a, body_b);
} }
mMgr->x_27(body_a, body_b, position, normal, material_masks[0], material_masks[1]); mMgr->setImpulseEntryContactInfo(body_a, body_b, position, normal, material_masks[0],
material_masks[1]);
} }
return result; return result;

View File

@ -6,13 +6,13 @@ namespace ksys::phys {
MaterialMask::MaterialMask() = default; MaterialMask::MaterialMask() = default;
MaterialMask::MaterialMask(MaterialMaskData data) : mData(data) {} MaterialMask::MaterialMask(u32 data) : mData(data) {}
MaterialMask::MaterialMask(Material mat, FloorCode floor, WallCode wall, bool flag) { MaterialMask::MaterialMask(Material mat, FloorCode floor, WallCode wall, bool flag) {
mData.material.Init(mat); mData.material.Init(mat);
mData.floor.Init(floor); mData.floor.Init(floor);
mData.wall.Init(wall); mData.wall.Init(wall);
mData.setFlag(flag); mData.setFlag31(flag);
} }
MaterialMask::MaterialMask(Material mat, const char* submat_name, FloorCode floor, WallCode wall, MaterialMask::MaterialMask(Material mat, const char* submat_name, FloorCode floor, WallCode wall,
@ -26,7 +26,7 @@ MaterialMask::MaterialMask(Material mat, const char* submat_name, FloorCode floo
mData.sub_material.Init(submat_idx); mData.sub_material.Init(submat_idx);
mData.floor.Init(floor); mData.floor.Init(floor);
mData.wall.Init(wall); mData.wall.Init(wall);
mData.setFlag(flag); mData.setFlag31(flag);
} }
MaterialMask::MaterialMask(Material mat, int submat_idx, FloorCode floor, WallCode wall, bool flag) MaterialMask::MaterialMask(Material mat, int submat_idx, FloorCode floor, WallCode wall, bool flag)
@ -36,7 +36,7 @@ MaterialMask::MaterialMask(Material mat, int submat_idx, FloorCode floor, WallCo
mData.sub_material.Init(submat_idx); mData.sub_material.Init(submat_idx);
mData.floor.Init(floor); mData.floor.Init(floor);
mData.wall.Init(wall); mData.wall.Init(wall);
mData.setFlag(flag); mData.setFlag31(flag);
} }
MaterialMask::~MaterialMask() = default; MaterialMask::~MaterialMask() = default;

View File

@ -28,14 +28,14 @@ union MaterialMaskData {
FloorCode getFloorCode() const { return int(floor.Value()); } FloorCode getFloorCode() const { return int(floor.Value()); }
WallCode getWallCode() const { return int(wall.Value()); } WallCode getWallCode() const { return int(wall.Value()); }
void setFlag(bool b) { void setFlag31(bool b) {
if (!b) if (!b)
clearFlag(); clearFlag31();
else else
setFlag(); setFlag31();
} }
void setFlag() { flag = 1; } void setFlag31() { flag31 = 1; }
void clearFlag() { flag = 0; } void clearFlag31() { flag31 = 0; }
void setCustomFlag(CustomFlag custom_flag) { void setCustomFlag(CustomFlag custom_flag) {
raw |= 1 << (decltype(custom_flags)::StartBit() + custom_flag); raw |= 1 << (decltype(custom_flags)::StartBit() + custom_flag);
@ -46,16 +46,18 @@ union MaterialMaskData {
util::BitField<6, 4, int, u32> sub_material; util::BitField<6, 4, int, u32> sub_material;
util::BitField<10, 5, u32> floor; util::BitField<10, 5, u32> floor;
util::BitField<15, 5, u32> wall; util::BitField<15, 5, u32> wall;
util::BitField<23, 8, u32> custom_flags; // TODO: rename once we figure out what these flags are
// TODO: rename once we figure out what this flag is util::BitField<23, 7, u32> custom_flags;
util::BitField<31, 1, u32> flag; util::BitField<30, 1, u32> flag30;
util::BitField<31, 1, u32> flag31;
}; };
static_assert(sizeof(MaterialMaskData) == sizeof(u32)); static_assert(sizeof(MaterialMaskData) == sizeof(u32));
class MaterialMask { class MaterialMask {
public: public:
MaterialMask(); MaterialMask();
MaterialMask(MaterialMaskData data); // NOLINT(google-explicit-constructor) explicit MaterialMask(u32 data);
explicit MaterialMask(u64 havok_user_data) : MaterialMask(static_cast<u32>(havok_user_data)) {}
MaterialMask(Material mat, FloorCode floor, WallCode wall, bool flag = false); MaterialMask(Material mat, FloorCode floor, WallCode wall, bool flag = false);
MaterialMask(Material mat, const char* submat_name, FloorCode floor, WallCode wall, MaterialMask(Material mat, const char* submat_name, FloorCode floor, WallCode wall,
bool flag = false); bool flag = false);

View File

@ -1,12 +1,24 @@
#pragma once #pragma once
#include <math/seadMathCalcCommon.h>
#include <math/seadVector.h> #include <math/seadVector.h>
namespace ksys::util { namespace ksys::util {
/// Remap `value` from a [low, high] range to [new_low, new_high].
inline float remapRange(float value, float low, float high, float new_low, float new_high) {
return new_low + (value - low) * (new_high - new_low) / (high - low);
}
/// Clamp `value` to [low, high] and then remap the value to the range [new_low, new_high].
inline float clampAndRemapRange(float value, float low, float high, float new_low, float new_high) {
value = sead::Mathf::clamp(value, low, high);
return remapRange(value, low, high, new_low, new_high);
}
// too specific for sead // too specific for sead
inline float sqXZDistance(const sead::Vector3f& a, const sead::Vector3f& b) { inline float sqXZDistance(const sead::Vector3f& a, const sead::Vector3f& b) {
return sead::Mathf::square(a.x - b.x) + sead::Mathf::square(a.z - b.z); return sead::Mathf::square(a.x - b.x) + sead::Mathf::square(a.z - b.z);
} }
} // namespace ksys::util } // namespace ksys::util