mirror of https://github.com/zeldaret/botw.git
ksys/phys: Finish EntityContactListener
This commit is contained in:
parent
8cbdcbf6ea
commit
0e717ed15d
|
@ -83827,7 +83827,7 @@ Address,Quality,Size,Name
|
|||
0x0000007100fb6134,O,000008,_ZN14hkpGroupFilter11dummyUnusedEv
|
||||
0x0000007100fb613c,O,000204,_ZNK4ksys4phys17EntityGroupFilter27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x0000007100fb6208,O,000092,_ZNK4ksys4phys17EntityGroupFilter18getRuntimeTypeInfoEv
|
||||
0x0000007100fb6264,O,000044,_ZN4ksys4phys17EntityGroupFilter2m2ENS0_12ContactLayerES2_
|
||||
0x0000007100fb6264,O,000044,_ZN4ksys4phys17EntityGroupFilter27shouldContactNeverBeIgnoredENS0_12ContactLayerES2_
|
||||
0x0000007100fb6290,O,000028,_ZN4ksys4phys17EntityGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitE
|
||||
0x0000007100fb62ac,O,000020,_ZN4ksys4phys17EntityGroupFilter27getCollisionFilterInfoLayerEj
|
||||
0x0000007100fb62c0,O,000028,_ZN4ksys4phys17EntityGroupFilter22makeQueryCollisionMaskEjNS0_9GroundHitEb
|
||||
|
@ -83842,18 +83842,18 @@ Address,Quality,Size,Name
|
|||
0x0000007100fb643c,O,000108,_ZN4ksys4phys21EntityContactListener4makeEPNS0_10ContactMgrEPN4sead4HeapE
|
||||
0x0000007100fb64a8,O,000004,_ZN4ksys4phys21EntityContactListenerD1Ev
|
||||
0x0000007100fb64ac,O,000036,_ZN4ksys4phys21EntityContactListenerD0Ev
|
||||
0x0000007100fb64d0,U,000456,
|
||||
0x0000007100fb6698,U,000472,
|
||||
0x0000007100fb6870,U,000320,
|
||||
0x0000007100fb69b0,U,000304,
|
||||
0x0000007100fb6ae0,U,000492,
|
||||
0x0000007100fb6ccc,U,000120,
|
||||
0x0000007100fb64d0,O,000456,_ZN4ksys4phys21EntityContactListener22collisionAddedCallbackERK17hkpCollisionEvent
|
||||
0x0000007100fb6698,O,000472,_ZN4ksys4phys21EntityContactListener37setMagneMassScalingForContactIfNeededERK17hkpCollisionEventPNS0_9RigidBodyES6_
|
||||
0x0000007100fb6870,O,000320,_ZN4ksys4phys21EntityContactListener34setImpulseScalingForTerrainContactERK17hkpCollisionEventPNS0_9RigidBodyES6_
|
||||
0x0000007100fb69b0,O,000304,_ZN4ksys4phys21EntityContactListener24collisionRemovedCallbackERK17hkpCollisionEvent
|
||||
0x0000007100fb6ae0,O,000492,_ZN4ksys4phys21EntityContactListener40removeViscousSurfaceModifierAndCollisionERK17hkpCollisionEventPNS0_9RigidBodyES6_
|
||||
0x0000007100fb6ccc,O,000120,_ZN4ksys4phys21EntityContactListener3m15EPNS0_9RigidBodyES3_
|
||||
0x0000007100fb6d44,O,000084,_ZN4ksys4phys21EntityContactListener27isObjectOrGroundOrNPCOrTreeERKNS0_9RigidBodyE
|
||||
0x0000007100fb6d98,O,000128,_ZN4ksys4phys21EntityContactListener27isObjectOrGroundOrNPCOrTreeERK9hkpCdBody
|
||||
0x0000007100fb6e18,U,000460,
|
||||
0x0000007100fb6e18,O,000460,_ZN4ksys4phys21EntityContactListener24contactPointCallbackImplEjjPNS0_9RigidBodyES3_NS0_12ContactLayerES4_RK20hkpContactPointEvent
|
||||
0x0000007100fb6fe4,O,000284,_ZN4ksys4phys21EntityContactListener3m11ERK20hkpContactPointEventRKNS0_23RigidBodyCollisionMasksES7_PNS0_9RigidBodyES9_
|
||||
0x0000007100fb7100,U,000344,
|
||||
0x0000007100fb7258,U,002036,
|
||||
0x0000007100fb7100,O,000344,_ZN4ksys4phys21EntityContactListener29setMagneMassScalingForContactERK17hkpCollisionEventPNS0_9RigidBodyES6_
|
||||
0x0000007100fb7258,m,002036,_ZN4ksys4phys21EntityContactListener27regularContactPointCallbackERK20hkpContactPointEventPNS0_9RigidBodyES6_PN4sead9SafeArrayIjLi2EEE
|
||||
0x0000007100fb7a4c,O,000204,_ZNK4ksys4phys21EntityContactListener27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x0000007100fb7b18,O,000092,_ZNK4ksys4phys21EntityContactListener18getRuntimeTypeInfoEv
|
||||
0x0000007100fb7b74,O,000140,_ZNK4sead15RuntimeTypeInfo6DeriveIN4ksys4phys15ContactListenerEE9isDerivedEPKNS0_9InterfaceE
|
||||
|
@ -84150,7 +84150,7 @@ Address,Quality,Size,Name
|
|||
0x0000007100fc8528,O,000004,_ZN4ksys4phys24SensorSystemGroupHandlerD0Ev
|
||||
0x0000007100fc852c,O,000204,_ZNK4ksys4phys17SensorGroupFilter27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x0000007100fc85f8,O,000092,_ZNK4ksys4phys17SensorGroupFilter18getRuntimeTypeInfoEv
|
||||
0x0000007100fc8654,O,000008,_ZN4ksys4phys11GroupFilter2m2ENS0_12ContactLayerES2_
|
||||
0x0000007100fc8654,O,000008,_ZN4ksys4phys11GroupFilter27shouldContactNeverBeIgnoredENS0_12ContactLayerES2_
|
||||
0x0000007100fc865c,O,000048,_ZN4ksys4phys17SensorGroupFilter23makeCollisionFilterInfoENS0_12ContactLayerENS0_9GroundHitE
|
||||
0x0000007100fc868c,O,000024,_ZN4ksys4phys17SensorGroupFilter27getCollisionFilterInfoLayerEj
|
||||
0x0000007100fc86a4,O,000008,_ZN4ksys4phys17SensorGroupFilter22makeQueryCollisionMaskEjNS0_9GroundHitEb
|
||||
|
@ -84307,7 +84307,7 @@ Address,Quality,Size,Name
|
|||
0x0000007100fce54c,O,000048,_ZN4ksys4phys15ContactListener28getContactLayerCollisionInfoEjj
|
||||
0x0000007100fce57c,O,000308,_ZN4ksys4phys15ContactListener20contactPointCallbackERK20hkpContactPointEvent
|
||||
0x0000007100fce6b0,O,000580,_ZN4ksys4phys15ContactListener28manifoldContactPointCallbackERK20hkpContactPointEventPNS0_9RigidBodyES6_
|
||||
0x0000007100fce8f4,O,000764,_ZN4ksys4phys15ContactListener27regularContactPointCallbackERK20hkpContactPointEventPNS0_9RigidBodyES6_PN4sead9SafeArrayINS0_16MaterialMaskDataELi2EEE
|
||||
0x0000007100fce8f4,O,000764,_ZN4ksys4phys15ContactListener27regularContactPointCallbackERK20hkpContactPointEventPNS0_9RigidBodyES6_PN4sead9SafeArrayIjLi2EEE
|
||||
0x0000007100fcebf0,O,001052,_ZN4ksys4phys15ContactListener22notifyContactPointInfoEPNS0_9RigidBodyES3_NS0_12ContactLayerES4_RKNS0_23RigidBodyCollisionMasksES7_RK20hkpContactPointEventb
|
||||
0x0000007100fcf00c,M,000660,_ZN4ksys4phys15ContactListener27notifyLayerContactPointInfoERKNS1_24TrackedContactPointLayerEiPNS0_9RigidBodyES6_NS0_12ContactLayerES7_jjRK20hkpContactPointEvent
|
||||
0x0000007100fcf2a0,O,000356,_ZN4ksys4phys15ContactListener31addLayerPairForContactPointInfoEPNS0_21LayerContactPointInfoENS0_12ContactLayerES4_b
|
||||
|
@ -84319,7 +84319,7 @@ Address,Quality,Size,Name
|
|||
0x0000007100fcf7e4,O,000112,_ZNK4ksys4phys15ContactListener27checkDerivedRuntimeTypeInfoEPKN4sead15RuntimeTypeInfo9InterfaceE
|
||||
0x0000007100fcf854,O,000092,_ZNK4ksys4phys15ContactListener18getRuntimeTypeInfoEv
|
||||
0x0000007100fcf8b0,O,000004,_ZN4ksys4phys15ContactListener3m11ERK20hkpContactPointEventRKNS0_23RigidBodyCollisionMasksES7_PNS0_9RigidBodyES9_
|
||||
0x0000007100fcf8b4,O,000008,_ZN4ksys4phys15ContactListener3m15Ev
|
||||
0x0000007100fcf8b4,O,000008,_ZN4ksys4phys15ContactListener3m15EPNS0_9RigidBodyES3_
|
||||
0x0000007100fcf8bc,O,000072,_ZN4ksys4phys21LayerContactPointInfo4makeEPN4sead4HeapEiiRKNS2_14SafeStringBaseIcEEiii
|
||||
0x0000007100fcf904,O,000348,_ZN4ksys4phys21LayerContactPointInfo17registerLayerPairENS0_12ContactLayerES2_b
|
||||
0x0000007100fcfa60,O,000024,_ZN4ksys4phys21LayerContactPointInfo4freeEPS1_
|
||||
|
|
Can't render this file because it is too large.
|
|
@ -179,6 +179,7 @@ add_library(hkStubs OBJECT
|
|||
Havok/Physics2012/Dynamics/World/Memory/hkpWorldMemoryAvailableWatchDog.h
|
||||
Havok/Physics2012/Dynamics/World/Memory/Default/hkpDefaultWorldMemoryWatchDog.h
|
||||
Havok/Physics2012/Dynamics/World/Simulation/hkpSimulation.h
|
||||
Havok/Physics2012/Dynamics/World/Util/hkpWorldConstraintUtil.h
|
||||
|
||||
Havok/Physics2012/Internal/Collide/Mopp/Code/hkpMoppCode.h
|
||||
Havok/Physics2012/Internal/Solver/Contact/hkpSimpleContactConstraintDataInfo.h
|
||||
|
|
|
@ -14,7 +14,7 @@ public:
|
|||
HK_DECLARE_CLASS_ALLOCATOR(hkpConstraintData)
|
||||
HK_DECLARE_REFLECTION()
|
||||
|
||||
enum ConstraintType {
|
||||
enum ConstraintType : int {
|
||||
CONSTRAINT_TYPE_BALLANDSOCKET = 0,
|
||||
CONSTRAINT_TYPE_HINGE = 1,
|
||||
CONSTRAINT_TYPE_LIMITEDHINGE = 2,
|
||||
|
@ -65,7 +65,7 @@ public:
|
|||
explicit hkpConstraintData(hkFinishLoadedObjectFlag f);
|
||||
HK_FORCE_INLINE ~hkpConstraintData() override;
|
||||
|
||||
virtual int getType() const = 0;
|
||||
virtual ConstraintType getType() const = 0;
|
||||
virtual void getConstraintInfo(ConstraintInfo& infoOut) const = 0;
|
||||
virtual hkBool isValid() const = 0;
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ public:
|
|||
void getConstraintInfo(hkpConstraintData::ConstraintInfo& infoOut) const override;
|
||||
void getRuntimeInfo(hkBool wantRuntime, hkpConstraintData::RuntimeInfo& infoOut) const override;
|
||||
hkpSolverResults* getSolverResults(hkpConstraintRuntime* runtime) const override;
|
||||
int getType() const override;
|
||||
ConstraintType getType() const override;
|
||||
|
||||
virtual void collisionResponseBeginCallback(const hkContactPoint& cp,
|
||||
struct hkpSimpleConstraintInfoInitInput& inA,
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include <Havok/Common/Base/hkBase.h>
|
||||
#include <Havok/Physics/Constraint/Atom/hkpConstraintAtom.h>
|
||||
|
||||
struct hkConstraintInternal;
|
||||
|
||||
class hkpConstraintInstance;
|
||||
class hkpConstraintOwner;
|
||||
class hkpEntity;
|
||||
struct hkpModifierConstraintAtom;
|
||||
class hkpWorld;
|
||||
|
||||
class hkpWorldConstraintUtil {
|
||||
public:
|
||||
static void addConstraint(hkpWorld* world, hkpConstraintInstance* constraint);
|
||||
|
||||
static void removeConstraint(hkpConstraintInstance* constraint);
|
||||
|
||||
static hkpConstraintInstance* getConstraint(const hkpEntity* entityA, const hkpEntity* entityB);
|
||||
|
||||
static void addModifier(hkpConstraintInstance* instance, hkpConstraintOwner& constraintOwner,
|
||||
hkpModifierConstraintAtom* s);
|
||||
|
||||
static void removeAndDeleteModifier(hkpConstraintInstance* instance,
|
||||
hkpConstraintOwner& constraintOwner,
|
||||
hkpConstraintAtom::AtomType type);
|
||||
|
||||
static hkpModifierConstraintAtom* findModifier(hkpConstraintInstance* instance,
|
||||
hkpConstraintAtom::AtomType type);
|
||||
|
||||
static hkpModifierConstraintAtom* findLastModifier(hkpConstraintInstance* instance);
|
||||
|
||||
static void updateFatherOfMovedAtom(hkpConstraintInstance* instance,
|
||||
const hkpConstraintAtom* oldAtom,
|
||||
const hkpConstraintAtom* updatedAtom,
|
||||
int updatedSizeOfAtom);
|
||||
|
||||
HK_FORCE_INLINE static hkpConstraintAtom*
|
||||
getTerminalAtom(const hkConstraintInternal* cInternal);
|
||||
};
|
|
@ -87,6 +87,8 @@ target_sources(uking PRIVATE
|
|||
RigidBody/TeraMesh/physTeraMeshRigidBodyResource.cpp
|
||||
RigidBody/TeraMesh/physTeraMeshRigidBodyResource.h
|
||||
|
||||
RigidBody/TerrainHeightField/physTerrainHeightFieldRigidBody.h
|
||||
|
||||
StaticCompound/physStaticCompound.cpp
|
||||
StaticCompound/physStaticCompound.h
|
||||
StaticCompound/physStaticCompoundAutogen.cpp
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
|
||||
|
||||
namespace ksys::phys {
|
||||
|
||||
class TerrainHeightFieldRigidBody : public RigidBody {
|
||||
SEAD_RTTI_OVERRIDE(TerrainHeightFieldRigidBody, RigidBody)
|
||||
public:
|
||||
bool getD8() const { return _d8; }
|
||||
|
||||
private:
|
||||
void* _d0{};
|
||||
bool _d8 = false;
|
||||
};
|
||||
|
||||
} // namespace ksys::phys
|
|
@ -30,6 +30,12 @@ public:
|
|||
_200 = 1 << 9,
|
||||
};
|
||||
|
||||
enum class ContactFlag {
|
||||
_1 = 1 << 0,
|
||||
_2 = 1 << 1,
|
||||
_4 = 1 << 2,
|
||||
};
|
||||
|
||||
explicit RigidBodyMotionEntity(RigidBody* body);
|
||||
|
||||
void setTransform(const sead::Matrix34f& mtx, bool propagate_to_linked_motions) override;
|
||||
|
@ -122,6 +128,9 @@ public:
|
|||
void resetFlag(Flag flag) { mFlags.reset(flag); }
|
||||
void changeFlag(Flag flag, bool on) { mFlags.change(flag, on); }
|
||||
|
||||
auto& getContactFlags() { return mContactFlags; }
|
||||
auto& getContactFlags() const { return mContactFlags; }
|
||||
|
||||
static void setImpulseEpsilon(float epsilon);
|
||||
static void setDefaultMaxImpulse(float max_impulse);
|
||||
|
||||
|
@ -152,7 +161,7 @@ private:
|
|||
float mRestitutionScale = 1.0f;
|
||||
float mMaxImpulse = -1.0f;
|
||||
float mColImpulseScale = 1.0f;
|
||||
sead::Atomic<u32> _c4;
|
||||
sead::TypedBitFlag<ContactFlag, sead::Atomic<u32>> mContactFlags;
|
||||
sead::TypedBitFlag<Flag, sead::Atomic<u32>> mFlags;
|
||||
u32 _cc{};
|
||||
sead::CriticalSection mCS;
|
||||
|
|
|
@ -18,18 +18,6 @@
|
|||
|
||||
namespace ksys::phys {
|
||||
|
||||
static void clearCallbackDelay(const hkpContactPointEvent& event) {
|
||||
event.m_contactMgr->m_contactPointCallbackDelay = 0;
|
||||
}
|
||||
|
||||
static void disableContact(const hkpContactPointEvent& event) {
|
||||
event.m_contactPointProperties->m_flags |= hkpContactPointProperties::CONTACT_IS_DISABLED;
|
||||
}
|
||||
|
||||
static bool isContactDisabled(const hkpContactPointEvent& event) {
|
||||
return event.m_contactPointProperties->m_flags & hkpContactPointProperties::CONTACT_IS_DISABLED;
|
||||
}
|
||||
|
||||
ContactListener::ContactListener(ContactMgr* mgr, ContactLayerType layer_type, int layer_count)
|
||||
: mMgr(mgr), mLayerType(layer_type), mLayerBase(getContactLayerBase(layer_type)),
|
||||
mLayerCount(layer_count) {}
|
||||
|
@ -168,9 +156,9 @@ bool ContactListener::manifoldContactPointCallback(const hkpContactPointEvent& e
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ContactListener::regularContactPointCallback(
|
||||
const hkpContactPointEvent& event, RigidBody* body_a, RigidBody* body_b,
|
||||
sead::SafeArray<MaterialMaskData, 2>* out_material_masks) {
|
||||
bool ContactListener::regularContactPointCallback(const hkpContactPointEvent& event,
|
||||
RigidBody* body_a, RigidBody* body_b,
|
||||
sead::SafeArray<u32, 2>* out_material_masks) {
|
||||
auto* filter = System::instance()->getGroupFilter(mLayerType);
|
||||
|
||||
RigidBody::CollisionMasks masks_a, masks_b;
|
||||
|
@ -181,8 +169,8 @@ bool ContactListener::regularContactPointCallback(
|
|||
body_b->getCollisionMasks(&masks_b, event.getShapeKeys(1), contact_point_pos);
|
||||
|
||||
if (out_material_masks) {
|
||||
(*out_material_masks)[0] = MaterialMaskData(masks_a.material_mask);
|
||||
(*out_material_masks)[1] = MaterialMaskData(masks_b.material_mask);
|
||||
(*out_material_masks)[0] = masks_a.material_mask;
|
||||
(*out_material_masks)[1] = masks_b.material_mask;
|
||||
}
|
||||
|
||||
const auto layer_a = filter->getCollisionFilterInfoLayer(masks_a.collision_filter_info);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <Havok/Physics2012/Dynamics/Collide/ContactListener/hkpContactListener.h>
|
||||
#include <Havok/Physics2012/Dynamics/Collide/ContactListener/hkpContactPointEvent.h>
|
||||
#include <Havok/Physics2012/Dynamics/Collide/hkpSimpleConstraintContactMgr.h>
|
||||
#include <Havok/Physics2012/Dynamics/Constraint/Contact/hkpContactPointProperties.h>
|
||||
#include <container/seadBuffer.h>
|
||||
#include <container/seadObjArray.h>
|
||||
#include <hostio/seadHostIONode.h>
|
||||
|
@ -46,6 +49,23 @@ public:
|
|||
void contactPointRemovedCallback(hkpContactPointRemovedEvent& event) override {}
|
||||
void contactProcessCallback(hkpContactProcessEvent& event) override {}
|
||||
|
||||
static void clearCallbackDelay(const hkpContactPointEvent& event) {
|
||||
event.m_contactMgr->m_contactPointCallbackDelay = 0;
|
||||
}
|
||||
|
||||
static void enableContact(const hkpContactPointEvent& event) {
|
||||
event.m_contactPointProperties->m_flags &= ~hkpContactPointProperties::CONTACT_IS_DISABLED;
|
||||
}
|
||||
|
||||
static void disableContact(const hkpContactPointEvent& event) {
|
||||
event.m_contactPointProperties->m_flags |= hkpContactPointProperties::CONTACT_IS_DISABLED;
|
||||
}
|
||||
|
||||
static bool isContactDisabled(const hkpContactPointEvent& event) {
|
||||
return event.m_contactPointProperties->m_flags &
|
||||
hkpContactPointProperties::CONTACT_IS_DISABLED;
|
||||
}
|
||||
|
||||
protected:
|
||||
struct TrackedContactPointLayer {
|
||||
LayerContactPointInfo* info;
|
||||
|
@ -72,12 +92,11 @@ protected:
|
|||
RigidBody* body_b);
|
||||
|
||||
/// @param out_material_masks [Optional] Pass this to get the materials of the rigid bodies.
|
||||
virtual bool
|
||||
regularContactPointCallback(const hkpContactPointEvent& event, RigidBody* body_a,
|
||||
RigidBody* body_b,
|
||||
sead::SafeArray<MaterialMaskData, 2>* out_material_masks);
|
||||
virtual bool regularContactPointCallback(const hkpContactPointEvent& event, RigidBody* body_a,
|
||||
RigidBody* body_b,
|
||||
sead::SafeArray<u32, 2>* out_material_masks);
|
||||
|
||||
virtual u32 m15() { return 0; }
|
||||
virtual bool m15(RigidBody* body_a, RigidBody* body_b) { return false; }
|
||||
|
||||
/// Record a contact point in the ContactPointInfo instances of the bodies (if applicable).
|
||||
int notifyContactPointInfo(RigidBody* body_a, RigidBody* body_b, ContactLayer layer_a,
|
||||
|
@ -95,7 +114,7 @@ protected:
|
|||
return {layer1 - int(mLayerBase), layer2 - int(mLayerBase)};
|
||||
}
|
||||
|
||||
private:
|
||||
protected:
|
||||
ContactMgr* mMgr{};
|
||||
ContactLayerType mLayerType{};
|
||||
u32 mLayerBase{};
|
||||
|
@ -106,7 +125,8 @@ private:
|
|||
u32 mTrackedLayersBufferSize{};
|
||||
u32 mLayerCount{};
|
||||
sead::CriticalSection mCS;
|
||||
u16 _90{};
|
||||
bool _90 = false;
|
||||
bool _91 = false;
|
||||
bool mDisableContactPointInfoNotifications = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -146,8 +146,8 @@ public:
|
|||
// 0x0000007100fb4228
|
||||
void x_26(RigidBody* body_a, RigidBody* body_b);
|
||||
// 0x0000007100fb42f4
|
||||
void x_27(RigidBody* body_a, RigidBody* body_b, const sead::Vector3f&, const sead::Vector3f&,
|
||||
u32 material_a, u32 material_b);
|
||||
void x_27(RigidBody* body_a, RigidBody* body_b, const sead::Vector3f& point_position,
|
||||
const sead::Vector3f& point_separating_normal, u32 material_a, u32 material_b);
|
||||
// 0x0000007100fb4738
|
||||
void x_28(void* unk);
|
||||
// 0x0000007100fb49d4
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
#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/Collide/hkpResponseModifier.h>
|
||||
#include <Havok/Physics2012/Dynamics/Collide/hkpSimpleConstraintContactMgr.h>
|
||||
#include <Havok/Physics2012/Dynamics/Constraint/Contact/hkpContactPointProperties.h>
|
||||
#include <Havok/Physics2012/Dynamics/World/Util/hkpWorldConstraintUtil.h>
|
||||
#include <Havok/Physics2012/Dynamics/World/hkpSimulationIsland.h>
|
||||
#include <math/seadMathCalcCommon.h>
|
||||
#include "KingSystem/Physics/RigidBody/TerrainHeightField/physTerrainHeightFieldRigidBody.h"
|
||||
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
|
||||
#include "KingSystem/Physics/RigidBody/physRigidBodyMotionEntity.h"
|
||||
#include "KingSystem/Physics/System/physContactMgr.h"
|
||||
#include "KingSystem/Physics/System/physGroupFilter.h"
|
||||
#include "KingSystem/Physics/System/physMaterialTable.h"
|
||||
#include "KingSystem/Physics/System/physSystem.h"
|
||||
#include "KingSystem/Physics/physConversions.h"
|
||||
|
@ -11,6 +19,49 @@
|
|||
|
||||
namespace ksys::phys {
|
||||
|
||||
using ContactFlag = RigidBodyMotionEntity::ContactFlag;
|
||||
|
||||
static bool shouldProcessEntityContact(sead::BitFlag32 ignored_layers_a,
|
||||
sead::BitFlag32 ignored_layers_b, ContactLayer layer_a,
|
||||
ContactLayer layer_b) {
|
||||
auto* filter = System::instance()->getGroupFilter(ContactLayerType::Entity);
|
||||
return filter->shouldContactNeverBeIgnored(layer_a, layer_b) ||
|
||||
ignored_layers_a.isOffBit(layer_b) || ignored_layers_b.isOffBit(layer_a);
|
||||
}
|
||||
|
||||
static bool shouldProcessEntityContact(u32 ignored_layers_a, u32 ignored_layers_b,
|
||||
ContactLayer layer_a, ContactLayer layer_b) {
|
||||
return shouldProcessEntityContact(sead::BitFlag32(ignored_layers_a),
|
||||
sead::BitFlag32(ignored_layers_b), layer_a, layer_b);
|
||||
}
|
||||
|
||||
static bool shouldProcessEntityContact(const RigidBody* body_a, const RigidBody* body_b) {
|
||||
const auto ignored_layers_a = body_a->getIgnoredLayers();
|
||||
const auto ignored_layers_b = body_b->getIgnoredLayers();
|
||||
|
||||
const auto layer_a = body_a->getContactLayer();
|
||||
const auto layer_b = body_b->getContactLayer();
|
||||
|
||||
return shouldProcessEntityContact(ignored_layers_a, ignored_layers_b, layer_a, layer_b);
|
||||
}
|
||||
|
||||
// TODO: rename
|
||||
static bool hasEntityWithMotionFlag80(const hkpCollisionEvent& event) {
|
||||
bool has_flag_80 = false;
|
||||
auto* island = event.getSimulationIsland();
|
||||
for (int i = 0; i < island->getEntities().getSize(); ++i) {
|
||||
auto* entity = getHkpEntity(*island->getEntities()[i]->getCollidable());
|
||||
if (!entity)
|
||||
continue;
|
||||
|
||||
bool on = getRigidBody(entity)->isEntityMotionFlag80On();
|
||||
has_flag_80 |= on;
|
||||
if (on)
|
||||
break;
|
||||
}
|
||||
return has_flag_80;
|
||||
}
|
||||
|
||||
EntityContactListener* EntityContactListener::make(ContactMgr* mgr, sead::Heap* heap) {
|
||||
auto* listener = new (heap) EntityContactListener(mgr, heap);
|
||||
listener->init(heap);
|
||||
|
@ -22,6 +73,60 @@ EntityContactListener::EntityContactListener(ContactMgr* mgr, sead::Heap* heap)
|
|||
|
||||
EntityContactListener::~EntityContactListener() = default;
|
||||
|
||||
void EntityContactListener::collisionAddedCallback(const hkpCollisionEvent& event) {
|
||||
auto* body_a = getRigidBody(event.getBody(0));
|
||||
auto* body_b = getRigidBody(event.getBody(1));
|
||||
|
||||
handleCollisionAdded(event, body_a, body_b);
|
||||
|
||||
const auto ignored_layers_a = body_a->getIgnoredLayers();
|
||||
const auto ignored_layers_b = body_b->getIgnoredLayers();
|
||||
|
||||
const auto layer_a = body_a->getContactLayer();
|
||||
const auto layer_b = body_b->getContactLayer();
|
||||
|
||||
bool should_process =
|
||||
shouldProcessEntityContact(ignored_layers_a, ignored_layers_b, layer_a, layer_b);
|
||||
if (!should_process) {
|
||||
setMagneMassScalingForContactIfNeeded(event, body_a, body_b);
|
||||
setImpulseScalingForTerrainContact(event, body_a, body_b);
|
||||
}
|
||||
|
||||
if ((layer_a == ContactLayer::EntityWater &&
|
||||
body_b->getType() != RigidBody::Type::CharacterController) ||
|
||||
(layer_b == ContactLayer::EntityWater &&
|
||||
body_a->getType() != RigidBody::Type::CharacterController)) {
|
||||
body_a->onCollisionAdded();
|
||||
body_b->onCollisionAdded();
|
||||
}
|
||||
|
||||
if (!should_process && m15(body_a, body_b)) {
|
||||
mMgr->x_26(body_a, body_b);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityContactListener::collisionRemovedCallback(const hkpCollisionEvent& event) {
|
||||
auto* body_a = getRigidBody(event.getBody(0));
|
||||
auto* body_b = getRigidBody(event.getBody(1));
|
||||
|
||||
handleCollisionRemoved(event, body_a, body_b);
|
||||
removeViscousSurfaceModifierAndCollision(event, body_a, body_b);
|
||||
removeMassChangerModifier(event, body_a, body_b);
|
||||
}
|
||||
|
||||
bool EntityContactListener::m15(RigidBody* body_a, RigidBody* body_b) {
|
||||
if (body_a->isEntityMotionFlag4Off() && body_b->isEntityMotionFlag4Off() &&
|
||||
(body_a->getMaxImpulse() >= 0 || body_b->getMaxImpulse() >= 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (body_a->isEntityMotionFlag8On() || body_b->isEntityMotionFlag8On()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntityContactListener::isObjectOrGroundOrNPCOrTree(const RigidBody& body) {
|
||||
switch (body.getContactLayer().value()) {
|
||||
case ContactLayer::EntityObject:
|
||||
|
@ -45,6 +150,71 @@ bool EntityContactListener::isObjectOrGroundOrNPCOrTree(const hkpCdBody& cd_body
|
|||
return isObjectOrGroundOrNPCOrTree(*body);
|
||||
}
|
||||
|
||||
// TODO: rename
|
||||
static bool unkLayerCheck(const RigidBody* body_a, const RigidBody* body_b, ContactLayer layer_a,
|
||||
ContactLayer layer_b) {
|
||||
if (layer_a.value() == ContactLayer::EntityPlayer ||
|
||||
layer_a.value() == ContactLayer::EntityNPC) {
|
||||
switch (layer_b.value()) {
|
||||
case ContactLayer::EntityObject:
|
||||
case ContactLayer::EntityGroundObject:
|
||||
case ContactLayer::EntityTree:
|
||||
if (!body_b->hasFlag(RigidBody::Flag::_400000))
|
||||
return true;
|
||||
break;
|
||||
case ContactLayer::EntityPlayer:
|
||||
case ContactLayer::EntityNPC:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (layer_b.value() == ContactLayer::EntityPlayer ||
|
||||
layer_b.value() == ContactLayer::EntityNPC) {
|
||||
switch (layer_a.value()) {
|
||||
case ContactLayer::EntityObject:
|
||||
case ContactLayer::EntityGroundObject:
|
||||
case ContactLayer::EntityTree:
|
||||
if (!body_a->hasFlag(RigidBody::Flag::_400000))
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntityContactListener::contactPointCallbackImpl(u32 ignored_layers_a, u32 ignored_layers_b,
|
||||
RigidBody* body_a, RigidBody* body_b,
|
||||
ContactLayer layer_a, ContactLayer layer_b,
|
||||
const hkpContactPointEvent& event) {
|
||||
if (shouldProcessEntityContact(ignored_layers_a, ignored_layers_b, layer_a, layer_b) ||
|
||||
(_91 && unkLayerCheck(body_a, body_b, layer_a, layer_b))) {
|
||||
disableContact(event);
|
||||
|
||||
if (event.m_type == hkpContactPointEvent::TYPE_MANIFOLD &&
|
||||
(layer_a == ContactLayer::EntityWater || layer_b == ContactLayer::EntityWater)) {
|
||||
clearCallbackDelay(event);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isContactDisabled(event)) {
|
||||
auto* constraint = event.m_contactMgr->getConstraintInstance();
|
||||
if (constraint == nullptr ||
|
||||
constraint->getData()->getType() != hkpConstraintData::CONSTRAINT_TYPE_CONTACT ||
|
||||
!(constraint->getUserData() & 0x10000)) {
|
||||
// Clear the contact disabled flag.
|
||||
enableContact(event);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void EntityContactListener::m11(const hkpContactPointEvent& event,
|
||||
const RigidBodyCollisionMasks& masks_a,
|
||||
const RigidBodyCollisionMasks& masks_b, RigidBody* body_a,
|
||||
|
@ -70,4 +240,292 @@ void EntityContactListener::m11(const hkpContactPointEvent& event,
|
|||
hk_point_properties->setRestitution(restitution);
|
||||
}
|
||||
|
||||
KSYS_ALWAYS_INLINE static bool needsMagneMassScaling(const hkpCollisionEvent& event,
|
||||
RigidBody* body_a, RigidBody* body_b) {
|
||||
if (body_a->getMotionType() != MotionType::Dynamic ||
|
||||
body_b->getMotionType() != MotionType::Dynamic) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (body_a->getEntityMotionAccessor() == nullptr ||
|
||||
body_b->getEntityMotionAccessor() == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (body_a->getEntityMotionAccessor()->getContactFlags().isOff(ContactFlag::_1) &&
|
||||
body_b->getEntityMotionAccessor()->getContactFlags().isOff(ContactFlag::_1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasEntityWithMotionFlag80(event))
|
||||
return false;
|
||||
|
||||
return body_a->getMagneMassScalingFactor() >= 0 && body_b->getMagneMassScalingFactor() >= 0;
|
||||
}
|
||||
|
||||
static void updateMotionAccessorFlagsForMagneMassScaling(RigidBody* body_a, RigidBody* body_b) {
|
||||
// Set flag 1 and reset flag 2.
|
||||
body_a->getEntityMotionAccessor()->getContactFlags().set(ContactFlag::_1);
|
||||
body_b->getEntityMotionAccessor()->getContactFlags().set(ContactFlag::_1);
|
||||
|
||||
body_a->getEntityMotionAccessor()->getContactFlags().reset(ContactFlag::_2);
|
||||
body_b->getEntityMotionAccessor()->getContactFlags().reset(ContactFlag::_2);
|
||||
}
|
||||
|
||||
void EntityContactListener::setMagneMassScalingForContactIfNeeded(const hkpCollisionEvent& event,
|
||||
RigidBody* body_a,
|
||||
RigidBody* body_b) {
|
||||
if (!System::instance()->getEntityContactListenerField90())
|
||||
return;
|
||||
|
||||
if (!needsMagneMassScaling(event, body_a, body_b))
|
||||
return;
|
||||
|
||||
updateMotionAccessorFlagsForMagneMassScaling(body_a, body_b);
|
||||
setMagneMassScalingForContact(event, body_a, body_b);
|
||||
}
|
||||
|
||||
void EntityContactListener::setImpulseScalingForTerrainContact(const hkpCollisionEvent& event,
|
||||
RigidBody* body_a,
|
||||
RigidBody* body_b) {
|
||||
if (body_a->getType() != RigidBody::Type::TerrainHeightField &&
|
||||
body_b->getType() != RigidBody::Type::TerrainHeightField) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* body1 = body_a->getType() == RigidBody::Type::TerrainHeightField ? body_a : body_b;
|
||||
auto* body2 = body1 == body_a ? body_b : body_a;
|
||||
|
||||
if (body2->getType() != RigidBody::Type::CharacterController ||
|
||||
int(body1->getContactLayer()) != ContactLayer::EntityGround) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* height_field_body = sead::DynamicCast<TerrainHeightFieldRigidBody>(body1);
|
||||
if (!height_field_body || !height_field_body->getD8())
|
||||
return;
|
||||
|
||||
[[maybe_unused]] auto* constraint = event.m_contactMgr->getConstraintInstance();
|
||||
hkpResponseModifier::setImpulseScalingForContact(event.m_contactMgr, body_a->getHkBody(),
|
||||
body_b->getHkBody(),
|
||||
*event.getSimulationIsland(), 15.0, 25.0);
|
||||
}
|
||||
|
||||
static bool removeViscousSurfaceModifier(const hkpCollisionEvent& event) {
|
||||
constexpr auto type = hkpConstraintAtom::TYPE_MODIFIER_VISCOUS_SURFACE;
|
||||
auto* constraint = event.m_contactMgr->getConstraintInstance();
|
||||
if (!hkpWorldConstraintUtil::findModifier(constraint, type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* island = event.getSimulationIsland();
|
||||
hkpWorldConstraintUtil::removeAndDeleteModifier(constraint, *island, type);
|
||||
|
||||
if (constraint &&
|
||||
constraint->getData()->getType() == hkpConstraintData::CONSTRAINT_TYPE_CONTACT) {
|
||||
// TODO: add named constants for this flag?
|
||||
constraint->m_userData &= ~1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void EntityContactListener::removeViscousSurfaceModifierAndCollision(
|
||||
const hkpCollisionEvent& event, RigidBody* body_a, RigidBody* body_b) {
|
||||
if (!removeViscousSurfaceModifier(event))
|
||||
return;
|
||||
|
||||
const auto update_contact_flags = [](RigidBody* body) {
|
||||
if (!body->getEntityMotionAccessor()->getContactFlags().isOn(ContactFlag::_1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (body->isEntityMotionFlag80On())
|
||||
return;
|
||||
|
||||
body->getEntityMotionAccessor()->getContactFlags().reset(ContactFlag::_1);
|
||||
body->getEntityMotionAccessor()->getContactFlags().set(ContactFlag::_2);
|
||||
body->getEntityMotionAccessor()->getContactFlags().reset(ContactFlag::_4);
|
||||
};
|
||||
|
||||
update_contact_flags(body_a);
|
||||
update_contact_flags(body_b);
|
||||
body_a->onCollisionRemoved();
|
||||
body_b->onCollisionRemoved();
|
||||
}
|
||||
|
||||
KSYS_ALWAYS_INLINE inline void
|
||||
EntityContactListener::removeMassChangerModifier(const hkpCollisionEvent& event, RigidBody* body_a,
|
||||
RigidBody* body_b) {
|
||||
constexpr auto type = hkpConstraintAtom::TYPE_MODIFIER_MASS_CHANGER;
|
||||
auto* constraint = event.m_contactMgr->getConstraintInstance();
|
||||
if (hkpWorldConstraintUtil::findModifier(constraint, type)) {
|
||||
auto* island = event.getSimulationIsland();
|
||||
hkpWorldConstraintUtil::removeAndDeleteModifier(constraint, *island, type);
|
||||
}
|
||||
|
||||
const auto a_is_water_and_b_not_charctrl = [](RigidBody* a, RigidBody* b) {
|
||||
return a->getContactLayer() == ContactLayer::EntityWater &&
|
||||
b->getType() != RigidBody::Type::CharacterController;
|
||||
};
|
||||
|
||||
if (a_is_water_and_b_not_charctrl(body_a, body_b) ||
|
||||
a_is_water_and_b_not_charctrl(body_b, body_a)) {
|
||||
body_a->onCollisionRemoved();
|
||||
body_b->onCollisionRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
inline void EntityContactListener::setMagneMassScalingForContact(const hkpCollisionEvent& event,
|
||||
RigidBody* body_a,
|
||||
RigidBody* body_b) {
|
||||
const auto factor_a = body_a->getMagneMassScalingFactor();
|
||||
const auto factor_b = body_b->getMagneMassScalingFactor();
|
||||
|
||||
body_a->onCollisionAdded();
|
||||
body_b->onCollisionAdded();
|
||||
|
||||
const auto mass_a = body_a->getMass();
|
||||
const auto mass_b = body_b->getMass();
|
||||
|
||||
const auto* heavier_body = (mass_a < mass_b) ? body_b : body_a;
|
||||
const auto* lighter_body = (mass_a < mass_b) ? body_a : body_b;
|
||||
|
||||
const auto heavier_factor = (mass_a < mass_b) ? factor_b : factor_a;
|
||||
const auto lighter_factor = (mass_a < mass_b) ? factor_a : factor_b;
|
||||
|
||||
const auto effective_mass1 = lighter_body->getMass() * heavier_factor;
|
||||
const auto effective_mass2 = heavier_body->getMass() * lighter_factor;
|
||||
|
||||
hkVector4f mass_ratio;
|
||||
mass_ratio.setAll(effective_mass1 / effective_mass2);
|
||||
|
||||
hkpResponseModifier::setInvMassScalingForContact(event.m_contactMgr, lighter_body->getHkBody(),
|
||||
*event.getSimulationIsland(), mass_ratio);
|
||||
|
||||
if (auto* constraint = event.m_contactMgr->getConstraintInstance()) {
|
||||
if (constraint->getData()->getType() == hkpConstraintData::CONSTRAINT_TYPE_CONTACT)
|
||||
constraint->m_userData |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void updateMotionFlagsAtEndOfStep(const hkpCollisionEvent& event, RigidBody* body_a,
|
||||
RigidBody* body_b) {
|
||||
const auto update_flags1 = [](RigidBody* a, RigidBody* b) {
|
||||
if (!a->getEntityMotionAccessor()->getContactFlags().isOn(ContactFlag::_2))
|
||||
return false;
|
||||
if (!b->getEntityMotionAccessor()->getContactFlags().isOn(ContactFlag::_4))
|
||||
return false;
|
||||
|
||||
a->getEntityMotionAccessor()->getContactFlags().set(ContactFlag::_1);
|
||||
a->getEntityMotionAccessor()->getContactFlags().reset(ContactFlag::_2);
|
||||
a->getEntityMotionAccessor()->getContactFlags().set(ContactFlag::_4);
|
||||
return true;
|
||||
};
|
||||
|
||||
const auto update_flags2 = [](RigidBody* a, RigidBody* b) {
|
||||
if (!a->getEntityMotionAccessor()->getContactFlags().isOn(ContactFlag::_2))
|
||||
return false;
|
||||
if (b->isEntityMotionFlag80On())
|
||||
return false;
|
||||
if (!b->getEntityMotionAccessor()->getContactFlags().isOn(ContactFlag::_1))
|
||||
return false;
|
||||
|
||||
b->getEntityMotionAccessor()->getContactFlags().reset(ContactFlag::_1);
|
||||
b->getEntityMotionAccessor()->getContactFlags().set(ContactFlag::_2);
|
||||
return true;
|
||||
};
|
||||
|
||||
const auto update_flags3 = [](RigidBody* a, RigidBody* b) {
|
||||
if (!a->getEntityMotionAccessor()->getContactFlags().isOn(ContactFlag::_1))
|
||||
return false;
|
||||
if (!b->getEntityMotionAccessor()->getContactFlags().isOff(ContactFlag::_1))
|
||||
return false;
|
||||
|
||||
b->getEntityMotionAccessor()->getContactFlags().set(ContactFlag::_1);
|
||||
b->getEntityMotionAccessor()->getContactFlags().reset(ContactFlag::_2);
|
||||
return true;
|
||||
};
|
||||
|
||||
const auto update_flags4 = [](RigidBody* body) {
|
||||
if (!body->getEntityMotionAccessor()->getContactFlags().isOn(ContactFlag::_4))
|
||||
return false;
|
||||
if (body->isEntityMotionFlag80On())
|
||||
return false;
|
||||
if (body->x_105())
|
||||
return false;
|
||||
|
||||
body->getEntityMotionAccessor()->getContactFlags() = ContactFlag::_1;
|
||||
return true;
|
||||
};
|
||||
|
||||
bool updated1 = false;
|
||||
updated1 |= update_flags1(body_a, body_b);
|
||||
updated1 |= update_flags1(body_b, body_a);
|
||||
|
||||
if (!updated1) {
|
||||
bool updated2 = false;
|
||||
updated2 |= update_flags2(body_a, body_b);
|
||||
updated2 |= update_flags2(body_b, body_a);
|
||||
|
||||
if (updated2) {
|
||||
removeViscousSurfaceModifier(event);
|
||||
} else {
|
||||
update_flags3(body_a, body_b);
|
||||
update_flags3(body_b, body_a);
|
||||
}
|
||||
}
|
||||
|
||||
update_flags4(body_a);
|
||||
update_flags4(body_b);
|
||||
}
|
||||
|
||||
// NON_MATCHING: branching (body_a->getEntityMotionAccessor() call not merged)
|
||||
bool EntityContactListener::regularContactPointCallback(const hkpContactPointEvent& event,
|
||||
RigidBody* body_a, RigidBody* body_b,
|
||||
sead::SafeArray<u32, 2>*) {
|
||||
if (event.m_type == hkpContactPointEvent::TYPE_MANIFOLD_AT_END_OF_STEP) {
|
||||
auto* constraint = event.m_contactMgr->getConstraintInstance();
|
||||
|
||||
auto* modifier = hkpWorldConstraintUtil::findModifier(
|
||||
constraint, hkpConstraintAtom::TYPE_MODIFIER_VISCOUS_SURFACE);
|
||||
|
||||
const bool field90 = System::instance()->getEntityContactListenerField90();
|
||||
|
||||
if (modifier && constraint->getUserData() & 1) {
|
||||
clearCallbackDelay(event);
|
||||
|
||||
if (field90 && hasEntityWithMotionFlag80(event)) {
|
||||
updateMotionFlagsAtEndOfStep(event, body_a, body_b);
|
||||
} else {
|
||||
body_a->getEntityMotionAccessor()->getContactFlags().makeAllZero();
|
||||
body_b->getEntityMotionAccessor()->getContactFlags().makeAllZero();
|
||||
removeViscousSurfaceModifier(event);
|
||||
}
|
||||
} else if (field90 && needsMagneMassScaling(event, body_a, body_b) &&
|
||||
!shouldProcessEntityContact(body_a, body_b)) {
|
||||
updateMotionAccessorFlagsForMagneMassScaling(body_a, body_b);
|
||||
setMagneMassScalingForContact(event, body_a, body_b);
|
||||
}
|
||||
}
|
||||
|
||||
sead::SafeArray<u32, 2> material_masks;
|
||||
bool result =
|
||||
ContactListener::regularContactPointCallback(event, body_a, body_b, &material_masks);
|
||||
|
||||
if (event.m_contactPointProperties->m_flags & hkpContactPointProperties::CONTACT_IS_NEW &&
|
||||
m15(body_a, body_b)) {
|
||||
sead::Vector3f position, normal;
|
||||
storeToVec3(&position, event.m_contactPoint->getPosition());
|
||||
storeToVec3(&normal, event.m_contactPoint->getSeparatingNormal());
|
||||
if (body_a->isEntityMotionFlag40On() || body_b->isEntityMotionFlag40On()) {
|
||||
mMgr->x_26(body_a, body_b);
|
||||
}
|
||||
|
||||
mMgr->x_27(body_a, body_b, position, normal, material_masks[0], material_masks[1]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace ksys::phys
|
||||
|
|
|
@ -28,12 +28,27 @@ protected:
|
|||
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;
|
||||
bool regularContactPointCallback(const hkpContactPointEvent& event, RigidBody* body_a,
|
||||
RigidBody* body_b,
|
||||
sead::SafeArray<u32, 2>* out_material_masks) override;
|
||||
|
||||
u32 m15() override;
|
||||
bool m15(RigidBody* body_a, RigidBody* body_b) override;
|
||||
|
||||
private:
|
||||
void setMagneMassScalingForContactIfNeeded(const hkpCollisionEvent& event, RigidBody* body_a,
|
||||
RigidBody* body_b);
|
||||
|
||||
void setImpulseScalingForTerrainContact(const hkpCollisionEvent& event, RigidBody* body_a,
|
||||
RigidBody* body_b);
|
||||
|
||||
void removeViscousSurfaceModifierAndCollision(const hkpCollisionEvent& event, RigidBody* body_a,
|
||||
RigidBody* body_b);
|
||||
|
||||
void removeMassChangerModifier(const hkpCollisionEvent& event, RigidBody* body_a,
|
||||
RigidBody* body_b);
|
||||
|
||||
void setMagneMassScalingForContact(const hkpCollisionEvent& event, RigidBody* body_a,
|
||||
RigidBody* body_b);
|
||||
};
|
||||
|
||||
} // namespace ksys::phys
|
||||
|
|
|
@ -50,8 +50,8 @@ EntityGroupFilter::EntityGroupFilter(ContactLayer::ValueType first, ContactLayer
|
|||
EntityGroupFilter::~EntityGroupFilter() = default;
|
||||
|
||||
void EntityGroupFilter::doInit_(sead::Heap* heap) {
|
||||
// Enable all collisions by default.
|
||||
mMasks.fill(0xffffffff);
|
||||
// Allow any layer pairs to be ignored by a rigid body by default.
|
||||
mLayersThatCanBeIgnored.fill(0xffffffff);
|
||||
}
|
||||
|
||||
hkBool EntityGroupFilter::shouldHandleGroundCollision(u32 infoA, u32 infoB,
|
||||
|
|
|
@ -41,7 +41,7 @@ public:
|
|||
hkBool isCollisionEnabled(const hkpWorldRayCastInput& inputA,
|
||||
const hkpCollidable& collidableB) const override;
|
||||
|
||||
bool m2(ContactLayer layerA, ContactLayer layerB) override;
|
||||
bool shouldContactNeverBeIgnored(ContactLayer layerA, ContactLayer layerB) override;
|
||||
u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) override;
|
||||
ContactLayer getCollisionFilterInfoLayer(u32 info) override;
|
||||
u32 makeQueryCollisionMask(u32 layer_mask, GroundHit ground_hit, bool unk) override;
|
||||
|
@ -78,7 +78,10 @@ private:
|
|||
int getFreeListIndex(const SystemGroupHandler* handler) override;
|
||||
void doInit_(sead::Heap* heap) override;
|
||||
|
||||
sead::SafeArray<u32, ContactLayer::size()> mMasks;
|
||||
/// A ContactLayer::size() x ContactLayer::size() matrix such that M[i][j] indicates
|
||||
/// whether contact between layers i and layers j can be ignored.
|
||||
/// \see EntityContactListener and shouldContactNeverBeIgnored
|
||||
sead::SafeArray<u32, ContactLayer::size()> mLayersThatCanBeIgnored;
|
||||
};
|
||||
|
||||
void receiverMaskEnableLayer(SensorCollisionMask* mask, ContactLayer layer);
|
||||
|
@ -143,8 +146,9 @@ inline bool EntitySystemGroupHandler::m8() {
|
|||
return getIndex() > 0 && getIndex() < 0x400;
|
||||
}
|
||||
|
||||
inline bool EntityGroupFilter::m2(ContactLayer layerA, ContactLayer layerB) {
|
||||
return (mMasks[layerA.value()] & (1 << layerB.value())) == 0;
|
||||
inline bool EntityGroupFilter::shouldContactNeverBeIgnored(ContactLayer layerA,
|
||||
ContactLayer layerB) {
|
||||
return (mLayersThatCanBeIgnored[layerA.value()] & (1 << layerB.value())) == 0;
|
||||
}
|
||||
|
||||
inline u32 EntityGroupFilter::makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) {
|
||||
|
@ -185,7 +189,7 @@ inline const char* EntityGroupFilter::getCollisionFilterInfoLayerText(u32 info)
|
|||
}
|
||||
|
||||
inline void EntityGroupFilter::setLayerCustomMask(ContactLayer layer, u32 mask) {
|
||||
mMasks[layer] = mask;
|
||||
mLayersThatCanBeIgnored[layer] = mask;
|
||||
}
|
||||
|
||||
inline u32 EntityGroupFilter::getCollisionFilterInfoGroupHandlerIdx(u32 info) {
|
||||
|
|
|
@ -75,7 +75,11 @@ public:
|
|||
m_collisionLookupTable[layer - getLayerFirst()] = mask;
|
||||
}
|
||||
|
||||
virtual bool m2(ContactLayer layerA, ContactLayer layerB) { return true; }
|
||||
/// Indicates whether contact between layerA and layerB should never be ignored,
|
||||
/// even if the corresponding rigid bodies are configured to ignore each other's layer.
|
||||
virtual bool shouldContactNeverBeIgnored(ContactLayer layerA, ContactLayer layerB) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Make a collision filter mask with the specified layer and ground hit type.
|
||||
virtual u32 makeCollisionFilterInfo(ContactLayer layer, GroundHit ground_hit) = 0;
|
||||
|
|
|
@ -77,6 +77,12 @@ public:
|
|||
void lockWorld(ContactLayerType type, void* a = nullptr, int b = 0, bool c = false);
|
||||
void unlockWorld(ContactLayerType type, void* a = nullptr, int b = 0, bool c = false);
|
||||
|
||||
// TODO: rename
|
||||
// 0x0000007101216c60
|
||||
void setEntityContactListenerField90(bool value);
|
||||
// 0x0000007101216c74
|
||||
bool getEntityContactListenerField90() const;
|
||||
|
||||
// 0x0000007101216cec
|
||||
sead::Heap* getPhysicsTempHeap(LowPriority low_priority) const;
|
||||
|
||||
|
|
|
@ -101,16 +101,20 @@ inline u32 getShapeKeyOrMinus1(const u32* shape_key) {
|
|||
return shape_key ? *shape_key : u32(-1);
|
||||
}
|
||||
|
||||
inline const hkpEntity* getHkpEntity(const hkpCollidable& collidable) {
|
||||
if (collidable.getType() != hkpWorldObject::BroadPhaseType::BROAD_PHASE_ENTITY)
|
||||
return nullptr;
|
||||
|
||||
return static_cast<const hkpEntity*>(collidable.getOwner());
|
||||
}
|
||||
|
||||
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());
|
||||
auto* entity = getHkpEntity(collidable);
|
||||
if (!entity)
|
||||
return nullptr;
|
||||
|
||||
|
|
Loading…
Reference in New Issue