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