debug_ray.h

cross platform rendering playground

src/passes/debug/debug_ray.h

1.86 KB
#pragma once

#include "core/math_rtm.h"

struct DebugRay {
    vec3 origin = vec3(0.0f);
    vec3 dir = vec3(0.0f, 0.0f, 1.0f); // normalized
};

inline DebugRay debug_unproject(f32 ndc_x, f32 ndc_y, vec3 eye_pos, const mat4 &inv_view_proj) {
    vec4 near_p = transform_point(vec3(ndc_x, ndc_y, 1.0f), inv_view_proj);
    vec3 n = vec3(near_p.x / near_p.w, near_p.y / near_p.w, near_p.z / near_p.w);
    DebugRay r;
    r.origin = eye_pos;
    r.dir = (n - eye_pos).normalized();
    return r;
}

// returns true + nearest positive t on hit
inline bool debug_ray_vs_aabb(const DebugRay &ray, vec3 mn, vec3 mx, f32 &t_out) {
    f32 tmin = 0.0f;
    f32 tmax = 1e30f;
    const f32 o[3] = {ray.origin.x, ray.origin.y, ray.origin.z};
    const f32 d[3] = {ray.dir.x, ray.dir.y, ray.dir.z};
    const f32 bmin[3] = {mn.x, mn.y, mn.z};
    const f32 bmax[3] = {mx.x, mx.y, mx.z};
    for (int i = 0; i < 3; ++i) {
        if (d[i] == 0.0f) {
            if (o[i] < bmin[i] || o[i] > bmax[i]) {
                return false;
            }
        } else {
            f32 inv = 1.0f / d[i];
            f32 t0 = (bmin[i] - o[i]) * inv;
            f32 t1 = (bmax[i] - o[i]) * inv;
            if (t0 > t1) {
                f32 tmp = t0;
                t0 = t1;
                t1 = tmp;
            }
            tmin = t0 > tmin ? t0 : tmin;
            tmax = t1 < tmax ? t1 : tmax;
            if (tmax < tmin) {
                return false;
            }
        }
    }
    t_out = tmin;
    return true;
}

inline bool debug_ray_vs_sphere(const DebugRay &ray, vec3 center, f32 radius, f32 &t_out) {
    vec3 oc = ray.origin - center;
    f32 b = oc.dot(ray.dir);
    f32 c = oc.dot(oc) - radius * radius;
    f32 disc = b * b - c;
    if (disc < 0.0f) {
        return false;
    }
    f32 t = -b - sqrtf(disc);
    if (t < 0.0f) {
        return false;
    }
    t_out = t;
    return true;
}