From 8ab42d0fb70f5c74554350b10e35bd6b6a78ab1b Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Sat, 23 Dec 2017 21:14:06 -0800 Subject: ray: split object render from object description This moves the per-object _prepared state into ray_render_object_$type structs with all the rendering-related object methods switched to operate on the new render structs. Since the current rendering code just makes all these assumptions about light objects being point lights, I've just dropped all the stuff associated with rendering light objects for now. I think it will be refactored a bit later on when the rendering code stops hard-coding the point light stuff. These changes open up the possibility of constifying the scene and constituent objects, now that rendering doesn't shove the prepared state into the embedded _prepared object substructs. --- src/modules/ray/Makefile.am | 2 +- src/modules/ray/ray_object.h | 95 ---------------------- src/modules/ray/ray_object_light.h | 59 -------------- src/modules/ray/ray_object_plane.h | 45 ----------- src/modules/ray/ray_object_point.h | 28 ------- src/modules/ray/ray_object_sphere.h | 74 ------------------ src/modules/ray/ray_render.c | 52 +++++++------ src/modules/ray/ray_render_object.h | 121 +++++++++++++++++++++++++++++ src/modules/ray/ray_render_object_plane.h | 61 +++++++++++++++ src/modules/ray/ray_render_object_point.h | 45 +++++++++++ src/modules/ray/ray_render_object_sphere.h | 90 +++++++++++++++++++++ 11 files changed, 347 insertions(+), 325 deletions(-) create mode 100644 src/modules/ray/ray_render_object.h create mode 100644 src/modules/ray/ray_render_object_plane.h create mode 100644 src/modules/ray/ray_render_object_point.h create mode 100644 src/modules/ray/ray_render_object_sphere.h (limited to 'src/modules/ray') diff --git a/src/modules/ray/Makefile.am b/src/modules/ray/Makefile.am index a0d7cb9..b62e4ba 100644 --- a/src/modules/ray/Makefile.am +++ b/src/modules/ray/Makefile.am @@ -1,4 +1,4 @@ noinst_LIBRARIES = libray.a -libray_a_SOURCES = ray_3f.h ray.c ray_camera.c ray_camera.h ray_color.h ray_euler.c ray_euler.h ray_light_emitter.h ray_object.h ray_object_light.h ray_object_plane.h ray_object_point.h ray_object_sphere.h ray_object_type.h ray_ray.h ray_render.c ray_render.h ray_scene.h ray_surface.h +libray_a_SOURCES = ray_3f.h ray.c ray_camera.c ray_camera.h ray_color.h ray_euler.c ray_euler.h ray_light_emitter.h ray_object.h ray_object_light.h ray_object_plane.h ray_object_point.h ray_object_sphere.h ray_object_type.h ray_ray.h ray_render.c ray_render.h ray_render_object.h ray_render_object_plane.h ray_render_object_point.h ray_render_object_sphere.h ray_scene.h ray_surface.h libray_a_CFLAGS = @ROTOTILLER_CFLAGS@ -ffast-math libray_a_CPPFLAGS = @ROTOTILLER_CFLAGS@ -I@top_srcdir@/src diff --git a/src/modules/ray/ray_object.h b/src/modules/ray/ray_object.h index f882e86..fc5ae1b 100644 --- a/src/modules/ray/ray_object.h +++ b/src/modules/ray/ray_object.h @@ -1,16 +1,11 @@ #ifndef _RAY_OBJECT_H #define _RAY_OBJECT_H -#include - -#include "ray_camera.h" #include "ray_object_light.h" #include "ray_object_plane.h" #include "ray_object_point.h" #include "ray_object_sphere.h" #include "ray_object_type.h" -#include "ray_ray.h" -#include "ray_surface.h" typedef union ray_object_t { ray_object_type_t type; @@ -20,94 +15,4 @@ typedef union ray_object_t { ray_object_light_t light; } ray_object_t; - - -/* Prepare an object for rendering. - * If the object has any pre-calculating to do, this is where it happens. - * The pre-calculated stuff is object-resident under a _prepared struct member. - */ -static inline void ray_object_prepare(ray_object_t *object, ray_camera_t *camera) -{ - switch (object->type) { - case RAY_OBJECT_TYPE_SPHERE: - return ray_object_sphere_prepare(&object->sphere, camera); - - case RAY_OBJECT_TYPE_POINT: - return ray_object_point_prepare(&object->point, camera); - - case RAY_OBJECT_TYPE_PLANE: - return ray_object_plane_prepare(&object->plane, camera); - - case RAY_OBJECT_TYPE_LIGHT: - return ray_object_light_prepare(&object->light, camera); - default: - assert(0); - } -} - - -/* Determine if a ray intersects object. - * If the object is intersected, store where along the ray the intersection occurs in res_distance. - */ -static inline int ray_object_intersects_ray(ray_object_t *object, unsigned depth, ray_ray_t *ray, float *res_distance) -{ - switch (object->type) { - case RAY_OBJECT_TYPE_SPHERE: - return ray_object_sphere_intersects_ray(&object->sphere, depth, ray, res_distance); - - case RAY_OBJECT_TYPE_POINT: - return ray_object_point_intersects_ray(&object->point, depth, ray, res_distance); - - case RAY_OBJECT_TYPE_PLANE: - return ray_object_plane_intersects_ray(&object->plane, depth, ray, res_distance); - - case RAY_OBJECT_TYPE_LIGHT: - return ray_object_light_intersects_ray(&object->light, depth, ray, res_distance); - default: - assert(0); - } -} - - -/* Return the surface normal of object @ point */ -static inline ray_3f_t ray_object_normal(ray_object_t *object, ray_3f_t *point) -{ - switch (object->type) { - case RAY_OBJECT_TYPE_SPHERE: - return ray_object_sphere_normal(&object->sphere, point); - - case RAY_OBJECT_TYPE_POINT: - return ray_object_point_normal(&object->point, point); - - case RAY_OBJECT_TYPE_PLANE: - return ray_object_plane_normal(&object->plane, point); - - case RAY_OBJECT_TYPE_LIGHT: - return ray_object_light_normal(&object->light, point); - default: - assert(0); - } -} - - -/* Return the surface of object @ point */ -static inline ray_surface_t ray_object_surface(ray_object_t *object, ray_3f_t *point) -{ - switch (object->type) { - case RAY_OBJECT_TYPE_SPHERE: - return ray_object_sphere_surface(&object->sphere, point); - - case RAY_OBJECT_TYPE_POINT: - return ray_object_point_surface(&object->point, point); - - case RAY_OBJECT_TYPE_PLANE: - return ray_object_plane_surface(&object->plane, point); - - case RAY_OBJECT_TYPE_LIGHT: - return ray_object_light_surface(&object->light, point); - default: - assert(0); - } -} - #endif diff --git a/src/modules/ray/ray_object_light.h b/src/modules/ray/ray_object_light.h index a6213e8..ca9bac9 100644 --- a/src/modules/ray/ray_object_light.h +++ b/src/modules/ray/ray_object_light.h @@ -1,16 +1,8 @@ #ifndef _RAY_OBJECT_LIGHT_H #define _RAY_OBJECT_LIGHT_H -#include - -#include "ray_camera.h" #include "ray_light_emitter.h" -#include "ray_object_light.h" -#include "ray_object_point.h" -#include "ray_object_sphere.h" #include "ray_object_type.h" -#include "ray_ray.h" -#include "ray_surface.h" typedef struct ray_object_light_t { @@ -19,55 +11,4 @@ typedef struct ray_object_light_t { ray_light_emitter_t emitter; } ray_object_light_t; - -static void ray_object_light_prepare(ray_object_light_t *light, ray_camera_t *camera) -{ -} - - -/* TODO: point is really the only one I've implemented... */ -static inline int ray_object_light_intersects_ray(ray_object_light_t *light, unsigned depth, ray_ray_t *ray, float *res_distance) -{ - switch (light->emitter.type) { - case RAY_LIGHT_EMITTER_TYPE_POINT: - return ray_object_point_intersects_ray(&light->emitter.point, depth, ray, res_distance); - - case RAY_LIGHT_EMITTER_TYPE_SPHERE: - return ray_object_sphere_intersects_ray(&light->emitter.sphere, depth, ray, res_distance); - default: - assert(0); - } -} - - -static inline ray_3f_t ray_object_light_normal(ray_object_light_t *light, ray_3f_t *point) -{ - ray_3f_t normal; - - /* TODO */ - switch (light->emitter.type) { - case RAY_LIGHT_EMITTER_TYPE_SPHERE: - return normal; - - case RAY_LIGHT_EMITTER_TYPE_POINT: - return normal; - default: - assert(0); - } -} - - -static inline ray_surface_t ray_object_light_surface(ray_object_light_t *light, ray_3f_t *point) -{ - switch (light->emitter.type) { - case RAY_LIGHT_EMITTER_TYPE_SPHERE: - return ray_object_sphere_surface(&light->emitter.sphere, point); - - case RAY_LIGHT_EMITTER_TYPE_POINT: - return ray_object_point_surface(&light->emitter.point, point); - default: - assert(0); - } -} - #endif diff --git a/src/modules/ray/ray_object_plane.h b/src/modules/ray/ray_object_plane.h index 0d3a51b..96ed437 100644 --- a/src/modules/ray/ray_object_plane.h +++ b/src/modules/ray/ray_object_plane.h @@ -2,9 +2,7 @@ #define _RAY_OBJECT_PLANE_H #include "ray_3f.h" -#include "ray_camera.h" #include "ray_object_type.h" -#include "ray_ray.h" #include "ray_surface.h" @@ -13,49 +11,6 @@ typedef struct ray_object_plane_t { ray_surface_t surface; ray_3f_t normal; float distance; - struct { - float primary_dot_plus; - } _prepared; } ray_object_plane_t; - -static void ray_object_plane_prepare(ray_object_plane_t *plane, ray_camera_t *camera) -{ - plane->_prepared.primary_dot_plus = (ray_3f_dot(&plane->normal, &camera->position) + plane->distance); -} - - -static inline int ray_object_plane_intersects_ray(ray_object_plane_t *plane, unsigned depth, ray_ray_t *ray, float *res_distance) -{ - float d = ray_3f_dot(&plane->normal, &ray->direction); - - if (d < 0.0f) { - float distance = plane->_prepared.primary_dot_plus; - - if (depth) - distance = (ray_3f_dot(&plane->normal, &ray->origin) + plane->distance); - - distance /= -d; - if (distance > 0.0f) { - *res_distance = distance; - - return 1; - } - } - - return 0; -} - - -static inline ray_3f_t ray_object_plane_normal(ray_object_plane_t *plane, ray_3f_t *point) -{ - return plane->normal; -} - - -static inline ray_surface_t ray_object_plane_surface(ray_object_plane_t *plane, ray_3f_t *point) -{ - return plane->surface; -} - #endif diff --git a/src/modules/ray/ray_object_point.h b/src/modules/ray/ray_object_point.h index 2b58f5f..5685fdc 100644 --- a/src/modules/ray/ray_object_point.h +++ b/src/modules/ray/ray_object_point.h @@ -2,9 +2,7 @@ #define _RAY_OBJECT_POINT_H #include "ray_3f.h" -#include "ray_camera.h" #include "ray_object_type.h" -#include "ray_ray.h" #include "ray_surface.h" @@ -14,30 +12,4 @@ typedef struct ray_object_point_t { ray_3f_t center; } ray_object_point_t; - -static void ray_object_point_prepare(ray_object_point_t *point, ray_camera_t *camera) -{ -} - - -static inline int ray_object_point_intersects_ray(ray_object_point_t *point, unsigned depth, ray_ray_t *ray, float *res_distance) -{ - /* TODO: determine a ray:point intersection */ - return 0; -} - - -static inline ray_3f_t ray_object_point_normal(ray_object_point_t *point, ray_3f_t *_point) -{ - ray_3f_t normal; - - return normal; -} - - -static inline ray_surface_t ray_object_point_surface(ray_object_point_t *point, ray_3f_t *_point) -{ - return point->surface; -} - #endif diff --git a/src/modules/ray/ray_object_sphere.h b/src/modules/ray/ray_object_sphere.h index 0077a68..71b6334 100644 --- a/src/modules/ray/ray_object_sphere.h +++ b/src/modules/ray/ray_object_sphere.h @@ -1,13 +1,8 @@ #ifndef _RAY_OBJECT_SPHERE_H #define _RAY_OBJECT_SPHERE_H -#include - #include "ray_3f.h" -#include "ray_camera.h" -#include "ray_color.h" #include "ray_object_type.h" -#include "ray_ray.h" #include "ray_surface.h" @@ -16,75 +11,6 @@ typedef struct ray_object_sphere_t { ray_surface_t surface; ray_3f_t center; float radius; - struct { - ray_3f_t primary_v; - float primary_dot_vv; - float r2; - float r_inv; - } _prepared; } ray_object_sphere_t; - -static void ray_object_sphere_prepare(ray_object_sphere_t *sphere, ray_camera_t *camera) -{ - sphere->_prepared.primary_v = ray_3f_sub(&sphere->center, &camera->position); - sphere->_prepared.primary_dot_vv = ray_3f_dot(&sphere->_prepared.primary_v, &sphere->_prepared.primary_v); - - sphere->_prepared.r2 = sphere->radius * sphere->radius; - - /* to divide by radius via multiplication in ray_object_sphere_normal() */ - sphere->_prepared.r_inv = 1.0f / sphere->radius; -} - - -static inline int ray_object_sphere_intersects_ray(ray_object_sphere_t *sphere, unsigned depth, ray_ray_t *ray, float *res_distance) -{ - ray_3f_t v = sphere->_prepared.primary_v; - float dot_vv = sphere->_prepared.primary_dot_vv; - float b, disc; - - if (depth) { - v = ray_3f_sub(&sphere->center, &ray->origin); - dot_vv = ray_3f_dot(&v, &v); - } - - b = ray_3f_dot(&v, &ray->direction); - disc = sphere->_prepared.r2 - (dot_vv - (b * b)); - if (disc > 0) { - float i1, i2; - - disc = sqrtf(disc); - - i1 = b - disc; - i2 = b + disc; - - if (i2 > 0 && i1 > 0) { - *res_distance = i1; - return 1; - } - } - - return 0; -} - - -/* return the normal of the surface at the specified point */ -static inline ray_3f_t ray_object_sphere_normal(ray_object_sphere_t *sphere, ray_3f_t *point) -{ - ray_3f_t normal; - - normal = ray_3f_sub(point, &sphere->center); - normal = ray_3f_mult_scalar(&normal, sphere->_prepared.r_inv); /* normalize without the sqrt() */ - - return normal; -} - - -/* return the surface of the sphere @ point */ -static inline ray_surface_t ray_object_sphere_surface(ray_object_sphere_t *sphere, ray_3f_t *point) -{ - /* uniform solids for now... */ - return sphere->surface; -} - #endif diff --git a/src/modules/ray/ray_render.c b/src/modules/ray/ray_render.c index bfa5112..c17e1b9 100644 --- a/src/modules/ray/ray_render.c +++ b/src/modules/ray/ray_render.c @@ -5,7 +5,7 @@ #include "ray_camera.h" #include "ray_color.h" -#include "ray_object.h" +#include "ray_render_object.h" #include "ray_ray.h" #include "ray_scene.h" @@ -18,17 +18,19 @@ typedef struct ray_render_t { ray_color_t ambient_light; ray_camera_frame_t frame; + + ray_render_object_t objects[]; } ray_render_t; /* Determine if the ray is obstructed by an object within the supplied distance, for shadows */ static inline int ray_is_obstructed(ray_render_t *render, unsigned depth, ray_ray_t *ray, float distance) { - ray_object_t *object; + ray_render_object_t *object; - for (object = render->scene->objects; object->type; object++) { + for (object = render->objects; object->type; object++) { float ood; - if (ray_object_intersects_ray(object, depth, ray, &ood) && + if (ray_render_object_intersects_ray(object, depth, ray, &ood) && ood < distance) { return 1; } @@ -64,9 +66,9 @@ static inline float approx_powf(float x, float y) /* Determine the color @ distance on ray on object viewed from origin */ -static inline ray_color_t shade_intersection(ray_render_t *render, ray_object_t *object, ray_ray_t *ray, ray_3f_t *intersection, ray_3f_t *normal, unsigned depth, float *res_reflectivity) +static inline ray_color_t shade_intersection(ray_render_t *render, ray_render_object_t *object, ray_ray_t *ray, ray_3f_t *intersection, ray_3f_t *normal, unsigned depth, float *res_reflectivity) { - ray_surface_t surface = ray_object_surface(object, intersection); + ray_surface_t surface = ray_render_object_surface(object, intersection); ray_color_t color = ray_3f_mult(&surface.color, &render->ambient_light); ray_object_t *light; @@ -116,13 +118,13 @@ static inline ray_color_t shade_intersection(ray_render_t *render, ray_object_t } -static inline ray_object_t * find_nearest_intersection(ray_render_t *render, ray_object_t *reflector, ray_ray_t *ray, unsigned depth, float *res_distance) +static inline ray_render_object_t * find_nearest_intersection(ray_render_t *render, ray_render_object_t *reflector, ray_ray_t *ray, unsigned depth, float *res_distance) { - ray_object_t *nearest_object = NULL; - float nearest_object_distance = INFINITY; - ray_object_t *object; + ray_render_object_t *nearest_object = NULL; + float nearest_object_distance = INFINITY; + ray_render_object_t *object; - for (object = render->scene->objects; object->type; object++) { + for (object = render->objects; object->type; object++) { float distance; /* Don't bother checking if a reflected ray intersects the object reflecting it, @@ -131,7 +133,7 @@ static inline ray_object_t * find_nearest_intersection(ray_render_t *render, ray continue; /* Does this ray intersect object? */ - if (ray_object_intersects_ray(object, depth, ray, &distance)) { + if (ray_render_object_intersects_ray(object, depth, ray, &distance)) { /* Is it the nearest intersection? */ if (distance < nearest_object_distance) { nearest_object = object; @@ -149,15 +151,15 @@ static inline ray_object_t * find_nearest_intersection(ray_render_t *render, ray static inline ray_color_t trace_ray(ray_render_t *render, ray_ray_t *primary_ray) { - ray_color_t color = { .x = 0.0f, .y = 0.0f, .z = 0.0f }; - ray_3f_t intersection, normal; - ray_object_t *reflector = NULL; - float relevance = 1.0f, reflectivity; - unsigned depth = 0; - ray_ray_t reflected_ray, *ray = primary_ray; + ray_color_t color = { .x = 0.0f, .y = 0.0f, .z = 0.0f }; + ray_3f_t intersection, normal; + ray_render_object_t *reflector = NULL; + float relevance = 1.0f, reflectivity; + unsigned depth = 0; + ray_ray_t reflected_ray, *ray = primary_ray; do { - ray_object_t *nearest_object; + ray_render_object_t *nearest_object; float nearest_distance; if (reflector) { @@ -179,7 +181,7 @@ static inline ray_color_t trace_ray(ray_render_t *render, ray_ray_t *primary_ray rvec = ray_3f_mult_scalar(&ray->direction, nearest_distance); intersection = ray_3f_add(&ray->origin, &rvec); - normal = ray_object_normal(nearest_object, &intersection); + normal = ray_render_object_normal(nearest_object, &intersection); more_color = shade_intersection(render, nearest_object, ray, &intersection, &normal, depth, &reflectivity); more_color = ray_3f_mult_scalar(&more_color, relevance); @@ -218,8 +220,12 @@ ray_render_t * ray_render_new(ray_scene_t *scene, ray_camera_t *camera) { ray_render_t *render; ray_object_t *object; + unsigned i; + + for (i = 0, object = scene->objects; object->type; object++) + i++; - render = malloc(sizeof(ray_render_t)); + render = malloc(sizeof(ray_render_t) + i * sizeof(ray_render_object_t)); if (!render) return NULL; @@ -229,8 +235,8 @@ ray_render_t * ray_render_new(ray_scene_t *scene, ray_camera_t *camera) render->ambient_light = ray_3f_mult_scalar(&scene->ambient_color, scene->ambient_brightness); ray_camera_frame_prepare(camera, &render->frame); - for (object = scene->objects; object->type; object++) - ray_object_prepare(object, camera); + for (i = 0, object = scene->objects; object->type; object++) + render->objects[i++] = ray_render_object_prepare(object, camera); return render; } diff --git a/src/modules/ray/ray_render_object.h b/src/modules/ray/ray_render_object.h new file mode 100644 index 0000000..5b4ce25 --- /dev/null +++ b/src/modules/ray/ray_render_object.h @@ -0,0 +1,121 @@ +#ifndef _RAY_RENDER_OBJECT_H +#define _RAY_RENDER_OBJECT_H + +#include + +#include "ray_camera.h" +#include "ray_object.h" +#include "ray_object_type.h" +#include "ray_render_object_plane.h" +#include "ray_render_object_point.h" +#include "ray_render_object_sphere.h" +#include "ray_ray.h" +#include "ray_surface.h" + +typedef union ray_render_object_t { + ray_object_type_t type; + ray_render_object_sphere_t sphere; + ray_render_object_point_t point; + ray_render_object_plane_t plane; +} ray_render_object_t; + + + +/* Prepare an object for rendering. + * If the object has any pre-calculating to do, this is where it happens. + * The pre-calculated stuff is object-resident under a _prepared struct member. + */ +static inline ray_render_object_t ray_render_object_prepare(ray_object_t *object, ray_camera_t *camera) +{ + ray_render_object_t prepared = { .type = object->type }; + + switch (object->type) { + case RAY_OBJECT_TYPE_SPHERE: + prepared.sphere = ray_render_object_sphere_prepare(&object->sphere, camera); + break; + + case RAY_OBJECT_TYPE_POINT: + prepared.point = ray_render_object_point_prepare(&object->point, camera); + break; + + case RAY_OBJECT_TYPE_PLANE: + prepared.plane = ray_render_object_plane_prepare(&object->plane, camera); + break; + + case RAY_OBJECT_TYPE_LIGHT: + /* TODO */ + break; + + default: + assert(0); + } + + return prepared; +} + + +/* Determine if a ray intersects object. + * If the object is intersected, store where along the ray the intersection occurs in res_distance. + */ +static inline int ray_render_object_intersects_ray(ray_render_object_t *object, unsigned depth, ray_ray_t *ray, float *res_distance) +{ + switch (object->type) { + case RAY_OBJECT_TYPE_SPHERE: + return ray_render_object_sphere_intersects_ray(&object->sphere, depth, ray, res_distance); + + case RAY_OBJECT_TYPE_POINT: + return ray_render_object_point_intersects_ray(&object->point, depth, ray, res_distance); + + case RAY_OBJECT_TYPE_PLANE: + return ray_render_object_plane_intersects_ray(&object->plane, depth, ray, res_distance); + + case RAY_OBJECT_TYPE_LIGHT: + /* TODO */ + default: + assert(0); + } +} + + +/* Return the surface normal of object @ point */ +static inline ray_3f_t ray_render_object_normal(ray_render_object_t *object, ray_3f_t *point) +{ + switch (object->type) { + case RAY_OBJECT_TYPE_SPHERE: + return ray_render_object_sphere_normal(&object->sphere, point); + + case RAY_OBJECT_TYPE_POINT: + return ray_render_object_point_normal(&object->point, point); + + case RAY_OBJECT_TYPE_PLANE: + return ray_render_object_plane_normal(&object->plane, point); + + case RAY_OBJECT_TYPE_LIGHT: + /* TODO */ + default: + assert(0); + } +} + + +/* Return the surface of object @ point */ +static inline ray_surface_t ray_render_object_surface(ray_render_object_t *object, ray_3f_t *point) +{ + switch (object->type) { + case RAY_OBJECT_TYPE_SPHERE: + return ray_render_object_sphere_surface(&object->sphere, point); + + case RAY_OBJECT_TYPE_POINT: + return ray_render_object_point_surface(&object->point, point); + + case RAY_OBJECT_TYPE_PLANE: + return ray_render_object_plane_surface(&object->plane, point); + + case RAY_OBJECT_TYPE_LIGHT: + /* TODO */ + default: + assert(0); + } +} + +#endif diff --git a/src/modules/ray/ray_render_object_plane.h b/src/modules/ray/ray_render_object_plane.h new file mode 100644 index 0000000..e5c6fa7 --- /dev/null +++ b/src/modules/ray/ray_render_object_plane.h @@ -0,0 +1,61 @@ +#ifndef _RAY_RENDER_OBJECT_PLANE_H +#define _RAY_RENDER_OBJECT_PLANE_H + +#include "ray_3f.h" +#include "ray_camera.h" +#include "ray_object_plane.h" +#include "ray_object_type.h" +#include "ray_ray.h" +#include "ray_surface.h" + + +typedef struct ray_render_object_plane_t { + ray_object_plane_t object; + float primary_dot_plus; +} ray_render_object_plane_t; + + +static ray_render_object_plane_t ray_render_object_plane_prepare(ray_object_plane_t *plane, ray_camera_t *camera) +{ + ray_render_object_plane_t prepared = { .object = *plane }; + + prepared.primary_dot_plus = ray_3f_dot(&plane->normal, &camera->position) + plane->distance; + + return prepared; +} + + +static inline int ray_render_object_plane_intersects_ray(ray_render_object_plane_t *plane, unsigned depth, ray_ray_t *ray, float *res_distance) +{ + float d = ray_3f_dot(&plane->object.normal, &ray->direction); + + if (d < 0.0f) { + float distance = plane->primary_dot_plus; + + if (depth) + distance = (ray_3f_dot(&plane->object.normal, &ray->origin) + plane->object.distance); + + distance /= -d; + if (distance > 0.0f) { + *res_distance = distance; + + return 1; + } + } + + return 0; +} + + +static inline ray_3f_t ray_render_object_plane_normal(ray_render_object_plane_t *plane, ray_3f_t *point) +{ + return plane->object.normal; +} + + +static inline ray_surface_t ray_render_object_plane_surface(ray_render_object_plane_t *plane, ray_3f_t *point) +{ + return plane->object.surface; +} + +#endif diff --git a/src/modules/ray/ray_render_object_point.h b/src/modules/ray/ray_render_object_point.h new file mode 100644 index 0000000..43e48a1 --- /dev/null +++ b/src/modules/ray/ray_render_object_point.h @@ -0,0 +1,45 @@ +#ifndef _RAY_RENDER_OBJECT_POINT_H +#define _RAY_RENDER_OBJECT_POINT_H + +#include "ray_3f.h" +#include "ray_camera.h" +#include "ray_object_point.h" +#include "ray_object_type.h" +#include "ray_ray.h" +#include "ray_surface.h" + + +typedef struct ray_render_object_point_t { + ray_object_point_t object; +} ray_render_object_point_t; + + +static ray_render_object_point_t ray_render_object_point_prepare(ray_object_point_t *point, ray_camera_t *camera) +{ + ray_render_object_point_t prepared = { .object = *point }; + + return prepared; +} + + +static inline int ray_render_object_point_intersects_ray(ray_render_object_point_t *point, unsigned depth, ray_ray_t *ray, float *res_distance) +{ + /* TODO: determine a ray:point intersection */ + return 0; +} + + +static inline ray_3f_t ray_render_object_point_normal(ray_render_object_point_t *point, ray_3f_t *_point) +{ + ray_3f_t normal; + + return normal; +} + + +static inline ray_surface_t ray_render_object_point_surface(ray_render_object_point_t *point, ray_3f_t *_point) +{ + return point->object.surface; +} + +#endif diff --git a/src/modules/ray/ray_render_object_sphere.h b/src/modules/ray/ray_render_object_sphere.h new file mode 100644 index 0000000..548eb6b --- /dev/null +++ b/src/modules/ray/ray_render_object_sphere.h @@ -0,0 +1,90 @@ +#ifndef _RAY_RENDER_OBJECT_SPHERE_H +#define _RAY_RENDER_OBJECT_SPHERE_H + +#include + +#include "ray_3f.h" +#include "ray_camera.h" +#include "ray_color.h" +#include "ray_object_sphere.h" +#include "ray_object_type.h" +#include "ray_ray.h" +#include "ray_surface.h" + + +typedef struct ray_render_object_sphere_t { + ray_object_sphere_t object; + ray_3f_t primary_v; + float primary_dot_vv; + float r2; + float r_inv; +} ray_render_object_sphere_t; + + +static ray_render_object_sphere_t ray_render_object_sphere_prepare(ray_object_sphere_t *sphere, ray_camera_t *camera) +{ + ray_render_object_sphere_t prepared = { .object = *sphere }; + + prepared.primary_v = ray_3f_sub(&sphere->center, &camera->position); + prepared.primary_dot_vv = ray_3f_dot(&prepared.primary_v, &prepared.primary_v); + + prepared.r2 = sphere->radius * sphere->radius; + + /* to divide by radius via multiplication in ray_object_sphere_normal() */ + prepared.r_inv = 1.0f / sphere->radius; + + return prepared; +} + + +static inline int ray_render_object_sphere_intersects_ray(ray_render_object_sphere_t *sphere, unsigned depth, ray_ray_t *ray, float *res_distance) +{ + ray_3f_t v = sphere->primary_v; + float dot_vv = sphere->primary_dot_vv; + float b, disc; + + if (depth) { + v = ray_3f_sub(&sphere->object.center, &ray->origin); + dot_vv = ray_3f_dot(&v, &v); + } + + b = ray_3f_dot(&v, &ray->direction); + disc = sphere->r2 - (dot_vv - (b * b)); + if (disc > 0) { + float i1, i2; + + disc = sqrtf(disc); + + i1 = b - disc; + i2 = b + disc; + + if (i2 > 0 && i1 > 0) { + *res_distance = i1; + return 1; + } + } + + return 0; +} + + +/* return the normal of the surface at the specified point */ +static inline ray_3f_t ray_render_object_sphere_normal(ray_render_object_sphere_t *sphere, ray_3f_t *point) +{ + ray_3f_t normal; + + normal = ray_3f_sub(point, &sphere->object.center); + normal = ray_3f_mult_scalar(&normal, sphere->r_inv); /* normalize without the sqrt() */ + + return normal; +} + + +/* return the surface of the sphere @ point */ +static inline ray_surface_t ray_render_object_sphere_surface(ray_render_object_sphere_t *sphere, ray_3f_t *point) +{ + /* uniform solids for now... */ + return sphere->object.surface; +} + +#endif -- cgit v1.2.3