De-ugifying

This commit is contained in:
2026-04-14 14:29:48 -05:00
parent 4009130f6e
commit c7a3e5601c
8 changed files with 267 additions and 289 deletions
+1 -1
View File
@@ -85,7 +85,7 @@ void capsuleBuffer(
const float_t lxz1 = radius * cosf(phi1); const float_t lxz1 = radius * cosf(phi1);
const float_t lxz2 = radius * cosf(phi2); const float_t lxz2 = radius * cosf(phi2);
/* UV: top cap occupies v in [0.5 + halfHeightFrac .. 1.0] we use a /* UV: top cap occupies v in [0.5 + halfHeightFrac .. 1.0]: we use a
* simple per-band normalisation against the full height. */ * simple per-band normalisation against the full height. */
const float_t v1 = 1.0f - (float_t)i / (float_t)(2 * capRings + 1); const float_t v1 = 1.0f - (float_t)i / (float_t)(2 * capRings + 1);
const float_t v2 = 1.0f - (float_t)(i + 1) / (float_t)(2 * capRings + 1); const float_t v2 = 1.0f - (float_t)(i + 1) / (float_t)(2 * capRings + 1);
+6 -6
View File
@@ -62,7 +62,7 @@ void cubeBuffer(
const float_t x0 = min[0], y0 = min[1], z0 = min[2]; const float_t x0 = min[0], y0 = min[1], z0 = min[2];
const float_t x1 = max[0], y1 = max[1], z1 = max[2]; const float_t x1 = max[0], y1 = max[1], z1 = max[2];
// Front face (+Z normal) CCW when viewed from +Z // Front face (+Z normal): CCW when viewed from +Z
CUBE_VERT( 0, x0, y0, z1, 0.0f, 0.0f); CUBE_VERT( 0, x0, y0, z1, 0.0f, 0.0f);
CUBE_VERT( 1, x1, y0, z1, 1.0f, 0.0f); CUBE_VERT( 1, x1, y0, z1, 1.0f, 0.0f);
CUBE_VERT( 2, x1, y1, z1, 1.0f, 1.0f); CUBE_VERT( 2, x1, y1, z1, 1.0f, 1.0f);
@@ -70,7 +70,7 @@ void cubeBuffer(
CUBE_VERT( 4, x1, y1, z1, 1.0f, 1.0f); CUBE_VERT( 4, x1, y1, z1, 1.0f, 1.0f);
CUBE_VERT( 5, x0, y1, z1, 0.0f, 1.0f); CUBE_VERT( 5, x0, y1, z1, 0.0f, 1.0f);
// Back face (-Z normal) CCW when viewed from -Z // Back face (-Z normal): CCW when viewed from -Z
CUBE_VERT( 6, x1, y0, z0, 0.0f, 0.0f); CUBE_VERT( 6, x1, y0, z0, 0.0f, 0.0f);
CUBE_VERT( 7, x0, y0, z0, 1.0f, 0.0f); CUBE_VERT( 7, x0, y0, z0, 1.0f, 0.0f);
CUBE_VERT( 8, x0, y1, z0, 1.0f, 1.0f); CUBE_VERT( 8, x0, y1, z0, 1.0f, 1.0f);
@@ -78,7 +78,7 @@ void cubeBuffer(
CUBE_VERT(10, x0, y1, z0, 1.0f, 1.0f); CUBE_VERT(10, x0, y1, z0, 1.0f, 1.0f);
CUBE_VERT(11, x1, y1, z0, 0.0f, 1.0f); CUBE_VERT(11, x1, y1, z0, 0.0f, 1.0f);
// Right face (+X normal) CCW when viewed from +X // Right face (+X normal): CCW when viewed from +X
CUBE_VERT(12, x1, y0, z1, 0.0f, 0.0f); CUBE_VERT(12, x1, y0, z1, 0.0f, 0.0f);
CUBE_VERT(13, x1, y0, z0, 1.0f, 0.0f); CUBE_VERT(13, x1, y0, z0, 1.0f, 0.0f);
CUBE_VERT(14, x1, y1, z0, 1.0f, 1.0f); CUBE_VERT(14, x1, y1, z0, 1.0f, 1.0f);
@@ -86,7 +86,7 @@ void cubeBuffer(
CUBE_VERT(16, x1, y1, z0, 1.0f, 1.0f); CUBE_VERT(16, x1, y1, z0, 1.0f, 1.0f);
CUBE_VERT(17, x1, y1, z1, 0.0f, 1.0f); CUBE_VERT(17, x1, y1, z1, 0.0f, 1.0f);
// Left face (-X normal) CCW when viewed from -X // Left face (-X normal): CCW when viewed from -X
CUBE_VERT(18, x0, y0, z0, 0.0f, 0.0f); CUBE_VERT(18, x0, y0, z0, 0.0f, 0.0f);
CUBE_VERT(19, x0, y0, z1, 1.0f, 0.0f); CUBE_VERT(19, x0, y0, z1, 1.0f, 0.0f);
CUBE_VERT(20, x0, y1, z1, 1.0f, 1.0f); CUBE_VERT(20, x0, y1, z1, 1.0f, 1.0f);
@@ -94,7 +94,7 @@ void cubeBuffer(
CUBE_VERT(22, x0, y1, z1, 1.0f, 1.0f); CUBE_VERT(22, x0, y1, z1, 1.0f, 1.0f);
CUBE_VERT(23, x0, y1, z0, 0.0f, 1.0f); CUBE_VERT(23, x0, y1, z0, 0.0f, 1.0f);
// Top face (+Y normal) CCW when viewed from +Y // Top face (+Y normal): CCW when viewed from +Y
CUBE_VERT(24, x0, y1, z1, 0.0f, 0.0f); CUBE_VERT(24, x0, y1, z1, 0.0f, 0.0f);
CUBE_VERT(25, x1, y1, z1, 1.0f, 0.0f); CUBE_VERT(25, x1, y1, z1, 1.0f, 0.0f);
CUBE_VERT(26, x1, y1, z0, 1.0f, 1.0f); CUBE_VERT(26, x1, y1, z0, 1.0f, 1.0f);
@@ -102,7 +102,7 @@ void cubeBuffer(
CUBE_VERT(28, x1, y1, z0, 1.0f, 1.0f); CUBE_VERT(28, x1, y1, z0, 1.0f, 1.0f);
CUBE_VERT(29, x0, y1, z0, 0.0f, 1.0f); CUBE_VERT(29, x0, y1, z0, 0.0f, 1.0f);
// Bottom face (-Y normal) CCW when viewed from -Y // Bottom face (-Y normal): CCW when viewed from -Y
CUBE_VERT(30, x0, y0, z0, 0.0f, 0.0f); CUBE_VERT(30, x0, y0, z0, 0.0f, 0.0f);
CUBE_VERT(31, x1, y0, z0, 1.0f, 0.0f); CUBE_VERT(31, x1, y0, z0, 1.0f, 0.0f);
CUBE_VERT(32, x1, y0, z1, 1.0f, 1.0f); CUBE_VERT(32, x1, y0, z1, 1.0f, 1.0f);
+3 -3
View File
@@ -36,9 +36,9 @@ errorret_t planeInit();
* *
* The min/max corners fully describe the plane in 3D space. The axis enum * The min/max corners fully describe the plane in 3D space. The axis enum
* controls which dimension is treated as the "depth" (normal) axis: * controls which dimension is treated as the "depth" (normal) axis:
* PLANE_AXIS_XY spans X and Y, depth from min[2]/max[2] (uses min[2]) * PLANE_AXIS_XY: spans X and Y, depth from min[2]/max[2] (uses min[2])
* PLANE_AXIS_XZ spans X and Z, depth from min[1]/max[1] (uses min[1]) * PLANE_AXIS_XZ: spans X and Z, depth from min[1]/max[1] (uses min[1])
* PLANE_AXIS_YZ spans Y and Z, depth from min[0]/max[0] (uses min[0]) * PLANE_AXIS_YZ: spans Y and Z, depth from min[0]/max[0] (uses min[0])
* *
* @param vertices Vertex array to write into (must hold PLANE_VERTEX_COUNT). * @param vertices Vertex array to write into (must hold PLANE_VERTEX_COUNT).
* @param axis Which axis the plane's normal points along. * @param axis Which axis the plane's normal points along.
+1 -1
View File
@@ -118,7 +118,7 @@ errorret_t engineUpdate(void) {
entityPhysicsSetVelocity(phBoxEnt, phBoxPhys, (vec3){ 0.0f, 0.0f, 0.0f }); entityPhysicsSetVelocity(phBoxEnt, phBoxPhys, (vec3){ 0.0f, 0.0f, 0.0f });
} }
/* Step physics positions are updated directly on POSITION components. */ /* Step physics: positions are updated directly on POSITION components. */
physicsManagerUpdate(); physicsManagerUpdate();
errorChain(gameUpdate()); errorChain(gameUpdate());
@@ -87,7 +87,7 @@ void entityPhysicsApplyImpulse(
entityphysics_t *phys = entityPhysicsGet(entityId, componentId); entityphysics_t *phys = entityPhysicsGet(entityId, componentId);
assertNotNull(phys, "Failed to get physics component data"); assertNotNull(phys, "Failed to get physics component data");
if (phys->type == PHYSICS_BODY_STATIC) return; if(phys->type == PHYSICS_BODY_STATIC) return;
glm_vec3_add(phys->velocity, impulse, phys->velocity); glm_vec3_add(phys->velocity, impulse, phys->velocity);
} }
+34 -270
View File
@@ -7,234 +7,7 @@
#include "physicstest.h" #include "physicstest.h"
/* ============================================================ bool physicsTestAabbVsAabb(
* Forward declarations
* ============================================================ */
/**
* Tests overlap between two axis-aligned bounding boxes.
* outNormal points from B toward A.
*
* @param ac Center of AABB A.
* @param ah Half-extents of AABB A.
* @param bc Center of AABB B.
* @param bh Half-extents of AABB B.
* @param outNormal Push-out normal (B toward A).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
static bool physicsTestAabbVsAabb(
const vec3 ac, const vec3 ah,
const vec3 bc, const vec3 bh,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between two spheres.
* outNormal points from B toward A.
*
* @param ac Center of sphere A.
* @param ar Radius of sphere A.
* @param bc Center of sphere B.
* @param br Radius of sphere B.
* @param outNormal Push-out normal (B toward A).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
static bool physicsTestSphereVsSphere(
const vec3 ac, const float_t ar,
const vec3 bc, const float_t br,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between a sphere and an axis-aligned bounding box.
* outNormal points from the AABB toward the sphere.
*
* @param sc Center of the sphere.
* @param sr Radius of the sphere.
* @param ac Center of the AABB.
* @param ah Half-extents of the AABB.
* @param outNormal Push-out normal (AABB toward sphere).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
static bool physicsTestSphereVsAabb(
const vec3 sc, const float_t sr,
const vec3 ac, const vec3 ah,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between a sphere and an infinite plane.
* outNormal equals the plane normal (pointing away from the surface).
*
* @param sc Center of the sphere.
* @param sr Radius of the sphere.
* @param pn Plane normal (unit vector, world-space).
* @param pd Plane offset: dot(pn, surfacePoint) == pd.
* @param outNormal Push-out normal (equals pn).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
static bool physicsTestSphereVsPlane(
const vec3 sc, const float_t sr,
const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between an AABB and an infinite plane.
* outNormal equals the plane normal.
*
* @param ac Center of the AABB.
* @param ah Half-extents of the AABB.
* @param pn Plane normal (unit vector, world-space).
* @param pd Plane offset (see physicsTestSphereVsPlane).
* @param outNormal Push-out normal (equals pn).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
static bool physicsTestAabbVsPlane(
const vec3 ac, const vec3 ah,
const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth
);
/**
* Finds the closest point on segment [a, b] to query point p.
*
* @param a Start of the segment.
* @param b End of the segment.
* @param p Query point.
* @param out Receives the closest point on [a, b] to p.
*/
static void physicsTestClosestPointOnSegment(
const vec3 a, const vec3 b, const vec3 p, vec3 out
);
/**
* Finds the closest points between two line segments.
*
* @param a1 Start of segment 1.
* @param b1 End of segment 1.
* @param a2 Start of segment 2.
* @param b2 End of segment 2.
* @param outP1 Receives the closest point on segment 1.
* @param outP2 Receives the closest point on segment 2.
*/
static void physicsTestClosestPointsBetweenSegments(
const vec3 a1, const vec3 b1,
const vec3 a2, const vec3 b2,
vec3 outP1, vec3 outP2
);
/**
* Tests overlap between a Y-axis-aligned capsule and a sphere.
* outNormal points from the sphere toward the capsule.
*
* @param cc Center of the capsule.
* @param cr Radius of the capsule.
* @param chh Half-height of the capsule's cylindrical segment.
* @param sc Center of the sphere.
* @param sr Radius of the sphere.
* @param outNormal Push-out normal (sphere toward capsule).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
static bool physicsTestCapsuleVsSphere(
const vec3 cc, const float_t cr, const float_t chh,
const vec3 sc, const float_t sr,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between a Y-axis-aligned capsule and an AABB.
* outNormal points from the AABB toward the capsule.
*
* @param cc Center of the capsule.
* @param cr Radius of the capsule.
* @param chh Half-height of the capsule's cylindrical segment.
* @param ac Center of the AABB.
* @param ah Half-extents of the AABB.
* @param outNormal Push-out normal (AABB toward capsule).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
static bool physicsTestCapsuleVsAabb(
const vec3 cc, const float_t cr, const float_t chh,
const vec3 ac, const vec3 ah,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between a Y-axis-aligned capsule and an infinite plane.
* outNormal equals the plane normal.
*
* @param cc Center of the capsule.
* @param cr Radius of the capsule.
* @param chh Half-height of the capsule's cylindrical segment.
* @param pn Plane normal (unit vector, world-space).
* @param pd Plane offset (see physicsTestSphereVsPlane).
* @param outNormal Push-out normal (equals pn).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
static bool physicsTestCapsuleVsPlane(
const vec3 cc, const float_t cr, const float_t chh,
const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between two Y-axis-aligned capsules.
* outNormal points from capsule B toward capsule A.
*
* @param c1 Center of capsule A.
* @param r1 Radius of capsule A.
* @param hh1 Half-height of capsule A's cylindrical segment.
* @param c2 Center of capsule B.
* @param r2 Radius of capsule B.
* @param hh2 Half-height of capsule B's cylindrical segment.
* @param outNormal Push-out normal (B toward A).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
static bool physicsTestCapsuleVsCapsule(
const vec3 c1, const float_t r1, const float_t hh1,
const vec3 c2, const float_t r2, const float_t hh2,
vec3 outNormal, float_t *outDepth
);
/**
* Routes a shape-pair collision test to the correct primitive.
* When A is a plane, delegates with swapped arguments and negates
* the resulting normal. outNormal points from B toward A.
*
* @param aPos Position of shape A.
* @param aShape Shape descriptor of A.
* @param bPos Position of shape B.
* @param bShape Shape descriptor of B.
* @param outNormal Push-out normal (B toward A).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
static bool physicsTestDispatch(
const vec3 aPos, const physicsshape_t aShape,
const vec3 bPos, const physicsshape_t bShape,
vec3 outNormal, float_t *outDepth
);
/* ============================================================
* Collision primitives.
* Convention:
* outNormal — points from shape-B toward shape-A
* (add outNormal * outDepth to A to separate)
* outDepth — positive penetration depth
* return — true if overlapping
* ============================================================ */
static bool physicsTestAabbVsAabb(
const vec3 ac, const vec3 ah, const vec3 ac, const vec3 ah,
const vec3 bc, const vec3 bh, const vec3 bc, const vec3 bh,
vec3 outNormal, float_t *outDepth vec3 outNormal, float_t *outDepth
@@ -247,13 +20,13 @@ static bool physicsTestAabbVsAabb(
float_t py = (ah[1] + bh[1]) - fabsf(dy); float_t py = (ah[1] + bh[1]) - fabsf(dy);
float_t pz = (ah[2] + bh[2]) - fabsf(dz); float_t pz = (ah[2] + bh[2]) - fabsf(dz);
if (px <= 0.0f || py <= 0.0f || pz <= 0.0f) return false; if(px <= 0.0f || py <= 0.0f || pz <= 0.0f) return false;
outNormal[0] = outNormal[1] = outNormal[2] = 0.0f; outNormal[0] = outNormal[1] = outNormal[2] = 0.0f;
if (px < py && px < pz) { if(px < py && px < pz) {
*outDepth = px; *outDepth = px;
outNormal[0] = dx >= 0.0f ? 1.0f : -1.0f; outNormal[0] = dx >= 0.0f ? 1.0f : -1.0f;
} else if (py < pz) { } else if(py < pz) {
*outDepth = py; *outDepth = py;
outNormal[1] = dy >= 0.0f ? 1.0f : -1.0f; outNormal[1] = dy >= 0.0f ? 1.0f : -1.0f;
} else { } else {
@@ -263,7 +36,7 @@ static bool physicsTestAabbVsAabb(
return true; return true;
} }
static bool physicsTestSphereVsSphere( bool physicsTestSphereVsSphere(
const vec3 ac, const float_t ar, const vec3 ac, const float_t ar,
const vec3 bc, const float_t br, const vec3 bc, const float_t br,
vec3 outNormal, float_t *outDepth vec3 outNormal, float_t *outDepth
@@ -273,12 +46,12 @@ static bool physicsTestSphereVsSphere(
float_t dist2 = glm_vec3_norm2(diff); float_t dist2 = glm_vec3_norm2(diff);
float_t sumR = ar + br; float_t sumR = ar + br;
if (dist2 >= sumR * sumR) return false; if(dist2 >= sumR * sumR) return false;
float_t dist = sqrtf(dist2); float_t dist = sqrtf(dist2);
*outDepth = sumR - dist; *outDepth = sumR - dist;
if (dist > 1e-6f) { if(dist > 1e-6f) {
glm_vec3_scale(diff, 1.0f / dist, outNormal); glm_vec3_scale(diff, 1.0f / dist, outNormal);
} else { } else {
outNormal[0] = 0.0f; outNormal[0] = 0.0f;
@@ -288,7 +61,7 @@ static bool physicsTestSphereVsSphere(
return true; return true;
} }
static bool physicsTestSphereVsAabb( bool physicsTestSphereVsAabb(
const vec3 sc, const float_t sr, const vec3 sc, const float_t sr,
const vec3 ac, const vec3 ah, const vec3 ac, const vec3 ah,
vec3 outNormal, float_t *outDepth vec3 outNormal, float_t *outDepth
@@ -304,14 +77,13 @@ static bool physicsTestSphereVsAabb(
float_t dist2 = glm_vec3_norm2(diff); float_t dist2 = glm_vec3_norm2(diff);
bool inside = (dist2 < 1e-10f); bool inside = (dist2 < 1e-10f);
if (!inside && dist2 >= sr * sr) return false; if(!inside && dist2 >= sr * sr) return false;
if (!inside) { if(!inside) {
float_t dist = sqrtf(dist2); float_t dist = sqrtf(dist2);
*outDepth = sr - dist; *outDepth = sr - dist;
glm_vec3_scale(diff, 1.0f / dist, outNormal); glm_vec3_scale(diff, 1.0f / dist, outNormal);
} else { } else {
/* Sphere center inside the AABB — push out via nearest face. */
float_t faces[6] = { float_t faces[6] = {
(ac[0] + ah[0]) - sc[0], (ac[0] + ah[0]) - sc[0],
sc[0] - (ac[0] - ah[0]), sc[0] - (ac[0] - ah[0]),
@@ -320,12 +92,12 @@ static bool physicsTestSphereVsAabb(
(ac[2] + ah[2]) - sc[2], (ac[2] + ah[2]) - sc[2],
sc[2] - (ac[2] - ah[2]) sc[2] - (ac[2] - ah[2])
}; };
static const float_t normals[6][3] = { const float_t normals[6][3] = {
{1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1} {1,0,0},{-1,0,0},{0,1,0},{0,-1,0},{0,0,1},{0,0,-1}
}; };
int mi = 0; int mi = 0;
for (int k = 1; k < 6; k++) { for(int k = 1; k < 6; k++) {
if (faces[k] < faces[mi]) mi = k; if(faces[k] < faces[mi]) mi = k;
} }
*outDepth = sr + faces[mi]; *outDepth = sr + faces[mi];
outNormal[0] = normals[mi][0]; outNormal[0] = normals[mi][0];
@@ -335,19 +107,19 @@ static bool physicsTestSphereVsAabb(
return true; return true;
} }
static bool physicsTestSphereVsPlane( bool physicsTestSphereVsPlane(
const vec3 sc, const float_t sr, const vec3 sc, const float_t sr,
const vec3 pn, const float_t pd, const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth vec3 outNormal, float_t *outDepth
) { ) {
float_t signedDist = glm_vec3_dot((float_t *)pn, (float_t *)sc) - pd; float_t signedDist = glm_vec3_dot((float_t *)pn, (float_t *)sc) - pd;
*outDepth = sr - signedDist; *outDepth = sr - signedDist;
if (*outDepth <= 0.0f) return false; if(*outDepth <= 0.0f) return false;
glm_vec3_copy((float_t *)pn, outNormal); glm_vec3_copy((float_t *)pn, outNormal);
return true; return true;
} }
static bool physicsTestAabbVsPlane( bool physicsTestAabbVsPlane(
const vec3 ac, const vec3 ah, const vec3 ac, const vec3 ah,
const vec3 pn, const float_t pd, const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth vec3 outNormal, float_t *outDepth
@@ -357,12 +129,12 @@ static bool physicsTestAabbVsPlane(
+ fabsf(pn[2] * ah[2]); + fabsf(pn[2] * ah[2]);
float_t signedDist = glm_vec3_dot((float_t *)pn, (float_t *)ac) - pd; float_t signedDist = glm_vec3_dot((float_t *)pn, (float_t *)ac) - pd;
*outDepth = proj - signedDist; *outDepth = proj - signedDist;
if (*outDepth <= 0.0f) return false; if(*outDepth <= 0.0f) return false;
glm_vec3_copy((float_t *)pn, outNormal); glm_vec3_copy((float_t *)pn, outNormal);
return true; return true;
} }
static void physicsTestClosestPointOnSegment( void physicsTestClosestPointOnSegment(
const vec3 a, const vec3 b, const vec3 p, vec3 out const vec3 a, const vec3 b, const vec3 p, vec3 out
) { ) {
vec3 ab, ap; vec3 ab, ap;
@@ -375,7 +147,7 @@ static void physicsTestClosestPointOnSegment(
glm_vec3_lerp((float_t *)a, (float_t *)b, t, out); glm_vec3_lerp((float_t *)a, (float_t *)b, t, out);
} }
static void physicsTestClosestPointsBetweenSegments( void physicsTestClosestPointsBetweenSegments(
const vec3 a1, const vec3 b1, const vec3 a1, const vec3 b1,
const vec3 a2, const vec3 b2, const vec3 a2, const vec3 b2,
vec3 outP1, vec3 outP2 vec3 outP1, vec3 outP2
@@ -390,17 +162,17 @@ static void physicsTestClosestPointsBetweenSegments(
float_t f = glm_vec3_dot(d2, r); float_t f = glm_vec3_dot(d2, r);
float_t s, t; float_t s, t;
if (a <= 1e-10f && e <= 1e-10f) { if(a <= 1e-10f && e <= 1e-10f) {
glm_vec3_copy((float_t *)a1, outP1); glm_vec3_copy((float_t *)a1, outP1);
glm_vec3_copy((float_t *)a2, outP2); glm_vec3_copy((float_t *)a2, outP2);
return; return;
} }
if (a <= 1e-10f) { if(a <= 1e-10f) {
t = 0.0f; t = 0.0f;
s = glm_clamp(f / e, 0.0f, 1.0f); s = glm_clamp(f / e, 0.0f, 1.0f);
} else { } else {
float_t c = glm_vec3_dot(d1, r); float_t c = glm_vec3_dot(d1, r);
if (e <= 1e-10f) { if(e <= 1e-10f) {
s = 0.0f; s = 0.0f;
t = glm_clamp(-c / a, 0.0f, 1.0f); t = glm_clamp(-c / a, 0.0f, 1.0f);
} else { } else {
@@ -417,9 +189,7 @@ static void physicsTestClosestPointsBetweenSegments(
glm_vec3_lerp((float_t *)a2, (float_t *)b2, s, outP2); glm_vec3_lerp((float_t *)a2, (float_t *)b2, s, outP2);
} }
/* capsule axis: (cc.x, cc.y ± halfHeight, cc.z), oriented along Y. */ bool physicsTestCapsuleVsSphere(
static bool physicsTestCapsuleVsSphere(
const vec3 cc, const float_t cr, const float_t chh, const vec3 cc, const float_t cr, const float_t chh,
const vec3 sc, const float_t sr, const vec3 sc, const float_t sr,
vec3 outNormal, float_t *outDepth vec3 outNormal, float_t *outDepth
@@ -433,7 +203,7 @@ static bool physicsTestCapsuleVsSphere(
); );
} }
static bool physicsTestCapsuleVsAabb( bool physicsTestCapsuleVsAabb(
const vec3 cc, const float_t cr, const float_t chh, const vec3 cc, const float_t cr, const float_t chh,
const vec3 ac, const vec3 ah, const vec3 ac, const vec3 ah,
vec3 outNormal, float_t *outDepth vec3 outNormal, float_t *outDepth
@@ -447,7 +217,7 @@ static bool physicsTestCapsuleVsAabb(
); );
} }
static bool physicsTestCapsuleVsPlane( bool physicsTestCapsuleVsPlane(
const vec3 cc, const float_t cr, const float_t chh, const vec3 cc, const float_t cr, const float_t chh,
const vec3 pn, const float_t pd, const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth vec3 outNormal, float_t *outDepth
@@ -458,12 +228,12 @@ static bool physicsTestCapsuleVsPlane(
float_t db = glm_vec3_dot((float_t *)pn, capB) - pd; float_t db = glm_vec3_dot((float_t *)pn, capB) - pd;
float_t minDist = (da < db) ? da : db; float_t minDist = (da < db) ? da : db;
*outDepth = cr - minDist; *outDepth = cr - minDist;
if (*outDepth <= 0.0f) return false; if(*outDepth <= 0.0f) return false;
glm_vec3_copy((float_t *)pn, outNormal); glm_vec3_copy((float_t *)pn, outNormal);
return true; return true;
} }
static bool physicsTestCapsuleVsCapsule( bool physicsTestCapsuleVsCapsule(
const vec3 c1, const float_t r1, const float_t hh1, const vec3 c1, const float_t r1, const float_t hh1,
const vec3 c2, const float_t r2, const float_t hh2, const vec3 c2, const float_t r2, const float_t hh2,
vec3 outNormal, float_t *outDepth vec3 outNormal, float_t *outDepth
@@ -477,11 +247,7 @@ static bool physicsTestCapsuleVsCapsule(
return physicsTestSphereVsSphere(p1, r1, p2, r2, outNormal, outDepth); return physicsTestSphereVsSphere(p1, r1, p2, r2, outNormal, outDepth);
} }
/* ============================================================ bool physicsTestDispatch(
* Dispatch
* ============================================================ */
static bool physicsTestDispatch(
const vec3 aPos, const physicsshape_t aShape, const vec3 aPos, const physicsshape_t aShape,
const vec3 bPos, const physicsshape_t bShape, const vec3 bPos, const physicsshape_t bShape,
vec3 outNormal, float_t *outDepth vec3 outNormal, float_t *outDepth
@@ -489,8 +255,7 @@ static bool physicsTestDispatch(
physicshapetype_t ta = aShape.type; physicshapetype_t ta = aShape.type;
physicshapetype_t tb = bShape.type; physicshapetype_t tb = bShape.type;
/* Plane is always the reference surface; keep it as B. */ if(tb == PHYSICS_SHAPE_PLANE) {
if (tb == PHYSICS_SHAPE_PLANE) {
const float_t *pn = bShape.data.plane.normal; const float_t *pn = bShape.data.plane.normal;
const float_t pd = bShape.data.plane.distance; const float_t pd = bShape.data.plane.distance;
switch (ta) { switch (ta) {
@@ -516,10 +281,9 @@ static bool physicsTestDispatch(
} }
} }
/* If A is a plane, swap roles and negate the normal. */ if(ta == PHYSICS_SHAPE_PLANE) {
if (ta == PHYSICS_SHAPE_PLANE) {
vec3 tmp; float_t d; vec3 tmp; float_t d;
if (!physicsTestDispatch( if(!physicsTestDispatch(
bPos, bShape, aPos, aShape, tmp, &d bPos, bShape, aPos, aShape, tmp, &d
)) return false; )) return false;
glm_vec3_scale(tmp, -1.0f, outNormal); glm_vec3_scale(tmp, -1.0f, outNormal);
@@ -540,7 +304,7 @@ static bool physicsTestDispatch(
); );
case PHYSICS_SHAPE_SPHERE: { case PHYSICS_SHAPE_SPHERE: {
vec3 tmp; float_t d; vec3 tmp; float_t d;
if (!physicsTestSphereVsAabb( if(!physicsTestSphereVsAabb(
bPos, bShape.data.sphere.radius, bPos, bShape.data.sphere.radius,
ac, ah, tmp, &d ac, ah, tmp, &d
)) return false; )) return false;
@@ -550,7 +314,7 @@ static bool physicsTestDispatch(
} }
case PHYSICS_SHAPE_CAPSULE: { case PHYSICS_SHAPE_CAPSULE: {
vec3 tmp; float_t d; vec3 tmp; float_t d;
if (!physicsTestCapsuleVsAabb( if(!physicsTestCapsuleVsAabb(
bPos, bPos,
bShape.data.capsule.radius, bShape.data.capsule.radius,
bShape.data.capsule.halfHeight, bShape.data.capsule.halfHeight,
@@ -581,7 +345,7 @@ static bool physicsTestDispatch(
); );
case PHYSICS_SHAPE_CAPSULE: { case PHYSICS_SHAPE_CAPSULE: {
vec3 tmp; float_t d; vec3 tmp; float_t d;
if (!physicsTestCapsuleVsSphere( if(!physicsTestCapsuleVsSphere(
bPos, bPos,
bShape.data.capsule.radius, bShape.data.capsule.radius,
bShape.data.capsule.halfHeight, bShape.data.capsule.halfHeight,
+214
View File
@@ -8,6 +8,220 @@
#pragma once #pragma once
#include "physicsshape.h" #include "physicsshape.h"
/**
* Tests overlap between two axis-aligned bounding boxes.
* outNormal points from B toward A.
*
* @param ac Center of AABB A.
* @param ah Half-extents of AABB A.
* @param bc Center of AABB B.
* @param bh Half-extents of AABB B.
* @param outNormal Push-out normal (B toward A).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
bool_t physicsTestAabbVsAabb(
const vec3 ac, const vec3 ah,
const vec3 bc, const vec3 bh,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between two spheres.
* outNormal points from B toward A.
*
* @param ac Center of sphere A.
* @param ar Radius of sphere A.
* @param bc Center of sphere B.
* @param br Radius of sphere B.
* @param outNormal Push-out normal (B toward A).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
bool_t physicsTestSphereVsSphere(
const vec3 ac, const float_t ar,
const vec3 bc, const float_t br,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between a sphere and an axis-aligned bounding box.
* outNormal points from the AABB toward the sphere.
*
* @param sc Center of the sphere.
* @param sr Radius of the sphere.
* @param ac Center of the AABB.
* @param ah Half-extents of the AABB.
* @param outNormal Push-out normal (AABB toward sphere).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
bool_t physicsTestSphereVsAabb(
const vec3 sc, const float_t sr,
const vec3 ac, const vec3 ah,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between a sphere and an infinite plane.
* outNormal equals the plane normal (pointing away from the surface).
*
* @param sc Center of the sphere.
* @param sr Radius of the sphere.
* @param pn Plane normal (unit vector, world-space).
* @param pd Plane offset: dot(pn, surfacePoint) == pd.
* @param outNormal Push-out normal (equals pn).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
bool_t physicsTestSphereVsPlane(
const vec3 sc, const float_t sr,
const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between an AABB and an infinite plane.
* outNormal equals the plane normal.
*
* @param ac Center of the AABB.
* @param ah Half-extents of the AABB.
* @param pn Plane normal (unit vector, world-space).
* @param pd Plane offset (see physicsTestSphereVsPlane).
* @param outNormal Push-out normal (equals pn).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
bool_t physicsTestAabbVsPlane(
const vec3 ac, const vec3 ah,
const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth
);
/**
* Finds the closest point on segment [a, b] to query point p.
*
* @param a Start of the segment.
* @param b End of the segment.
* @param p Query point.
* @param out Receives the closest point on [a, b] to p.
*/
void physicsTestClosestPointOnSegment(
const vec3 a, const vec3 b, const vec3 p, vec3 out
);
/**
* Finds the closest points between two line segments.
*
* @param a1 Start of segment 1.
* @param b1 End of segment 1.
* @param a2 Start of segment 2.
* @param b2 End of segment 2.
* @param outP1 Receives the closest point on segment 1.
* @param outP2 Receives the closest point on segment 2.
*/
void physicsTestClosestPointsBetweenSegments(
const vec3 a1, const vec3 b1,
const vec3 a2, const vec3 b2,
vec3 outP1, vec3 outP2
);
/**
* Tests overlap between a Y-axis-aligned capsule and a sphere.
* outNormal points from the sphere toward the capsule.
*
* @param cc Center of the capsule.
* @param cr Radius of the capsule.
* @param chh Half-height of the capsule's cylindrical segment.
* @param sc Center of the sphere.
* @param sr Radius of the sphere.
* @param outNormal Push-out normal (sphere toward capsule).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
bool_t physicsTestCapsuleVsSphere(
const vec3 cc, const float_t cr, const float_t chh,
const vec3 sc, const float_t sr,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between a Y-axis-aligned capsule and an AABB.
* outNormal points from the AABB toward the capsule.
*
* @param cc Center of the capsule.
* @param cr Radius of the capsule.
* @param chh Half-height of the capsule's cylindrical segment.
* @param ac Center of the AABB.
* @param ah Half-extents of the AABB.
* @param outNormal Push-out normal (AABB toward capsule).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
bool_t physicsTestCapsuleVsAabb(
const vec3 cc, const float_t cr, const float_t chh,
const vec3 ac, const vec3 ah,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between a Y-axis-aligned capsule and an infinite plane.
* outNormal equals the plane normal.
*
* @param cc Center of the capsule.
* @param cr Radius of the capsule.
* @param chh Half-height of the capsule's cylindrical segment.
* @param pn Plane normal (unit vector, world-space).
* @param pd Plane offset (see physicsTestSphereVsPlane).
* @param outNormal Push-out normal (equals pn).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
bool_t physicsTestCapsuleVsPlane(
const vec3 cc, const float_t cr, const float_t chh,
const vec3 pn, const float_t pd,
vec3 outNormal, float_t *outDepth
);
/**
* Tests overlap between two Y-axis-aligned capsules.
* outNormal points from capsule B toward capsule A.
*
* @param c1 Center of capsule A.
* @param r1 Radius of capsule A.
* @param hh1 Half-height of capsule A's cylindrical segment.
* @param c2 Center of capsule B.
* @param r2 Radius of capsule B.
* @param hh2 Half-height of capsule B's cylindrical segment.
* @param outNormal Push-out normal (B toward A).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
bool_t physicsTestCapsuleVsCapsule(
const vec3 c1, const float_t r1, const float_t hh1,
const vec3 c2, const float_t r2, const float_t hh2,
vec3 outNormal, float_t *outDepth
);
/**
* Routes a shape-pair collision test to the correct primitive.
* When A is a plane, delegates with swapped arguments and negates
* the resulting normal. outNormal points from B toward A.
*
* @param aPos Position of shape A.
* @param aShape Shape descriptor of A.
* @param bPos Position of shape B.
* @param bShape Shape descriptor of B.
* @param outNormal Push-out normal (B toward A).
* @param outDepth Penetration depth.
* @return true if overlapping.
*/
bool_t physicsTestDispatch(
const vec3 aPos, const physicsshape_t aShape,
const vec3 bPos, const physicsshape_t bShape,
vec3 outNormal, float_t *outDepth
);
/** /**
* Tests for collision between two shapes. Returns true if they * Tests for collision between two shapes. Returns true if they
* overlap, and if so, outputs the push-out normal and depth. * overlap, and if so, outputs the push-out normal and depth.
+1 -1
View File
@@ -30,7 +30,7 @@ with open(args.csv, newline="", encoding="utf-8") as f:
item_types.append(item_type) item_types.append(item_type)
rows[item_id] = row rows[item_id] = row
# Assign enum values types and IDs share a single counter so values never collide # Assign enum values: types and IDs share a single counter so values never collide
count = 0 count = 0
type_values = {} type_values = {}
id_values = {} id_values = {}