summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/dimension/scene.h7
-rw-r--r--libdimension/raytrace.c76
-rw-r--r--libdimension/scene.c1
-rw-r--r--libdimensionxx/dimensionxx/scene.hpp26
-rw-r--r--libdimensionxx/scene.cpp23
-rw-r--r--tests/tests.c2
-rw-r--r--tests/testsxx.cpp14
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<Object>& objects();
const Array<Object>& 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<dmnsn_quality>(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<Quality>(dmnsn()->quality);
+ }
+
+ void
+ Scene::quality(Quality quality)
+ {
+ dmnsn()->quality = static_cast<dmnsn_quality>(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;
}