diff --git a/CMakeLists.txt b/CMakeLists.txt index e061c73..b7eb995 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ macro(configure_target target) endmacro() add_library(batomorph + src/camera.c src/ff.c src/obj.c src/vec3.c diff --git a/demo.c b/demo.c index af02ceb..88d104e 100644 --- a/demo.c +++ b/demo.c @@ -1,3 +1,4 @@ +#include "camera.h" #include "ff.h" #include "obj.h" #include "ray.h" @@ -11,35 +12,23 @@ #define W 800 #define H 600 -#define VP_H 2.0 -#define VP_W (VP_H * W / H) - -#define FOCLEN 1.0 +#define FOCAL_LEN 1.0 +#define VIEWPORT_H 2.0 #define NELEMS(arr) (sizeof(arr) / sizeof(arr[0])) -typedef struct { - vec3_t centre; - double rad; -} sphere_t; - static const vec3_t lightblue = { 0.4, 0.6, 1.0 }; static const vec3_t white = { 1.0, 1.0, 1.0 }; static const vec3_t red = { 1.0, 0.1, 0.2 }; -static const vec3_t camera = { 0, 0, 0 }; -static const vec3_t vp_disp = { 0, 0, FOCLEN }; -static const vec3_t vp_u = { VP_W, 0, 0 }; -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_y_step = { 0, -VP_H / H, 0 }; +static const vec3_t camera_pos = { 0.0, 0.0, 0.0 }; static const obj_t scene[] = { SPHERE(1.0, 0.0, -3.0, 1.0), SPHERE(-2.0, 0.0, -5.0, 1.0), }; -static pix_t pix[W * H]; +static pix_t pixbuf[W * H]; static vec3_t raycol(ray_t ray) { @@ -63,27 +52,23 @@ static void setpix(vec3_t col, pix_t *out) int main() { - img_t img = { .w = W, .h = H, .pix = pix }; - - const vec3_t vp_topleft = vec3_sub( - vec3_sub(vec3_sub(camera, vp_disp), vec3_scale(vp_u, 0.5)), - vec3_scale(vp_v, 0.5)); - const vec3_t pix_orig = vec3_add( - vec3_add(vp_topleft, vec3_scale(pix_x_step, 0.5)), - vec3_scale(pix_y_step, 0.5)); + img_t img = { .w = W, .h = H, .pix = pixbuf }; + camera_t camera = camera_init(camera_pos, FOCAL_LEN, VIEWPORT_H, W, H); for (unsigned y = 0; y < H; ++y) { fprintf(stderr, "\r[%3d/%3d]", y, H); fflush(stderr); - const vec3_t row = vec3_add(pix_orig, vec3_scale(pix_y_step, y)); + const vec3_t row + = vec3_add(camera.pix_origin, vec3_scale(camera.y_step, y)); for (unsigned x = 0; x < W; ++x) { + const vec3_t pix = vec3_add(row, vec3_scale(camera.x_step, x)); const ray_t ray = { - .orig = camera, - .dir = vec3_unit(vec3_add(row, vec3_scale(pix_x_step, x))), + .orig = camera.pos, + .dir = vec3_unit(pix), }; const vec3_t col = raycol(ray); - setpix(col, pix + (W * y + x)); + setpix(col, img.pix + (W * y + x)); } } diff --git a/include/camera.h b/include/camera.h new file mode 100644 index 0000000..c4d6e0c --- /dev/null +++ b/include/camera.h @@ -0,0 +1,17 @@ +#ifndef CAMERA_H +#define CAMERA_H + +#include "vec3.h" + +#include + +typedef struct { + vec3_t pos; + vec3_t pix_origin, x_step, y_step; +} camera_t; + +camera_t camera_init( + vec3_t pos, double focal_len, double viewport_height, uint32_t img_width, + uint32_t img_height); + +#endif diff --git a/src/camera.c b/src/camera.c new file mode 100644 index 0000000..dbd200b --- /dev/null +++ b/src/camera.c @@ -0,0 +1,26 @@ +#include "camera.h" + +camera_t camera_init( + vec3_t pos, double focal_len, double viewport_height, uint32_t img_width, + uint32_t img_height) +{ + const double aspect = (double)img_width / (double)img_height; + const double viewport_width = viewport_height * aspect; + const vec3_t viewport_disp = { 0, 0, focal_len }; + const vec3_t u = { viewport_width, 0, 0 }; + const vec3_t v = { 0, -viewport_height, 0 }; + const vec3_t topleft = vec3_sub( + vec3_sub(pos, viewport_disp), vec3_scale(vec3_add(u, v), 0.5)); + + const vec3_t x_step = vec3_scale(u, 1.0 / (double)img_width); + const vec3_t y_step = vec3_scale(v, 1.0 / (double)img_height); + const vec3_t pix_origin + = vec3_add(topleft, vec3_scale(vec3_add(x_step, y_step), 0.5)); + + return (camera_t) { + .pos = pos, + .pix_origin = pix_origin, + .x_step = x_step, + .y_step = y_step, + }; +}