From 597b9a13dae1f514ca8afa56bab008cb67d4ac40 Mon Sep 17 00:00:00 2001
From: Tavian Barnes <tavianator@gmail.com>
Date: Sun, 12 Jul 2009 21:17:20 +0000
Subject: Add ability to set rendering quality.

---
 libdimension/dimension/scene.h |  7 ++++
 libdimension/raytrace.c        | 76 ++++++++++++++++++++++--------------------
 libdimension/scene.c           |  1 +
 3 files changed, 47 insertions(+), 37 deletions(-)

(limited to 'libdimension')

diff --git a/libdimension/dimension/scene.h b/libdimension/dimension/scene.h
index e76aef3..8104917 100644
--- a/libdimension/dimension/scene.h
+++ b/libdimension/dimension/scene.h
@@ -25,11 +25,18 @@
 #ifndef DIMENSION_SCENE_H
 #define DIMENSION_SCENE_H
 
+typedef enum {
+  DMNSN_RENDER_NONE,
+  DMNSN_RENDER_OBJECTS,
+  DMNSN_RENDER_FULL
+} dmnsn_quality;
+
 typedef struct {
   dmnsn_color background;
   dmnsn_array *objects;
   dmnsn_camera *camera;
   dmnsn_canvas *canvas;
+  dmnsn_quality quality;
 } dmnsn_scene;
 
 /* Create a scene, initializing only the ->objects field */
diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c
index 7c3637e..03dcbab 100644
--- a/libdimension/raytrace.c
+++ b/libdimension/raytrace.c
@@ -183,6 +183,10 @@ dmnsn_raytrace_scene_multithread_thread(void *ptr)
   return retval;
 }
 
+/* Helper for dmnsn_raytrace_scene_impl - shoot a ray */
+static dmnsn_color dmnsn_raytrace_shoot(dmnsn_scene *scene, dmnsn_color color,
+                                        unsigned int x, unsigned int y);
+
 /*
  * Actually raytrace a scene
  */
@@ -190,14 +194,9 @@ static int
 dmnsn_raytrace_scene_impl(dmnsn_progress *progress, dmnsn_scene *scene,
                           unsigned int index, unsigned int threads)
 {
-  unsigned int x, y, i, j;
+  unsigned int x, y;
   unsigned int width, height;
-  double t, t_temp;
-  dmnsn_object *object;
-  dmnsn_line ray, ray_trans;
-  dmnsn_array *intersections;
   dmnsn_color color;
-  dmnsn_CIE_Lab Lab = { 0.0, 0.0, 0.0 }; /* Shut up uninitialized use warning */
 
   width  = scene->canvas->x;
   height = scene->canvas->y;
@@ -210,46 +209,49 @@ dmnsn_raytrace_scene_impl(dmnsn_progress *progress, dmnsn_scene *scene,
     for (x -= width; x < width; x += threads) {
       /* Set the pixel to the background color */
       color = scene->background;
-      t = -1.0;
 
-      /* Get the ray corresponding to the (x,y)'th pixel */
-      ray = (*scene->camera->ray_fn)(scene->camera, scene->canvas, x, y);
+      if (scene->quality >= DMNSN_RENDER_OBJECTS) {
+        color = dmnsn_raytrace_shoot(scene, color, x, y);
+      }
 
-      for (i = 0; i < dmnsn_array_size(scene->objects); ++i) {
-        dmnsn_array_get(scene->objects, i, &object);
+      dmnsn_set_pixel(scene->canvas, x, y, color);
+    }
 
-        /* Transform the ray according to the object */
-        ray_trans = dmnsn_matrix_line_mul(object->trans, ray);
+    dmnsn_increment_progress(progress);
+  }
 
-        /* Test for intersections with objects */
-        intersections = (*object->intersections_fn)(object, ray_trans);
-        /* Find the closest intersection */
-        for (j = 0; j < dmnsn_array_size(intersections); ++j) {
-          dmnsn_array_get(intersections, j, &t_temp);
-          if ((t_temp < t && t_temp >= 0.0) || t < 0.0) {
-            t = t_temp;
+  return 0;
+}
 
-            /* Color each object differently */
-            Lab.a = sin((double)(i + 8));
-            Lab.b = cos((double)(i + 8));
-          }
-        }
-        dmnsn_delete_array(intersections);
-      }
+/* Shoot a ray, and calculate the color, using `color' as the background */
+static dmnsn_color
+dmnsn_raytrace_shoot(dmnsn_scene *scene, dmnsn_color color,
+                     unsigned int x, unsigned int y)
+{
+  dmnsn_line ray, ray_trans;
+  dmnsn_object *object;
+  dmnsn_array *intersections;
+  unsigned int i;
 
-      /* Shade according to distance from camera */
-      if (t >= 0.0) {
-        Lab.L = 100.0*(1.0 - (t - 2.25)/2.25);
-        Lab.a *= Lab.L/1.1;
-        Lab.b *= Lab.L/1.1;
-        color = dmnsn_color_from_Lab(Lab, dmnsn_whitepoint);
-      }
+  /* Get the ray corresponding to the (x,y)'th pixel */
+  ray = (*scene->camera->ray_fn)(scene->camera, scene->canvas, x, y);
 
-      dmnsn_set_pixel(scene->canvas, x, y, color);
+  for (i = 0; i < dmnsn_array_size(scene->objects); ++i) {
+    dmnsn_array_get(scene->objects, i, &object);
+
+    /* Transform the ray according to the object */
+    ray_trans = dmnsn_matrix_line_mul(object->trans, ray);
+
+    /* Test for intersections with objects */
+    intersections = (*object->intersections_fn)(object, ray_trans);
+
+    if (dmnsn_array_size(intersections) > 0) {
+      color = dmnsn_color_from_XYZ(dmnsn_whitepoint);
     }
 
-    dmnsn_increment_progress(progress);
+    /* Delete the intersections array */
+    dmnsn_delete_array(intersections);
   }
 
-  return 0;
+  return color;
 }
diff --git a/libdimension/scene.c b/libdimension/scene.c
index afda2ce..12bab73 100644
--- a/libdimension/scene.c
+++ b/libdimension/scene.c
@@ -28,6 +28,7 @@ dmnsn_new_scene()
   dmnsn_scene *scene = malloc(sizeof(dmnsn_scene));
   if (scene) {
     scene->objects = dmnsn_new_array(sizeof(dmnsn_object*));
+    scene->quality = DMNSN_RENDER_NONE;
   }
   return scene;
 }
-- 
cgit v1.2.3