Engine²
Open-source game engine written in C++.
Loading...
Searching...
No Matches
SoftBody.hpp
Go to the documentation of this file.
1/**************************************************************************
2 * EngineSquared v0.1.1
3 *
4 * EngineSquared is a software package, part of the Engine² organization.
5 *
6 * This file is part of the EngineSquared project that is under MIT License.
7 * Copyright © 2025-present by @EngineSquared, All rights reserved.
8 *
9 * EngineSquared is a free software: you can redistribute it and/or modify
10 * it under the terms of the MIT License. See the project's LICENSE file for
11 * the full license text and details.
12 *
13 * @file SoftBody.hpp
14 * @brief Soft body component for deformable physics objects
15 *
16 * Integrates with Jolt Physics SoftBody system for cloth, ropes, and
17 * deformable objects with realistic physics simulation.
18 *
19 * @author @EngineSquared
20 * @version 0.1.1
21 * @date 2025-12-05
22 **************************************************************************/
23
24#pragma once
25
26#include <algorithm>
27#include <glm/glm.hpp>
28#include <glm/gtc/quaternion.hpp>
29#include <utility>
30#include <vector>
31
32#include "component/Mesh.hpp"
33
34namespace Physics::Component {
35
46
51 //=========================================================================
52 // Simulation parameters
53 //=========================================================================
54
56 uint32_t solverIterations = 5;
57
59 float linearDamping = 0.1f;
60
62 float maxLinearVelocity = 500.0f;
63
65 float gravityFactor = 1.0f;
66
67 //=========================================================================
68 // Material properties
69 //=========================================================================
70
72 float restitution = 0.0f;
73
75 float friction = 0.2f;
76
79 float pressure = 0.0f;
80
81 //=========================================================================
82 // Constraint parameters
83 //=========================================================================
84
86 float edgeCompliance = 0.0f;
87
89 float shearCompliance = 0.0f;
90
92 float bendCompliance = 1.0f;
93
94 //=========================================================================
95 // Collision
96 //=========================================================================
97
99 float vertexRadius = 0.0f;
100
102 bool allowSleeping = true;
103
105 bool doubleSidedFaces = false;
106
107 //=========================================================================
108 // Factory methods
109 //=========================================================================
110
114 static SoftBodySettings Default() { return {}; }
115
121 static SoftBodySettings Cloth(float stiffness = 0.5f)
122 {
124 s.solverIterations = 8;
125 s.linearDamping = 0.2f;
126 s.gravityFactor = 1.0f;
127 s.friction = 0.3f;
128 s.edgeCompliance = (1.0f - stiffness) * 0.001f;
129 s.shearCompliance = (1.0f - stiffness) * 0.002f;
130 s.bendCompliance = (1.0f - stiffness) * 0.5f;
131 s.vertexRadius = 0.01f;
132 s.doubleSidedFaces = true;
133 return s;
134 }
135
141 static SoftBodySettings Rope(float stiffness = 0.9f)
142 {
144 s.solverIterations = 10;
145 s.linearDamping = 0.3f;
146 s.gravityFactor = 1.0f;
147 s.friction = 0.5f;
148 s.edgeCompliance = (1.0f - stiffness) * 0.0001f;
149 s.shearCompliance = 1e10f; // Disable shear for 1D
150 s.bendCompliance = (1.0f - stiffness) * 0.01f;
151 s.vertexRadius = 0.02f;
152 return s;
153 }
154
164 static SoftBodySettings Balloon(float pressure = 1000.0f)
165 {
167 s.solverIterations = 10;
168 s.linearDamping = 0.1f;
169 s.pressure = pressure;
170 s.restitution = 0.5f;
171 s.friction = 0.3f;
172 // Jolt defaults: { 1.0e-4f, 1.0e-4f, 1.0e-3f } for edge/shear/bend
173 s.edgeCompliance = 1.0e-4f;
174 s.shearCompliance = 1.0e-4f;
175 s.bendCompliance = 1.0e-3f;
176 s.vertexRadius = 0.02f; // Small, only for z-fighting prevention
177 return s;
178 }
179
185 {
187 s.solverIterations = 5;
188 s.linearDamping = 0.2f;
189 s.restitution = 0.8f;
190 s.friction = 0.1f;
191 s.edgeCompliance = 0.01f;
192 s.shearCompliance = 0.02f;
193 s.bendCompliance = 0.5f;
194 s.pressure = 500.0f;
195 return s;
196 }
197};
198
241struct SoftBody {
242 //=========================================================================
243 // Configuration
244 //=========================================================================
245
248
251
252 //=========================================================================
253 // Per-vertex physics data (parallel arrays with Mesh.vertices)
254 //=========================================================================
255
257 std::vector<float> invMasses;
258
260 std::vector<uint32_t> pinnedVertices;
261
264 std::vector<std::pair<uint32_t, uint32_t>> edges;
265
266 //=========================================================================
267 // Methods
268 //=========================================================================
269
273 [[nodiscard]] size_t GetVertexCount() const { return invMasses.size(); }
274
278 [[nodiscard]] size_t GetEdgeCount() const { return edges.size(); }
279
284 void PinVertex(uint32_t vertexIndex)
285 {
286 if (vertexIndex < invMasses.size())
287 {
288 invMasses[vertexIndex] = 0.0f;
289 if (std::ranges::find(pinnedVertices, vertexIndex) == pinnedVertices.end())
290 {
291 pinnedVertices.push_back(vertexIndex);
292 }
293 }
294 }
295
304 void UnpinVertex(uint32_t vertexIndex, float mass = 1.0f)
305 {
306 static constexpr float kMinMass = 1.0e-6f;
307
308 if (vertexIndex >= invMasses.size())
309 return;
310
311 if (mass <= 0.0f)
312 {
313 // mass <= 0 means pin the vertex, delegate to PinVertex
314 PinVertex(vertexIndex);
315 return;
316 }
317
318 float safeMass = mass < kMinMass ? kMinMass : mass;
319 invMasses[vertexIndex] = 1.0f / safeMass;
320 pinnedVertices.erase(std::ranges::remove(pinnedVertices, vertexIndex).begin(), pinnedVertices.end());
321 }
322
326 [[nodiscard]] bool IsVertexPinned(uint32_t vertexIndex) const
327 {
328 return vertexIndex < invMasses.size() && invMasses[vertexIndex] == 0.0f;
329 }
330
335 [[nodiscard]] bool IsValid() const { return !invMasses.empty(); }
336
337 //=========================================================================
338 // Constructors
339 //=========================================================================
340
349 SoftBody() = default;
350
356
363};
364
365} // namespace Physics::Component
Definition BoxCollider.hpp:27
SoftBodyType
Type of soft body for preset configurations.
Definition SoftBody.hpp:39
@ Cloth
2D grid for flags, capes, curtains
Definition SoftBody.hpp:41
@ Custom
User-defined configuration.
Definition SoftBody.hpp:40
@ Cube
3D volumetric soft body
Definition SoftBody.hpp:43
@ Rope
1D chain for ropes, cables, chains
Definition SoftBody.hpp:42
@ Pressure
Pressure-based soft body (balloons, inflatables).
Definition SoftBody.hpp:44
Soft body simulation settings.
Definition SoftBody.hpp:50
float linearDamping
Linear damping (velocity decay).
Definition SoftBody.hpp:59
static SoftBodySettings Cloth(float stiffness=0.5f)
Settings optimized for cloth simulation.
Definition SoftBody.hpp:121
uint32_t solverIterations
Number of solver iterations (higher = more accurate but slower).
Definition SoftBody.hpp:56
static SoftBodySettings Default()
Default soft body settings.
Definition SoftBody.hpp:114
float shearCompliance
Shear constraint compliance.
Definition SoftBody.hpp:89
float vertexRadius
Vertex collision radius (for collision detection).
Definition SoftBody.hpp:99
float edgeCompliance
Edge constraint compliance (0 = rigid, higher = softer).
Definition SoftBody.hpp:86
float restitution
Restitution (bounciness) [0, 1].
Definition SoftBody.hpp:72
float friction
Friction coefficient [0, 1].
Definition SoftBody.hpp:75
float gravityFactor
Gravity factor (1.0 = normal gravity).
Definition SoftBody.hpp:65
static SoftBodySettings Rope(float stiffness=0.9f)
Settings optimized for rope simulation.
Definition SoftBody.hpp:141
float maxLinearVelocity
Maximum linear velocity (m/s).
Definition SoftBody.hpp:62
float pressure
Definition SoftBody.hpp:79
float bendCompliance
Bend constraint compliance (FLT_MAX = disable bending).
Definition SoftBody.hpp:92
bool allowSleeping
Allow sleeping when stable.
Definition SoftBody.hpp:102
static SoftBodySettings Balloon(float pressure=1000.0f)
Settings for pressure-based soft bodies (balloons).
Definition SoftBody.hpp:164
bool doubleSidedFaces
Treat faces as double-sided for collision.
Definition SoftBody.hpp:105
static SoftBodySettings Jelly()
Settings for jelly-like objects.
Definition SoftBody.hpp:184
SoftBody(const SoftBodySettings &settings)
Construct with specific settings.
Definition SoftBody.hpp:355
SoftBody(SoftBodyType bodyType, const SoftBodySettings &settings)
Construct with type and settings.
Definition SoftBody.hpp:362
size_t GetEdgeCount() const
Get number of edge constraints.
Definition SoftBody.hpp:278
void UnpinVertex(uint32_t vertexIndex, float mass=1.0f)
Unpin a vertex.
Definition SoftBody.hpp:304
SoftBodyType type
Type of soft body (affects default settings).
Definition SoftBody.hpp:247
bool IsValid() const
Check if the soft body configuration is valid.
Definition SoftBody.hpp:335
SoftBody()=default
Default constructor - creates an empty SoftBody.
std::vector< std::pair< uint32_t, uint32_t > > edges
Definition SoftBody.hpp:264
std::vector< float > invMasses
Vertex inverse masses (0 = pinned/fixed). Size must match Mesh.vertices.size().
Definition SoftBody.hpp:257
SoftBodySettings settings
Simulation settings.
Definition SoftBody.hpp:250
size_t GetVertexCount() const
Get number of vertices (from invMasses size).
Definition SoftBody.hpp:273
std::vector< uint32_t > pinnedVertices
Indices of pinned (fixed) vertices.
Definition SoftBody.hpp:260
bool IsVertexPinned(uint32_t vertexIndex) const
Check if a vertex is pinned.
Definition SoftBody.hpp:326
void PinVertex(uint32_t vertexIndex)
Pin a vertex (fix it in space).
Definition SoftBody.hpp:284