diff options
| author | Léo Lam <leo@leolam.fr> | 2022-03-08 19:14:03 +0100 |
|---|---|---|
| committer | Léo Lam <leo@leolam.fr> | 2022-03-08 20:30:12 +0100 |
| commit | a9ee6f839e40fbef0c8bd6eb40999aacfbda906d (patch) | |
| tree | 7e7a8c6f0a22c74862d019d4c81b0fd47dc955fc /src/KingSystem | |
| parent | c11a33c5abbbe7696c6a46ee591bc9e84e65d766 (diff) | |
ksys/phys: Start adding EntityContactListener
Diffstat (limited to 'src/KingSystem')
| -rw-r--r-- | src/KingSystem/Physics/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/KingSystem/Physics/System/physEntityContactListener.cpp | 73 | ||||
| -rw-r--r-- | src/KingSystem/Physics/System/physEntityContactListener.h | 39 | ||||
| -rw-r--r-- | src/KingSystem/Physics/System/physMaterialTable.h | 12 | ||||
| -rw-r--r-- | src/KingSystem/Physics/physConversions.h | 22 | ||||
| -rw-r--r-- | src/KingSystem/Physics/physMaterialMask.h | 12 |
6 files changed, 158 insertions, 2 deletions
diff --git a/src/KingSystem/Physics/CMakeLists.txt b/src/KingSystem/Physics/CMakeLists.txt index d437e5ef..cecb70e5 100644 --- a/src/KingSystem/Physics/CMakeLists.txt +++ b/src/KingSystem/Physics/CMakeLists.txt @@ -121,6 +121,8 @@ target_sources(uking PRIVATE System/physContactPointInfo.h System/physLayerContactPointInfo.cpp System/physLayerContactPointInfo.h + System/physEntityContactListener.cpp + System/physEntityContactListener.h System/physEntityGroupFilter.cpp System/physEntityGroupFilter.h System/physGroupFilter.cpp diff --git a/src/KingSystem/Physics/System/physEntityContactListener.cpp b/src/KingSystem/Physics/System/physEntityContactListener.cpp new file mode 100644 index 00000000..c7ae31ee --- /dev/null +++ b/src/KingSystem/Physics/System/physEntityContactListener.cpp @@ -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 diff --git a/src/KingSystem/Physics/System/physEntityContactListener.h b/src/KingSystem/Physics/System/physEntityContactListener.h new file mode 100644 index 00000000..11445013 --- /dev/null +++ b/src/KingSystem/Physics/System/physEntityContactListener.h @@ -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 diff --git a/src/KingSystem/Physics/System/physMaterialTable.h b/src/KingSystem/Physics/System/physMaterialTable.h index 9d94bd81..89dedf7d 100644 --- a/src/KingSystem/Physics/System/physMaterialTable.h +++ b/src/KingSystem/Physics/System/physMaterialTable.h @@ -13,6 +13,13 @@ namespace ksys::phys { class MaterialTable { 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 { 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 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& getSoundMatchingSubMaterial(Material material, int submat_idx) const; diff --git a/src/KingSystem/Physics/physConversions.h b/src/KingSystem/Physics/physConversions.h index b6dcd984..1f9aeece 100644 --- a/src/KingSystem/Physics/physConversions.h +++ b/src/KingSystem/Physics/physConversions.h @@ -1,12 +1,18 @@ #pragma once #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/seadQuat.h> #include <math/seadVector.h> namespace ksys::phys { +class RigidBody; + inline void toVec3(sead::Vector3f* out, const hkVector4f& vec) { out->x = vec.getX(); out->y = vec.getY(); @@ -96,4 +102,20 @@ inline u32 getShapeKeyOrMinus1(const u32* shape_key) { 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 diff --git a/src/KingSystem/Physics/physMaterialMask.h b/src/KingSystem/Physics/physMaterialMask.h index 40e73a63..f4482325 100644 --- a/src/KingSystem/Physics/physMaterialMask.h +++ b/src/KingSystem/Physics/physMaterialMask.h @@ -23,6 +23,11 @@ union MaterialMaskData { 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) { if (!b) clearFlag(); @@ -75,8 +80,11 @@ public: MaterialMaskData& getData() { return mData; } const MaterialMaskData& getData() const { return mData; } 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* getSubMaterialName() const; |
