mirror of https://github.com/zeldaret/botw.git
ksys/phys: Add impulse related ContactMgr functions
This commit is contained in:
parent
ad6c11f468
commit
e27c55361d
|
@ -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.
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue