From cbc6c0eaf45a7ede48465d1f6d6f7e24c14bd9ce Mon Sep 17 00:00:00 2001
From: Vito Caputo <vcaputo@pengaru.com>
Date: Fri, 2 Jun 2017 11:00:36 -0700
Subject: ray: plumb depth and camera to objects

To enable prepare to precompute aspects of primary rays which all have a
common origin at the camera, bring the camera to ray_object*_prepare() and
bring the depth to ray_object*_intersects_ray() for primary ray detection.

This is only scaffolding, functionally unchanged.
---
 src/modules/ray/ray.c               |  2 +-
 src/modules/ray/ray_object.h        | 21 +++++++++++----------
 src/modules/ray/ray_object_light.h  |  9 +++++----
 src/modules/ray/ray_object_plane.h  |  5 +++--
 src/modules/ray/ray_object_point.h  |  5 +++--
 src/modules/ray/ray_object_sphere.h |  5 +++--
 src/modules/ray/ray_scene.c         | 20 +++++++++++---------
 src/modules/ray/ray_scene.h         |  2 +-
 8 files changed, 38 insertions(+), 31 deletions(-)

diff --git a/src/modules/ray/ray.c b/src/modules/ray/ray.c
index 1143db1..b80f384 100644
--- a/src/modules/ray/ray.c
+++ b/src/modules/ray/ray.c
@@ -146,7 +146,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);
+	ray_scene_prepare(&scene, &camera);
 }
 
 
diff --git a/src/modules/ray/ray_object.h b/src/modules/ray/ray_object.h
index f4c3225..f882e86 100644
--- a/src/modules/ray/ray_object.h
+++ b/src/modules/ray/ray_object.h
@@ -3,6 +3,7 @@
 
 #include <assert.h>
 
+#include "ray_camera.h"
 #include "ray_object_light.h"
 #include "ray_object_plane.h"
 #include "ray_object_point.h"
@@ -25,20 +26,20 @@ typedef union ray_object_t {
  * 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)
+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);
+		return ray_object_sphere_prepare(&object->sphere, camera);
 
 	case RAY_OBJECT_TYPE_POINT:
-		return ray_object_point_prepare(&object->point);
+		return ray_object_point_prepare(&object->point, camera);
 
 	case RAY_OBJECT_TYPE_PLANE:
-		return ray_object_plane_prepare(&object->plane);
+		return ray_object_plane_prepare(&object->plane, camera);
 
 	case RAY_OBJECT_TYPE_LIGHT:
-		return ray_object_light_prepare(&object->light);
+		return ray_object_light_prepare(&object->light, camera);
 	default:
 		assert(0);
 	}
@@ -48,20 +49,20 @@ static inline void ray_object_prepare(ray_object_t *object)
 /* 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, ray_ray_t *ray, float *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, ray, res_distance);
+		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, ray, res_distance);
+		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, ray, res_distance);
+		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, ray, res_distance);
+		return ray_object_light_intersects_ray(&object->light, depth, ray, res_distance);
 	default:
 		assert(0);
 	}
diff --git a/src/modules/ray/ray_object_light.h b/src/modules/ray/ray_object_light.h
index 44b59d4..a6213e8 100644
--- a/src/modules/ray/ray_object_light.h
+++ b/src/modules/ray/ray_object_light.h
@@ -3,6 +3,7 @@
 
 #include <assert.h>
 
+#include "ray_camera.h"
 #include "ray_light_emitter.h"
 #include "ray_object_light.h"
 #include "ray_object_point.h"
@@ -19,20 +20,20 @@ typedef struct ray_object_light_t {
 } ray_object_light_t;
 
 
-static void ray_object_light_prepare(ray_object_light_t *light)
+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, ray_ray_t *ray, float *res_distance)
+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, ray, res_distance);
+		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, ray, res_distance);
+		return ray_object_sphere_intersects_ray(&light->emitter.sphere, depth, ray, res_distance);
 	default:
 		assert(0);
 	}
diff --git a/src/modules/ray/ray_object_plane.h b/src/modules/ray/ray_object_plane.h
index cc7ea8d..0be28f4 100644
--- a/src/modules/ray/ray_object_plane.h
+++ b/src/modules/ray/ray_object_plane.h
@@ -2,6 +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"
@@ -15,12 +16,12 @@ typedef struct ray_object_plane_t {
 } ray_object_plane_t;
 
 
-static void ray_object_plane_prepare(ray_object_plane_t *plane)
+static void ray_object_plane_prepare(ray_object_plane_t *plane, ray_camera_t *camera)
 {
 }
 
 
-static inline int ray_object_plane_intersects_ray(ray_object_plane_t *plane, ray_ray_t *ray, float *res_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);
 
diff --git a/src/modules/ray/ray_object_point.h b/src/modules/ray/ray_object_point.h
index 0eddf25..2b58f5f 100644
--- a/src/modules/ray/ray_object_point.h
+++ b/src/modules/ray/ray_object_point.h
@@ -2,6 +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,12 +15,12 @@ typedef struct ray_object_point_t {
 } ray_object_point_t;
 
 
-static void ray_object_point_prepare(ray_object_point_t *point)
+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, ray_ray_t *ray, float *res_distance)
+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;
diff --git a/src/modules/ray/ray_object_sphere.h b/src/modules/ray/ray_object_sphere.h
index aadda18..9c74752 100644
--- a/src/modules/ray/ray_object_sphere.h
+++ b/src/modules/ray/ray_object_sphere.h
@@ -4,6 +4,7 @@
 #include <math.h>
 
 #include "ray_3f.h"
+#include "ray_camera.h"
 #include "ray_color.h"
 #include "ray_object_type.h"
 #include "ray_ray.h"
@@ -22,7 +23,7 @@ typedef struct ray_object_sphere_t {
 } ray_object_sphere_t;
 
 
-static void ray_object_sphere_prepare(ray_object_sphere_t *sphere)
+static void ray_object_sphere_prepare(ray_object_sphere_t *sphere, ray_camera_t *camera)
 {
 	sphere->_prepared.r2 = sphere->radius * sphere->radius;
 
@@ -31,7 +32,7 @@ static void ray_object_sphere_prepare(ray_object_sphere_t *sphere)
 }
 
 
-static inline int ray_object_sphere_intersects_ray(ray_object_sphere_t *sphere, ray_ray_t *ray, float *res_distance)
+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 = ray_3f_sub(&ray->origin, &sphere->center);
 	float		b = ray_3f_dot(&v, &ray->direction);
diff --git a/src/modules/ray/ray_scene.c b/src/modules/ray/ray_scene.c
index a95058f..b5d1e81 100644
--- a/src/modules/ray/ray_scene.c
+++ b/src/modules/ray/ray_scene.c
@@ -16,14 +16,14 @@ static ray_color_t trace_ray(ray_scene_t *scene, ray_ray_t *ray, unsigned depth)
 
 
 /* Determine if the ray is obstructed by an object within the supplied distance, for shadows */
-static inline int ray_is_obstructed(ray_scene_t *scene, ray_ray_t *ray, float distance)
+static inline int ray_is_obstructed(ray_scene_t *scene, unsigned depth, ray_ray_t *ray, float distance)
 {
 	unsigned	i;
 
 	for (i = 0; i < scene->n_objects; i++) {
 		float	ood;
 
-		if (ray_object_intersects_ray(&scene->objects[i], ray, &ood) &&
+		if (ray_object_intersects_ray(&scene->objects[i], depth, ray, &ood) &&
 		    ood < distance) {
 			return 1;
 		}
@@ -34,7 +34,7 @@ static inline int ray_is_obstructed(ray_scene_t *scene, ray_ray_t *ray, float di
 
 
 /* shadow test */
-static inline int point_is_shadowed(ray_scene_t *scene, ray_3f_t *light_direction, float distance, ray_3f_t *point)
+static inline int point_is_shadowed(ray_scene_t *scene, unsigned depth, ray_3f_t *light_direction, float distance, ray_3f_t *point)
 {
 	ray_ray_t	shadow_ray;
 
@@ -46,7 +46,7 @@ static inline int point_is_shadowed(ray_scene_t *scene, ray_3f_t *light_directio
 	shadow_ray.origin = ray_3f_mult_scalar(&shadow_ray.direction, 0.00001f);
 	shadow_ray.origin = ray_3f_add(&shadow_ray.origin, point);
 
-	if (ray_is_obstructed(scene, &shadow_ray, distance))
+	if (ray_is_obstructed(scene, depth + 1, &shadow_ray, distance))
 		return 1;
 
 	return 0;
@@ -84,7 +84,7 @@ static inline ray_color_t shade_ray(ray_scene_t *scene, ray_ray_t *ray, ray_obje
 
 		lvec = ray_3f_mult_scalar(&lvec, (1.0f / ldist)); /* normalize lvec */
 #if 1
-		if (point_is_shadowed(scene, &lvec, ldist, &intersection))
+		if (point_is_shadowed(scene, depth, &lvec, ldist, &intersection))
 			continue;
 #endif
 		lvec_normal_dot = ray_3f_dot(&normal, &lvec);
@@ -149,7 +149,7 @@ static ray_color_t trace_ray(ray_scene_t *scene, ray_ray_t *ray, unsigned depth)
 		float	distance;
 
 		/* Does this ray intersect object? */
-		if (ray_object_intersects_ray(&scene->objects[i], ray, &distance)) {
+		if (ray_object_intersects_ray(&scene->objects[i], depth, ray, &distance)) {
 
 			/* Is it the nearest intersection? */
 			if (distance < nearest_object_distance) {
@@ -187,13 +187,15 @@ void ray_scene_render_fragment(ray_scene_t *scene, ray_camera_t *camera, fb_frag
 }
 
 
-/* prepare the scene for rendering, must be called whenever the scene has been changed. */
-void ray_scene_prepare(ray_scene_t *scene)
+/* prepare the scene for rendering with camera, must be called whenever anything in the scene+camera pair has been changed. */
+/* this is basically a time for the raytracer to precompute whatever it can which otherwise ends up occurring per-ray */
+/* the camera is included so primary rays which all have a common origin may be optimized for */
+void ray_scene_prepare(ray_scene_t *scene, ray_camera_t *camera)
 {
 	unsigned	i;
 
 	scene->_prepared.ambient_light = ray_3f_mult_scalar(&scene->ambient_color, scene->ambient_brightness);
 
 	for (i = 0; i < scene->n_objects; i++)
-		ray_object_prepare(&scene->objects[i]);
+		ray_object_prepare(&scene->objects[i], camera);
 }
diff --git a/src/modules/ray/ray_scene.h b/src/modules/ray/ray_scene.h
index 820b16b..98928ee 100644
--- a/src/modules/ray/ray_scene.h
+++ b/src/modules/ray/ray_scene.h
@@ -24,7 +24,7 @@ typedef struct ray_scene_t {
 	} _prepared;
 } ray_scene_t;
 
-void ray_scene_prepare(ray_scene_t *scene);
+void ray_scene_prepare(ray_scene_t *scene, ray_camera_t *camera);
 void ray_scene_render_fragment(ray_scene_t *scene, ray_camera_t *camera, fb_fragment_t *fragment);
 
 #endif
-- 
cgit v1.2.3