ksys/phys: Start adding EntityContactListener

This commit is contained in:
Léo Lam 2022-03-08 19:14:03 +01:00
parent c11a33c5ab
commit a9ee6f839e
No known key found for this signature in database
GPG Key ID: 0DF30F9081000741
7 changed files with 167 additions and 11 deletions

View File

@ -83839,24 +83839,24 @@ Address,Quality,Size,Name
0x0000007100fb6368,O,000044,_ZN4ksys4phys17EntityGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitEjj 0x0000007100fb6368,O,000044,_ZN4ksys4phys17EntityGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitEjj
0x0000007100fb6394,O,000028,_ZN4ksys4phys17EntityGroupFilter34setEntityLayerCollisionEnabledMaskENS0_12ContactLayerEj 0x0000007100fb6394,O,000028,_ZN4ksys4phys17EntityGroupFilter34setEntityLayerCollisionEnabledMaskENS0_12ContactLayerEj
0x0000007100fb63b0,O,000140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys4phys11GroupFilterEE9isDerivedEPKNS0_9InterfaceE 0x0000007100fb63b0,O,000140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys4phys11GroupFilterEE9isDerivedEPKNS0_9InterfaceE
0x0000007100fb643c,U,000108,phys::makeEntityContactListener 0x0000007100fb643c,O,000108,_ZN4ksys4phys21EntityContactListener4makeEPNS0_10ContactMgrEPN4sead4HeapE
0x0000007100fb64a8,U,000004,j_ksys::phys::ContactListener::dtor 0x0000007100fb64a8,O,000004,_ZN4ksys4phys21EntityContactListenerD1Ev
0x0000007100fb64ac,U,000036, 0x0000007100fb64ac,O,000036,_ZN4ksys4phys21EntityContactListenerD0Ev
0x0000007100fb64d0,U,000456, 0x0000007100fb64d0,U,000456,
0x0000007100fb6698,U,000472, 0x0000007100fb6698,U,000472,
0x0000007100fb6870,U,000320, 0x0000007100fb6870,U,000320,
0x0000007100fb69b0,U,000304, 0x0000007100fb69b0,U,000304,
0x0000007100fb6ae0,U,000492, 0x0000007100fb6ae0,U,000492,
0x0000007100fb6ccc,U,000120, 0x0000007100fb6ccc,U,000120,
0x0000007100fb6d44,U,000084, 0x0000007100fb6d44,O,000084,_ZN4ksys4phys21EntityContactListener27isObjectOrGroundOrNPCOrTreeERKNS0_9RigidBodyE
0x0000007100fb6d98,U,000128, 0x0000007100fb6d98,O,000128,_ZN4ksys4phys21EntityContactListener27isObjectOrGroundOrNPCOrTreeERK9hkpCdBody
0x0000007100fb6e18,U,000460, 0x0000007100fb6e18,U,000460,
0x0000007100fb6fe4,U,000284, 0x0000007100fb6fe4,O,000284,_ZN4ksys4phys21EntityContactListener3m11ERK20hkpContactPointEventRKNS0_23RigidBodyCollisionMasksES7_PNS0_9RigidBodyES9_
0x0000007100fb7100,U,000344, 0x0000007100fb7100,U,000344,
0x0000007100fb7258,U,002036, 0x0000007100fb7258,U,002036,
0x0000007100fb7a4c,U,000204, 0x0000007100fb7a4c,O,000204,_ZNK4ksys4phys21EntityContactListener27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
0x0000007100fb7b18,U,000092, 0x0000007100fb7b18,O,000092,_ZNK4ksys4phys21EntityContactListener18getRuntimeTypeInfoEv
0x0000007100fb7b74,U,000140, 0x0000007100fb7b74,O,000140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys4phys15ContactListenerEE9isDerivedEPKNS0_9InterfaceE
0x0000007100fb7c00,U,000788,ActorPhysics::ctor 0x0000007100fb7c00,U,000788,ActorPhysics::ctor
0x0000007100fb7f14,U,000020, 0x0000007100fb7f14,U,000020,
0x0000007100fb7f28,U,000004,j__ZdlPv_1006 0x0000007100fb7f28,U,000004,j__ZdlPv_1006

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

View File

