1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#include "KingSystem/Physics/System/physPhantom.h"
#include <Havok/Physics2012/Dynamics/World/hkpWorld.h>
#include <math/seadVector.h>
#include <prim/seadSafeString.h>
#include "KingSystem/Physics/RigidBody/physRigidBodyRequestMgr.h"
#include "KingSystem/Physics/System/physSystem.h"
#include "KingSystem/Physics/System/physUserTag.h"
#include "KingSystem/Physics/physConversions.h"
#include "KingSystem/Utils/Debug.h"
#include "KingSystem/Utils/HeapUtil.h"
namespace ksys::phys {
Phantom* Phantom::make(sead::Heap* heap, const sead::BoundBox3f& aabb, ContactLayerType layer_type,
const LayerMaskBuilder* layer_mask_builder, hkpAabbPhantom* havok_phantom) {
auto* phantom = util::allocWithAlign<Phantom>(heap, 0x10, aabb, layer_type);
phantom->initHavokPhantom(havok_phantom);
if (layer_mask_builder != nullptr)
phantom->setLayerMask(*layer_mask_builder);
return phantom;
}
void Phantom::free(Phantom* phantom) {
phantom->removePhantomFromWorld();
phantom->mHavokPhantom->removeReference();
delete phantom;
}
Phantom::Phantom(const sead::BoundBox3f& aabb, ContactLayerType layer_type)
: mAabb(aabb), mLayerType(layer_type) {}
void Phantom::initHavokPhantom(hkpAabbPhantom* havok_phantom) {
hkAabb aabb;
loadFromVec3(&aabb.m_min, mAabb.getMin());
loadFromVec3(&aabb.m_max, mAabb.getMax());
if (havok_phantom) {
mHavokPhantom = havok_phantom;
havok_phantom->setAabb(aabb);
} else {
mHavokPhantom = new hkpAabbPhantom(aabb);
}
}
void Phantom::setLayerMask(const LayerMaskBuilder& builder) {
mLayerMask = builder.getMasks()[int(mLayerType)].layers;
mDirtyLayerMask = true;
mHavokPhantom->getCollidableRw()->setCollisionFilterInfo(mLayerMask);
}
bool Phantom::isAddedToWorld() const {
return mHavokPhantom->isAddedToWorld();
}
void Phantom::addPhantomToWorld() {
if (isAddedToWorld())
return;
System::instance()->lockWorld(mLayerType);
System::instance()->getHavokWorld(mLayerType)->addPhantom(mHavokPhantom);
System::instance()->unlockWorld(mLayerType);
}
void Phantom::removePhantomFromWorld() {
if (!isAddedToWorld())
return;
System::instance()->lockWorld(mLayerType);
System::instance()->getHavokWorld(mLayerType)->removePhantom(mHavokPhantom);
System::instance()->unlockWorld(mLayerType);
}
void Phantom::updateHavokFilterInfoAndAabb() {
bool added = isAddedToWorld();
if (added)
System::instance()->lockWorld(mLayerType);
if (mDirtyLayerMask) {
mHavokPhantom->getCollidableRw()->setCollisionFilterInfo(mLayerMask);
mDirtyLayerMask = false;
}
hkAabb aabb;
loadFromVec3(&aabb.m_min, mAabb.getMin());
loadFromVec3(&aabb.m_max, mAabb.getMax());
mHavokPhantom->setAabb(aabb);
if (added)
System::instance()->unlockWorld(mLayerType);
}
WorldBorderPhantom::WorldBorderPhantom()
: hkpAabbPhantom(hkAabb{hkVector4f::zero(), hkVector4f(1, 1, 1, 0)}) {}
WorldBorderPhantom::~WorldBorderPhantom() = default;
void WorldBorderPhantom::addOverlappingCollidable(hkpCollidable* collidable) {
auto* body = getRigidBody(*collidable);
if (!body)
return;
auto position = sead::Vector3f::zero;
auto user_name = sead::SafeString::cEmptyString;
auto body_name = sead::SafeString::cEmptyString;
body->getPosition(&position);
body_name = body->getHkBodyName();
if (auto* tag = body->getUserTag()) {
user_name = tag->getName(body);
}
util::PrintDebugFmt("rigid body overlapped with WorldBorderPhantom: %f %f %f %s %s", position.x,
position.y, position.z, user_name, body_name);
System::instance()->getRigidBodyRequestMgr()->onMaxPositionExceeded(body->getLayerType(), body);
}
} // namespace ksys::phys
|