mirror of
https://github.com/zeldaret/botw
synced 2026-08-17 05:01:25 -04:00
ksys/phys: Start adding EntityContactListener
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user