From 597b9a13dae1f514ca8afa56bab008cb67d4ac40 Mon Sep 17 00:00:00 2001 From: Tavian Barnes 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 + libdimensionxx/dimensionxx/scene.hpp | 26 +++++++++--- libdimensionxx/scene.cpp | 23 ++++++++++- tests/tests.c | 2 + tests/testsxx.cpp | 14 ++++--- 7 files changed, 99 insertions(+), 50 deletions(-) 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; } diff --git a/libdimensionxx/dimensionxx/scene.hpp b/libdimensionxx/dimensionxx/scene.hpp index 8b5270c..c79152f 100644 --- a/libdimensionxx/dimensionxx/scene.hpp +++ b/libdimensionxx/dimensionxx/scene.hpp @@ -25,12 +25,19 @@ namespace Dimension { + // Wrapper for dmnsn_quality + enum Quality { + RENDER_NONE = DMNSN_RENDER_NONE, + RENDER_OBJECTS = DMNSN_RENDER_OBJECTS, + RENDER_FULL = DMNSN_RENDER_FULL + }; + // Base scene class. Wraps a dmnsn_scene*. class Scene { public: // Allocate a dmnsn_scene* - Scene(const Color& background, Camera& camera, Canvas& canvas); + Scene(Camera& camera, Canvas& canvas); // Scene(const Scene& scene); @@ -38,14 +45,21 @@ namespace Dimension ~Scene(); // Element access - Color background() const; - Camera& camera(); - const Camera& camera() const; - Canvas& canvas(); - const Canvas& canvas() const; + Color background() const; + void background(const Color& color); + + Camera& camera(); + const Camera& camera() const; + + Canvas& canvas(); + const Canvas& canvas() const; + Array& objects(); const Array& objects() const; + Quality quality() const; + void quality(Quality quality); + // Access the wrapped C object. dmnsn_scene* dmnsn(); const dmnsn_scene* dmnsn() const; diff --git a/libdimensionxx/scene.cpp b/libdimensionxx/scene.cpp index f41f3b5..5695c1b 100644 --- a/libdimensionxx/scene.cpp +++ b/libdimensionxx/scene.cpp @@ -23,7 +23,7 @@ namespace Dimension { // Allocate a dmnsn_scene - Scene::Scene(const Color& background, Camera& camera, Canvas& canvas) + Scene::Scene(Camera& camera, Canvas& canvas) : m_scene(new dmnsn_scene*(dmnsn_new_scene())), m_camera(camera.copy()), m_canvas(new Canvas(canvas)), m_objects(dmnsn()->objects) { @@ -31,9 +31,10 @@ namespace Dimension throw Dimension_Error("Couldn't allocate scene."); } - dmnsn()->background = background.dmnsn(); + dmnsn()->background = Color(sRGB(0.0, 0.0, 0.0)).dmnsn(); dmnsn()->camera = this->camera().dmnsn(); dmnsn()->canvas = this->canvas().dmnsn(); + dmnsn()->quality = static_cast(RENDER_FULL); } // Delete the scene @@ -53,6 +54,12 @@ namespace Dimension return Color(dmnsn()->background); } + void + Scene::background(const Color& color) + { + dmnsn()->background = color.dmnsn(); + } + Camera& Scene::camera() { @@ -89,6 +96,18 @@ namespace Dimension return m_objects; } + Quality + Scene::quality() const + { + return static_cast(dmnsn()->quality); + } + + void + Scene::quality(Quality quality) + { + dmnsn()->quality = static_cast(quality); + } + // Access the wrapped C object. dmnsn_scene* diff --git a/tests/tests.c b/tests/tests.c index 3696216..8743119 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -101,6 +101,8 @@ dmnsn_new_default_scene() ); dmnsn_array_push(scene->objects, &cube); + scene->quality = DMNSN_RENDER_FULL; + return scene; } diff --git a/tests/testsxx.cpp b/tests/testsxx.cpp index b4c28d9..114fb4a 100644 --- a/tests/testsxx.cpp +++ b/tests/testsxx.cpp @@ -26,10 +26,6 @@ namespace Dimension Scene default_scene() { - // Background color - Color background = sRGB(0.0, 0.1, 0.25); - background.filter(0.1); - // Canvas Canvas canvas(768, 480); @@ -45,7 +41,7 @@ namespace Dimension ); // Scene - Scene scene(background, camera, canvas); + Scene scene(camera, canvas); // Objects in scene @@ -57,6 +53,14 @@ namespace Dimension cube.trans(inverse(Matrix::rotation(Vector(0.75, 0.0, 0.0)))); scene.objects().push(cube); + // Background color + Color background = sRGB(0.0, 0.1, 0.25); + background.filter(0.1); + scene.background(background); + + // Quality + scene.quality(RENDER_FULL); + return scene; } -- cgit v1.2.3