diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2014-08-19 17:10:03 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2015-10-25 11:03:56 -0400 |
commit | 7b09710392d35fb55b52031d447a542d99fc6b4b (patch) | |
tree | 270eb927ee8c52ceeb99926ebf4843704775a610 /libdimension/dimension | |
parent | 200c86b91ea7063d35be3bffc11c5da53c054653 (diff) | |
download | dimension-7b09710392d35fb55b52031d447a542d99fc6b4b.tar.xz |
Modularize the libdimension codebase.
Diffstat (limited to 'libdimension/dimension')
-rw-r--r-- | libdimension/dimension/base.h | 46 | ||||
-rw-r--r-- | libdimension/dimension/base/array.h (renamed from libdimension/dimension/array.h) | 4 | ||||
-rw-r--r-- | libdimension/dimension/base/common.h (renamed from libdimension/dimension/common.h) | 4 | ||||
-rw-r--r-- | libdimension/dimension/base/compiler.h (renamed from libdimension/dimension/compiler.h) | 4 | ||||
-rw-r--r-- | libdimension/dimension/base/dictionary.h (renamed from libdimension/dimension/dictionary.h) | 4 | ||||
-rw-r--r-- | libdimension/dimension/base/error.h (renamed from libdimension/dimension/error.h) | 9 | ||||
-rw-r--r-- | libdimension/dimension/base/malloc.h (renamed from libdimension/dimension/malloc.h) | 4 | ||||
-rw-r--r-- | libdimension/dimension/base/pool.h (renamed from libdimension/dimension/pool.h) | 4 | ||||
-rw-r--r-- | libdimension/dimension/canvas.h | 114 | ||||
-rw-r--r-- | libdimension/dimension/canvas/canvas.h | 131 | ||||
-rw-r--r-- | libdimension/dimension/canvas/gl.h (renamed from libdimension/dimension/gl.h) | 4 | ||||
-rw-r--r-- | libdimension/dimension/canvas/png.h (renamed from libdimension/dimension/png.h) | 4 | ||||
-rw-r--r-- | libdimension/dimension/color.h | 177 | ||||
-rw-r--r-- | libdimension/dimension/color/color.h | 198 | ||||
-rw-r--r-- | libdimension/dimension/color/tcolor.h (renamed from libdimension/dimension/tcolor.h) | 4 | ||||
-rw-r--r-- | libdimension/dimension/concurrency.h | 39 | ||||
-rw-r--r-- | libdimension/dimension/concurrency/future.h (renamed from libdimension/dimension/future.h) | 6 | ||||
-rw-r--r-- | libdimension/dimension/geometry.h | 500 | ||||
-rw-r--r-- | libdimension/dimension/math.h | 82 | ||||
-rw-r--r-- | libdimension/dimension/math/aabb.h | 129 | ||||
-rw-r--r-- | libdimension/dimension/math/matrix.h | 193 | ||||
-rw-r--r-- | libdimension/dimension/math/ray.h | 83 | ||||
-rw-r--r-- | libdimension/dimension/math/scalar.h | 103 | ||||
-rw-r--r-- | libdimension/dimension/math/vector.h | 183 | ||||
-rw-r--r-- | libdimension/dimension/model.h | 59 | ||||
-rw-r--r-- | libdimension/dimension/model/camera.h (renamed from libdimension/dimension/camera.h) | 5 | ||||
-rw-r--r-- | libdimension/dimension/model/cameras.h (renamed from libdimension/dimension/cameras.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/csg.h (renamed from libdimension/dimension/csg.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/finish.h (renamed from libdimension/dimension/finish.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/finishes.h (renamed from libdimension/dimension/finishes.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/interior.h (renamed from libdimension/dimension/interior.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/light.h (renamed from libdimension/dimension/light.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/lights.h (renamed from libdimension/dimension/lights.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/object.h (renamed from libdimension/dimension/object.h) | 25 | ||||
-rw-r--r-- | libdimension/dimension/model/objects.h (renamed from libdimension/dimension/objects.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/pigment.h (renamed from libdimension/dimension/pigment.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/pigments.h (renamed from libdimension/dimension/pigments.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/scene.h (renamed from libdimension/dimension/scene.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/model/texture.h (renamed from libdimension/dimension/texture.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/pattern.h | 50 | ||||
-rw-r--r-- | libdimension/dimension/pattern/map.h (renamed from libdimension/dimension/map.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/pattern/pattern.h | 62 | ||||
-rw-r--r-- | libdimension/dimension/pattern/patterns.h (renamed from libdimension/dimension/patterns.h) | 0 | ||||
-rw-r--r-- | libdimension/dimension/platform.h | 39 | ||||
-rw-r--r-- | libdimension/dimension/platform/timer.h (renamed from libdimension/dimension/timer.h) | 4 | ||||
-rw-r--r-- | libdimension/dimension/polynomial.h | 85 | ||||
-rw-r--r-- | libdimension/dimension/render.h | 41 | ||||
-rw-r--r-- | libdimension/dimension/render/render.h (renamed from libdimension/dimension/ray_trace.h) | 14 |
48 files changed, 1440 insertions, 973 deletions
diff --git a/libdimension/dimension/base.h b/libdimension/dimension/base.h new file mode 100644 index 0000000..d9f063f --- /dev/null +++ b/libdimension/dimension/base.h @@ -0,0 +1,46 @@ +/************************************************************************* + * Copyright (C) 2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Basic functionality: compiler abstractions, error reporting, memory + * management, data structures, etc. + */ + +#ifndef DMNSN_BASE_H +#define DMNSN_BASE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <dimension/base/compiler.h> +#include <dimension/base/common.h> +#include <dimension/base/error.h> +#include <dimension/base/malloc.h> +#include <dimension/base/pool.h> +#include <dimension/base/array.h> +#include <dimension/base/dictionary.h> + +#ifdef __cplusplus +} +#endif + +#endif /* DMNSN_BASE_H */ diff --git a/libdimension/dimension/array.h b/libdimension/dimension/base/array.h index 9261a0e..a54d0e5 100644 --- a/libdimension/dimension/array.h +++ b/libdimension/dimension/base/array.h @@ -23,6 +23,10 @@ * Simple dynamic arrays. */ +#ifndef DMNSN_BASE_H +#error "Please include <dimension/base.h> instead of this header directly." +#endif + #include <stddef.h> /* For size_t */ #include <stdlib.h> /* For qsort() */ #include <string.h> /* For memcpy() */ diff --git a/libdimension/dimension/common.h b/libdimension/dimension/base/common.h index 15bafd8..b947b4a 100644 --- a/libdimension/dimension/common.h +++ b/libdimension/dimension/base/common.h @@ -23,6 +23,10 @@ * Common types and utilities. */ +#ifndef DMNSN_BASE_H +#error "Please include <dimension/base.h> instead of this header directly." +#endif + /** * Generic callback type. * @param[in,out] ptr A pointer to an object to act on. diff --git a/libdimension/dimension/compiler.h b/libdimension/dimension/base/compiler.h index af3f4c8..a83f1b9 100644 --- a/libdimension/dimension/compiler.h +++ b/libdimension/dimension/base/compiler.h @@ -23,6 +23,10 @@ * Compiler abstractions. */ +#ifndef DMNSN_BASE_H +#error "Please include <dimension/base.h> instead of this header directly." +#endif + /** * @internal * @def DMNSN_C_VERSION diff --git a/libdimension/dimension/dictionary.h b/libdimension/dimension/base/dictionary.h index 887b171..7360b45 100644 --- a/libdimension/dimension/dictionary.h +++ b/libdimension/dimension/base/dictionary.h @@ -23,6 +23,10 @@ * Simple associative arrays. */ +#ifndef DMNSN_BASE_H +#error "Please include <dimension/base.h> instead of this header directly." +#endif + /** A string-object associative array. */ typedef struct dmnsn_dictionary dmnsn_dictionary; diff --git a/libdimension/dimension/error.h b/libdimension/dimension/base/error.h index 0561b8a..d039081 100644 --- a/libdimension/dimension/error.h +++ b/libdimension/dimension/base/error.h @@ -20,12 +20,13 @@ /** * @file - * Error reporting interface. Errors are reported at a given severity by the - * dmnsn_error() macro at a given severity, which prints a warning if it is - * below the set resilience, or prints an error and exits if it's at or above - * the set resilience. + * Error reporting. */ +#ifndef DMNSN_BASE_H +#error "Please include <dimension/base.h> instead of this header directly." +#endif + #include <stdbool.h> /** diff --git a/libdimension/dimension/malloc.h b/libdimension/dimension/base/malloc.h index 742e3a2..fcc492e 100644 --- a/libdimension/dimension/malloc.h +++ b/libdimension/dimension/base/malloc.h @@ -25,6 +25,10 @@ * fails, they instead call dmnsn_error(). */ +#ifndef DMNSN_BASE_H +#error "Please include <dimension/base.h> instead of this header directly." +#endif + #include <stddef.h> /* For size_t */ /** diff --git a/libdimension/dimension/pool.h b/libdimension/dimension/base/pool.h index 164bbbc..9983f1d 100644 --- a/libdimension/dimension/pool.h +++ b/libdimension/dimension/base/pool.h @@ -25,6 +25,10 @@ * once once a scene is rendered (for example). */ +#ifndef DMNSN_BASE_H +#error "Please include <dimension/base.h> instead of this header directly." +#endif + #include <stddef.h> /* For size_t */ /* Forward-declare dmnsn_pool. */ diff --git a/libdimension/dimension/canvas.h b/libdimension/dimension/canvas.h index e325364..53bbda3 100644 --- a/libdimension/dimension/canvas.h +++ b/libdimension/dimension/canvas.h @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * Copyright (C) 2014 Tavian Barnes <tavianator@tavianator.com> * * * * This file is part of The Dimension Library. * * * @@ -20,108 +20,26 @@ /** * @file - * A canvas which is rendered to. + * Using, importing, and exporting canvases. */ -#include <stddef.h> +#ifndef DMNSN_CANVAS_H +#define DMNSN_CANVAS_H -/** A canvas, or image. */ -typedef struct dmnsn_canvas { - size_t width; /**< Canvas width. */ - size_t height; /**< Canvas height. */ +#ifdef __cplusplus +extern "C" { +#endif - /** An array of <tt>dmnsn_canvas_optimizer</tt>s. */ - dmnsn_array *optimizers; +#include <dimension/base.h> +#include <dimension/concurrency.h> +#include <dimension/color.h> - /** - * @internal - * Stored in first-quadrant representation (origin is bottom-left). The pixel - * at (a,b) is accessible as pixels[b*width + a]. - */ - dmnsn_tcolor *pixels; -} dmnsn_canvas; +#include <dimension/canvas/canvas.h> +#include <dimension/canvas/png.h> +#include <dimension/canvas/gl.h> -/* Forward-declare dmnsn_canvas_optimizer. */ -typedef struct dmnsn_canvas_optimizer dmnsn_canvas_optimizer; - -/** - * Canvas optimizer callback type. - * @param[in] optimizer The canvas optimizer. - * @param[in] canvas The canvas that was just updated. - * @param[in] x The x-coordinate that was just updated. - * @param[in] y The y-coordinate that was just updated. - */ -typedef void dmnsn_canvas_optimizer_fn(dmnsn_canvas_optimizer *optimizer, const dmnsn_canvas *canvas, size_t x, size_t y); - -/** Canvas optimizer. */ -struct dmnsn_canvas_optimizer { - dmnsn_canvas_optimizer_fn *optimizer_fn; /**< Optimizer callback. */ -}; - -/** - * Allocate a new canvas. - * @param[in] pool The memory pool to allocate from. - * @param[in] width The width of the canvas to allocate (in pixels). - * @param[in] height The height of the canvas to allocate (in pixels). - * @return The allocated canvas. - */ -dmnsn_canvas *dmnsn_new_canvas(dmnsn_pool *pool, size_t width, size_t height); - -/** - * Initialize a dmnsn_canvas_optimizer field - * @param[in] optimizer The optimizer to initialize. - */ -void dmnsn_init_canvas_optimizer(dmnsn_canvas_optimizer *optimizer); - -/** - * Set a canvas optimizer - * @param[in,out] canvas The canvas to optimize. - * @param[in] optimizer The optimizer to use. - */ -void dmnsn_canvas_optimize(dmnsn_canvas *canvas, - const dmnsn_canvas_optimizer *optimizer); - -/** - * Find a canvas optimizer by its callback. - * @param[in] canvas The canvas to check. - * @param[in] optimizer_fn The callback to search for for. - * @return A pointer to the canvas optimizer with the callback \p optimizer_fn, - * or NULL if none is found. - */ -dmnsn_canvas_optimizer * -dmnsn_canvas_find_optimizer(const dmnsn_canvas *canvas, - dmnsn_canvas_optimizer_fn *optimizer_fn); - -/* Pixel accessors */ - -/** - * Get the color of a pixel. - * @param[in] canvas The canvas to access. - * @param[in] x The x coordinate. - * @param[in] y The y coordinate. - * @return The color of the pixel at (\p x, \p y). - */ -DMNSN_INLINE dmnsn_tcolor -dmnsn_canvas_get_pixel(const dmnsn_canvas *canvas, size_t x, size_t y) -{ - dmnsn_assert(x < canvas->width && y < canvas->height, - "Canvas access out of bounds."); - return canvas->pixels[y*canvas->width + x]; +#ifdef __cplusplus } +#endif -/** - * Set the value of a pixel. - * @param[in,out] canvas The canvas to modify. - * @param[in] x The x coordinate of the pixel. - * @param[in] y The y coordinate of the pixel. - * @param[in] tcolor The value to set the pixel at (\p x, \p y) to. - */ -void dmnsn_canvas_set_pixel(dmnsn_canvas *canvas, size_t x, size_t y, - dmnsn_tcolor tcolor); - -/** - * Clear a canvas uniformly with a given color. - * @param[in,out] canvas The canvas to erase. - * @param[in] tcolor The color to paint it with. - */ -void dmnsn_canvas_clear(dmnsn_canvas *canvas, dmnsn_tcolor tcolor); +#endif /* DMNSN_CANVAS_H */ diff --git a/libdimension/dimension/canvas/canvas.h b/libdimension/dimension/canvas/canvas.h new file mode 100644 index 0000000..07d4fde --- /dev/null +++ b/libdimension/dimension/canvas/canvas.h @@ -0,0 +1,131 @@ +/************************************************************************* + * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * A canvas which is rendered to. + */ + +#ifndef DMNSN_CANVAS_H +#error "Please include <dimension/canvas.h> instead of this header directly." +#endif + +#include <stddef.h> + +/** A canvas, or image. */ +typedef struct dmnsn_canvas { + size_t width; /**< Canvas width. */ + size_t height; /**< Canvas height. */ + + /** An array of <tt>dmnsn_canvas_optimizer</tt>s. */ + dmnsn_array *optimizers; + + /** + * @internal + * Stored in first-quadrant representation (origin is bottom-left). The pixel + * at (a,b) is accessible as pixels[b*width + a]. + */ + dmnsn_tcolor *pixels; +} dmnsn_canvas; + +/* Forward-declare dmnsn_canvas_optimizer. */ +typedef struct dmnsn_canvas_optimizer dmnsn_canvas_optimizer; + +/** + * Canvas optimizer callback type. + * @param[in] optimizer The canvas optimizer. + * @param[in] canvas The canvas that was just updated. + * @param[in] x The x-coordinate that was just updated. + * @param[in] y The y-coordinate that was just updated. + */ +typedef void dmnsn_canvas_optimizer_fn(dmnsn_canvas_optimizer *optimizer, const dmnsn_canvas *canvas, size_t x, size_t y); + +/** Canvas optimizer. */ +struct dmnsn_canvas_optimizer { + dmnsn_canvas_optimizer_fn *optimizer_fn; /**< Optimizer callback. */ +}; + +/** + * Allocate a new canvas. + * @param[in] pool The memory pool to allocate from. + * @param[in] width The width of the canvas to allocate (in pixels). + * @param[in] height The height of the canvas to allocate (in pixels). + * @return The allocated canvas. + */ +dmnsn_canvas *dmnsn_new_canvas(dmnsn_pool *pool, size_t width, size_t height); + +/** + * Initialize a dmnsn_canvas_optimizer field + * @param[in] optimizer The optimizer to initialize. + */ +void dmnsn_init_canvas_optimizer(dmnsn_canvas_optimizer *optimizer); + +/** + * Set a canvas optimizer + * @param[in,out] canvas The canvas to optimize. + * @param[in] optimizer The optimizer to use. + */ +void dmnsn_canvas_optimize(dmnsn_canvas *canvas, + const dmnsn_canvas_optimizer *optimizer); + +/** + * Find a canvas optimizer by its callback. + * @param[in] canvas The canvas to check. + * @param[in] optimizer_fn The callback to search for for. + * @return A pointer to the canvas optimizer with the callback \p optimizer_fn, + * or NULL if none is found. + */ +dmnsn_canvas_optimizer * +dmnsn_canvas_find_optimizer(const dmnsn_canvas *canvas, + dmnsn_canvas_optimizer_fn *optimizer_fn); + +/* Pixel accessors */ + +/** + * Get the color of a pixel. + * @param[in] canvas The canvas to access. + * @param[in] x The x coordinate. + * @param[in] y The y coordinate. + * @return The color of the pixel at (\p x, \p y). + */ +DMNSN_INLINE dmnsn_tcolor +dmnsn_canvas_get_pixel(const dmnsn_canvas *canvas, size_t x, size_t y) +{ + dmnsn_assert(x < canvas->width && y < canvas->height, + "Canvas access out of bounds."); + return canvas->pixels[y*canvas->width + x]; +} + +/** + * Set the value of a pixel. + * @param[in,out] canvas The canvas to modify. + * @param[in] x The x coordinate of the pixel. + * @param[in] y The y coordinate of the pixel. + * @param[in] tcolor The value to set the pixel at (\p x, \p y) to. + */ +void dmnsn_canvas_set_pixel(dmnsn_canvas *canvas, size_t x, size_t y, + dmnsn_tcolor tcolor); + +/** + * Clear a canvas uniformly with a given color. + * @param[in,out] canvas The canvas to erase. + * @param[in] tcolor The color to paint it with. + */ +void dmnsn_canvas_clear(dmnsn_canvas *canvas, dmnsn_tcolor tcolor); diff --git a/libdimension/dimension/gl.h b/libdimension/dimension/canvas/gl.h index 284a248..c2d77a1 100644 --- a/libdimension/dimension/gl.h +++ b/libdimension/dimension/canvas/gl.h @@ -23,6 +23,10 @@ * OpenGL export/import of canvases. */ +#ifndef DMNSN_CANVAS_H +#error "Please include <dimension/canvas.h> instead of this header directly." +#endif + /** * Optimize a canvas for GL drawing * @param[in] pool The memory pool to allocate from. diff --git a/libdimension/dimension/png.h b/libdimension/dimension/canvas/png.h index f4d2c1e..57a68c2 100644 --- a/libdimension/dimension/png.h +++ b/libdimension/dimension/canvas/png.h @@ -23,6 +23,10 @@ * PNG import/export of canvases. */ +#ifndef DMNSN_CANVAS_H +#error "Please include <dimension/canvas.h> instead of this header directly." +#endif + #include <stdio.h> /** diff --git a/libdimension/dimension/color.h b/libdimension/dimension/color.h index adbd396..74bed59 100644 --- a/libdimension/dimension/color.h +++ b/libdimension/dimension/color.h @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * Copyright (C) 2014 Tavian Barnes <tavianator@tavianator.com> * * * * This file is part of The Dimension Library. * * * @@ -20,174 +20,23 @@ /** * @file - * Colors. + * Color handling. */ -#include <stdbool.h> +#ifndef DMNSN_COLOR_H +#define DMNSN_COLOR_H -/** A color value. */ -typedef struct { - double R; /**< Red component. */ - double G; /**< Green component. */ - double B; /**< Blue component. */ -} dmnsn_color; +#ifdef __cplusplus +extern "C" { +#endif -/** A standard format string for colors. */ -#define DMNSN_COLOR_FORMAT "Color<%g, %g, %g>" -/** The appropriate arguements to printf() a color. */ -#define DMNSN_COLOR_PRINTF(c) (c).R, (c).G, (c).B +#include <dimension/math.h> -/** Construct a new color. */ -DMNSN_INLINE dmnsn_color -dmnsn_new_color(double R, double G, double B) -{ - dmnsn_color ret = { R, G, B }; - return ret; -} - -/** Apply sRGB gamma */ -DMNSN_INLINE double -dmnsn_sRGB_gamma(double Clinear) -{ - /* - * If C represents R, G, and B, then the sRGB values are now found as follows: - * - * { 12.92*Clinear, Clinear <= 0.0031308 - * Csrgb = { 1/2.4 - * { (1.055)*Clinear - 0.055, Clinear > 0.0031308 - */ - if (Clinear == 1.0) { - return 1.0; /* Map 1.0 to 1.0 instead of 0.9999999999999999 */ - } else if (Clinear > 0.0031308) { - return 1.055*pow(Clinear, 1.0/2.4) - 0.055; - } else { - return 12.92*Clinear; - } -} - -/** Convert to sRGB space. */ -DMNSN_INLINE dmnsn_color -dmnsn_color_to_sRGB(dmnsn_color color) -{ - return dmnsn_new_color( - dmnsn_sRGB_gamma(color.R), - dmnsn_sRGB_gamma(color.G), - dmnsn_sRGB_gamma(color.B) - ); -} - -/** Remove sRGB gamma */ -DMNSN_INLINE double -dmnsn_sRGB_inverse_gamma(double CsRGB) -{ - /* - * If C represents R, G, and B, then the Clinear values are now found as - * follows: - * - * { Csrgb/12.92, Csrgb <= 0.04045 - * Clinear = { 2.4 - * { ((Csrgb + 0.055)/1.055) , Csrgb > 0.04045 - */ - if (CsRGB == 1.0) { - return 1.0; /* Map 1.0 to 1.0 instead of 0.9999999999999999 */ - } else if (CsRGB <= 0.040449936) { - return CsRGB/12.92; - } else { - return pow((CsRGB + 0.055)/1.055, 2.4); - } -} - -/** Convert from sRGB space. */ -DMNSN_INLINE dmnsn_color -dmnsn_color_from_sRGB(dmnsn_color color) -{ - return dmnsn_new_color( - dmnsn_sRGB_inverse_gamma(color.R), - dmnsn_sRGB_inverse_gamma(color.G), - dmnsn_sRGB_inverse_gamma(color.B) - ); -} - -/** Greyscale color intensity. */ -DMNSN_INLINE double -dmnsn_color_intensity(dmnsn_color color) -{ - return 0.2126*color.R + 0.7152*color.G + 0.0722*color.B; -} - -/** Add two colors together. */ -DMNSN_INLINE dmnsn_color -dmnsn_color_add(dmnsn_color lhs, dmnsn_color rhs) -{ - return dmnsn_new_color(lhs.R + rhs.R, lhs.G + rhs.G, lhs.B + rhs.B); -} - -/** Subtract two colors. */ -DMNSN_INLINE dmnsn_color -dmnsn_color_sub(dmnsn_color lhs, dmnsn_color rhs) -{ - return dmnsn_new_color(lhs.R - rhs.R, lhs.G - rhs.G, lhs.B - rhs.B); -} - -/** Scale a color's intensity. */ -DMNSN_INLINE dmnsn_color -dmnsn_color_mul(double n, dmnsn_color color) -{ - return dmnsn_new_color(n*color.R, n*color.G, n*color.B); -} - -/** Return the color at \p n on a gradient from \p c1 at 0 to \p c2 at 1. */ -DMNSN_INLINE dmnsn_color -dmnsn_color_gradient(dmnsn_color c1, dmnsn_color c2, double n) -{ - return dmnsn_new_color( - n*(c2.R - c1.R) + c1.R, - n*(c2.G - c1.G) + c1.G, - n*(c2.B - c1.B) + c1.B - ); -} - -/** Illuminate \p color with \p light. */ -DMNSN_INLINE dmnsn_color -dmnsn_color_illuminate(dmnsn_color light, dmnsn_color color) -{ - return dmnsn_new_color(light.R*color.R, light.G*color.G, light.B*color.B); -} +#include <dimension/color/color.h> +#include <dimension/color/tcolor.h> -/** Saturate the color components to [0.0, 1.0]. */ -DMNSN_INLINE dmnsn_color -dmnsn_color_clamp(dmnsn_color color) -{ - color.R = dmnsn_clamp(color.R, 0.0, 1.0); - color.G = dmnsn_clamp(color.G, 0.0, 1.0); - color.B = dmnsn_clamp(color.B, 0.0, 1.0); - return color; +#ifdef __cplusplus } +#endif -/** Return whether a color contains any NaN components. */ -DMNSN_INLINE bool -dmnsn_color_isnan(dmnsn_color color) -{ - return dmnsn_isnan(color.R) || dmnsn_isnan(color.G) || dmnsn_isnan(color.B); -} - -/* Standard colors */ - -/** Black. */ -#define dmnsn_black dmnsn_new_color(0.0, 0.0, 0.0) -/** White. */ -#define dmnsn_white dmnsn_new_color(1.0, 1.0, 1.0) -/** Red. */ -#define dmnsn_red dmnsn_new_color(1.0, 0.0, 0.0) -/** Green. */ -#define dmnsn_green dmnsn_new_color(0.0, 1.0, 0.0) -/** Blue. */ -#define dmnsn_blue dmnsn_new_color(0.0, 0.0, 1.0) -/** Magenta. */ -#define dmnsn_magenta dmnsn_new_color(1.0, 0.0, 1.0) -/** Orange. */ -#define dmnsn_orange dmnsn_new_color(1.0, 0.21404114048223255, 0.0) -/** Yellow. */ -#define dmnsn_yellow dmnsn_new_color(1.0, 1.0, 0.0) -/** Cyan. */ -#define dmnsn_cyan dmnsn_new_color(0.0, 1.0, 1.0) +#endif /* DMNSN_COLOR_H */ diff --git a/libdimension/dimension/color/color.h b/libdimension/dimension/color/color.h new file mode 100644 index 0000000..84e66ea --- /dev/null +++ b/libdimension/dimension/color/color.h @@ -0,0 +1,198 @@ +/************************************************************************* + * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Colors. + */ + +#ifndef DMNSN_COLOR_H +#error "Please include <dimension/color.h> instead of this header directly." +#endif + +#include <math.h> +#include <stdbool.h> + +/** A color value. */ +typedef struct { + double R; /**< Red component. */ + double G; /**< Green component. */ + double B; /**< Blue component. */ +} dmnsn_color; + +/** A standard format string for colors. */ +#define DMNSN_COLOR_FORMAT "Color<%g, %g, %g>" +/** The appropriate arguements to printf() a color. */ +#define DMNSN_COLOR_PRINTF(c) (c).R, (c).G, (c).B + +/** Construct a new color. */ +DMNSN_INLINE dmnsn_color +dmnsn_new_color(double R, double G, double B) +{ + dmnsn_color ret = { R, G, B }; + return ret; +} + +/** Apply sRGB gamma */ +DMNSN_INLINE double +dmnsn_sRGB_gamma(double Clinear) +{ + /* + * If C represents R, G, and B, then the sRGB values are now found as follows: + * + * { 12.92*Clinear, Clinear <= 0.0031308 + * Csrgb = { 1/2.4 + * { (1.055)*Clinear - 0.055, Clinear > 0.0031308 + */ + if (Clinear == 1.0) { + return 1.0; /* Map 1.0 to 1.0 instead of 0.9999999999999999 */ + } else if (Clinear > 0.0031308) { + return 1.055*pow(Clinear, 1.0/2.4) - 0.055; + } else { + return 12.92*Clinear; + } +} + +/** Convert to sRGB space. */ +DMNSN_INLINE dmnsn_color +dmnsn_color_to_sRGB(dmnsn_color color) +{ + return dmnsn_new_color( + dmnsn_sRGB_gamma(color.R), + dmnsn_sRGB_gamma(color.G), + dmnsn_sRGB_gamma(color.B) + ); +} + +/** Remove sRGB gamma */ +DMNSN_INLINE double +dmnsn_sRGB_inverse_gamma(double CsRGB) +{ + /* + * If C represents R, G, and B, then the Clinear values are now found as + * follows: + * + * { Csrgb/12.92, Csrgb <= 0.04045 + * Clinear = { 2.4 + * { ((Csrgb + 0.055)/1.055) , Csrgb > 0.04045 + */ + if (CsRGB == 1.0) { + return 1.0; /* Map 1.0 to 1.0 instead of 0.9999999999999999 */ + } else if (CsRGB <= 0.040449936) { + return CsRGB/12.92; + } else { + return pow((CsRGB + 0.055)/1.055, 2.4); + } +} + +/** Convert from sRGB space. */ +DMNSN_INLINE dmnsn_color +dmnsn_color_from_sRGB(dmnsn_color color) +{ + return dmnsn_new_color( + dmnsn_sRGB_inverse_gamma(color.R), + dmnsn_sRGB_inverse_gamma(color.G), + dmnsn_sRGB_inverse_gamma(color.B) + ); +} + +/** Greyscale color intensity. */ +DMNSN_INLINE double +dmnsn_color_intensity(dmnsn_color color) +{ + return 0.2126*color.R + 0.7152*color.G + 0.0722*color.B; +} + +/** Add two colors together. */ +DMNSN_INLINE dmnsn_color +dmnsn_color_add(dmnsn_color lhs, dmnsn_color rhs) +{ + return dmnsn_new_color(lhs.R + rhs.R, lhs.G + rhs.G, lhs.B + rhs.B); +} + +/** Subtract two colors. */ +DMNSN_INLINE dmnsn_color +dmnsn_color_sub(dmnsn_color lhs, dmnsn_color rhs) +{ + return dmnsn_new_color(lhs.R - rhs.R, lhs.G - rhs.G, lhs.B - rhs.B); +} + +/** Scale a color's intensity. */ +DMNSN_INLINE dmnsn_color +dmnsn_color_mul(double n, dmnsn_color color) +{ + return dmnsn_new_color(n*color.R, n*color.G, n*color.B); +} + +/** Return the color at \p n on a gradient from \p c1 at 0 to \p c2 at 1. */ +DMNSN_INLINE dmnsn_color +dmnsn_color_gradient(dmnsn_color c1, dmnsn_color c2, double n) +{ + return dmnsn_new_color( + n*(c2.R - c1.R) + c1.R, + n*(c2.G - c1.G) + c1.G, + n*(c2.B - c1.B) + c1.B + ); +} + +/** Illuminate \p color with \p light. */ +DMNSN_INLINE dmnsn_color +dmnsn_color_illuminate(dmnsn_color light, dmnsn_color color) +{ + return dmnsn_new_color(light.R*color.R, light.G*color.G, light.B*color.B); +} + +/** Saturate the color components to [0.0, 1.0]. */ +DMNSN_INLINE dmnsn_color +dmnsn_color_clamp(dmnsn_color color) +{ + color.R = dmnsn_clamp(color.R, 0.0, 1.0); + color.G = dmnsn_clamp(color.G, 0.0, 1.0); + color.B = dmnsn_clamp(color.B, 0.0, 1.0); + return color; +} + +/** Return whether a color contains any NaN components. */ +DMNSN_INLINE bool +dmnsn_color_isnan(dmnsn_color color) +{ + return dmnsn_isnan(color.R) || dmnsn_isnan(color.G) || dmnsn_isnan(color.B); +} + +/* Standard colors */ + +/** Black. */ +#define dmnsn_black dmnsn_new_color(0.0, 0.0, 0.0) +/** White. */ +#define dmnsn_white dmnsn_new_color(1.0, 1.0, 1.0) +/** Red. */ +#define dmnsn_red dmnsn_new_color(1.0, 0.0, 0.0) +/** Green. */ +#define dmnsn_green dmnsn_new_color(0.0, 1.0, 0.0) +/** Blue. */ +#define dmnsn_blue dmnsn_new_color(0.0, 0.0, 1.0) +/** Magenta. */ +#define dmnsn_magenta dmnsn_new_color(1.0, 0.0, 1.0) +/** Orange. */ +#define dmnsn_orange dmnsn_new_color(1.0, 0.21404114048223255, 0.0) +/** Yellow. */ +#define dmnsn_yellow dmnsn_new_color(1.0, 1.0, 0.0) +/** Cyan. */ +#define dmnsn_cyan dmnsn_new_color(0.0, 1.0, 1.0) diff --git a/libdimension/dimension/tcolor.h b/libdimension/dimension/color/tcolor.h index 8c48800..b4b4167 100644 --- a/libdimension/dimension/tcolor.h +++ b/libdimension/dimension/color/tcolor.h @@ -23,6 +23,10 @@ * Colors with transparency information. */ +#ifndef DMNSN_COLOR_H +#error "Please include <dimension/color.h> instead of this header directly." +#endif + /** A transparent color. */ typedef struct dmnsn_tcolor { dmnsn_color c; /**< Color. */ diff --git a/libdimension/dimension/concurrency.h b/libdimension/dimension/concurrency.h new file mode 100644 index 0000000..6c8c29c --- /dev/null +++ b/libdimension/dimension/concurrency.h @@ -0,0 +1,39 @@ +/************************************************************************* + * Copyright (C) 2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Concurrency concerns. + */ + +#ifndef DMNSN_CONCURRENCY_H +#define DMNSN_CONCURRENCY_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <dimension/concurrency/future.h> + +#ifdef __cplusplus +} +#endif + +#endif /* DMNSN_CONCURRENCY_H */ diff --git a/libdimension/dimension/future.h b/libdimension/dimension/concurrency/future.h index 9ba28b1..24d5ee2 100644 --- a/libdimension/dimension/future.h +++ b/libdimension/dimension/concurrency/future.h @@ -26,6 +26,12 @@ * is returned as an int from dmnsn_finish_progress(). */ +#ifndef DMNSN_CONCURRENCY_H +#error "Please include <dimension/concurrency.h> instead of this header directly." +#endif + +#include <stdbool.h> + /** A future object. */ typedef struct dmnsn_future dmnsn_future; diff --git a/libdimension/dimension/geometry.h b/libdimension/dimension/geometry.h deleted file mode 100644 index 2ea10ca..0000000 --- a/libdimension/dimension/geometry.h +++ /dev/null @@ -1,500 +0,0 @@ -/************************************************************************* - * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * - * * - * This file is part of The Dimension Library. * - * * - * The Dimension Library is free software; you can redistribute it and/ * - * or modify it under the terms of the GNU Lesser General Public License * - * as published by the Free Software Foundation; either version 3 of the * - * License, or (at your option) any later version. * - * * - * The Dimension Library is distributed in the hope that it will be * - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with this program. If not, see * - * <http://www.gnu.org/licenses/>. * - *************************************************************************/ - -/** - * @file - * Core geometric types like vectors, matricies, and rays. - */ - -#include <math.h> -#include <stdbool.h> - -/** A vector in 3 dimensions. */ -typedef struct dmnsn_vector { - double x; /**< The x component. */ - double y; /**< The y component. */ - double z; /**< The z component. */ -} dmnsn_vector; - -/** A standard format string for vectors. */ -#define DMNSN_VECTOR_FORMAT "<%g, %g, %g>" -/** The appropriate arguements to printf() a vector. */ -#define DMNSN_VECTOR_PRINTF(v) (v).x, (v).y, (v).z - -/** A 4x4 affine transformation matrix, with implied [0 0 0 1] bottom row. */ -typedef struct dmnsn_matrix { - double n[3][4]; /**< The matrix elements in row-major order. */ -} dmnsn_matrix; - -/** A standard format string for matricies. */ -#define DMNSN_MATRIX_FORMAT \ - "[%g\t%g\t%g\t%g]\n" \ - "[%g\t%g\t%g\t%g]\n" \ - "[%g\t%g\t%g\t%g]\n" \ - "[%g\t%g\t%g\t%g]" -/** The appropriate arguements to printf() a matrix. */ -#define DMNSN_MATRIX_PRINTF(m) \ - (m).n[0][0], (m).n[0][1], (m).n[0][2], (m).n[0][3], \ - (m).n[1][0], (m).n[1][1], (m).n[1][2], (m).n[1][3], \ - (m).n[2][0], (m).n[2][1], (m).n[2][2], (m).n[2][3], \ - 0.0, 0.0, 0.0, 1.0 - -/** A line, or ray. */ -typedef struct dmnsn_line { - dmnsn_vector x0; /**< A point on the line. */ - dmnsn_vector n; /**< A normal vector; the direction of the line. */ -} dmnsn_line; - -/** A standard format string for lines. */ -#define DMNSN_LINE_FORMAT "(<%g, %g, %g> + t*<%g, %g, %g>)" -/** The appropriate arguements to printf() a line. */ -#define DMNSN_LINE_PRINTF(l) \ - DMNSN_VECTOR_PRINTF((l).x0), DMNSN_VECTOR_PRINTF((l).n) - -/** An axis-aligned bounding box (AABB). */ -typedef struct dmnsn_bounding_box { - dmnsn_vector min; /**< The coordinate-wise minimum extent of the box. */ - dmnsn_vector max; /**< The coordinate-wise maximum extent of the box. */ -} dmnsn_bounding_box; - -/** A standard format string for bounding boxes. */ -#define DMNSN_BOUNDING_BOX_FORMAT "(<%g, %g, %g> ==> <%g, %g, %g>)" -/** The appropriate arguements to printf() a bounding box. */ -#define DMNSN_BOUNDING_BOX_PRINTF(box) \ - DMNSN_VECTOR_PRINTF((box).min), DMNSN_VECTOR_PRINTF((box).max) - -/* Constants */ - -/** The zero vector. */ -static const dmnsn_vector dmnsn_zero = { 0.0, 0.0, 0.0 }; -/** The x vector. */ -static const dmnsn_vector dmnsn_x = { 1.0, 0.0, 0.0 }; -/** The y vector. */ -static const dmnsn_vector dmnsn_y = { 0.0, 1.0, 0.0 }; -/** The z vector. */ -static const dmnsn_vector dmnsn_z = { 0.0, 0.0, 1.0 }; - -/* Shorthand for vector/matrix construction */ - -/** Construct a new vector. */ -DMNSN_INLINE dmnsn_vector -dmnsn_new_vector(double x, double y, double z) -{ - dmnsn_vector v = { x, y, z }; - return v; -} - -/** Construct a new transformation matrix. */ -DMNSN_INLINE dmnsn_matrix -dmnsn_new_matrix(double a0, double a1, double a2, double a3, - double b0, double b1, double b2, double b3, - double c0, double c1, double c2, double c3) -{ - dmnsn_matrix m = { { { a0, a1, a2, a3 }, - { b0, b1, b2, b3 }, - { c0, c1, c2, c3 } } }; - return m; -} - -/** Construct a new transformation matrix from column vectors. */ -DMNSN_INLINE dmnsn_matrix -dmnsn_new_matrix4(dmnsn_vector a, dmnsn_vector b, dmnsn_vector c, - dmnsn_vector d) -{ - dmnsn_matrix m = { { { a.x, b.x, c.x, d.x }, - { a.y, b.y, c.y, d.y }, - { a.z, b.z, c.z, d.z } } }; - return m; -} - -/** Extract column vectors from a matrix. */ -DMNSN_INLINE dmnsn_vector -dmnsn_matrix_column(dmnsn_matrix M, unsigned int i) -{ - return dmnsn_new_vector(M.n[0][i], M.n[1][i], M.n[2][i]); -} - -/** Return the identity matrix. */ -dmnsn_matrix dmnsn_identity_matrix(void); - -/** - * A scale transformation. - * @param[in] s A vector with components representing the scaling factor in - * each axis. - * @return The transformation matrix. - */ -dmnsn_matrix dmnsn_scale_matrix(dmnsn_vector s); -/** - * A translation. - * @param[in] d The vector to translate by. - * @return The transformation matrix. - */ -dmnsn_matrix dmnsn_translation_matrix(dmnsn_vector d); -/** - * A left-handed rotation. - * @param[in] theta A vector representing an axis and angle. - * @f$ axis = \vec{\theta}/|\vec{\theta}| @f$, - * @f$ angle = |\vec{\theta}| @f$ - * @return The transformation matrix. - */ -dmnsn_matrix dmnsn_rotation_matrix(dmnsn_vector theta); -/** - * An alignment matrix. - * @param[in] from The initial vector. - * @param[in] to The desired direction. - * @param[in] axis1 The first axis about which to rotate. - * @param[in] axis2 The second axis about which to rotate. - * @return A transformation matrix that will rotate \p from to \p to. - */ -dmnsn_matrix dmnsn_alignment_matrix(dmnsn_vector from, dmnsn_vector to, - dmnsn_vector axis1, dmnsn_vector axis2); - -/** - * Construct a new line. - * @param[in] x0 A point on the line. - * @param[in] n The direction of the line. - * @return The new line. - */ -DMNSN_INLINE dmnsn_line -dmnsn_new_line(dmnsn_vector x0, dmnsn_vector n) -{ - dmnsn_line l = { x0, n }; - return l; -} - -/** - * Construct a new bounding box. - * @param[in] min The minimal extent of the bounding box. - * @param[in] max The maximal extent of the bounding box. - * @return The new bounding box. - */ -DMNSN_INLINE dmnsn_bounding_box -dmnsn_new_bounding_box(dmnsn_vector min, dmnsn_vector max) -{ - dmnsn_bounding_box box = { min, max }; - return box; -} - -/** Return the bounding box which contains nothing. */ -DMNSN_INLINE dmnsn_bounding_box -dmnsn_zero_bounding_box(void) -{ - dmnsn_bounding_box box = { - { DMNSN_INFINITY, DMNSN_INFINITY, DMNSN_INFINITY }, - { -DMNSN_INFINITY, -DMNSN_INFINITY, -DMNSN_INFINITY } - }; - return box; -} - -/** Return the bounding box which contains everything. */ -DMNSN_INLINE dmnsn_bounding_box -dmnsn_infinite_bounding_box(void) -{ - dmnsn_bounding_box box = { - { -DMNSN_INFINITY, -DMNSN_INFINITY, -DMNSN_INFINITY }, - { DMNSN_INFINITY, DMNSN_INFINITY, DMNSN_INFINITY } - }; - return box; -} - -/* Vector and matrix arithmetic */ - -/** Negate a vector. */ -DMNSN_INLINE dmnsn_vector -dmnsn_vector_negate(dmnsn_vector rhs) -{ - /* 3 negations */ - dmnsn_vector v = { -rhs.x, -rhs.y, -rhs.z }; - return v; -} - -/** Add two vectors. */ -DMNSN_INLINE dmnsn_vector -dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs) -{ - /* 3 additions */ - dmnsn_vector v = { lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z }; - return v; -} - -/** Subtract two vectors. */ -DMNSN_INLINE dmnsn_vector -dmnsn_vector_sub(dmnsn_vector lhs, dmnsn_vector rhs) -{ - /* 3 additions */ - dmnsn_vector v = { lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z }; - return v; -} - -/** Multiply a vector by a scalar. */ -DMNSN_INLINE dmnsn_vector -dmnsn_vector_mul(double lhs, dmnsn_vector rhs) -{ - /* 3 multiplications */ - dmnsn_vector v = { lhs*rhs.x, lhs*rhs.y, lhs*rhs.z }; - return v; -} - -/** Divide a vector by a scalar. */ -DMNSN_INLINE dmnsn_vector -dmnsn_vector_div(dmnsn_vector lhs, double rhs) -{ - /* 3 divisions */ - dmnsn_vector v = { lhs.x/rhs, lhs.y/rhs, lhs.z/rhs }; - return v; -} - -/** Return the dot product of two vectors. */ -DMNSN_INLINE double -dmnsn_vector_dot(dmnsn_vector lhs, dmnsn_vector rhs) -{ - /* 3 multiplications, 2 additions */ - return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z; -} - -/** Return the cross product of two vectors. */ -DMNSN_INLINE dmnsn_vector -dmnsn_vector_cross(dmnsn_vector lhs, dmnsn_vector rhs) -{ - /* 6 multiplications, 3 additions */ - dmnsn_vector v = { lhs.y*rhs.z - lhs.z*rhs.y, - lhs.z*rhs.x - lhs.x*rhs.z, - lhs.x*rhs.y - lhs.y*rhs.x }; - return v; -} - -/** Return the projection of \p u onto \p d. */ -DMNSN_INLINE dmnsn_vector -dmnsn_vector_proj(dmnsn_vector u, dmnsn_vector d) -{ - /* 1 division, 9 multiplications, 4 additions */ - return dmnsn_vector_mul(dmnsn_vector_dot(u, d)/dmnsn_vector_dot(d, d), d); -} - -/** Return the magnitude of a vector. */ -DMNSN_INLINE double -dmnsn_vector_norm(dmnsn_vector n) -{ - /* 1 sqrt, 3 multiplications, 2 additions */ - return sqrt(dmnsn_vector_dot(n, n)); -} - -/** Return the direction of a vector. */ -DMNSN_INLINE dmnsn_vector -dmnsn_vector_normalized(dmnsn_vector n) -{ - /* 1 sqrt, 3 divisions, 3 multiplications, 2 additions */ - return dmnsn_vector_div(n, dmnsn_vector_norm(n)); -} - -/** Return the component-wise minimum of two vectors. */ -DMNSN_INLINE dmnsn_vector -dmnsn_vector_min(dmnsn_vector a, dmnsn_vector b) -{ - return dmnsn_new_vector( - dmnsn_min(a.x, b.x), - dmnsn_min(a.y, b.y), - dmnsn_min(a.z, b.z) - ); -} - -/** Return the component-wise maximum of two vectors. */ -DMNSN_INLINE dmnsn_vector -dmnsn_vector_max(dmnsn_vector a, dmnsn_vector b) -{ - return dmnsn_new_vector( - dmnsn_max(a.x, b.x), - dmnsn_max(a.y, b.y), - dmnsn_max(a.z, b.z) - ); -} - -/** Invert a matrix. */ -dmnsn_matrix dmnsn_matrix_inverse(dmnsn_matrix A); - -/** Multiply two matricies. */ -dmnsn_matrix dmnsn_matrix_mul(dmnsn_matrix lhs, dmnsn_matrix rhs); - -/** Transform a point by a matrix. */ -DMNSN_INLINE dmnsn_vector -dmnsn_transform_point(dmnsn_matrix T, dmnsn_vector v) -{ - /* 9 multiplications, 9 additions */ - dmnsn_vector r; - r.x = T.n[0][0]*v.x + T.n[0][1]*v.y + T.n[0][2]*v.z + T.n[0][3]; - r.y = T.n[1][0]*v.x + T.n[1][1]*v.y + T.n[1][2]*v.z + T.n[1][3]; - r.z = T.n[2][0]*v.x + T.n[2][1]*v.y + T.n[2][2]*v.z + T.n[2][3]; - return r; -} - -/** Transform a direction by a matrix. */ -DMNSN_INLINE dmnsn_vector -dmnsn_transform_direction(dmnsn_matrix T, dmnsn_vector v) -{ - /* 9 multiplications, 6 additions */ - dmnsn_vector r; - r.x = T.n[0][0]*v.x + T.n[0][1]*v.y + T.n[0][2]*v.z; - r.y = T.n[1][0]*v.x + T.n[1][1]*v.y + T.n[1][2]*v.z; - r.z = T.n[2][0]*v.x + T.n[2][1]*v.y + T.n[2][2]*v.z; - return r; -} - -/** - * Transform a pseudovector by a matrix. - * @param[in] Tinv The inverse of the transformation matrix. - * @param[in] v The pseudovector to transform - * @return The transformed pseudovector. - */ -DMNSN_INLINE dmnsn_vector -dmnsn_transform_normal(dmnsn_matrix Tinv, dmnsn_vector v) -{ - /* Multiply by the transpose of the inverse - (9 multiplications, 6 additions) */ - dmnsn_vector r; - r.x = Tinv.n[0][0]*v.x + Tinv.n[1][0]*v.y + Tinv.n[2][0]*v.z; - r.y = Tinv.n[0][1]*v.x + Tinv.n[1][1]*v.y + Tinv.n[2][1]*v.z; - r.z = Tinv.n[0][2]*v.x + Tinv.n[1][2]*v.y + Tinv.n[2][2]*v.z; - return r; -} - -/** Transform a bounding box by a matrix. */ -dmnsn_bounding_box dmnsn_transform_bounding_box(dmnsn_matrix T, - dmnsn_bounding_box box); - -/** - * Transform a line by a matrix. - * \f$ n' = T(l.\vec{x_0} + l.\vec{n}) - T(l.\vec{x_0}) \f$, - * \f$ \vec{x_0}' = T(l.\vec{x_0}) \f$ - */ -DMNSN_INLINE dmnsn_line -dmnsn_transform_line(dmnsn_matrix T, dmnsn_line l) -{ - /* 18 multiplications, 15 additions */ - dmnsn_line ret; - ret.x0 = dmnsn_transform_point(T, l.x0); - ret.n = dmnsn_transform_direction(T, l.n); - return ret; -} - -/** - * Return the point at \p t on a line. - * The point is defined by \f$ l.\vec{x_0} + t \cdot l.\vec{n} \f$ - */ -DMNSN_INLINE dmnsn_vector -dmnsn_line_point(dmnsn_line l, double t) -{ - return dmnsn_vector_add(l.x0, dmnsn_vector_mul(t, l.n)); -} - -/** Add epsilon*l.n to l.x0, to avoid self-intersections. */ -DMNSN_INLINE dmnsn_line -dmnsn_line_add_epsilon(dmnsn_line l) -{ - return dmnsn_new_line( - dmnsn_vector_add( - l.x0, - dmnsn_vector_mul(1.0e3*dmnsn_epsilon, l.n) - ), - l.n - ); -} - -/** - * Construct a new symmetric bounding box. - * @param[in] r The extent of the bounding box from the origin. - * @return The new bounding box. - */ -DMNSN_INLINE dmnsn_bounding_box -dmnsn_symmetric_bounding_box(dmnsn_vector r) -{ - dmnsn_vector minus_r = dmnsn_vector_negate(r); - dmnsn_bounding_box box = { - dmnsn_vector_min(r, minus_r), - dmnsn_vector_max(r, minus_r) - }; - return box; -} - -/** Return whether \p p is within the axis-aligned bounding box. */ -DMNSN_INLINE bool -dmnsn_bounding_box_contains(dmnsn_bounding_box box, dmnsn_vector p) -{ - return (p.x >= box.min.x && p.y >= box.min.y && p.z >= box.min.z) - && (p.x <= box.max.x && p.y <= box.max.y && p.z <= box.max.z); -} - -/** Return whether a bounding box is infinite. */ -DMNSN_INLINE bool -dmnsn_bounding_box_is_infinite(dmnsn_bounding_box box) -{ - return box.min.x == -DMNSN_INFINITY; -} - -/** - * Expand a bounding box to contain a point - * @param[in] box The bounding box to expand. - * @param[in] point The point to swallow. - * @return The expanded bounding box. - */ -DMNSN_INLINE dmnsn_bounding_box -dmnsn_bounding_box_swallow(dmnsn_bounding_box box, dmnsn_vector point) -{ - dmnsn_bounding_box ret = { - dmnsn_vector_min(box.min, point), - dmnsn_vector_max(box.max, point) - }; - return ret; -} - -/** Return whether a vector contains any NaN components. */ -DMNSN_INLINE bool -dmnsn_vector_isnan(dmnsn_vector v) -{ - return dmnsn_isnan(v.x) || dmnsn_isnan(v.y) || dmnsn_isnan(v.z); -} - -/** Return whether a matrix contains any NaN components. */ -DMNSN_INLINE bool -dmnsn_matrix_isnan(dmnsn_matrix m) -{ - size_t i, j; - for (i = 0; i < 3; ++i) { - for (j = 0; j < 4; ++j) { - if (dmnsn_isnan(m.n[i][j])) { - return true; - } - } - } - return false; -} - -/** Return whether a line contains any NaN entries. */ -DMNSN_INLINE bool -dmnsn_line_isnan(dmnsn_line l) -{ - return dmnsn_vector_isnan(l.x0) || dmnsn_vector_isnan(l.n); -} - -/** Return whether a bounding box has any NaN components. */ -DMNSN_INLINE bool -dmnsn_bounding_box_isnan(dmnsn_bounding_box box) -{ - return dmnsn_vector_isnan(box.min) || dmnsn_vector_isnan(box.max); -} diff --git a/libdimension/dimension/math.h b/libdimension/dimension/math.h index 597be36..603373f 100644 --- a/libdimension/dimension/math.h +++ b/libdimension/dimension/math.h @@ -20,80 +20,26 @@ /** * @file - * Useful math functions. + * Mathematical functions and types. */ -#include <math.h> -#include <stdbool.h> +#ifndef DMNSN_MATH_H +#define DMNSN_MATH_H -/** The smallest value considered non-zero by some numerical algorithms. */ -#define dmnsn_epsilon 1.0e-10 - -/** - * @def DMNSN_INFINITY - * Expands to floating-point infinity. - */ -#if defined(INFINITY) || DMNSN_C99 - #define DMNSN_INFINITY INFINITY -#else - #define DMNSN_INFINITY HUGE_VAL +#ifdef __cplusplus +extern "C" { #endif -/** Find the minimum of two values. */ -DMNSN_INLINE double -dmnsn_min(double a, double b) -{ - return a < b ? a : b; -} - -/** Find the maximum of two values. */ -DMNSN_INLINE double -dmnsn_max(double a, double b) -{ - return a > b ? a : b; -} - -/** Clamp a value to an interval. */ -DMNSN_INLINE double -dmnsn_clamp(double n, double min, double max) -{ - return dmnsn_min(dmnsn_max(n, min), max); -} - -/** Convert degrees to radians. */ -DMNSN_INLINE double -dmnsn_radians(double degrees) -{ - return degrees*(atan(1.0)/45.0); -} +#include <dimension/base.h> -/** Convert radians to degrees. */ -DMNSN_INLINE double -dmnsn_degrees(double radians) -{ - return radians*(45.0/atan(1.0)); -} +#include <dimension/math/scalar.h> +#include <dimension/math/vector.h> +#include <dimension/math/ray.h> +#include <dimension/math/aabb.h> +#include <dimension/math/matrix.h> -/** Signum function: return the sign of a value. */ -DMNSN_INLINE int -dmnsn_sgn(double n) -{ - if (n > 0.0) { - return 1; - } else if (n < 0.0) { - return -1; - } else { - return 0; - } +#ifdef __cplusplus } - -/** Return whether a value is NaN. */ -DMNSN_INLINE bool -dmnsn_isnan(double n) -{ -#if DMNSN_C99 - return isnan(n); -#else - return n != n; #endif -} + +#endif /* DMNSN_MATH_H */ diff --git a/libdimension/dimension/math/aabb.h b/libdimension/dimension/math/aabb.h new file mode 100644 index 0000000..14cc575 --- /dev/null +++ b/libdimension/dimension/math/aabb.h @@ -0,0 +1,129 @@ +/************************************************************************* + * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Axis-aligned bounding boxes. + */ + +#ifndef DMNSN_MATH_H +#error "Please include <dimension/math.h> instead of this header directly." +#endif + +/** An axis-aligned bounding box. */ +typedef struct dmnsn_aabb { + dmnsn_vector min; /**< The coordinate-wise minimum extent of the box. */ + dmnsn_vector max; /**< The coordinate-wise maximum extent of the box. */ +} dmnsn_aabb; + +/** A standard format string for bounding boxes. */ +#define DMNSN_AABB_FORMAT "(<%g, %g, %g> ==> <%g, %g, %g>)" +/** The appropriate arguements to printf() a bounding box. */ +#define DMNSN_AABB_PRINTF(box) \ + DMNSN_VECTOR_PRINTF((box).min), DMNSN_VECTOR_PRINTF((box).max) + +/** + * Construct a new bounding box. + * @param[in] min The minimal extent of the bounding box. + * @param[in] max The maximal extent of the bounding box. + * @return The new bounding box. + */ +DMNSN_INLINE dmnsn_aabb +dmnsn_new_aabb(dmnsn_vector min, dmnsn_vector max) +{ + dmnsn_aabb box = { min, max }; + return box; +} + +/** Return the bounding box which contains nothing. */ +DMNSN_INLINE dmnsn_aabb +dmnsn_zero_aabb(void) +{ + dmnsn_aabb box = { + { DMNSN_INFINITY, DMNSN_INFINITY, DMNSN_INFINITY }, + { -DMNSN_INFINITY, -DMNSN_INFINITY, -DMNSN_INFINITY } + }; + return box; +} + +/** Return the bounding box which contains everything. */ +DMNSN_INLINE dmnsn_aabb +dmnsn_infinite_aabb(void) +{ + dmnsn_aabb box = { + { -DMNSN_INFINITY, -DMNSN_INFINITY, -DMNSN_INFINITY }, + { DMNSN_INFINITY, DMNSN_INFINITY, DMNSN_INFINITY } + }; + return box; +} + +/** + * Construct a new symmetric bounding box. + * @param[in] r The extent of the bounding box from the origin. + * @return The new bounding box. + */ +DMNSN_INLINE dmnsn_aabb +dmnsn_symmetric_aabb(dmnsn_vector r) +{ + dmnsn_vector minus_r = dmnsn_vector_negate(r); + dmnsn_aabb box = { + dmnsn_vector_min(r, minus_r), + dmnsn_vector_max(r, minus_r) + }; + return box; +} + +/** Return whether \p p is within the axis-aligned bounding box. */ +DMNSN_INLINE bool +dmnsn_aabb_contains(dmnsn_aabb box, dmnsn_vector p) +{ + return (p.x >= box.min.x && p.y >= box.min.y && p.z >= box.min.z) + && (p.x <= box.max.x && p.y <= box.max.y && p.z <= box.max.z); +} + +/** Return whether a bounding box is infinite. */ +DMNSN_INLINE bool +dmnsn_aabb_is_infinite(dmnsn_aabb box) +{ + return box.min.x == -DMNSN_INFINITY; +} + +/** + * Expand a bounding box to contain a point + * @param[in] box The bounding box to expand. + * @param[in] point The point to swallow. + * @return The expanded bounding box. + */ +DMNSN_INLINE dmnsn_aabb +dmnsn_aabb_swallow(dmnsn_aabb box, dmnsn_vector point) +{ + dmnsn_aabb ret = { + dmnsn_vector_min(box.min, point), + dmnsn_vector_max(box.max, point) + }; + return ret; +} + +/** Return whether a bounding box has any NaN components. */ +DMNSN_INLINE bool +dmnsn_aabb_isnan(dmnsn_aabb box) +{ + return dmnsn_vector_isnan(box.min) || dmnsn_vector_isnan(box.max); +} diff --git a/libdimension/dimension/math/matrix.h b/libdimension/dimension/math/matrix.h new file mode 100644 index 0000000..7471bf5 --- /dev/null +++ b/libdimension/dimension/math/matrix.h @@ -0,0 +1,193 @@ +/************************************************************************* + * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Affine transformation matrices. + */ + +#ifndef DMNSN_MATH_H +#error "Please include <dimension/math.h> instead of this header directly." +#endif + +/** A 4x4 affine transformation matrix, with implied [0 0 0 1] bottom row. */ +typedef struct dmnsn_matrix { + double n[3][4]; /**< The matrix elements in row-major order. */ +} dmnsn_matrix; + +/** A standard format string for matricies. */ +#define DMNSN_MATRIX_FORMAT \ + "[%g\t%g\t%g\t%g]\n" \ + "[%g\t%g\t%g\t%g]\n" \ + "[%g\t%g\t%g\t%g]\n" \ + "[%g\t%g\t%g\t%g]" +/** The appropriate arguements to printf() a matrix. */ +#define DMNSN_MATRIX_PRINTF(m) \ + (m).n[0][0], (m).n[0][1], (m).n[0][2], (m).n[0][3], \ + (m).n[1][0], (m).n[1][1], (m).n[1][2], (m).n[1][3], \ + (m).n[2][0], (m).n[2][1], (m).n[2][2], (m).n[2][3], \ + 0.0, 0.0, 0.0, 1.0 + +/** Construct a new transformation matrix. */ +DMNSN_INLINE dmnsn_matrix +dmnsn_new_matrix(double a0, double a1, double a2, double a3, + double b0, double b1, double b2, double b3, + double c0, double c1, double c2, double c3) +{ + dmnsn_matrix m = { { { a0, a1, a2, a3 }, + { b0, b1, b2, b3 }, + { c0, c1, c2, c3 } } }; + return m; +} + +/** Construct a new transformation matrix from column vectors. */ +DMNSN_INLINE dmnsn_matrix +dmnsn_new_matrix4(dmnsn_vector a, dmnsn_vector b, dmnsn_vector c, + dmnsn_vector d) +{ + dmnsn_matrix m = { { { a.x, b.x, c.x, d.x }, + { a.y, b.y, c.y, d.y }, + { a.z, b.z, c.z, d.z } } }; + return m; +} + +/** Extract column vectors from a matrix. */ +DMNSN_INLINE dmnsn_vector +dmnsn_matrix_column(dmnsn_matrix M, unsigned int i) +{ + return dmnsn_new_vector(M.n[0][i], M.n[1][i], M.n[2][i]); +} + +/** Return the identity matrix. */ +dmnsn_matrix dmnsn_identity_matrix(void); + +/** + * A scale transformation. + * @param[in] s A vector with components representing the scaling factor in + * each axis. + * @return The transformation matrix. + */ +dmnsn_matrix dmnsn_scale_matrix(dmnsn_vector s); +/** + * A translation. + * @param[in] d The vector to translate by. + * @return The transformation matrix. + */ +dmnsn_matrix dmnsn_translation_matrix(dmnsn_vector d); +/** + * A left-handed rotation. + * @param[in] theta A vector representing an axis and angle. + * @f$ axis = \vec{\theta}/|\vec{\theta}| @f$, + * @f$ angle = |\vec{\theta}| @f$ + * @return The transformation matrix. + */ +dmnsn_matrix dmnsn_rotation_matrix(dmnsn_vector theta); + +/** + * An alignment matrix. + * @param[in] from The initial vector. + * @param[in] to The desired direction. + * @param[in] axis1 The first axis about which to rotate. + * @param[in] axis2 The second axis about which to rotate. + * @return A transformation matrix that will rotate \p from to \p to. + */ +dmnsn_matrix dmnsn_alignment_matrix(dmnsn_vector from, dmnsn_vector to, + dmnsn_vector axis1, dmnsn_vector axis2); + +/** Invert a matrix. */ +dmnsn_matrix dmnsn_matrix_inverse(dmnsn_matrix A); + +/** Multiply two matricies. */ +dmnsn_matrix dmnsn_matrix_mul(dmnsn_matrix lhs, dmnsn_matrix rhs); + +/** Transform a point by a matrix. */ +DMNSN_INLINE dmnsn_vector +dmnsn_transform_point(dmnsn_matrix T, dmnsn_vector v) +{ + /* 9 multiplications, 9 additions */ + dmnsn_vector r; + r.x = T.n[0][0]*v.x + T.n[0][1]*v.y + T.n[0][2]*v.z + T.n[0][3]; + r.y = T.n[1][0]*v.x + T.n[1][1]*v.y + T.n[1][2]*v.z + T.n[1][3]; + r.z = T.n[2][0]*v.x + T.n[2][1]*v.y + T.n[2][2]*v.z + T.n[2][3]; + return r; +} + +/** Transform a direction by a matrix. */ +DMNSN_INLINE dmnsn_vector +dmnsn_transform_direction(dmnsn_matrix T, dmnsn_vector v) +{ + /* 9 multiplications, 6 additions */ + dmnsn_vector r; + r.x = T.n[0][0]*v.x + T.n[0][1]*v.y + T.n[0][2]*v.z; + r.y = T.n[1][0]*v.x + T.n[1][1]*v.y + T.n[1][2]*v.z; + r.z = T.n[2][0]*v.x + T.n[2][1]*v.y + T.n[2][2]*v.z; + return r; +} + +/** + * Transform a pseudovector by a matrix. + * @param[in] Tinv The inverse of the transformation matrix. + * @param[in] v The pseudovector to transform + * @return The transformed pseudovector. + */ +DMNSN_INLINE dmnsn_vector +dmnsn_transform_normal(dmnsn_matrix Tinv, dmnsn_vector v) +{ + /* Multiply by the transpose of the inverse + (9 multiplications, 6 additions) */ + dmnsn_vector r; + r.x = Tinv.n[0][0]*v.x + Tinv.n[1][0]*v.y + Tinv.n[2][0]*v.z; + r.y = Tinv.n[0][1]*v.x + Tinv.n[1][1]*v.y + Tinv.n[2][1]*v.z; + r.z = Tinv.n[0][2]*v.x + Tinv.n[1][2]*v.y + Tinv.n[2][2]*v.z; + return r; +} + +/** + * Transform a ray by a matrix. + * \f$ n' = T(l.\vec{x_0} + l.\vec{n}) - T(l.\vec{x_0}) \f$, + * \f$ \vec{x_0}' = T(l.\vec{x_0}) \f$ + */ +DMNSN_INLINE dmnsn_ray +dmnsn_transform_ray(dmnsn_matrix T, dmnsn_ray l) +{ + /* 18 multiplications, 15 additions */ + dmnsn_ray ret; + ret.x0 = dmnsn_transform_point(T, l.x0); + ret.n = dmnsn_transform_direction(T, l.n); + return ret; +} + +/** Transform a bounding box by a matrix. */ +dmnsn_aabb dmnsn_transform_aabb(dmnsn_matrix T, dmnsn_aabb box); + +/** Return whether a matrix contains any NaN components. */ +DMNSN_INLINE bool +dmnsn_matrix_isnan(dmnsn_matrix m) +{ + size_t i, j; + for (i = 0; i < 3; ++i) { + for (j = 0; j < 4; ++j) { + if (dmnsn_isnan(m.n[i][j])) { + return true; + } + } + } + return false; +} diff --git a/libdimension/dimension/math/ray.h b/libdimension/dimension/math/ray.h new file mode 100644 index 0000000..1dd98f7 --- /dev/null +++ b/libdimension/dimension/math/ray.h @@ -0,0 +1,83 @@ +/************************************************************************* + * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Lines in 3-D space. + */ + +#ifndef DMNSN_MATH_H +#error "Please include <dimension/math.h> instead of this header directly." +#endif + +/** A line, or ray. */ +typedef struct dmnsn_ray { + dmnsn_vector x0; /**< The origin of the ray. */ + dmnsn_vector n; /**< The direction of the ray. */ +} dmnsn_ray; + +/** A standard format string for rays. */ +#define DMNSN_RAY_FORMAT "(<%g, %g, %g> + t*<%g, %g, %g>)" +/** The appropriate arguements to printf() a ray. */ +#define DMNSN_RAY_PRINTF(l) \ + DMNSN_VECTOR_PRINTF((l).x0), DMNSN_VECTOR_PRINTF((l).n) + +/** + * Construct a new ray. + * @param[in] x0 The origin of the ray. + * @param[in] n The direction of the ray. + * @return The new ray. + */ +DMNSN_INLINE dmnsn_ray +dmnsn_new_ray(dmnsn_vector x0, dmnsn_vector n) +{ + dmnsn_ray l = { x0, n }; + return l; +} + +/** + * Return the point at \p t on a ray. + * The point is defined by \f$ l.\vec{x_0} + t \cdot l.\vec{n} \f$ + */ +DMNSN_INLINE dmnsn_vector +dmnsn_ray_point(dmnsn_ray l, double t) +{ + return dmnsn_vector_add(l.x0, dmnsn_vector_mul(t, l.n)); +} + +/** Add epsilon*l.n to l.x0, to avoid self-intersections. */ +DMNSN_INLINE dmnsn_ray +dmnsn_ray_add_epsilon(dmnsn_ray l) +{ + return dmnsn_new_ray( + dmnsn_vector_add( + l.x0, + dmnsn_vector_mul(1.0e3*dmnsn_epsilon, l.n) + ), + l.n + ); +} + +/** Return whether a ray contains any NaN entries. */ +DMNSN_INLINE bool +dmnsn_ray_isnan(dmnsn_ray l) +{ + return dmnsn_vector_isnan(l.x0) || dmnsn_vector_isnan(l.n); +} diff --git a/libdimension/dimension/math/scalar.h b/libdimension/dimension/math/scalar.h new file mode 100644 index 0000000..3887c14 --- /dev/null +++ b/libdimension/dimension/math/scalar.h @@ -0,0 +1,103 @@ +/************************************************************************* + * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Mathematical functions of one variable. + */ + +#ifndef DMNSN_MATH_H +#error "Please include <dimension/math.h> instead of this header directly." +#endif + +#include <math.h> +#include <stdbool.h> + +/** The smallest value considered non-zero by some numerical algorithms. */ +#define dmnsn_epsilon 1.0e-10 + +/** + * @def DMNSN_INFINITY + * Expands to floating-point infinity. + */ +#if defined(INFINITY) || DMNSN_C99 + #define DMNSN_INFINITY INFINITY +#else + #define DMNSN_INFINITY HUGE_VAL +#endif + +/** Find the minimum of two values. */ +DMNSN_INLINE double +dmnsn_min(double a, double b) +{ + return a < b ? a : b; +} + +/** Find the maximum of two values. */ +DMNSN_INLINE double +dmnsn_max(double a, double b) +{ + return a > b ? a : b; +} + +/** Clamp a value to an interval. */ +DMNSN_INLINE double +dmnsn_clamp(double n, double min, double max) +{ + return dmnsn_min(dmnsn_max(n, min), max); +} + +/** Convert degrees to radians. */ +DMNSN_INLINE double +dmnsn_radians(double degrees) +{ + return degrees*(atan(1.0)/45.0); +} + +/** Convert radians to degrees. */ +DMNSN_INLINE double +dmnsn_degrees(double radians) +{ + return radians*(45.0/atan(1.0)); +} + +/** Signum function: return the sign of a value. */ +DMNSN_INLINE int +dmnsn_sgn(double n) +{ + if (n > 0.0) { + return 1; + } else if (n < 0.0) { + return -1; + } else { + return 0; + } +} + +/** Return whether a value is NaN. */ +DMNSN_INLINE bool +dmnsn_isnan(double n) +{ +#if DMNSN_C99 + return isnan(n); +#else + return n != n; +#endif +} diff --git a/libdimension/dimension/math/vector.h b/libdimension/dimension/math/vector.h new file mode 100644 index 0000000..8eacee9 --- /dev/null +++ b/libdimension/dimension/math/vector.h @@ -0,0 +1,183 @@ +/************************************************************************* + * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Vectors in 3-D space. + */ + +#ifndef DMNSN_MATH_H +#error "Please include <dimension/math.h> instead of this header directly." +#endif + +#include <math.h> +#include <stdbool.h> + +/** A vector in 3 dimensions. */ +typedef struct dmnsn_vector { + double x; /**< The x component. */ + double y; /**< The y component. */ + double z; /**< The z component. */ +} dmnsn_vector; + +/** A standard format string for vectors. */ +#define DMNSN_VECTOR_FORMAT "<%g, %g, %g>" +/** The appropriate arguements to printf() a vector. */ +#define DMNSN_VECTOR_PRINTF(v) (v).x, (v).y, (v).z + +/* Constants */ + +/** The zero vector. */ +static const dmnsn_vector dmnsn_zero = { 0.0, 0.0, 0.0 }; +/** The x vector. */ +static const dmnsn_vector dmnsn_x = { 1.0, 0.0, 0.0 }; +/** The y vector. */ +static const dmnsn_vector dmnsn_y = { 0.0, 1.0, 0.0 }; +/** The z vector. */ +static const dmnsn_vector dmnsn_z = { 0.0, 0.0, 1.0 }; + +/* Shorthand for vector construction */ + +/** Construct a new vector. */ +DMNSN_INLINE dmnsn_vector +dmnsn_new_vector(double x, double y, double z) +{ + dmnsn_vector v = { x, y, z }; + return v; +} + +/* Vector arithmetic */ + +/** Negate a vector. */ +DMNSN_INLINE dmnsn_vector +dmnsn_vector_negate(dmnsn_vector rhs) +{ + /* 3 negations */ + dmnsn_vector v = { -rhs.x, -rhs.y, -rhs.z }; + return v; +} + +/** Add two vectors. */ +DMNSN_INLINE dmnsn_vector +dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs) +{ + /* 3 additions */ + dmnsn_vector v = { lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z }; + return v; +} + +/** Subtract two vectors. */ +DMNSN_INLINE dmnsn_vector +dmnsn_vector_sub(dmnsn_vector lhs, dmnsn_vector rhs) +{ + /* 3 additions */ + dmnsn_vector v = { lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z }; + return v; +} + +/** Multiply a vector by a scalar. */ +DMNSN_INLINE dmnsn_vector +dmnsn_vector_mul(double lhs, dmnsn_vector rhs) +{ + /* 3 multiplications */ + dmnsn_vector v = { lhs*rhs.x, lhs*rhs.y, lhs*rhs.z }; + return v; +} + +/** Divide a vector by a scalar. */ +DMNSN_INLINE dmnsn_vector +dmnsn_vector_div(dmnsn_vector lhs, double rhs) +{ + /* 3 divisions */ + dmnsn_vector v = { lhs.x/rhs, lhs.y/rhs, lhs.z/rhs }; + return v; +} + +/** Return the dot product of two vectors. */ +DMNSN_INLINE double +dmnsn_vector_dot(dmnsn_vector lhs, dmnsn_vector rhs) +{ + /* 3 multiplications, 2 additions */ + return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z; +} + +/** Return the cross product of two vectors. */ +DMNSN_INLINE dmnsn_vector +dmnsn_vector_cross(dmnsn_vector lhs, dmnsn_vector rhs) +{ + /* 6 multiplications, 3 additions */ + dmnsn_vector v = { lhs.y*rhs.z - lhs.z*rhs.y, + lhs.z*rhs.x - lhs.x*rhs.z, + lhs.x*rhs.y - lhs.y*rhs.x }; + return v; +} + +/** Return the projection of \p u onto \p d. */ +DMNSN_INLINE dmnsn_vector +dmnsn_vector_proj(dmnsn_vector u, dmnsn_vector d) +{ + /* 1 division, 9 multiplications, 4 additions */ + return dmnsn_vector_mul(dmnsn_vector_dot(u, d)/dmnsn_vector_dot(d, d), d); +} + +/** Return the magnitude of a vector. */ +DMNSN_INLINE double +dmnsn_vector_norm(dmnsn_vector n) +{ + /* 1 sqrt, 3 multiplications, 2 additions */ + return sqrt(dmnsn_vector_dot(n, n)); +} + +/** Return the direction of a vector. */ +DMNSN_INLINE dmnsn_vector +dmnsn_vector_normalized(dmnsn_vector n) +{ + /* 1 sqrt, 3 divisions, 3 multiplications, 2 additions */ + return dmnsn_vector_div(n, dmnsn_vector_norm(n)); +} + +/** Return the component-wise minimum of two vectors. */ +DMNSN_INLINE dmnsn_vector +dmnsn_vector_min(dmnsn_vector a, dmnsn_vector b) +{ + return dmnsn_new_vector( + dmnsn_min(a.x, b.x), + dmnsn_min(a.y, b.y), + dmnsn_min(a.z, b.z) + ); +} + +/** Return the component-wise maximum of two vectors. */ +DMNSN_INLINE dmnsn_vector +dmnsn_vector_max(dmnsn_vector a, dmnsn_vector b) +{ + return dmnsn_new_vector( + dmnsn_max(a.x, b.x), + dmnsn_max(a.y, b.y), + dmnsn_max(a.z, b.z) + ); +} + +/** Return whether a vector contains any NaN components. */ +DMNSN_INLINE bool +dmnsn_vector_isnan(dmnsn_vector v) +{ + return dmnsn_isnan(v.x) || dmnsn_isnan(v.y) || dmnsn_isnan(v.z); +} diff --git a/libdimension/dimension/model.h b/libdimension/dimension/model.h new file mode 100644 index 0000000..5367729 --- /dev/null +++ b/libdimension/dimension/model.h @@ -0,0 +1,59 @@ +/************************************************************************* + * Copyright (C) 2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Scene modeling. + */ + +#ifndef DMNSN_MODEL_H +#define DMNSN_MODEL_H + +#include "dimension/base.h" +#include "dimension/color.h" +#include "dimension/canvas.h" +#include "dimension/pattern.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include <dimension/platform.h> + +#include <dimension/model/pigment.h> +#include <dimension/model/pigments.h> +#include <dimension/model/finish.h> +#include <dimension/model/finishes.h> +#include <dimension/model/texture.h> +#include <dimension/model/interior.h> +#include <dimension/model/object.h> +#include <dimension/model/objects.h> +#include <dimension/model/csg.h> +#include <dimension/model/light.h> +#include <dimension/model/lights.h> +#include <dimension/model/camera.h> +#include <dimension/model/cameras.h> +#include <dimension/model/scene.h> + +#ifdef __cplusplus +} +#endif + +#endif /* DMNSN_MODEL_H */ diff --git a/libdimension/dimension/camera.h b/libdimension/dimension/model/camera.h index 3c6494c..37f80b9 100644 --- a/libdimension/dimension/camera.h +++ b/libdimension/dimension/model/camera.h @@ -33,8 +33,7 @@ typedef struct dmnsn_camera dmnsn_camera; * @param[in] y The y coordinate of the pixel (in [0, 1]). * @return The ray through (\p x, \p y). */ -typedef dmnsn_line dmnsn_camera_ray_fn(const dmnsn_camera *camera, - double x, double y); +typedef dmnsn_ray dmnsn_camera_ray_fn(const dmnsn_camera *camera, double x, double y); /** A camera. */ struct dmnsn_camera { @@ -64,4 +63,4 @@ void dmnsn_init_camera(dmnsn_camera *camera); * @param[in] y The y coordinate of the pixel (in [0, 1]). * @return The ray through (\p x, \p y). */ -dmnsn_line dmnsn_camera_ray(const dmnsn_camera *camera, double x, double y); +dmnsn_ray dmnsn_camera_ray(const dmnsn_camera *camera, double x, double y); diff --git a/libdimension/dimension/cameras.h b/libdimension/dimension/model/cameras.h index 9ef2646..9ef2646 100644 --- a/libdimension/dimension/cameras.h +++ b/libdimension/dimension/model/cameras.h diff --git a/libdimension/dimension/csg.h b/libdimension/dimension/model/csg.h index b2ce83f..b2ce83f 100644 --- a/libdimension/dimension/csg.h +++ b/libdimension/dimension/model/csg.h diff --git a/libdimension/dimension/finish.h b/libdimension/dimension/model/finish.h index d975877..d975877 100644 --- a/libdimension/dimension/finish.h +++ b/libdimension/dimension/model/finish.h diff --git a/libdimension/dimension/finishes.h b/libdimension/dimension/model/finishes.h index e1f7b44..e1f7b44 100644 --- a/libdimension/dimension/finishes.h +++ b/libdimension/dimension/model/finishes.h diff --git a/libdimension/dimension/interior.h b/libdimension/dimension/model/interior.h index 0ff697d..0ff697d 100644 --- a/libdimension/dimension/interior.h +++ b/libdimension/dimension/model/interior.h diff --git a/libdimension/dimension/light.h b/libdimension/dimension/model/light.h index 218611d..218611d 100644 --- a/libdimension/dimension/light.h +++ b/libdimension/dimension/model/light.h diff --git a/libdimension/dimension/lights.h b/libdimension/dimension/model/lights.h index e7de4cc..e7de4cc 100644 --- a/libdimension/dimension/lights.h +++ b/libdimension/dimension/model/lights.h diff --git a/libdimension/dimension/object.h b/libdimension/dimension/model/object.h index c8e9d86..287d838 100644 --- a/libdimension/dimension/object.h +++ b/libdimension/dimension/model/object.h @@ -30,8 +30,8 @@ typedef struct dmnsn_object dmnsn_object; /** A type to represent a ray-object intersection. */ typedef struct dmnsn_intersection { - dmnsn_line ray; /**< The ray that intersected. */ - double t; /**< The line index that intersected. */ + dmnsn_ray ray; /**< The ray that intersected. */ + double t; /**< The ray index that intersected. */ /** The surface normal at the intersection point. */ dmnsn_vector normal; @@ -43,12 +43,12 @@ typedef struct dmnsn_intersection { /** * Ray-object intersection callback. * @param[in] object The object to test. - * @param[in] line The line to test. + * @param[in] ray The ray to test. * @param[out] intersection Where to store the intersection details of the * closest (if any) intersection. - * @return Whether \p line intersected \p object. + * @return Whether \p ray intersected \p object. */ -typedef bool dmnsn_object_intersection_fn(const dmnsn_object *object, dmnsn_line line, dmnsn_intersection *intersection); +typedef bool dmnsn_object_intersection_fn(const dmnsn_object *object, dmnsn_ray ray, dmnsn_intersection *intersection); /** * Object inside callback. @@ -62,8 +62,9 @@ typedef bool dmnsn_object_inside_fn(const dmnsn_object *object, dmnsn_vector poi * Object bounding callback. * @param[in,out] object The object to bound. * @param[in,out] trans The effective transformation for the object. + * @return A world-coordinate bounding box computed for the object. */ -typedef dmnsn_bounding_box dmnsn_object_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans); +typedef dmnsn_aabb dmnsn_object_bounding_fn(const dmnsn_object *object, dmnsn_matrix trans); /** * Object precomputation callback. @@ -96,7 +97,7 @@ struct dmnsn_object { bool precomputed; /**< @internal Whether the object is precomputed yet. */ dmnsn_matrix trans_inv; /**< Inverse of the transformation matrix. */ dmnsn_matrix pigment_trans; /**< Inverse transformation for the texture. */ - dmnsn_bounding_box bounding_box; /**< Bounding box in world coordinates. */ + dmnsn_aabb aabb; /**< Bounding box in world coordinates. */ }; /** @@ -121,19 +122,19 @@ void dmnsn_object_precompute(dmnsn_object *object); /** * Appropriately transform a ray, then test for an intersection. * @param[in] object The object to test. - * @param[in] line The ray to test. + * @param[in] ray The ray to test. * @param[out] intersection Where to store the intersection details. * @return Whether there was an intersection. */ DMNSN_INLINE bool -dmnsn_object_intersection(const dmnsn_object *object, dmnsn_line line, +dmnsn_object_intersection(const dmnsn_object *object, dmnsn_ray ray, dmnsn_intersection *intersection) { - dmnsn_line line_trans = dmnsn_transform_line(object->trans_inv, line); + dmnsn_ray ray_trans = dmnsn_transform_ray(object->trans_inv, ray); intersection->object = NULL; - if (object->vtable->intersection_fn(object, line_trans, intersection)) { + if (object->vtable->intersection_fn(object, ray_trans, intersection)) { /* Get us back into world coordinates */ - intersection->ray = line; + intersection->ray = ray; intersection->normal = dmnsn_vector_normalized( dmnsn_transform_normal(object->trans_inv, intersection->normal) ); diff --git a/libdimension/dimension/objects.h b/libdimension/dimension/model/objects.h index 2865d82..2865d82 100644 --- a/libdimension/dimension/objects.h +++ b/libdimension/dimension/model/objects.h diff --git a/libdimension/dimension/pigment.h b/libdimension/dimension/model/pigment.h index 14d8bae..14d8bae 100644 --- a/libdimension/dimension/pigment.h +++ b/libdimension/dimension/model/pigment.h diff --git a/libdimension/dimension/pigments.h b/libdimension/dimension/model/pigments.h index 100016d..100016d 100644 --- a/libdimension/dimension/pigments.h +++ b/libdimension/dimension/model/pigments.h diff --git a/libdimension/dimension/scene.h b/libdimension/dimension/model/scene.h index dd0c1ba..dd0c1ba 100644 --- a/libdimension/dimension/scene.h +++ b/libdimension/dimension/model/scene.h diff --git a/libdimension/dimension/texture.h b/libdimension/dimension/model/texture.h index df08a4a..df08a4a 100644 --- a/libdimension/dimension/texture.h +++ b/libdimension/dimension/model/texture.h diff --git a/libdimension/dimension/pattern.h b/libdimension/dimension/pattern.h index 2caed07..17a43a9 100644 --- a/libdimension/dimension/pattern.h +++ b/libdimension/dimension/pattern.h @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * Copyright (C) 2014 Tavian Barnes <tavianator@tavianator.com> * * * * This file is part of The Dimension Library. * * * @@ -20,43 +20,25 @@ /** * @file - * Patterns. Patterns are functions which map vectors to scalars, which are - * used for pigments and normals. + * Patterns. */ -/* Forward-declare dmnsn_pattern */ -typedef struct dmnsn_pattern dmnsn_pattern; +#ifndef DMNSN_PATTERN_H +#define DMNSN_PATTERN_H -/** - * Pattern callback. - * @param[in] pattern The pattern itself. - * @param[in] v The point at which to evaluate the pattern. - * @return The value of the pattern at \p v. - */ -typedef double dmnsn_pattern_fn(const dmnsn_pattern *pattern, dmnsn_vector v); +#ifdef __cplusplus +extern "C" { +#endif -/** A pattern. */ -struct dmnsn_pattern { - dmnsn_pattern_fn *pattern_fn; /**< The pattern callback. */ -}; +#include <dimension/base.h> +#include <dimension/math.h> -/** - * Allocate a dummy pattern. - * @param[in] pool The memory pool to allocate from. - * @return A pattern with no callbacks set. - */ -dmnsn_pattern *dmnsn_new_pattern(dmnsn_pool *pool); +#include <dimension/pattern/pattern.h> +#include <dimension/pattern/patterns.h> +#include <dimension/pattern/map.h> -/** - * Initialize a dmnsn_pattern field. - * @param[out] pattern The pattern to initialize. - */ -void dmnsn_init_pattern(dmnsn_pattern *pattern); +#ifdef __cplusplus +} +#endif -/** - * Invoke the pattern callback. - * @param[in] pattern The pattern to evaluate. - * @param[in] v The point to get the pattern value for. - * @return The value of the pattern at \p v. - */ -double dmnsn_pattern_value(const dmnsn_pattern *pattern, dmnsn_vector v); +#endif /* DMNSN_PATTERN_H */ diff --git a/libdimension/dimension/map.h b/libdimension/dimension/pattern/map.h index 7229a24..7229a24 100644 --- a/libdimension/dimension/map.h +++ b/libdimension/dimension/pattern/map.h diff --git a/libdimension/dimension/pattern/pattern.h b/libdimension/dimension/pattern/pattern.h new file mode 100644 index 0000000..2caed07 --- /dev/null +++ b/libdimension/dimension/pattern/pattern.h @@ -0,0 +1,62 @@ +/************************************************************************* + * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Patterns. Patterns are functions which map vectors to scalars, which are + * used for pigments and normals. + */ + +/* Forward-declare dmnsn_pattern */ +typedef struct dmnsn_pattern dmnsn_pattern; + +/** + * Pattern callback. + * @param[in] pattern The pattern itself. + * @param[in] v The point at which to evaluate the pattern. + * @return The value of the pattern at \p v. + */ +typedef double dmnsn_pattern_fn(const dmnsn_pattern *pattern, dmnsn_vector v); + +/** A pattern. */ +struct dmnsn_pattern { + dmnsn_pattern_fn *pattern_fn; /**< The pattern callback. */ +}; + +/** + * Allocate a dummy pattern. + * @param[in] pool The memory pool to allocate from. + * @return A pattern with no callbacks set. + */ +dmnsn_pattern *dmnsn_new_pattern(dmnsn_pool *pool); + +/** + * Initialize a dmnsn_pattern field. + * @param[out] pattern The pattern to initialize. + */ +void dmnsn_init_pattern(dmnsn_pattern *pattern); + +/** + * Invoke the pattern callback. + * @param[in] pattern The pattern to evaluate. + * @param[in] v The point to get the pattern value for. + * @return The value of the pattern at \p v. + */ +double dmnsn_pattern_value(const dmnsn_pattern *pattern, dmnsn_vector v); diff --git a/libdimension/dimension/patterns.h b/libdimension/dimension/pattern/patterns.h index 59b7fec..59b7fec 100644 --- a/libdimension/dimension/patterns.h +++ b/libdimension/dimension/pattern/patterns.h diff --git a/libdimension/dimension/platform.h b/libdimension/dimension/platform.h new file mode 100644 index 0000000..4c01709 --- /dev/null +++ b/libdimension/dimension/platform.h @@ -0,0 +1,39 @@ +/************************************************************************* + * Copyright (C) 2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Platform abstractions. + */ + +#ifndef DMNSN_PLATFORM_H +#define DMNSN_PLATFORM_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <dimension/platform/timer.h> + +#ifdef __cplusplus +} +#endif + +#endif /* DMNSN_PLATFORM_H */ diff --git a/libdimension/dimension/timer.h b/libdimension/dimension/platform/timer.h index 55d66ff..bcf4a9d 100644 --- a/libdimension/dimension/timer.h +++ b/libdimension/dimension/platform/timer.h @@ -23,6 +23,10 @@ * A platform-agnostic timer abstraction. */ +#ifndef DMNSN_PLATFORM_H +#error "Please include <dimension/platform.h> instead of this header directly." +#endif + /** A platform-agnotic timer. */ typedef struct dmnsn_timer { double real; /**< Wall-clock time. */ diff --git a/libdimension/dimension/polynomial.h b/libdimension/dimension/polynomial.h deleted file mode 100644 index ab95d50..0000000 --- a/libdimension/dimension/polynomial.h +++ /dev/null @@ -1,85 +0,0 @@ -/************************************************************************* - * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> * - * * - * This file is part of The Dimension Library. * - * * - * The Dimension Library is free software; you can redistribute it and/ * - * or modify it under the terms of the GNU Lesser General Public License * - * as published by the Free Software Foundation; either version 3 of the * - * License, or (at your option) any later version. * - * * - * The Dimension Library is distributed in the hope that it will be * - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU Lesser General Public * - * License along with this program. If not, see * - * <http://www.gnu.org/licenses/>. * - *************************************************************************/ - -/** - * @file - * Utility functions for working with and numerically solving polynomials. - * Polynomials are represented as simple arrays where the ith element is the - * coefficient on x^i. In general, we are only interested in positive roots. - */ - -#include <stddef.h> -#include <stdio.h> - -/** - * Evaluate a polynomial at \p x. - * @param[in] poly The coefficients of the polynomial to evaluate, in order - * from lowest degree to highest degree. The array should - * have dimension <tt>degree + 1</tt>. - * @param[in] degree The degree of the polynomial. - * @param[in] x The value of the variable at which to evaluate. - */ -DMNSN_INLINE double -dmnsn_polynomial_evaluate(const double poly[], size_t degree, double x) -{ - double ret = poly[degree]; - size_t i; - for (i = degree; i-- > 0;) { - ret = ret*x + poly[i]; - } - return ret; -} - -/** - * Evaluate the derivative of a polynomial at \p x. - * @param[in] poly The coefficients of the polynomial to evaluate. - * @param[in] degree The degree of the polynomial. - * @param[in] x The value of the variable at which to evaluate. - */ -DMNSN_INLINE double -dmnsn_polynomial_evaluate_derivative(const double poly[], size_t degree, - double x) -{ - double ret = poly[degree]*degree; - size_t i; - for (i = degree - 1; i >= 1; --i) { - ret = ret*x + poly[i]*i; - } - return ret; -} - -/** - * Find the positive roots of a polynomial. - * @param[in] poly The coefficients of the polynomial to solve. - * @param[in] degree The degree of the polynomial. - * @param[out] x An array in which to store the roots. It should have - * dimension \p degree. - * @return The number of positive roots stored in \c x[]. - */ -size_t dmnsn_polynomial_solve(const double poly[], size_t degree, double x[]); - -/** - * Output a polynomial. The polynomial is printed as a function of x suitable - * for input into a CAS, and without a trailing newline. - * @param[in,out] file The file to write to. - * @param[in] poly The coefficients of the polynomial to print. - * @param[in] degree The degree of the polynomial. - */ -void dmnsn_polynomial_print(FILE *file, const double poly[], size_t degree); diff --git a/libdimension/dimension/render.h b/libdimension/dimension/render.h new file mode 100644 index 0000000..296d7a3 --- /dev/null +++ b/libdimension/dimension/render.h @@ -0,0 +1,41 @@ +/************************************************************************* + * Copyright (C) 2014 Tavian Barnes <tavianator@tavianator.com> * + * * + * This file is part of The Dimension Library. * + * * + * The Dimension Library is free software; you can redistribute it and/ * + * or modify it under the terms of the GNU Lesser General Public License * + * as published by the Free Software Foundation; either version 3 of the * + * License, or (at your option) any later version. * + * * + * The Dimension Library is distributed in the hope that it will be * + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this program. If not, see * + * <http://www.gnu.org/licenses/>. * + *************************************************************************/ + +/** + * @file + * Rendering. + */ + +#ifndef DMNSN_RENDER_H +#define DMNSN_RENDER_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <dimension/model.h> + +#include <dimension/render/render.h> + +#ifdef __cplusplus +} +#endif + +#endif /* DMNSN_RENDER_H */ diff --git a/libdimension/dimension/ray_trace.h b/libdimension/dimension/render/render.h index 82fb759..69f52c2 100644 --- a/libdimension/dimension/ray_trace.h +++ b/libdimension/dimension/render/render.h @@ -1,5 +1,5 @@ /************************************************************************* - * Copyright (C) 2009-2011 Tavian Barnes <tavianator@tavianator.com> * + * Copyright (C) 2009-2014 Tavian Barnes <tavianator@tavianator.com> * * * * This file is part of The Dimension Library. * * * @@ -20,18 +20,22 @@ /** * @file - * Ray-trace a scene. + * Rendering. */ +#ifndef DMNSN_RENDER_H +#error "Please include <dimension/render.h> instead of this header directly." +#endif + /** - * Render a scene by ray tracing. + * Render a scene. * @param[in,out] scene The scene to render. */ -void dmnsn_ray_trace(dmnsn_scene *scene); +void dmnsn_render(dmnsn_scene *scene); /** * Render a scene in the background. * @param[in,out] scene The scene to render. * @return A \p dmnsn_future object. */ -dmnsn_future *dmnsn_ray_trace_async(dmnsn_scene *scene); +dmnsn_future *dmnsn_render_async(dmnsn_scene *scene); |