Create obj module for scene objects

This commit is contained in:
Camden Dixie O'Brien
2025-09-21 11:41:50 +01:00
parent 88dc098db2
commit a345835703
5 changed files with 85 additions and 26 deletions

View File

@@ -10,6 +10,7 @@ endmacro()
add_library(batomorph add_library(batomorph
src/ff.c src/ff.c
src/obj.c
src/vec3.c src/vec3.c
) )
configure_target(batomorph) configure_target(batomorph)

36
demo.c
View File

@@ -1,4 +1,6 @@
#include "ff.h" #include "ff.h"
#include "obj.h"
#include "ray.h"
#include "vec3.h" #include "vec3.h"
#include <limits.h> #include <limits.h>
@@ -14,9 +16,7 @@
#define FOCLEN 1.0 #define FOCLEN 1.0
typedef struct { #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0]))
vec3_t orig, dir;
} ray_t;
typedef struct { typedef struct {
vec3_t centre; vec3_t centre;
@@ -34,35 +34,19 @@ static const vec3_t vp_v = { 0, -VP_H, 0 };
static const vec3_t pix_x_step = { VP_W / W, 0, 0 }; static const vec3_t pix_x_step = { VP_W / W, 0, 0 };
static const vec3_t pix_y_step = { 0, -VP_H / H, 0 }; static const vec3_t pix_y_step = { 0, -VP_H / H, 0 };
static const sphere_t obj = { static const obj_t scene[] = {
.centre = { 1.0, 0.0, -3.0 }, SPHERE(1.0, 0.0, -3.0, 1.0),
.rad = 1.0, SPHERE(-2.0, 0.0, -5.0, 1.0),
}; };
static pix_t pix[W * H]; static pix_t pix[W * H];
static double intersect(sphere_t sphere, ray_t ray)
{
const vec3_t disp = vec3_sub(sphere.centre, ray.orig);
const double a = vec3_dot(ray.dir, ray.dir);
const double b = -2.0 * vec3_dot(ray.dir, disp);
const double c = vec3_dot(disp, disp) - sphere.rad * sphere.rad;
const double discriminant = b * b - 4 * a * c;
if (discriminant < 0)
return -1.0;
else
return (-b - sqrt(discriminant)) / (2.0 * a);
}
static vec3_t raycol(ray_t ray) static vec3_t raycol(ray_t ray)
{ {
const double t = intersect(obj, ray); hit_t hit;
if (t > 0.0) { for (unsigned i = 0; i < NELEMS(scene); ++i) {
const vec3_t p = vec3_add(ray.orig, vec3_scale(ray.dir, t)); if (scene[i].intersect(scene[i].params, ray, &hit))
const vec3_t normal = vec3_unit(vec3_sub(p, obj.centre)); return vec3_scale(vec3_add(hit.normal, white), 0.5);
return vec3_scale(vec3_add(normal, white), 0.5);
} }
const double a = (ray.dir.y + 1.0) / 2.0; const double a = (ray.dir.y + 1.0) / 2.0;

35
include/obj.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef OBJ_H
#define OBJ_H
#include "ray.h"
#define SPHERE(x, y, z, r) \
{ \
.intersect = intersect_sphere, \
.params = { \
.sphere = { .centre = { x, y, z }, .radius = r }, \
}, \
}
typedef struct {
vec3_t point, normal;
double t;
} hit_t;
typedef struct {
vec3_t centre;
double radius;
} sphere_params_t;
typedef union {
sphere_params_t sphere;
} obj_params_t;
typedef struct {
bool (*intersect)(obj_params_t params, ray_t ray, hit_t *hit_out);
obj_params_t params;
} obj_t;
bool intersect_sphere(obj_params_t params, ray_t ray, hit_t *hit_out);
#endif

10
include/ray.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef RAY_H
#define RAY_H
#include "vec3.h"
typedef struct {
vec3_t orig, dir;
} ray_t;
#endif

29
src/obj.c Normal file
View File

@@ -0,0 +1,29 @@
#include "obj.h"
#include <math.h>
bool intersect_sphere(obj_params_t params, ray_t ray, hit_t *hit_out)
{
const vec3_t centre = params.sphere.centre;
const double r = params.sphere.radius;
const vec3_t disp = vec3_sub(centre, ray.orig);
const double a = vec3_dot(ray.dir, ray.dir);
const double b = -2.0 * vec3_dot(ray.dir, disp);
const double c = vec3_dot(disp, disp) - r * r;
const double discriminant = b * b - 4 * a * c;
if (discriminant < 0)
return false;
const double t = (-b - sqrt(discriminant)) / (2.0 * a);
const vec3_t point = vec3_add(ray.orig, vec3_scale(ray.dir, t));
const vec3_t normal = vec3_unit(vec3_sub(point, centre));
if (hit_out != nullptr) {
hit_out->point = point;
hit_out->normal = normal;
hit_out->t = t;
}
return true;
}