@ -121,6 +121,8 @@ target_sources(uking PRIVATE
System/physContactPointInfo.h System/physContactPointInfo.h
System/physLayerContactPointInfo.cpp System/physLayerContactPointInfo.cpp
System/physLayerContactPointInfo.h System/physLayerContactPointInfo.h
System/physEntityContactListener.cpp
System/physEntityContactListener.h
System/physEntityGroupFilter.cpp System/physEntityGroupFilter.cpp
System/physEntityGroupFilter.h System/physEntityGroupFilter.h
System/physGroupFilter.cpp System/physGroupFilter.cpp

View File

@ -0,0 +1,73 @@
#include "KingSystem/Physics/System/physEntityContactListener.h"
#include <Havok/Physics2012/Collide/Agent/Collidable/hkpCdBody.h>
#include <Havok/Physics2012/Dynamics/Collide/ContactListener/hkpContactPointEvent.h>
#include <Havok/Physics2012/Dynamics/Constraint/Contact/hkpContactPointProperties.h>
#include <math/seadMathCalcCommon.h>
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
#include "KingSystem/Physics/System/physMaterialTable.h"
#include "KingSystem/Physics/System/physSystem.h"
#include "KingSystem/Physics/physConversions.h"
#include "KingSystem/Physics/physMaterialMask.h"
namespace ksys::phys {
EntityContactListener* EntityContactListener::make(ContactMgr* mgr, sead::Heap* heap) {
auto* listener = new (heap) EntityContactListener(mgr, heap);
listener->init(heap);
return listener;
}
EntityContactListener::EntityContactListener(ContactMgr* mgr, sead::Heap* heap)
: ContactListener(mgr, ContactLayerType::Entity, MaxNumLayersPerType) {}
EntityContactListener::~EntityContactListener() = default;
bool EntityContactListener::isObjectOrGroundOrNPCOrTree(const RigidBody& body) {
switch (body.getContactLayer().value()) {
case ContactLayer::EntityObject:
case ContactLayer::EntityGroundObject:
case ContactLayer::EntityNPC:
case ContactLayer::EntityTree:
if (body.hasFlag(RigidBody::Flag::_400000))
break;
return true;
default:
break;
}
return false;
}
bool EntityContactListener::isObjectOrGroundOrNPCOrTree(const hkpCdBody& cd_body) {
auto* body = getRigidBody(*cd_body.getRootCollidable());
if (!body)
return false;
return isObjectOrGroundOrNPCOrTree(*body);
}
void EntityContactListener::m11(const hkpContactPointEvent& event,
const RigidBodyCollisionMasks& masks_a,
const RigidBodyCollisionMasks& masks_b, RigidBody* body_a,
RigidBody* body_b) {
auto* hk_point_properties = event.m_contactPointProperties;
const MaterialMask mat_mask_a = MaterialMaskData(masks_a.material_mask);
const MaterialMask mat_mask_b = MaterialMaskData(masks_b.material_mask);
const auto* material_table = System::instance()->getMaterialTable();
const auto mat_a = mat_mask_a.getMaterial();
const auto mat_b = mat_mask_b.getMaterial();
const auto properties = material_table->getPairProperties(mat_a, mat_b);
const float friction = properties.friction *
sead::Mathf::min(body_a->getFrictionScale(), body_b->getFrictionScale());
const float restitution =
properties.restitution * sead::Mathf::min(body_a->getEffectiveRestitutionScale(),
body_b->getEffectiveRestitutionScale());
hk_point_properties->setFriction(friction);
hk_point_properties->setRestitution(restitution);
}
} // namespace ksys::phys

View File

@ -0,0 +1,39 @@
#pragma once
#include "KingSystem/Physics/System/physContactListener.h"
class hkpCdBody;
namespace ksys::phys {
class EntityContactListener : public ContactListener {
SEAD_RTTI_OVERRIDE(EntityContactListener, ContactListener)
public:
static EntityContactListener* make(ContactMgr* mgr, sead::Heap* heap);
~EntityContactListener() override;
void collisionAddedCallback(const hkpCollisionEvent& event) override;
void collisionRemovedCallback(const hkpCollisionEvent& event) override;
static bool isObjectOrGroundOrNPCOrTree(const RigidBody& body);
static bool isObjectOrGroundOrNPCOrTree(const hkpCdBody& cd_body);
protected:
EntityContactListener(ContactMgr* mgr, sead::Heap* heap);
bool contactPointCallbackImpl(u32 ignored_layers_a, u32 ignored_layers_b, RigidBody* body_a,
RigidBody* body_b, ContactLayer layer_a, ContactLayer layer_b,
const hkpContactPointEvent& event) override;
void m11(const hkpContactPointEvent& event, const RigidBodyCollisionMasks& masks_a,
const RigidBodyCollisionMasks& masks_b, RigidBody* body_a, RigidBody* body_b) override;
bool
regularContactPointCallback(const hkpContactPointEvent& event, RigidBody* body_a,
RigidBody* body_b,
sead::SafeArray<MaterialMaskData, 2>* out_material_masks) override;
u32 m15() override;
};
} // namespace ksys::phys

View File

@ -13,6 +13,13 @@ namespace ksys::phys {
class MaterialTable { class MaterialTable {
public: public:
/// Properties for interactions between two materials.
struct MaterialPairProperties {
float friction;
float restitution;
};
/// Parameter object that stores an entire row of InteractionProperties.
struct Values : agl::utl::IParameterObj { struct Values : agl::utl::IParameterObj {
sead::SafeArray<agl::utl::Parameter<sead::Vector2f>, Material::size()> values; sead::SafeArray<agl::utl::Parameter<sead::Vector2f>, Material::size()> values;
}; };
@ -30,6 +37,11 @@ public:
void loadMaterialTable(sead::Heap* heap, agl::utl::ResParameterArchive archive); void loadMaterialTable(sead::Heap* heap, agl::utl::ResParameterArchive archive);
void loadSubMaterialTable(sead::Heap* heap, agl::utl::ResParameterArchive archive); void loadSubMaterialTable(sead::Heap* heap, agl::utl::ResParameterArchive archive);
MaterialPairProperties getPairProperties(Material mat_a, Material mat_b) const {
auto& vec = mMaterialTable[mat_a].values[mat_b];
return {vec->x, vec->y};
}
const sead::SafeString& getSubMaterial(Material material, int submat_idx) const; const sead::SafeString& getSubMaterial(Material material, int submat_idx) const;
const sead::SafeString& getSoundMatchingSubMaterial(Material material, int submat_idx) const; const sead::SafeString& getSoundMatchingSubMaterial(Material material, int submat_idx) const;

View File

@ -1,12 +1,18 @@
#pragma once #pragma once
#include <Havok/Common/Base/hkBase.h> #include <Havok/Common/Base/hkBase.h>
#include <Havok/Physics2012/Collide/Agent/Collidable/hkpCdBody.h>
#include <Havok/Physics2012/Collide/Agent/Collidable/hkpCollidable.h>
#include <Havok/Physics2012/Dynamics/Entity/hkpEntity.h>
#include <Havok/Physics2012/Dynamics/World/hkpWorldObject.h>
#include <math/seadMatrix.h> #include <math/seadMatrix.h>
#include <math/seadQuat.h> #include <math/seadQuat.h>
#include <math/seadVector.h> #include <math/seadVector.h>
namespace ksys::phys { namespace ksys::phys {
class RigidBody;
inline void toVec3(sead::Vector3f* out, const hkVector4f& vec) { inline void toVec3(sead::Vector3f* out, const hkVector4f& vec) {
out->x = vec.getX(); out->x = vec.getX();
out->y = vec.getY(); out->y = vec.getY();
@ -96,4 +102,20 @@ inline u32 getShapeKeyOrMinus1(const u32* shape_key) {
return shape_key ? *shape_key : u32(-1); return shape_key ? *shape_key : u32(-1);
} }
inline RigidBody* getRigidBody(const hkpEntity* entity) {
// This needs to be kept in sync with the RigidBody constructor!
return reinterpret_cast<RigidBody*>(entity->getUserData());
}
inline RigidBody* getRigidBody(const hkpCollidable& collidable) {
if (collidable.getType() != hkpWorldObject::BroadPhaseType::BROAD_PHASE_ENTITY)
return nullptr;
auto* entity = static_cast<const hkpEntity*>(collidable.getOwner());
if (!entity)
return nullptr;
return getRigidBody(entity);
}
} // namespace ksys::phys } // namespace ksys::phys

View File

@ -23,6 +23,11 @@ union MaterialMaskData {
return u32(idx) < (1 << decltype(sub_material)::NumBits()); return u32(idx) < (1 << decltype(sub_material)::NumBits());
} }
Material getMaterial() const { return int(material.Value()); }
int getSubMaterialIndex() const { return int(sub_material.Value()); }
FloorCode getFloorCode() const { return int(floor.Value()); }
WallCode getWallCode() const { return int(wall.Value()); }
void setFlag(bool b) { void setFlag(bool b) {
if (!b) if (!b)
clearFlag(); clearFlag();
@ -75,8 +80,11 @@ public:
MaterialMaskData& getData() { return mData; } MaterialMaskData& getData() { return mData; }
const MaterialMaskData& getData() const { return mData; } const MaterialMaskData& getData() const { return mData; }
u32 getRawData() const { return mData.raw; } u32 getRawData() const { return mData.raw; }
Material getMaterial() const { return Material::ValueType(mData.material.Value()); }
int getSubMaterialIdx() const { return mData.sub_material; } Material getMaterial() const { return mData.getMaterial(); }
int getSubMaterialIdx() const { return mData.getSubMaterialIndex(); }
FloorCode getFloorCode() const { return mData.getFloorCode(); }
WallCode getWallCode() const { return mData.getWallCode(); }
const char* getMaterialName() const; const char* getMaterialName() const;
const char* getSubMaterialName() const; const char* getSubMaterialName() const;