rusting_engine 1.4.0

Vulkan 3D game engine with GPU-accelerated physics for massive physics-heavy scenes
// Collider shapes shared by the built-in physics shader and the GPU
// body-contact passes. Not part of the custom-shader ABI.

#include <sim_math.glsl>

// Shape encoding: x = kind (0 box, 1 sphere, 2 capsule along local Y,
// 3 none); box yzw = half extents; sphere y = radius; capsule y = half
// height, z = radius. Material x = friction, y = restitution. Layers x =
// memberships, y = filters.
struct BodyShape {
    vec4 shape;
    vec4 material;
    uvec4 layers;
};
layout(set = 0, binding = 6) readonly buffer BodyShapes { BodyShape data[]; } body_shapes;

// How far a shape reaches from its center along world direction `n`.
float support(vec4 shape, mat3 rotation, vec3 n) {
    vec3 local = sim_mul_transposed(rotation, n);
    if (shape.x < 0.5) return sim_dot(abs(local), shape.yzw);
    if (shape.x < 1.5) return shape.y;
    precise float reach = shape.z + abs(local.y) * shape.y;
    return reach;
}

// Radius of the sphere around the center that holds the whole shape.
float bounding_radius(vec4 shape) {
    if (shape.x < 0.5) return sim_length(shape.yzw);
    if (shape.x < 1.5) return shape.y;
    precise float radius = shape.y + shape.z;
    return radius;
}

// Rotation of a model matrix with its scale removed.
mat3 rotation_of(mat4 model) {
    return mat3(sim_normalize(model[0].xyz), sim_normalize(model[1].xyz), sim_normalize(model[2].xyz));
}

// Direction from the surface of `shape` (centered at `origin`, turned by
// `rotation`) to `point`, and the signed distance (negative inside).
void shape_distance(vec4 shape, mat3 rotation, vec3 origin, vec3 point, out vec3 normal, out float distance) {
    precise vec3 offset = point - origin;
    vec3 local = sim_mul_transposed(rotation, offset);
    vec3 local_normal = vec3(0.0, 1.0, 0.0);
    if (shape.x < 0.5) {
        vec3 half_extents = shape.yzw;
        precise vec3 outside = abs(local) - half_extents;
        float largest = max(outside.x, max(outside.y, outside.z));
        if (largest > 0.0) {
            precise vec3 delta = local - clamp(local, -half_extents, half_extents);
            distance = sim_length(delta);
            local_normal = sim_div(delta, distance);
        } else {
            // Inside: leave through the nearest face.
            distance = largest;
            if (outside.x == largest) local_normal = vec3(local.x < 0.0 ? -1.0 : 1.0, 0.0, 0.0);
            else if (outside.y == largest) local_normal = vec3(0.0, local.y < 0.0 ? -1.0 : 1.0, 0.0);
            else local_normal = vec3(0.0, 0.0, local.z < 0.0 ? -1.0 : 1.0);
        }
    } else {
        // A sphere is a capsule with no height.
        float half_height = shape.x < 1.5 ? 0.0 : shape.y;
        float radius = shape.x < 1.5 ? shape.y : shape.z;
        precise vec3 delta = local - vec3(0.0, clamp(local.y, -half_height, half_height), 0.0);
        float length_delta = sim_length(delta);
        if (length_delta > 0.000001) local_normal = sim_div(delta, length_delta);
        precise float surface = length_delta - radius;
        distance = surface;
    }
    normal = sim_mul(rotation, local_normal);
}