Interaction Test
Its annoying, but its typical in games to actually interact with things. Whats double annoying is this is typically done with math. Rays and what not. Triple annoying, I'm a fucking moron and instead of #include <bullet.h> or some such I'll now proceed to thump my head on the keyboard until this works.
For now our goal is going to be to determine what we might want to interact with.
Dilemma incoming ... I'm not math enough to know if a Ray should be a position and direction or a start and end. I want to choose start/end from a rendering point of view, but the remains of my university math memories is telling me to do start, direction ... hmmm, I'll choose start, direction until I find a reason not to.
Lets keep this simple, lets have a ray and sphere and write some code to test if ray intersects said sphere.
struct m_ray {
m_vector3 start, dir;
};
struct m_sphere {
m_vector3 center;
float radius;
};Now we have some types lets have some functions to build ray, and also test it against a sphere.
Actually I this bastardized code from 'Realtime Collision Detection' buy the put it on your bookshelf and feel pride (works for me anyway).
int
m_ray_intersects_sphere(struct m_ray ray, struct m_sphere sphere) {
struct m_vector3 m = m_vec3_sub_vec3(r.start, s.center);
float b = m_vec3_dot_vec3(m, r.dir);
float c = m_vec3_dot_vec3(m, m) - (s.radius * s.radius);
if(c > 0.f && b > 0.f) {
return 0.f;
}
float discr = b * b - c;
if(discr < 0.f) {
return 0.f;
}
float t = -b - sqrt(discr);
/* Ray is inside */
if(t < 0.f) {
t = 0.f;
}
return t;
}
Now we can hit a sphere with a ray, whats our next step?
Keeping things simple we need to first generate a ray from the camera's transform, then we need to use that ray to test all the 'interactables' which are just spheres in an array.
struct interactables {
float position[3];
uint32_t color;
};Should one hit we'll change its color, the renderer will pick that up.
void update(struct game *game) {
/* Generate the ray information from the player (camera) */
struct m_vector3 ray_dir = m_vec3_from_array(
game->player.fwd);
struct m_vector3 ray_pos = m_vec3_from_array(
game->player.tform.position);
struct m_ray r = m_ray_from_origin_and_dir(ray_pos, ray_dir);
for(int i = 0; i < ROA_ARR_COUNT(game->interactables); ++i) {
struct m_sphere s = {
.center = m_vec3_from_array(game->interactables[i].tform.position),
.radius = 1,
};
float dist = m_ray_vs_sphere_hit(r, s);
game->cfg.interaction_ray_length);
game->interactables[i].color = (uint32_t[2]) {
0xFF0000FF,
0xFFFF00FF,
} [!!dist];
}
}Future work, we might need to interact with non-spheres, but since I don't know what I'm building that is a requirement that doesn't exist just yet. Also right now you can hit more than one thing in theory but again ... need to define if that's a good thing or not. Maybe I want some gravity gun that sucks all things towards it.

Oops! yeah the ray tests spheres but the render is cubes, we'll blame Derek in the rendering department for that, what a damn tool that guy is.