Toast Engine
Loading...
Searching...
No Matches
manifold.hpp
Go to the documentation of this file.
1
8
9#pragma once
10#include "collision.hpp"
11#include "collision_world.hpp"
12#include "material_defaults.hpp"
13#include "voxel_shape_data.hpp"
14
15#include <array>
16#include <cstddef>
17#include <cstdint>
18#include <glm/glm.hpp>
19#include <optional>
20#include <span>
21#include <vector>
22
23namespace physics {
24
26 float restitution = material_defaults::k_restitution;
27 float static_friction = material_defaults::k_static_friction;
28 float dynamic_friction = material_defaults::k_dynamic_friction;
29 float rolling_friction = material_defaults::k_rolling_friction;
30 float spin_friction = material_defaults::k_spin_friction;
31};
32
34 glm::vec3 position = {};
35 float penetration = 0.0f;
36 ContactFeatureID feature_a = {};
37 ContactFeatureID feature_b = {};
38 ContactMaterial material;
39};
40
41struct Manifold {
42 BroadPhasePair pair;
43 glm::vec3 normal = {};
44 uint8_t normal_index = k_primitive_manifold_normal_index;
45 std::array<ContactPoint, 4> contacts = {};
46 uint8_t contact_count = 0;
47};
48
49[[nodiscard]]
50inline auto operator<(const Manifold& lhs, const Manifold& rhs) -> bool {
51 if (lhs.pair != rhs.pair) {
52 return lhs.pair < rhs.pair;
53 }
54
55 if (lhs.normal_index != rhs.normal_index) {
56 return lhs.normal_index < rhs.normal_index;
57 }
58
59 if (lhs.contact_count != rhs.contact_count) {
60 return lhs.contact_count < rhs.contact_count;
61 }
62
63 for (std::size_t index = 0; index < lhs.contact_count && index < lhs.contacts.size(); ++index) {
64 const ContactPoint& lhs_contact = lhs.contacts[index];
65 const ContactPoint& rhs_contact = rhs.contacts[index];
66
67 if (lhs_contact.feature_a != rhs_contact.feature_a) {
68 return lhs_contact.feature_a < rhs_contact.feature_a;
69 }
70 if (lhs_contact.feature_b != rhs_contact.feature_b) {
71 return lhs_contact.feature_b < rhs_contact.feature_b;
72 }
73 }
74
75 return false;
76}
77
79 ContactFeatureID feature_a = {};
80 ContactFeatureID feature_b = {};
81 float normal_impulse = 0.0f;
82 glm::vec3 tangent_impulse = {};
83};
84
86 BroadPhasePair pair;
88 glm::vec3 normal = {};
89 uint8_t normal_index = k_primitive_manifold_normal_index;
90 uint32_t shape_a_revision = 0;
91 uint32_t shape_b_revision = 0;
92 std::array<CachedContact, 4> contacts = {};
93 uint8_t contact_count = 0;
94};
95
96namespace _detail {
97
98inline constexpr float direction_epsilon_sq = 1.0e-10f;
99inline constexpr float parallel_axis_epsilon_sq = 1.0e-10f;
100inline constexpr float contact_tolerance = 1.0e-5f;
101inline constexpr float duplicate_point_epsilon_sq = 1.0e-8f;
102inline constexpr float unit_normal_tolerance = 1.0e-3f;
103
105 glm::vec3 center;
106 float radius;
107};
108
110 glm::vec3 point_a;
111 glm::vec3 point_b;
112 float radius;
113};
114
115struct WorldBox {
116 glm::vec3 center;
117 glm::mat3 rotation;
118 glm::vec3 half_extents;
119};
120
122 glm::vec3 point;
123 float parameter;
124};
125
127 glm::vec3 point_a;
128 glm::vec3 point_b;
129 float parameter_a;
130 float parameter_b;
131};
132
133enum class BoxFeatureType : uint8_t {
134 interior,
135 face,
136 edge,
137 vertex
138};
139
141 BoxFeatureType type = BoxFeatureType::interior;
142 uint8_t axis_mask = 0;
143 uint8_t positive_mask = 0;
144 auto operator<=>(const BoxFeature&) const = default;
145};
146
148 glm::vec3 segment_point;
149 glm::vec3 box_point;
150 float segment_parameter;
151 BoxFeature box_feature;
152};
153
155 glm::vec3 segment_point;
156 glm::vec3 box_point;
157 float segment_parameter;
158};
159
161 glm::vec3 local_normal;
162 glm::vec3 local_point;
163 glm::vec3 local_surface;
164 float penetration;
165 float segment_parameter;
166};
167
169 glm::vec3 position {};
170 float penetration = 0.0f;
171 ContactFeatureID feature_a {};
172 ContactFeatureID feature_b {};
173};
174
175[[nodiscard]]
176auto boxFeature(const glm::vec3& point, const glm::vec3& half_extents) -> BoxFeature;
177[[nodiscard]]
178auto contactFeature(const BoxFeature& feature) -> ContactFeatureID;
179[[nodiscard]]
180auto worldSphere(const Body& body, const SphereShape& sphere) -> WorldSphere;
181[[nodiscard]]
182auto worldCapsule(const Body& body, const CapsuleShape& capsule) -> WorldCapsule;
183[[nodiscard]]
184auto worldBox(const Body& body, const BoxShape& box) -> WorldBox;
185[[nodiscard]]
186auto closestPointOnSegment(const glm::vec3& point, const glm::vec3& segment_a, const glm::vec3& segment_b) -> SegmentClosestPoint;
187[[nodiscard]]
188auto closestPointsBetweenSegments(const glm::vec3& a0, const glm::vec3& a1, const glm::vec3& b0, const glm::vec3& b1)
190[[nodiscard]]
191auto closestPointOnBox(const glm::vec3& point, const WorldBox& box) -> glm::vec3;
192[[nodiscard]]
193auto closestPointsSegmentBox(const glm::vec3& segment_a, const glm::vec3& segment_b, const WorldBox& box)
195[[nodiscard]]
196auto closestPointsSegmentAabb(const glm::vec3& local_a, const glm::vec3& local_b, const glm::vec3& half_extents)
198[[nodiscard]]
199auto capsuleVoxelContact(
200 const glm::vec3& segment_a, const glm::vec3& segment_b, float radius, const glm::vec3& voxel_min, uint8_t normal_index
201) -> std::optional<CapsuleVoxelContact>;
202[[nodiscard]]
203auto perpendicularTo(const glm::vec3& segment) -> glm::vec3;
204[[nodiscard]]
205auto combineMaterials(const PhysicsMaterial& a, const PhysicsMaterial& b) -> ContactMaterial;
206[[nodiscard]]
207auto surfaceMaterial(const voxel::PhysicalMaterial& material) -> PhysicsMaterial;
208
209}
210
212 const Shape& shape;
213 const Body& body;
214};
215
219 CollisionElement voxel;
220 const VoxelShapeData& voxel_data;
221 bool voxel_is_a = false;
222};
223
224[[nodiscard]]
225auto resolveBoxVoxelPair(CollisionWorldView world, BroadPhasePair pair) -> std::optional<BoxVoxelPairView>;
226
233
234[[nodiscard]]
235auto classifyBoxVoxelSplit(const BoxVoxelPairView& view) -> BoxVoxelSplitInfo;
236
238[[nodiscard]]
239auto splitVoxelRegions(const AABB& local_bounds, size_t region_count) -> std::vector<AABB>;
240
243 std::array<std::vector<_detail::ContactCandidate>, voxel::k_normal_direction_count> candidates_per_normal;
244 std::array<glm::vec3, voxel::k_normal_direction_count> normal_per_group {};
245 std::array<glm::vec3, voxel::k_normal_direction_count> normal_sum_per_group {};
246 std::array<ContactMaterial, voxel::k_normal_direction_count> material_per_group {};
247 std::array<bool, voxel::k_normal_direction_count> group_started {};
248};
249
250[[nodiscard]]
251auto collideBoxVoxelRegion(const BoxVoxelPairView& view, const AABB& region) -> VoxelPairPartial;
252
253void mergeBoxVoxelPartials(
254 BroadPhasePair pair, const BoxVoxelPairView& view, std::span<VoxelPairPartial> partials, std::vector<Manifold>& output
255);
256
259 CollisionElement probe;
260 const VoxelShapeData& probe_data;
262 const VoxelShapeData& ref_data;
263 bool a_is_probe = false;
264};
265
266[[nodiscard]]
267auto resolveVoxelVoxelPair(CollisionWorldView world, BroadPhasePair pair) -> std::optional<VoxelVoxelPairView>;
268
275
277[[nodiscard]]
278auto classifyVoxelVoxelSplit(const VoxelVoxelPairView& view) -> std::optional<VoxelVoxelSplitInfo>;
279
280[[nodiscard]]
281auto collideVoxelVoxelRegion(const VoxelVoxelPairView& view, const AABB& probe_region) -> VoxelPairPartial;
282
283void mergeVoxelVoxelPartials(
284 BroadPhasePair pair, const VoxelVoxelPairView& view, std::span<VoxelPairPartial> partials, std::vector<Manifold>& output
285);
286
287[[nodiscard]]
288auto collideSpheres(BroadPhasePair pair, CollisionElement a, CollisionElement b) -> std::optional<Manifold>;
289
290[[nodiscard]]
291auto collideSphereBox(BroadPhasePair pair, CollisionElement sphere, CollisionElement box) -> std::optional<Manifold>;
292
293[[nodiscard]]
294auto collideSphereCapsule(BroadPhasePair pair, CollisionElement sphere, CollisionElement capsule) -> std::optional<Manifold>;
295
296void collideSphereVoxel(
297 BroadPhasePair pair, CollisionElement sphere, CollisionElement voxel, const VoxelShapeData& voxel_data,
298 std::vector<Manifold>& output
299);
300
301[[nodiscard]]
302auto collideBoxes(BroadPhasePair pair, CollisionElement a, CollisionElement b) -> std::optional<Manifold>;
303
304void collideBoxVoxel(
305 BroadPhasePair pair, CollisionElement box, CollisionElement voxel, const VoxelShapeData& voxel_data,
306 std::vector<Manifold>& output
307);
308
309[[nodiscard]]
310auto collideCapsuleBox(BroadPhasePair pair, CollisionElement capsule, CollisionElement box) -> std::optional<Manifold>;
311
312void collideCapsuleVoxel(
313 BroadPhasePair pair, CollisionElement capsule, CollisionElement voxel, const VoxelShapeData& voxel_data,
314 std::vector<Manifold>& output
315);
316
317[[nodiscard]]
318auto collideCapsules(BroadPhasePair pair, CollisionElement a, CollisionElement b) -> std::optional<Manifold>;
319
320void collideVoxelVoxel(
321 BroadPhasePair pair, CollisionElement a, const VoxelShapeData& data_a, CollisionElement b, const VoxelShapeData& data_b,
322 std::vector<Manifold>& output
323);
324
325}
Canonical collision-pair records shared by broad and narrow phases.
Read-only access to physics data used by collision detection.
The values a material has when nothing sets them.
constexpr float k_rolling_friction
A ball rolling on a hard floor loses a few percent of its speed per metre.
Definition material_defaults.hpp:22
Definition aabb.hpp:16
Definition body.hpp:60
Definition shape.hpp:135
Box/voxel roles already resolved so splitting one pair across jobs only pays that resolution once.
Definition manifold.hpp:217
Definition manifold.hpp:227
AABB local_bounds
The box AABB in voxel local space safe to partition spatially across jobs.
Definition manifold.hpp:229
uint64_t estimated_voxels
Cheap surface area estimate, not an actual walk, since queryVoxelSurface only visits surface voxels.
Definition manifold.hpp:231
Definition collision.hpp:24
Definition manifold.hpp:78
Definition manifold.hpp:85
glm::vec3 normal
Points from pair.a to pair.b.
Definition manifold.hpp:88
Definition shape.hpp:141
Definition manifold.hpp:211
Definition collision_world.hpp:16
Definition shape.hpp:48
Definition manifold.hpp:25
Definition manifold.hpp:33
Definition manifold.hpp:41
Definition shape.hpp:21
Definition shape.hpp:161
Definition shape.hpp:130
One region share of a split pair candidates owned per call since concurrent regions need independent ...
Definition manifold.hpp:242
Definition voxel_shape_data.hpp:26
A voxel-voxel pair with the smaller-shape-is-probe role already resolved, same reasoning as BoxVoxelP...
Definition manifold.hpp:258
Definition manifold.hpp:269
uint64_t estimated_voxels
Same surface area estimate as BoxVoxelSplitInfo::estimated_voxels, see its comment for why.
Definition manifold.hpp:273
AABB probe_search_bounds
The probe shape search bounds in its own local space safe to partition spatially across jobs.
Definition manifold.hpp:271
Definition manifold.hpp:140
Definition manifold.hpp:160
Definition manifold.hpp:168
Definition manifold.hpp:121
Definition manifold.hpp:126
Definition manifold.hpp:115
Definition manifold.hpp:109
Definition manifold.hpp:104
Definition palette.hpp:94
Voxel data structures for physics system.