-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathjolt_implementation.hpp
183 lines (156 loc) · 7.39 KB
/
jolt_implementation.hpp
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// The Jolt headers don't include Jolt.h. Always include Jolt.h before including any other Jolt header.
// You can use Jolt.h in your precompiled header to speed up compilation.
#include <Jolt/Jolt.h>
// Jolt includes
#include <Jolt/Core/Factory.h>
#include <Jolt/Core/JobSystemThreadPool.h>
#include <Jolt/Core/TempAllocator.h>
#include <Jolt/Physics/Body/BodyActivationListener.h>
#include <Jolt/Physics/Body/BodyCreationSettings.h>
#include <Jolt/Physics/Collision/Shape/BoxShape.h>
#include <Jolt/Physics/Collision/Shape/SphereShape.h>
#include <Jolt/Physics/PhysicsSettings.h>
#include <Jolt/Physics/PhysicsSystem.h>
#include <Jolt/RegisterTypes.h>
// STL includes
#include <cstdarg>
#include <iostream>
#include <sys/types.h>
#include <thread>
// Disable common warnings triggered by Jolt, you can use JPH_SUPPRESS_WARNING_PUSH / JPH_SUPPRESS_WARNING_POP to store
// and restore the warning state
// JPH_SUPPRESS_WARNINGS
// If you want your code to compile using single or double precision write 0.0_r to get a Real value that compiles to
// double or float depending if JPH_DOUBLE_PRECISION is set or not.
using namespace JPH::literals;
// Callback for traces, connect this to your own trace function if you have one
static void TraceImpl(const char *inFMT, ...) {
// Format the message
va_list list;
va_start(list, inFMT);
char buffer[1024];
vsnprintf(buffer, sizeof(buffer), inFMT, list);
va_end(list);
// Print to the TTY
std::cout << buffer << std::endl;
}
#ifdef JPH_ENABLE_ASSERTS
// Callback for asserts, connect this to your own assert handler if you have one
static bool AssertFailedImpl(const char *inExpression, const char *inMessage, const char *inFile, unsigned int inLine) {
// Print to the TTY
std::cout << inFile << ":" << inLine << ": (" << inExpression << ") " << (inMessage != nullptr ? inMessage : "")
<< std::endl;
// Breakpoint
return true;
};
#endif // JPH_ENABLE_ASSERTS
// Layer that objects can be in, determines which other objects it can collide with
// Typically you at least want to have 1 layer for moving bodies and 1 layer for static bodies, but you can have more
// layers if you want. E.g. you could have a layer for high detail collision (which is not used by the physics
// simulation but only if you do collision testing).
namespace Layers {
static constexpr JPH::ObjectLayer NON_MOVING = 0;
static constexpr JPH::ObjectLayer MOVING = 1;
static constexpr JPH::ObjectLayer NUM_LAYERS = 2;
}; // namespace Layers
class ObjectLayerPairFilterImpl : public JPH::ObjectLayerPairFilter {
public:
virtual bool ShouldCollide(JPH::ObjectLayer inObject1, JPH::ObjectLayer inObject2) const override {
switch (inObject1) {
case Layers::NON_MOVING:
return inObject2 == Layers::MOVING; // Non moving only collides with moving
case Layers::MOVING:
return true; // Moving collides with everything
default:
JPH_ASSERT(false);
return false;
}
}
};
// Each broadphase layer results in a separate bounding volume tree in the broad phase. You at least want to have
// a layer for non-moving and moving objects to avoid having to update a tree full of static objects every frame.
// You can have a 1-on-1 mapping between object layers and broadphase layers (like in this case) but if you have
// many object layers you'll be creating many broad phase trees, which is not efficient. If you want to fine tune
// your broadphase layers define JPH_TRACK_BROADPHASE_STATS and look at the stats reported on the TTY.
namespace JPH::BroadPhaseLayers {
static constexpr JPH::BroadPhaseLayer NON_MOVING(0);
static constexpr JPH::BroadPhaseLayer MOVING(1);
static constexpr unsigned int NUM_LAYERS(2);
}; // namespace JPH::BroadPhaseLayers
// JPH::BroadPhaseLayerInterface implementation
// This defines a mapping between object and broadphase layers.
class BPLayerInterfaceImpl final : public JPH::BroadPhaseLayerInterface {
public:
BPLayerInterfaceImpl() {
// Create a mapping table from object to broad phase layer
mObjectToBroadPhase[Layers::NON_MOVING] = JPH::BroadPhaseLayers::NON_MOVING;
mObjectToBroadPhase[Layers::MOVING] = JPH::BroadPhaseLayers::MOVING;
}
virtual unsigned int GetNumBroadPhaseLayers() const override { return JPH::BroadPhaseLayers::NUM_LAYERS; }
virtual JPH::BroadPhaseLayer GetBroadPhaseLayer(JPH::ObjectLayer inLayer) const override {
JPH_ASSERT(inLayer < Layers::NUM_LAYERS);
return mObjectToBroadPhase[inLayer];
}
#if defined(JPH_EXTERNAL_PROFILE) || defined(JPH_PROFILE_ENABLED)
virtual const char *GetBroadPhaseLayerName(JPH::BroadPhaseLayer inLayer) const override {
switch ((JPH::BroadPhaseLayer::Type)inLayer) {
case (JPH::BroadPhaseLayer::Type)JPH::BroadPhaseLayers::NON_MOVING:
return "NON_MOVING";
case (JPH::BroadPhaseLayer::Type)JPH::BroadPhaseLayers::MOVING:
return "MOVING";
default:
JPH_ASSERT(false);
return "INVALID";
}
}
#endif // JPH_EXTERNAL_PROFILE || JPH_PROFILE_ENABLED
private:
JPH::BroadPhaseLayer mObjectToBroadPhase[Layers::NUM_LAYERS];
};
class ObjectVsBroadPhaseLayerFilterImpl : public JPH::ObjectVsBroadPhaseLayerFilter {
public:
virtual bool ShouldCollide(JPH::ObjectLayer inLayer1, JPH::BroadPhaseLayer inLayer2) const override {
switch (inLayer1) {
case Layers::NON_MOVING:
return inLayer2 == JPH::BroadPhaseLayers::MOVING;
case Layers::MOVING:
return true;
default:
JPH_ASSERT(false);
return false;
}
}
};
// An example contact listener
class MyContactListener : public JPH::ContactListener {
public:
// See: ContactListener
virtual JPH::ValidateResult OnContactValidate(const JPH::Body &inBody1, const JPH::Body &inBody2,
JPH::RVec3Arg inBaseOffset,
const JPH::CollideShapeResult &inCollisionResult) override {
// std::cout << "Contact validate callback" << std::endl;
// Allows you to ignore a contact before it is created (using layers to not make objects collide is cheaper!)
return JPH::ValidateResult::AcceptAllContactsForThisBodyPair;
}
virtual void OnContactAdded(const JPH::Body &inBody1, const JPH::Body &inBody2,
const JPH::ContactManifold &inManifold, JPH::ContactSettings &ioSettings) override {
// std::cout << "A contact was added" << std::endl;
}
virtual void OnContactPersisted(const JPH::Body &inBody1, const JPH::Body &inBody2,
const JPH::ContactManifold &inManifold, JPH::ContactSettings &ioSettings) override {
// std::cout << "A contact was persisted" << std::endl;
}
virtual void OnContactRemoved(const JPH::SubShapeIDPair &inSubShapePair) override {
// std::cout << "A contact was removed" << std::endl;
}
};
// An example activation listener
class MyBodyActivationListener : public JPH::BodyActivationListener {
public:
virtual void OnBodyActivated(const JPH::BodyID &inBodyID, JPH::uint64 inBodyUserData) override {
// std::cout << "A body got activated" << std::endl;
}
virtual void OnBodyDeactivated(const JPH::BodyID &inBodyID, JPH::uint64 inBodyUserData) override {
// std::cout << "A body went to sleep" << std::endl;
}
};