vkmEngine 1.0.0
A C++ game engine · vkmengine.com
Loading...
Searching...
No Matches
inertia.h
1#pragma once
2
3#include <glm/glm.hpp>
4#include <glm/gtc/constants.hpp>
5#include <glm/gtc/quaternion.hpp>
6#include <glm/gtx/matrix_operation.hpp>
7
8namespace Vkm::Engine {
9
19inline glm::mat3 boxInertiaLocal(float mass, const glm::vec3& halfExtents) {
20 if (mass <= 0.0f) return glm::mat3(0.0f);
21
22 const glm::vec3 full = halfExtents * 2.0f;
23 const float k = mass / 12.0f;
24 const float ix = k * (full.y * full.y + full.z * full.z);
25 const float iy = k * (full.x * full.x + full.z * full.z);
26 const float iz = k * (full.x * full.x + full.y * full.y);
27 if (ix <= 0.0f || iy <= 0.0f || iz <= 0.0f) return glm::mat3(0.0f);
28
29 return glm::diagonal3x3(glm::vec3(ix, iy, iz));
30}
31
43inline glm::mat3 capsuleInertiaLocal(float mass, float radius, float halfHeight) {
44 if (mass <= 0.0f || radius <= 0.0f) return glm::mat3(0.0f);
45
46 const float h = glm::max(halfHeight, 0.0f) * 2.0f;
47 const float r2 = radius * radius;
48 const float cylinderVolume = glm::pi<float>() * r2 * h;
49 const float capsVolume = (4.0f / 3.0f) * glm::pi<float>() * r2 * radius;
50 const float total = cylinderVolume + capsVolume;
51 if (total <= 0.0f) return glm::mat3(0.0f);
52
53 const float cylinderMass = mass * (cylinderVolume / total);
54 const float capsMass = mass * (capsVolume / total);
55
56 // The 3*h*r/8 term: hemisphere centroids sit 3r/8 past each cylinder end (parallel-axis shift).
57 const float axial = cylinderMass * r2 * 0.5f + capsMass * (2.0f / 5.0f) * r2;
58 const float perp = cylinderMass * (h * h / 12.0f + r2 * 0.25f)
59 + capsMass * ((2.0f / 5.0f) * r2 + h * h * 0.25f + 3.0f * h * radius / 8.0f);
60 if (axial <= 0.0f || perp <= 0.0f) return glm::mat3(0.0f);
61
62 return glm::diagonal3x3(glm::vec3(perp, axial, perp));
63}
64
75inline glm::mat3 parallelAxisShift(const glm::mat3& inertia, float mass, const glm::vec3& offset) {
76 const float d2 = glm::dot(offset, offset);
77 return inertia + mass * (glm::mat3(d2) - glm::outerProduct(offset, offset));
78}
79
89inline glm::mat3 inverseInertiaWorld(const glm::mat3& invInertiaLocal, const glm::quat& rotation) {
90 const glm::mat3 r = glm::mat3_cast(rotation);
91 return r * invInertiaLocal * glm::transpose(r);
92}
93
94} // namespace Vkm::Engine