From 73ef51a819138e50b3d0b162d61a9f272fe07d01 Mon Sep 17 00:00:00 2001 From: Vito Caputo Date: Fri, 12 May 2017 15:17:52 -0700 Subject: ray: add ray_scene_prepare() object precomputing Just embed a _prepared struct in the object where precomputed stuff can be cached. Gets called once before rendering, which ends up calling the object-specific ray_object_$type_prepare() methods per object. --- src/modules/ray/ray.c | 1 + src/modules/ray/ray_object.c | 24 ++++++++++++++++++++++++ src/modules/ray/ray_object.h | 1 + src/modules/ray/ray_object_light.h | 5 +++++ src/modules/ray/ray_object_plane.h | 5 +++++ src/modules/ray/ray_object_point.h | 5 +++++ src/modules/ray/ray_object_sphere.h | 11 ++++++++++- src/modules/ray/ray_scene.c | 10 ++++++++++ src/modules/ray/ray_scene.h | 1 + 9 files changed, 62 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/modules/ray/ray.c b/src/modules/ray/ray.c index a934c30..185b412 100644 --- a/src/modules/ray/ray.c +++ b/src/modules/ray/ray.c @@ -142,6 +142,7 @@ static void ray_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fra /* tilt camera pitch in time with up and down movements, phase shifted appreciably */ camera.orientation.pitch = sinf((M_PI * 1.5f) + r * 1.3f) * .6f + -.35f; #endif + ray_scene_prepare(&scene); } diff --git a/src/modules/ray/ray_object.c b/src/modules/ray/ray_object.c index 4c5ccaf..ec3dcd8 100644 --- a/src/modules/ray/ray_object.c +++ b/src/modules/ray/ray_object.c @@ -9,6 +9,30 @@ #include "ray_surface.h" +/* 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. + */ +void ray_object_prepare(ray_object_t *object) +{ + switch (object->type) { + case RAY_OBJECT_TYPE_SPHERE: + return ray_object_sphere_prepare(&object->sphere); + + case RAY_OBJECT_TYPE_POINT: + return ray_object_point_prepare(&object->point); + + case RAY_OBJECT_TYPE_PLANE: + return ray_object_plane_prepare(&object->plane); + + case RAY_OBJECT_TYPE_LIGHT: + return ray_object_light_prepare(&object->light); + 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. */ diff --git a/src/modules/ray/ray_object.h b/src/modules/ray/ray_object.h index abdb254..7edf955 100644 --- a/src/modules/ray/ray_object.h +++ b/src/modules/ray/ray_object.h @@ -17,6 +17,7 @@ typedef union ray_object_t { ray_object_light_t light; } ray_object_t; +void ray_object_prepare(ray_object_t *object); int ray_object_intersects_ray(ray_object_t *object, ray_ray_t *ray, float *res_distance); ray_3f_t ray_object_normal(ray_object_t *object, ray_3f_t *point); ray_surface_t ray_object_surface(ray_object_t *object, ray_3f_t *point); diff --git a/src/modules/ray/ray_object_light.h b/src/modules/ray/ray_object_light.h index 342c050..44b59d4 100644 --- a/src/modules/ray/ray_object_light.h +++ b/src/modules/ray/ray_object_light.h @@ -19,6 +19,11 @@ typedef struct ray_object_light_t { } ray_object_light_t; +static void ray_object_light_prepare(ray_object_light_t *light) +{ +} + + /* TODO: point is really the only one I've implemented... */ static inline int ray_object_light_intersects_ray(ray_object_light_t *light, ray_ray_t *ray, float *res_distance) { diff --git a/src/modules/ray/ray_object_plane.h b/src/modules/ray/ray_object_plane.h index 8fb64c8..cc7ea8d 100644 --- a/src/modules/ray/ray_object_plane.h +++ b/src/modules/ray/ray_object_plane.h @@ -15,6 +15,11 @@ typedef struct ray_object_plane_t { } ray_object_plane_t; +static void ray_object_plane_prepare(ray_object_plane_t *plane) +{ +} + + static inline int ray_object_plane_intersects_ray(ray_object_plane_t *plane, ray_ray_t *ray, float *res_distance) { float d = ray_3f_dot(&plane->normal, &ray->direction); diff --git a/src/modules/ray/ray_object_point.h b/src/modules/ray/ray_object_point.h index c0c9610..0eddf25 100644 --- a/src/modules/ray/ray_object_point.h +++ b/src/modules/ray/ray_object_point.h @@ -14,6 +14,11 @@ typedef struct ray_object_point_t { } ray_object_point_t; +static void ray_object_point_prepare(ray_object_point_t *point) +{ +} + + static inline int ray_object_point_intersects_ray(ray_object_point_t *point, ray_ray_t *ray, float *res_distance) { /* TODO: determine a ray:point intersection */ diff --git a/src/modules/ray/ray_object_sphere.h b/src/modules/ray/ray_object_sphere.h index 8a91316..cb8e665 100644 --- a/src/modules/ray/ray_object_sphere.h +++ b/src/modules/ray/ray_object_sphere.h @@ -15,14 +15,23 @@ typedef struct ray_object_sphere_t { ray_surface_t surface; ray_3f_t center; float radius; + struct { + float r2; + } _prepared; } ray_object_sphere_t; +static void ray_object_sphere_prepare(ray_object_sphere_t *sphere) +{ + sphere->_prepared.r2 = sphere->radius * sphere->radius; +} + + static inline int ray_object_sphere_intersects_ray(ray_object_sphere_t *sphere, ray_ray_t *ray, float *res_distance) { ray_3f_t v = ray_3f_sub(&ray->origin, &sphere->center); float b = ray_3f_dot(&v, &ray->direction); - float disc = (sphere->radius * sphere->radius) - (ray_3f_dot(&v, &v) - (b * b)); + float disc = sphere->_prepared.r2 - (ray_3f_dot(&v, &v) - (b * b)); if (disc > 0) { float i1, i2; diff --git a/src/modules/ray/ray_scene.c b/src/modules/ray/ray_scene.c index e2c7f2c..87a77af 100644 --- a/src/modules/ray/ray_scene.c +++ b/src/modules/ray/ray_scene.c @@ -167,3 +167,13 @@ void ray_scene_render_fragment(ray_scene_t *scene, ray_camera_t *camera, fb_frag buf += stride; } while (ray_camera_frame_y_step(&frame)); } + + +/* prepare the scene for rendering, must be called whenever the scene has been changed. */ +void ray_scene_prepare(ray_scene_t *scene) +{ + unsigned i; + + for (i = 0; i < scene->n_objects; i++) + ray_object_prepare(&scene->objects[i]); +} diff --git a/src/modules/ray/ray_scene.h b/src/modules/ray/ray_scene.h index 9a31d80..d8a1e7a 100644 --- a/src/modules/ray/ray_scene.h +++ b/src/modules/ray/ray_scene.h @@ -20,6 +20,7 @@ typedef struct ray_scene_t { float ambient_brightness; } ray_scene_t; +void ray_scene_prepare(ray_scene_t *scene); void ray_scene_render_fragment(ray_scene_t *scene, ray_camera_t *camera, fb_fragment_t *fragment); #endif -- cgit v1.2.3