summaryrefslogtreecommitdiff
path: root/src/KingSystem/Physics/RigidBody/physRigidBodyRequestMgr.h
blob: 1597b6430952fea893eb85604165f4b0c2c38857 (plain)
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#pragma once

#include <basis/seadRawPrint.h>
#include <container/seadBuffer.h>
#include <container/seadPtrArray.h>
#include <container/seadSafeArray.h>
#include <hostio/seadHostIONode.h>
#include <math/seadVector.h>
#include <prim/seadDelegate.h>
#include <thread/seadAtomic.h>
#include <thread/seadCriticalSection.h>
#include "KingSystem/Physics/System/physLayerContactPointInfo.h"
#include "KingSystem/Physics/physDefines.h"
#include "KingSystem/Utils/Container/LockFreeQueue.h"
#include "KingSystem/Utils/Types.h"

class hkpEntity;

namespace ksys::phys {

class MotionAccessor;
class RigidBody;

class RigidBodyRequestMgr : public sead::hostio::Node {
public:
    struct Config {
        float _0 = 0.6;
        float _4 = 0.7;
        float _8 = 1.25;
        float _c = 1.0;
        float _10 = 0.2;
        float _14 = 0.9;
        float _18 = 0.5;
        float _1c = 1.0;
        float _20 = 4.0;
        // 5000m/s (squared)
        float linear_velocity_threshold_sq = 2.5e7;

        static Config& get();
        static bool isLinearVelocityTooHigh(const sead::Vector3f& velocity);
        static void enableLinearVelocityChecks(bool enable);
    };

    RigidBodyRequestMgr();
    virtual ~RigidBodyRequestMgr();

    void init(sead::Heap* heap);

    // 0x0000007100fa6ac4
    void calc(ContactLayerType layer_type);
    void calc1(ContactLayerType layer_type, bool paused);

    bool pushRigidBody(ContactLayerType type, RigidBody* body);
    void addEntityToWorld(ContactLayerType type, hkpEntity* entity);
    void removeEntityFromWorld(ContactLayerType type, hkpEntity* entity);
    // 0x0000007100fa6ebc
    void removeRigidBody(ContactLayerType type, RigidBody* body);

    bool onMaxPositionExceeded(ContactLayerType layer_type, RigidBody* body);

    bool addImpulse(RigidBody* body_a, RigidBody* body_b, float impulse);

    bool registerMotionAccessor(MotionAccessor* accessor);
    bool deregisterMotionAccessor(MotionAccessor* accessor);

private:
    struct Unk1;
    struct Unk3;

    struct Unk4 {
        u8 _0[0x10];
    };
    KSYS_CHECK_SIZE_NX150(Unk4, 0x10);

    struct ImpulseEntry {
        RigidBody* body_a;
        RigidBody* body_b;
        float impulse_a;
    };
    KSYS_CHECK_SIZE_NX150(ImpulseEntry, 0x18);

    struct Unk6 {
        sead::Vector3f _0 = sead::Vector3f::zero;
        u32 _c = 0x1000000;
        sead::Vector3f _10 = sead::Vector3f::zero;
        void* _20{};
        sead::Vector3f _28 = sead::Vector3f::ey;
        float _34{};
        sead::Vector3f _38 = sead::Vector3f::zero;
        float _44{};
    };
    KSYS_CHECK_SIZE_NX150(Unk6, 0x48);

    struct PointCallback : LayerContactPointInfo::ContactCallback {
        explicit PointCallback(RigidBodyRequestMgr* mgr_) : mgr(mgr_) {}

        bool invoke(const LayerContactPointInfo::ContactEvent& event) override {
            return mgr->someFunction2(event);
        }

        RigidBodyRequestMgr* mgr;
    };

    // FIXME: rename, implement
    bool someFunction2(const LayerContactPointInfo::ContactEvent& event);
    static void someFunction(void* arg);

    void processImpulseEntries();
    void processOobRigidBodyEntries(ContactLayerType layer_type);

    static constexpr int NumRigidBodyBuffers = 2;
    static constexpr int MaxNumImpulseEntries = 0x100;

    sead::SafeArray<util::LockFreeQueue<RigidBody>, NumRigidBodyBuffers> mRigidBodies1;
    util::LockFreeQueue<Unk1> _38;
    util::LockFreeQueue<Unk1> _50;
    /// Rigid bodies that are out of bounds.
    sead::SafeArray<util::LockFreeQueue<RigidBody>, NumRigidBodyBuffers> mOobRigidBodies;
    util::LockFreeQueue<ImpulseEntry> mImpulseEntries;
    util::LockFreeQueue<Unk3> _b0;
    util::LockFreeQueue<Unk4> _c8;
    util::LockFreeQueue<Unk4> _e0;
    sead::PtrArray<MotionAccessor> mMotionAccessors;
    sead::Buffer<ImpulseEntry> mImpulseEntriesPool;
    sead::Atomic<int> mNumActiveImpulseEntries;
    sead::Buffer<Unk6> _120;
    sead::Atomic<u32> _130;
    sead::Buffer<Unk4> _138;
    u32 mNumEntitiesInWorld{};
    LayerContactPointInfo* mContactPoints{};
    sead::SafeArray<sead::CriticalSection, NumRigidBodyBuffers> mCriticalSections;
    sead::CriticalSection mCS;
    float _218 = 1.0;
    float _21c = 1.0 / 30.0;
    float _220 = 1.0 / 30.0;
    float _224 = 1.0 / 30.0;
    float _228 = 1.0 / 30.0;
    sead::Atomic<u32> _22c;
    u32 mWaterIceSubmatIdx{};
    u32 mWaterHotSubmatIdx{};
    u32 mWaterPoisonSubmatIdx{};
    PointCallback mCallback{this};
    sead::Delegate1Func<void*> _250{&RigidBodyRequestMgr::someFunction};
};
KSYS_CHECK_SIZE_NX150(RigidBodyRequestMgr, 0x260);

}  // namespace ksys::phys