diff options
Diffstat (limited to 'libdimension/dimension')
28 files changed, 1247 insertions, 341 deletions
diff --git a/libdimension/dimension/array.h b/libdimension/dimension/array.h index 87af84a..514e13e 100644 --- a/libdimension/dimension/array.h +++ b/libdimension/dimension/array.h @@ -18,24 +18,30 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Simple generalized arrays, for returning variable-length arrays from - * functions, and other fun stuff. All functions are inline for performance - * reasons. +/** + * @file + * Simple dynamic arrays. */ #ifndef DIMENSION_ARRAY_H #define DIMENSION_ARRAY_H -#include <stdlib.h> /* For size_t */ +#include <stddef.h> /* For size_t */ #include <string.h> /* For memcpy */ -typedef struct { - void *ptr; - size_t obj_size, length, capacity; +/** Dynamic array type */ +typedef struct dmnsn_array { + void *ptr; /**< @internal The actual memory */ + size_t obj_size; /**< @internal The size of each object */ + size_t length; /**< @internal The current size of the array */ + size_t capacity; /**< @internal The size of the allocated space */ } dmnsn_array; -/* Array allocation */ +/** + * Allocate an array. + * @param[in] obj_size The size of the objects to store in the array. + * @return An empty array. + */ DMNSN_INLINE dmnsn_array * dmnsn_new_array(size_t obj_size) { @@ -50,7 +56,10 @@ dmnsn_new_array(size_t obj_size) return array; } -/* Delete an array */ +/** + * Delete an array. + * @param[in,out] array The array to delete. + */ DMNSN_INLINE void dmnsn_delete_array(dmnsn_array *array) { @@ -60,14 +69,22 @@ dmnsn_delete_array(dmnsn_array *array) } } -/* Get the size of the array */ +/** + * Get the size of the array. + * @param[in] array The array in question. + * @return The number of elements in the array. + */ DMNSN_INLINE size_t dmnsn_array_size(const dmnsn_array *array) { return array->length; } -/* Set the size of the array */ +/** + * Set the size of the array. + * @param[in,out] array The array to resize. + * @param[in] length The new length of the array. + */ DMNSN_INLINE void dmnsn_array_resize(dmnsn_array *array, size_t length) { @@ -80,7 +97,12 @@ dmnsn_array_resize(dmnsn_array *array, size_t length) array->length = length; } -/* Get the i'th object, bailing out if i is out of range */ +/** + * Get the i'th element. + * @param[in] array The array to access. + * @param[in] i The index of the element to extract. + * @param[out] obj The location to store the extracted object. + */ DMNSN_INLINE void dmnsn_array_get(const dmnsn_array *array, size_t i, void *obj) { @@ -89,7 +111,12 @@ dmnsn_array_get(const dmnsn_array *array, size_t i, void *obj) } -/* Set the i'th object, expanding the array if necessary */ +/** + * Set the i'th object, expanding the array if necessary. + * @param[in,out] array The array to modify. + * @param[in] i The index to update. + * @param[in] obj The location of the object to copy into the array. + */ DMNSN_INLINE void dmnsn_array_set(dmnsn_array *array, size_t i, const void *obj) { @@ -100,21 +127,34 @@ dmnsn_array_set(dmnsn_array *array, size_t i, const void *obj) memcpy((char *)array->ptr + array->obj_size*i, obj, array->obj_size); } -/* First element */ +/** + * First element. + * @param[in] array The array to index. + * @return The address of the first element of the array. + */ DMNSN_INLINE void * dmnsn_array_first(const dmnsn_array *array) { return array->ptr; } -/* Last element */ +/** + * Last element. + * @param[in] array The array to index. + * @return The address of the last element of the array. + */ DMNSN_INLINE void * dmnsn_array_last(const dmnsn_array *array) { return (char *)array->ptr + array->obj_size*(array->length - 1); } -/* Arbitrary element access */ +/** + * Arbitrary element access. + * @param[in] array The array to index. + * @param[in] i The index to access. + * @return The address of the i'th element of the array. + */ DMNSN_INLINE void * dmnsn_array_at(const dmnsn_array *array, size_t i) { @@ -122,14 +162,22 @@ dmnsn_array_at(const dmnsn_array *array, size_t i) return (char *)array->ptr + array->obj_size*i; } -/* Push obj to the end of the array */ +/** + * Push an object to the end of the array. + * @param[in,out] array The array to append to. + * @param[in] obj The location of the object to push. + */ DMNSN_INLINE void dmnsn_array_push(dmnsn_array *array, const void *obj) { dmnsn_array_set(array, dmnsn_array_size(array), obj); } -/* Pop obj from the end of the array */ +/** + * Pop an object from the end of the array. + * @param[in,out] array The array to pop from. + * @param[out] obj The location to store the extracted object. + */ DMNSN_INLINE void dmnsn_array_pop(dmnsn_array *array, void *obj) { @@ -139,7 +187,12 @@ dmnsn_array_pop(dmnsn_array *array, void *obj) dmnsn_array_resize(array, size - 1); /* Shrink the array */ } -/* Insert an item into the middle of the array */ +/** + * Insert an item into the middle of the array. This is O(n). + * @param[in,out] array The array to insert to. + * @param[in] i The index at which to insert. + * @param[in] obj The object to insert. + */ DMNSN_INLINE void dmnsn_array_insert(dmnsn_array *array, size_t i, const void *obj) { @@ -156,7 +209,11 @@ dmnsn_array_insert(dmnsn_array *array, size_t i, const void *obj) memcpy((char *)array->ptr + array->obj_size*i, obj, array->obj_size); } -/* Remove an item from the middle of the array */ +/** + * Remove an item from the middle of the array. This is O(n). + * @param[in,out] array The array to remove from. + * @param[in] i The index to remove. + */ DMNSN_INLINE void dmnsn_array_remove(dmnsn_array *array, size_t i) { @@ -172,11 +229,29 @@ dmnsn_array_remove(dmnsn_array *array, size_t i) /* Macros to shorten array iteration */ +/** + * Iterate over an array. For example, + * @code + * DMNSN_ARRAY_FOREACH (int *, i, array) { + * printf("%d\n", *i); + * } + * @endcode + * + * @param type The (pointer) type to use as an iterator. + * @param i The name of the iterator within the loop body. + * @param[in] array The array to loop over. + */ #define DMNSN_ARRAY_FOREACH(type, i, array) \ for (type i = dmnsn_array_first(array); \ i - (type)dmnsn_array_first(array) < dmnsn_array_size(array); \ ++i) +/** + * Iterate over an array, in reverse order. + * @param type The (pointer) type to use as an iterator. + * @param i The name of the iterator within the loop body. + * @param[in] array The array to loop over. + */ #define DMNSN_ARRAY_FOREACH_REVERSE(type, i, array) \ for (type i = dmnsn_array_last(array); \ i - (type)dmnsn_array_first(array) >= 0; \ diff --git a/libdimension/dimension/camera.h b/libdimension/dimension/camera.h index e95ad18..e63cd80 100644 --- a/libdimension/dimension/camera.h +++ b/libdimension/dimension/camera.h @@ -18,8 +18,9 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * A camera. +/** + * @file + * Cameras. */ #ifndef DIMENSION_CAMERA_H @@ -28,20 +29,47 @@ /* Forward-declare dmnsn_camera */ typedef struct dmnsn_camera dmnsn_camera; -/* Camera callback types */ +/** + * Camera ray callback. + * @param[in] camera The camera itself. + * @param[in] x The x coordinate of the pixel (in [0, 1]). + * @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); +/** A camera. */ struct dmnsn_camera { /* Callback functions */ - dmnsn_camera_ray_fn *ray_fn; - dmnsn_free_fn *free_fn; + dmnsn_camera_ray_fn *ray_fn; /**< Camera ray callback. */ + dmnsn_free_fn *free_fn; /**< Destructor callback. */ + + dmnsn_matrix trans; /**< Transformation matrix. */ - /* Generic pointer for camera info */ + /** Generic pointer for camera info */ void *ptr; }; +/** + * Create a dummy camera. + * @return The allocated camera. + */ dmnsn_camera *dmnsn_new_camera(void); + +/** + * Delete a camera. + * @param[in,out] camera The camera to delete. + */ void dmnsn_delete_camera(dmnsn_camera *camera); +/** + * Invoke the camera ray callback, then correctly transform the ray. + * @param[in] camera The camera itself. + * @param[in] x The x coordinate of the pixel (in [0, 1]). + * @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); + #endif /* DIMENSION_CAMERA_H */ diff --git a/libdimension/dimension/cameras.h b/libdimension/dimension/cameras.h index 7f4d549..077aebc 100644 --- a/libdimension/dimension/cameras.h +++ b/libdimension/dimension/cameras.h @@ -18,20 +18,21 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Types of cameras. +/** + * @file + * Pre-defined camera types. */ #ifndef DIMENSION_CAMERAS_H #define DIMENSION_CAMERAS_H -/* A perspective camera, at the origin, looking at (0, 0, 1). The feild of view - is the section of the plane z = 1 from (-0.5, -0.5) to (0.5, 0.5). Rays are - transformed by the camera's transformation matrix. */ +/** + * A perspective camera. The camera is located at the origin, looking at + * (0, 0, 1). The feild of view is the section of the plane z = 1 from + * (-0.5, -0.5) to (0.5, 0.5). Rays are transformed by the camera's + * transformation matrix. + * @return A perspective camera. + */ dmnsn_camera *dmnsn_new_perspective_camera(void); -/* Get or set the transformation matrix */ -dmnsn_matrix dmnsn_get_perspective_camera_trans(const dmnsn_camera *camera); -void dmnsn_set_perspective_camera_trans(dmnsn_camera *camera, dmnsn_matrix T); - #endif /* DIMENSION_CAMERAS_H */ diff --git a/libdimension/dimension/canvas.h b/libdimension/dimension/canvas.h index 018dcda..bc98e71 100644 --- a/libdimension/dimension/canvas.h +++ b/libdimension/dimension/canvas.h @@ -18,7 +18,8 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* +/** + * @file * A canvas which is rendered to. */ @@ -27,16 +28,18 @@ #include <stddef.h> +/** A canvas, or image. */ typedef struct { - /* width, height */ - size_t x, y; + size_t width; /**< Canvas width */ + size_t height; /**< Canvas height */ - /* An array of dmnsn_canvas_optimizer's */ + /** 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*x + a]. + * at (a,b) is accessible as pixels[b*width + a]. */ dmnsn_color *pixels; } dmnsn_canvas; @@ -44,39 +47,79 @@ typedef struct { /* Forward-declare dmnsn_canvas_optimizer */ typedef struct dmnsn_canvas_optimizer dmnsn_canvas_optimizer; -/* Canvas optimizer callback types */ -typedef void dmnsn_canvas_optimizer_fn(dmnsn_canvas *canvas, +/** + * Canvas optimizer callback type. + * @param[in] canvas The canvas that was just updated. + * @param[in] optimizer The canvas optimizer itself. + * @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(const dmnsn_canvas *canvas, dmnsn_canvas_optimizer optimizer, size_t x, size_t y); -/* Canvas optimizer */ +/** Canvas optimizer */ struct dmnsn_canvas_optimizer { - /* Callback types */ - dmnsn_canvas_optimizer_fn *optimizer_fn; - dmnsn_free_fn *free_fn; + dmnsn_canvas_optimizer_fn *optimizer_fn; /**< Optimizer callback */ + dmnsn_free_fn *free_fn; /**< Destructor callback */ - /* Generic pointer */ - void *ptr; + void *ptr; /**< Generic pointer. */ }; -/* Allocate and free a canvas */ -dmnsn_canvas *dmnsn_new_canvas(size_t x, size_t y); +/** + * Allocate a new canvas. + * @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(size_t width, size_t height); + +/** + * Delete a canvas. + * @param[in,out] canvas The canvas to delete. + */ void dmnsn_delete_canvas(dmnsn_canvas *canvas); -/* Set a canvas optimizer */ +/** + * Set a canvas optimizer + * @param[in,out] canvas The canvas to optimize. + * @param[in] optimizer The optimizer to use. + */ void dmnsn_optimize_canvas(dmnsn_canvas *canvas, dmnsn_canvas_optimizer optimizer); /* 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 canvas at (\p x, \p y). + */ DMNSN_INLINE dmnsn_color dmnsn_get_pixel(const dmnsn_canvas *canvas, size_t x, size_t y) { - return canvas->pixels[y*canvas->x + x]; + dmnsn_assert(x < canvas->width && y < canvas->height, + "Canvas access out of bounds."); + return canvas->pixels[y*canvas->width + x]; } +/** + * Set the color 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] color The color to set the pixel at (\p x, \p y) to. + */ void dmnsn_set_pixel(dmnsn_canvas *canvas, size_t x, size_t y, dmnsn_color color); + +/** + * Clear a canvas uniformly with a given color. + * @param[in,out] canvas The canvas to erase. + * @param[in] color The color to paint it with. + */ void dmnsn_clear_canvas(dmnsn_canvas *canvas, dmnsn_color color); #endif /* DIMENSION_CANVAS_H */ diff --git a/libdimension/dimension/color.h b/libdimension/dimension/color.h index 9e47282..393778d 100644 --- a/libdimension/dimension/color.h +++ b/libdimension/dimension/color.h @@ -18,8 +18,9 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Types to represent color. +/** + * @file + * Color-related types and operations. */ #ifndef DIMENSION_COLOR_H @@ -27,71 +28,110 @@ #include <stdbool.h> -/* Internally, we use sRGB color. */ +/** A color value. */ typedef struct { - double filter, trans; /* Filter transparancy only lets light of this color - through; regular transparancy lets all colors - through. filter + trans should be <= 1.0. */ - double R, G, B; + /** Filtered transparency. */ + double filter; + /** Unfiltered transparency; <tt>filter + trans</tt> should be <= 1. */ + double trans; + + /* Internally we use sRGB color. */ + double R; /**< @internal sRGB red value. */ + double G; /**< @internal sRGB green value. */ + double B; /**< @internal sRGB blue value. */ } dmnsn_color; +/** sRGB color. */ typedef struct { - double X, Y, Z; /* X, Y, and Z are tristimulus values, unbounded above zero. - Diffuse white is (0.9505, 1, 1.089). */ + double R; /**< sRGB red value. */ + double G; /**< sRGB green value. */ + double B; /**< sRGB blue value. */ +} dmnsn_sRGB; + +/** CIE XYZ color. */ +typedef struct { + double X; /**< X component. */ + double Y; /**< Y (luminance) component. */ + double Z; /**< Z component. */ } dmnsn_CIE_XYZ; +/** CIE xyY color. */ typedef struct { - double x, y, Y; /* x and y are chromaticity coordinates, and Y is luminance, - in the CIE 1931 xyZ color space. We use an unlimited light - model, so x,y in [0, 1] and Y >= 0, with 1 = diffuse - white */ + double x; /**< x chromaticity coordinate (in [0, 1]) */ + double y; /**< y chromaticity coordinate (in [0, 1]) */ + double Y; /**< Luminance, unbounded >= 0; 1 is diffuse white. */ } dmnsn_CIE_xyY; +/** CIE 1976 (L*, a*, b*) color. */ typedef struct { - double L, a, b; /* L is luminence (100 = diffuse white); a and b are color- - opponent dimensions. This color space is used for color - arithmetic. */ + double L; /**< Luminance (100 is diffuse white). */ + double a; /**< Red/greed color-opponent value. */ + double b; /**< Yellow/blue color-opponent value. */ } dmnsn_CIE_Lab; +/** CIE 1976 (L*, u*, v*) color. */ typedef struct { - double L, u, v; /* L is luminence (100 = diffuse white); u and v are - chromaticity coordinates. */ + double L; /**< Luminance (same L* as CIE L*, a*, b*) */ + double u; /**< u* coordinate. */ + double v; /**< v* coordinate. */ } dmnsn_CIE_Luv; -typedef struct { - double R, G, B; /* sRGB R, G, and B values */ -} dmnsn_sRGB; - /* Standard colors */ -extern const dmnsn_color dmnsn_black, dmnsn_white, dmnsn_red, dmnsn_green, - dmnsn_blue, dmnsn_magenta, dmnsn_orange, dmnsn_yellow, dmnsn_cyan; - -/* Standard whitepoint, determined by the conversion of sRGB white to CIE XYZ */ +extern const dmnsn_color dmnsn_black; /**< Black. */ +extern const dmnsn_color dmnsn_white; /**< White. */ +extern const dmnsn_color dmnsn_red; /**< Red. */ +extern const dmnsn_color dmnsn_green; /**< Green. */ +extern const dmnsn_color dmnsn_blue; /**< Blue. */ +extern const dmnsn_color dmnsn_magenta; /**< Magenta. */ +extern const dmnsn_color dmnsn_orange; /**< Orange. */ +extern const dmnsn_color dmnsn_yellow; /**< Yellow. */ +extern const dmnsn_color dmnsn_cyan; /**< Cyan. */ + +/** Standard whitepoint, determined by the conversion of sRGB white to + CIE XYZ */ extern const dmnsn_CIE_XYZ dmnsn_whitepoint; -/* Is this color black? */ +/** Is this color black? */ bool dmnsn_color_is_black(dmnsn_color color); /* Color conversions */ +/** Convert an sRGB color to a Dimension color */ +dmnsn_color dmnsn_color_from_sRGB(dmnsn_sRGB sRGB); +/** Convert a CIE XYZ color to a Dimension color */ dmnsn_color dmnsn_color_from_XYZ(dmnsn_CIE_XYZ XYZ); +/** Convert a CIE xyY color to a Dimension color */ dmnsn_color dmnsn_color_from_xyY(dmnsn_CIE_xyY xyY); +/** Convert a CIE L*, a*, b* color to a Dimension color */ dmnsn_color dmnsn_color_from_Lab(dmnsn_CIE_Lab Lab, dmnsn_CIE_XYZ white); +/** Convert a CIE L*, u*, v* color to a Dimension color */ dmnsn_color dmnsn_color_from_Luv(dmnsn_CIE_Luv Luv, dmnsn_CIE_XYZ white); -dmnsn_color dmnsn_color_from_sRGB(dmnsn_sRGB sRGB); +/** Convert a Dimension color to sRGB */ +dmnsn_sRGB dmnsn_sRGB_from_color(dmnsn_color color); +/** Convert a Dimension color to CIE XYZ */ dmnsn_CIE_XYZ dmnsn_XYZ_from_color(dmnsn_color color); +/** Convert a Dimension color to CIE xyY */ dmnsn_CIE_xyY dmnsn_xyY_from_color(dmnsn_color color); +/** Convert a Dimension color to CIE L*, a*, b* */ dmnsn_CIE_Lab dmnsn_Lab_from_color(dmnsn_color color, dmnsn_CIE_XYZ white); +/** Convert a Dimension color to CIE L*, u*, v* */ dmnsn_CIE_Luv dmnsn_Luv_from_color(dmnsn_color color, dmnsn_CIE_XYZ white); -dmnsn_sRGB dmnsn_sRGB_from_color(dmnsn_color color); /* Perceptual color manipulation */ + +/** Add two colors together */ dmnsn_color dmnsn_color_add(dmnsn_color color1, dmnsn_color color2); +/** Multiply a color's intensity by \p n */ dmnsn_color dmnsn_color_mul(double n, dmnsn_color color); +/** Return the color at \p n on a gradient from \p c1 at 0 to \p c2 at 1 */ dmnsn_color dmnsn_color_gradient(dmnsn_color c1, dmnsn_color c2, double n); +/** Filter \p color through \p filter. */ dmnsn_color dmnsn_color_filter(dmnsn_color color, dmnsn_color filter); +/** Illuminate \p color with \p light. */ dmnsn_color dmnsn_color_illuminate(dmnsn_color light, dmnsn_color color); + +/** Return the perceptual difference between two colors. */ double dmnsn_color_difference(dmnsn_color color1, dmnsn_color color2); #endif /* DIMENSION_COLOR_H */ diff --git a/libdimension/dimension/csg.h b/libdimension/dimension/csg.h index 176467a..5d923bf 100644 --- a/libdimension/dimension/csg.h +++ b/libdimension/dimension/csg.h @@ -18,16 +18,43 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* +/** + * @file * Constructive solid geometry */ #ifndef DIMENSION_CSG_H #define DIMENSION_CSG_H -dmnsn_object *dmnsn_new_csg_union(dmnsn_array *objects); +/** + * CSG union. + * @param[in] objects The objects from which to compose the union. + * @return A union of the objects in \p objects. + */ +dmnsn_object *dmnsn_new_csg_union(const dmnsn_array *objects); + +/** + * CSG intersection. + * @param[in,out] A The first object. + * @param[in,out] B The second object. + * @return The intersection of \p A and \p B. + */ dmnsn_object *dmnsn_new_csg_intersection(dmnsn_object *A, dmnsn_object *B); + +/** + * CSG intersection. + * @param[in,out] A The outer object. + * @param[in,out] B The inner object. + * @return The difference between \p A and \p B. + */ dmnsn_object *dmnsn_new_csg_difference(dmnsn_object *A, dmnsn_object *B); + +/** + * CSG Merge. + * @param[in,out] A The first object. + * @param[in,out] B The second object. + * @return The merge of \p A and \p B. + */ dmnsn_object *dmnsn_new_csg_merge(dmnsn_object *A, dmnsn_object *B); #endif /* DIMENSION_CSG_H */ diff --git a/libdimension/dimension/error.h b/libdimension/dimension/error.h index a0b3857..8482266 100644 --- a/libdimension/dimension/error.h +++ b/libdimension/dimension/error.h @@ -18,22 +18,29 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Error handling. 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. +/** + * @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. */ #ifndef DIMENSION_ERROR_H #define DIMENSION_ERROR_H -typedef enum { - DMNSN_SEVERITY_LOW, /* Only die on low resilience */ - DMNSN_SEVERITY_MEDIUM, /* Die on low or medium resilience */ - DMNSN_SEVERITY_HIGH /* Always die */ +/** Error severity codes */ +typedef enum dmnsn_severity { + DMNSN_SEVERITY_LOW, /**< Only die on low resilience */ + DMNSN_SEVERITY_MEDIUM, /**< Die on low or medium resilience */ + DMNSN_SEVERITY_HIGH /**< Always die */ } dmnsn_severity; +/** + * @internal + * @def DMNSN_FUNC + * @brief Expands to the name of the current function + */ #ifdef __GNUC__ #define DMNSN_FUNC __PRETTY_FUNCTION__ #elif __STDC_VERSION__ >= 199901L @@ -42,13 +49,24 @@ typedef enum { #define DMNSN_FUNC "<unknown function>" #endif -/* Use this macro to report an error */ +/** + * Report an error. + * @param[in] severity A @ref dmnsn_severity representing the severity of the + * error. DMNSN_SEVERITY_HIGH will always terminate the + * running thread. + * @param[in] str A string to print explaining the error. + */ #define dmnsn_error(severity, str) \ dmnsn_report_error((dmnsn_severity)(severity), \ DMNSN_FUNC, __FILE__, __LINE__, \ str) -/* Make an assertion */ +/** + * @def dmnsn_assert + * Make an assertion. + * @param[in] expr The expression to assert. + * @param[in] str A string to print if the assertion fails. + */ #ifdef NDEBUG #define dmnsn_assert(expr, str) ((void)0) #else @@ -60,21 +78,50 @@ typedef enum { } while (0) #endif -/* Called by dmnsn_error() - don't call directly */ +/** + * @internal + * Called by dmnsn_error(); don't call directly. + * @param[in] severity The severity of the error. + * @param[in] func The name of the function where the error originated. + * @param[in] file The file where the error originated. + * @param[in] line The line number where the error originated. + * @param[in] str A string describing the error. + */ void dmnsn_report_error(dmnsn_severity severity, const char *func, const char *file, unsigned int line, const char *str); -/* Get and set the library resilience, thread-safely */ +/** + * Get the library resilience, thread-safely. + * @return The error severity considered fatal. + */ dmnsn_severity dmnsn_get_resilience(void); + +/** + * Set the library resilience, thread-safely. + * @param[in] resilience The new minimum severity that will cause a fatal + * error. + */ void dmnsn_set_resilience(dmnsn_severity resilience); -/* Fatal error callback type */ +/** + * Fatal error callback type. This function should never return. + */ typedef void dmnsn_fatal_error_fn(void); -/* Get and set libdimension fatal error handling strategy - the default is - exit(EXIT_FAILURE) */ +/** + * Get the libdimension fatal error handler, thread-safely. The default fatal + * error handler terminates the current thread, or the entire program if the + * current thread is the main thread. + * @return The current fatal error handler. + */ dmnsn_fatal_error_fn *dmnsn_get_fatal_error_fn(void); + +/** + * Set the libdimension fatal error handler, thread-safely. + * @param[in] fatal The new fatal error handler. This function must never + * return. + */ void dmnsn_set_fatal_error_fn(dmnsn_fatal_error_fn *fatal); #endif /* DIMENSION_ERROR_H */ diff --git a/libdimension/dimension/finishes.h b/libdimension/dimension/finishes.h index b84b5fb..bc07759 100644 --- a/libdimension/dimension/finishes.h +++ b/libdimension/dimension/finishes.h @@ -18,23 +18,51 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Custom finishes. +/** + * @file + * Pre-defined finishes. */ #ifndef DIMENSION_FINISHES_H #define DIMENSION_FINISHES_H -/* Add two finishes */ +/** + * Add two finishes together. + * @param[in,out] f1 The first finish. + * @param[in,out] f2 The second finish. + * @return A finish that adds the values of two finishes together. + */ dmnsn_finish *dmnsn_new_finish_combination(dmnsn_finish *f1, dmnsn_finish *f2); +/** + * Ambient finish. + * @param[in] ambient The color of the ambient light. + * @return A finish with ambient light. + */ dmnsn_finish *dmnsn_new_ambient_finish(dmnsn_color ambient); + +/** + * Diffuse finish. + * @param[in] diffuse The diffuse reflection coefficient. + * @return A finish with diffuse reflection. + */ dmnsn_finish *dmnsn_new_diffuse_finish(double diffuse); -/* A phong specular highlight */ +/** + * A phong specular highlight. + * @param[in] specular The specular reflection coefficient. + * @param[in] exp The exponent (roughly the highlight size). + * @return A finish with phong specular highlight. + */ dmnsn_finish *dmnsn_new_phong_finish(double specular, double exp); -/* Specular reflection */ +/** + * Specular (mirror) reflection. + * @param[in] min Reflection at paralell angles. + * @param[in] max Reflection at perpendicular angles (often == \p min). + * @param[in] falloff Degree of exponential falloff (usually 1). + * @return A finish with specular reflection. + */ dmnsn_finish *dmnsn_new_reflective_finish(dmnsn_color min, dmnsn_color max, double falloff); diff --git a/libdimension/dimension/geometry.h b/libdimension/dimension/geometry.h index adf41dc..a62fb75 100644 --- a/libdimension/dimension/geometry.h +++ b/libdimension/dimension/geometry.h @@ -18,7 +18,8 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* +/** + * @file * Core geometric types like vectors, matricies, and rays. */ @@ -28,74 +29,105 @@ #include <math.h> #include <stdbool.h> -/* Vector and matrix types */ +/** 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; -typedef struct dmnsn_vector { double x, y, z; } 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 -typedef struct dmnsn_matrix { double n[4][4]; } dmnsn_matrix; +/** A 4x4 affine transformation matrix. */ +typedef struct dmnsn_matrix { + double n[4][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], \ (m).n[3][0], (m).n[3][1], (m).n[3][2], (m).n[3][3] -/* A line, or ray */ +/** 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_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) -/* A bounding box */ -typedef struct dmnsn_bounding_box { dmnsn_vector min, max; } dmnsn_bounding_box; +/** 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 smallest value considered non-zero by some numerical algorithms */ #define dmnsn_epsilon 1.0e-10 +/** The zero vector */ static const dmnsn_vector dmnsn_zero = { 0.0, 0.0, 0.0 }; -static const dmnsn_vector dmnsn_x = { 1.0, 0.0, 0.0 }; -static const dmnsn_vector dmnsn_y = { 0.0, 1.0, 0.0 }; -static const dmnsn_vector dmnsn_z = { 0.0, 0.0, 1.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 }; /* Scalar functions */ +/** Find the minimum of two scalars. */ DMNSN_INLINE double dmnsn_min(double a, double b) { return a < b ? a : b; } +/** Find the maximum of two scalars. */ DMNSN_INLINE double dmnsn_max(double a, double b) { return a > b ? a : b; } +/** 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); } +/** Return the sign bit of a scalar. */ DMNSN_INLINE int dmnsn_signbit(double n) { @@ -105,6 +137,7 @@ dmnsn_signbit(double n) /* Shorthand for vector/matrix construction */ +/** Construct a new vector */ DMNSN_INLINE dmnsn_vector dmnsn_new_vector(double x, double y, double z) { @@ -112,6 +145,7 @@ dmnsn_new_vector(double x, double y, double z) return v; } +/** Construct a new matrix */ DMNSN_INLINE dmnsn_matrix dmnsn_new_matrix(double a0, double a1, double a2, double a3, double b0, double b1, double b2, double b3, @@ -125,12 +159,37 @@ dmnsn_new_matrix(double a0, double a1, double a2, double a3, return m; } +/** 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); -/* Left-handed rotation; theta/|theta| = axis, |theta| = angle */ +/** + * 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); +/** + * 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) { @@ -138,6 +197,7 @@ dmnsn_new_line(dmnsn_vector x0, dmnsn_vector n) return l; } +/** Return the bounding box which contains nothing. */ DMNSN_INLINE dmnsn_bounding_box dmnsn_zero_bounding_box(void) { @@ -148,6 +208,7 @@ dmnsn_zero_bounding_box(void) return box; } +/** Return the bounding box which contains everything. */ DMNSN_INLINE dmnsn_bounding_box dmnsn_infinite_bounding_box(void) { @@ -160,12 +221,20 @@ dmnsn_infinite_bounding_box(void) /* Vector element access */ +/** Constants for indexing a vector like an array. */ enum { - DMNSN_X, - DMNSN_Y, - DMNSN_Z + DMNSN_X, /**< The x component. */ + DMNSN_Y, /**< The y component. */ + DMNSN_Z /**< The z component. */ }; +/** + * Index a vector like an array. + * @param[in] n The vector to index. + * @param[in] elem Which element to access; one of \ref DMNSN_X, \ref DMNSN_Y, + * or \ref DMNSN_Z. + * @return The requested element. + */ DMNSN_INLINE double dmnsn_vector_element(dmnsn_vector n, int elem) { @@ -179,12 +248,13 @@ dmnsn_vector_element(dmnsn_vector n, int elem) default: dmnsn_assert(false, "Wrong vector element requested."); - return 0.0; /* Shut up compiler */ + return 0.0; } } /* Vector and matrix arithmetic */ +/** Negate a vector */ DMNSN_INLINE dmnsn_vector dmnsn_vector_negate(dmnsn_vector rhs) { @@ -193,6 +263,7 @@ dmnsn_vector_negate(dmnsn_vector rhs) return v; } +/** Add two vectors */ DMNSN_INLINE dmnsn_vector dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs) { @@ -201,6 +272,7 @@ dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs) return v; } +/** Subtract two vectors */ DMNSN_INLINE dmnsn_vector dmnsn_vector_sub(dmnsn_vector lhs, dmnsn_vector rhs) { @@ -209,6 +281,7 @@ dmnsn_vector_sub(dmnsn_vector lhs, dmnsn_vector rhs) return v; } +/** Multiply a vector by a scalar. */ DMNSN_INLINE dmnsn_vector dmnsn_vector_mul(double lhs, dmnsn_vector rhs) { @@ -217,6 +290,7 @@ dmnsn_vector_mul(double lhs, dmnsn_vector rhs) return v; } +/** Divide a vector by a scalar. */ DMNSN_INLINE dmnsn_vector dmnsn_vector_div(dmnsn_vector lhs, double rhs) { @@ -225,6 +299,7 @@ dmnsn_vector_div(dmnsn_vector lhs, double rhs) return v; } +/** Return the dot product of two vectors. */ DMNSN_INLINE double dmnsn_vector_dot(dmnsn_vector lhs, dmnsn_vector rhs) { @@ -232,6 +307,7 @@ dmnsn_vector_dot(dmnsn_vector lhs, dmnsn_vector rhs) 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) { @@ -242,6 +318,7 @@ dmnsn_vector_cross(dmnsn_vector lhs, dmnsn_vector rhs) return v; } +/** Return the projection of \p u onto \p d. */ DMNSN_INLINE dmnsn_vector dmnsn_vector_proj(dmnsn_vector u, dmnsn_vector d) { @@ -249,6 +326,7 @@ dmnsn_vector_proj(dmnsn_vector u, dmnsn_vector d) 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) { @@ -256,6 +334,7 @@ dmnsn_vector_norm(dmnsn_vector n) return sqrt(dmnsn_vector_dot(n, n)); } +/** Return the direction of a vector. */ DMNSN_INLINE dmnsn_vector dmnsn_vector_normalize(dmnsn_vector n) { @@ -263,6 +342,7 @@ dmnsn_vector_normalize(dmnsn_vector n) 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) { @@ -273,6 +353,7 @@ dmnsn_vector_min(dmnsn_vector a, dmnsn_vector b) ); } +/** Return the component-wise maximum of two vectors. */ DMNSN_INLINE dmnsn_vector dmnsn_vector_max(dmnsn_vector a, dmnsn_vector b) { @@ -283,54 +364,65 @@ dmnsn_vector_max(dmnsn_vector a, dmnsn_vector b) ); } +/** Return the angle between two vectors with respect to an axis. */ double dmnsn_vector_axis_angle(dmnsn_vector v1, dmnsn_vector v2, dmnsn_vector axis); +/** 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); -/* Affine transformation; lhs*(x,y,z,1), normalized so the fourth element is - 1 */ +/** Transform a vector by a matrix. */ DMNSN_INLINE dmnsn_vector -dmnsn_transform_vector(dmnsn_matrix lhs, dmnsn_vector rhs) +dmnsn_transform_vector(dmnsn_matrix T, dmnsn_vector v) { /* 12 multiplications, 3 divisions, 12 additions */ dmnsn_vector r; double w; - r.x = lhs.n[0][0]*rhs.x + lhs.n[0][1]*rhs.y + lhs.n[0][2]*rhs.z + lhs.n[0][3]; - r.y = lhs.n[1][0]*rhs.x + lhs.n[1][1]*rhs.y + lhs.n[1][2]*rhs.z + lhs.n[1][3]; - r.z = lhs.n[2][0]*rhs.x + lhs.n[2][1]*rhs.y + lhs.n[2][2]*rhs.z + lhs.n[2][3]; - w = lhs.n[3][0]*rhs.x + lhs.n[3][1]*rhs.y + lhs.n[3][2]*rhs.z + lhs.n[3][3]; + 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]; + w = T.n[3][0]*v.x + T.n[3][1]*v.y + T.n[3][2]*v.z + T.n[3][3]; return dmnsn_vector_div(r, w); } -dmnsn_bounding_box dmnsn_transform_bounding_box(dmnsn_matrix lhs, - dmnsn_bounding_box rhs); +/** Transform a bounding box by a matrix. */ +dmnsn_bounding_box dmnsn_transform_bounding_box(dmnsn_matrix T, + dmnsn_bounding_box box); -/* Affine line transformation; n = lhs*(x0 + n) - lhs*x0, x0 *= lhs */ +/** + * 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 lhs, dmnsn_line rhs) +dmnsn_transform_line(dmnsn_matrix T, dmnsn_line l) { /* 24 multiplications, 6 divisions, 30 additions */ - dmnsn_line l; - l.x0 = dmnsn_transform_vector(lhs, rhs.x0); - l.n = dmnsn_vector_sub( - dmnsn_transform_vector(lhs, dmnsn_vector_add(rhs.x0, rhs.n)), - l.x0 + dmnsn_line ret; + ret.x0 = dmnsn_transform_vector(T, l.x0); + ret.n = dmnsn_vector_sub( + dmnsn_transform_vector(T, dmnsn_vector_add(l.x0, l.n)), + ret.x0 ); - return l; + return ret; } -/* A point on a line, defined by x0 + t*n */ +/** + * 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 */ +/** Add epsilon*l.n to l.x0, to avoid self-intersections */ DMNSN_INLINE dmnsn_line dmnsn_line_add_epsilon(dmnsn_line l) { @@ -343,10 +435,7 @@ dmnsn_line_add_epsilon(dmnsn_line l) ); } -/* Solve for the t value such that x0 + t*n = x */ -double dmnsn_line_index(dmnsn_line l, dmnsn_vector x); - -/* Return whether p is within the axis-aligned bounding 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) { @@ -354,7 +443,7 @@ dmnsn_bounding_box_contains(dmnsn_bounding_box box, dmnsn_vector p) && (p.x <= box.max.x && p.y <= box.max.y && p.z <= box.max.z); } -/* Return whether `box' is infinite */ +/** Return whether a bounding box is infinite */ DMNSN_INLINE bool dmnsn_bounding_box_is_infinite(dmnsn_bounding_box box) { diff --git a/libdimension/dimension/gl.h b/libdimension/dimension/gl.h index 3eb292c..25979c4 100644 --- a/libdimension/dimension/gl.h +++ b/libdimension/dimension/gl.h @@ -18,21 +18,36 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Draw a canvas to a GL framebuffer with glDrawPixels, or read one with - * glReadPixels. Should be fast, so no _async() versions. +/** + * @file + * OpenGL export/import of canvases. */ #ifndef DIMENSION_GL_H #define DIMENSION_GL_H -/* Optimize canvas for GL drawing */ +/** + * Optimize a canvas for GL drawing + * @param[in,out] canvas The canvas to optimize. + * @return Whether the canvas was successfully optimized. + */ int dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas); -/* Write canvas to GL framebuffer. Returns 0 on success, nonzero on failure. */ +/** + * Write canvas to GL framebuffer. + * @param[in] canvas The canvas to write. + * @return 0 on success, non-zero on failure. + */ int dmnsn_gl_write_canvas(const dmnsn_canvas *canvas); -/* Read a canvas from a GL framebuffer. Returns NULL on failure. */ +/** + * Read a canvas from a GL framebuffer. + * @param[in] x0 The \a x screen coordinate to start copying from. + * @param[in] y0 The \a y screen coordinate to start copying from. + * @param[in] width The width of the read area. + * @param[in] height The height of the read area. + * @return The allocated canvas, or NULL on failure. + */ dmnsn_canvas *dmnsn_gl_read_canvas(size_t x0, size_t y0, size_t width, size_t height); diff --git a/libdimension/dimension/inline.h b/libdimension/dimension/inline.h index edf92b1..4f12c28 100644 --- a/libdimension/dimension/inline.h +++ b/libdimension/dimension/inline.h @@ -18,16 +18,22 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Handle inlines nicely without cheating and making them static. The - * DMNSN_INLINE macro is set appropriately for the version of C you're using, - * and non-inline versions are emitted in exactly one translation unit when - * necessary. +/** + * @file + * Inline function support. Handle inlines nicely without cheating and making + * them static. The DMNSN_INLINE macro is set appropriately for the version of + * C you're using, and non-inline versions are emitted in exactly one + * translation unit when necessary. */ #ifndef DIMENSION_INLINE_H #define DIMENSION_INLINE_H +/** + * @def DMNSN_INLINE + * A portable inline specifier. Expands to the correct method of declaring + * inline functions for the version of C you are using. + */ #ifndef DMNSN_INLINE #ifdef __cplusplus /* C++ inline semantics */ diff --git a/libdimension/dimension/interior.h b/libdimension/dimension/interior.h index 96168cf..7302426 100644 --- a/libdimension/dimension/interior.h +++ b/libdimension/dimension/interior.h @@ -18,28 +18,37 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* +/** + * @file * Object interiors. */ #ifndef DIMENSION_INTERIOR_H #define DIMENSION_INTERIOR_H +/** An interior */ typedef struct dmnsn_interior { - /* Refractive index */ - double ior; + double ior; /**< Refractive index. */ - /* Callbacks */ - dmnsn_free_fn *free_fn; + dmnsn_free_fn *free_fn; /**< Destructor callback. */ - /* Generic pointer */ + /** Generic pointer. */ void *ptr; - /* Reference count */ + /** @internal Reference count. */ unsigned int *refcount; } dmnsn_interior; +/** + * Create an interior object. + * @return The new interior. + */ dmnsn_interior *dmnsn_new_interior(void); + +/** + * Delete an interior. + * @param[in,out] interior The interior to delete. + */ void dmnsn_delete_interior(dmnsn_interior *interior); #endif /* DIMENSION_INTERIOR_H */ diff --git a/libdimension/dimension/light.h b/libdimension/dimension/light.h index 69ed9e7..dfda157 100644 --- a/libdimension/dimension/light.h +++ b/libdimension/dimension/light.h @@ -18,30 +18,47 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* +/** + * @file * Lights. */ #ifndef DIMENSION_LIGHT_H #define DIMENSION_LIGHT_H +/* Forward-declar dmnsn_light */ typedef struct dmnsn_light dmnsn_light; +/** + * Light callback. + * @param[in] light The light itself. + * @param[in] v The point to illuminate. + * @return The color of the light at \p v. + */ typedef dmnsn_color dmnsn_light_fn(const dmnsn_light *light, dmnsn_vector v); +/** A light. */ struct dmnsn_light { - /* Origin of light rays */ - dmnsn_vector x0; + dmnsn_vector x0; /**< Origin of light rays */ /* Callbacks */ - dmnsn_light_fn *light_fn; - dmnsn_free_fn *free_fn; + dmnsn_light_fn *light_fn; /**< Light callback. */ + dmnsn_free_fn *free_fn; /**< Desctructor callback. */ - /* Generic pointer for light info */ + /** Generic pointer for light info */ void *ptr; }; +/** + * Create a dummy light. + * @return The allocated light. + */ dmnsn_light *dmnsn_new_light(void); + +/** + * Delete a light. + * @param[in,out] light The light to delete. + */ void dmnsn_delete_light(dmnsn_light *light); #endif /* DIMENSION_LIGHT_H */ diff --git a/libdimension/dimension/lights.h b/libdimension/dimension/lights.h index 7b7385e..7c0f140 100644 --- a/libdimension/dimension/lights.h +++ b/libdimension/dimension/lights.h @@ -18,13 +18,20 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Types of lights. +/** + * @file + * Pre-defined light types. */ #ifndef DIMENSION_LIGHTS_H #define DIMENSION_LIGHTS_H +/** + * A point light. + * @param[in] x0 The origin of the light. + * @param[in] color The color of the light. + * @return A point light. + */ dmnsn_light *dmnsn_new_point_light(dmnsn_vector x0, dmnsn_color color); #endif /* DIMENSION_LIGHTS_H */ diff --git a/libdimension/dimension/list.h b/libdimension/dimension/list.h index dba18dc..9046583 100644 --- a/libdimension/dimension/list.h +++ b/libdimension/dimension/list.h @@ -18,8 +18,9 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Simple generalized doubly-linked lists. +/** + * @file + * Simple doubly-linked lists. */ #ifndef DIMENSION_LIST_H @@ -29,14 +30,22 @@ #include <stdlib.h> #include <string.h> +/** + * A list iterator. + */ typedef struct dmnsn_list_iterator { - void *ptr; - size_t obj_size; - struct dmnsn_list_iterator *prev, *next; + void *ptr; /**< @internal The stored object */ + size_t obj_size; /**< @internal The object size */ + struct dmnsn_list_iterator *prev; /**< @internal The previous iterator */ + struct dmnsn_list_iterator *next; /**< @internal The next iterator */ } dmnsn_list_iterator; -/* Internal iterator allocation */ - +/** + * @internal + * Iterator allocation. + * @param[in] obj The location of the object to store in the iterator. + * @param[in] obj_size The size of the object to store in the iterator. + */ DMNSN_INLINE dmnsn_list_iterator * dmnsn_new_list_iterator(const void *obj, size_t obj_size) { @@ -50,6 +59,11 @@ dmnsn_new_list_iterator(const void *obj, size_t obj_size) return i; } +/** + * @internal + * Iterator release. + * @param[in,out] i The iterator to free. + */ DMNSN_INLINE void dmnsn_delete_list_iterator(dmnsn_list_iterator *i) { @@ -59,12 +73,19 @@ dmnsn_delete_list_iterator(dmnsn_list_iterator *i) } } +/** A doubly-linked list. */ typedef struct dmnsn_list { - dmnsn_list_iterator *first, *last; - size_t obj_size, length; + dmnsn_list_iterator *first; /**< @internal The first iterator in the list */ + dmnsn_list_iterator *last; /**< @internal The last iterator in the list */ + size_t length; /**< @internal The size of the list */ + size_t obj_size; /**< @internal The size of list objects */ } dmnsn_list; -/* List allocation */ +/** + * Allocate a list. + * @param[in] obj_size The size of the objects to be stored. + * @return An empty list. + */ DMNSN_INLINE dmnsn_list * dmnsn_new_list(size_t obj_size) { @@ -76,25 +97,53 @@ dmnsn_new_list(size_t obj_size) return list; } -/* Construction to/from arrays */ +/** + * Delete a list. + * @param[in,out] list The list to delete. + */ +void dmnsn_delete_list(dmnsn_list *list); + +/** + * Construct a list from an array. + * @param[in] array The array to copy. + * @return A list with the same contents as \p array. + */ dmnsn_list *dmnsn_list_from_array(const dmnsn_array *array); -dmnsn_array *dmnsn_array_from_list(const dmnsn_list *list); -/* Delete a list */ -void dmnsn_delete_list(dmnsn_list *list); +/** + * Construct an array from a list. + * @param[in] list The list to copy. + * @return An array with the same contents as \p list. + */ +dmnsn_array *dmnsn_array_from_list(const dmnsn_list *list); +/** + * First element. + * @param[in] list The list to index. + * @return An iterator to the first list element, or NULL if the list is empty. + */ DMNSN_INLINE dmnsn_list_iterator * dmnsn_list_first(const dmnsn_list *list) { return list->first; } +/** + * Last element. + * @param[in] list The list to index. + * @return An iterator to the last list element, or NULL if the list is empty. + */ DMNSN_INLINE dmnsn_list_iterator * dmnsn_list_last(const dmnsn_list *list) { return list->last; } +/** + * Previous element. + * @param[in] i The iterator to follow. + * @return The iterator preceding \c i. + */ DMNSN_INLINE dmnsn_list_iterator * dmnsn_list_prev(const dmnsn_list_iterator *i) { @@ -102,6 +151,11 @@ dmnsn_list_prev(const dmnsn_list_iterator *i) return i->prev; } +/** + * Next element. + * @param[in] i The iterator to follow. + * @return The iterator following \c i. + */ DMNSN_INLINE dmnsn_list_iterator * dmnsn_list_next(const dmnsn_list_iterator *i) { @@ -109,13 +163,22 @@ dmnsn_list_next(const dmnsn_list_iterator *i) return i->next; } +/** + * Get the size of the list. + * @param[in] list The list in question. + * @return The number of elements in the list. + */ DMNSN_INLINE size_t dmnsn_list_size(const dmnsn_list *list) { return list->length; } -/* Get the i'th object */ +/** + * Get the i'th object. + * @param[in] i The iterator to dereference. + * @param[out] obj The location to store the object. + */ DMNSN_INLINE void dmnsn_list_get(const dmnsn_list_iterator *i, void *obj) { @@ -123,7 +186,11 @@ dmnsn_list_get(const dmnsn_list_iterator *i, void *obj) memcpy(obj, i->ptr, i->obj_size); } -/* Get a pointer to the i'th object */ +/** + * Get a pointer to the i'th object. + * @param[in] i The iterator to dereference. + * @return A pointer to the object stored at \c i. + */ DMNSN_INLINE void * dmnsn_list_at(const dmnsn_list_iterator *i) { @@ -131,7 +198,11 @@ dmnsn_list_at(const dmnsn_list_iterator *i) return i->ptr; } -/* Set the i'th object, expanding the list if necessary */ +/** + * Set the i'th object. + * @param[in,out] i The iterator to dereference. + * @param[in] obj The object to store at \c i. + */ DMNSN_INLINE void dmnsn_list_set(dmnsn_list_iterator *i, const void *obj) { @@ -139,7 +210,11 @@ dmnsn_list_set(dmnsn_list_iterator *i, const void *obj) memcpy(i->ptr, obj, i->obj_size); } -/* Swap two iterators */ +/** + * Swap the objects in two iterators. + * @param[in,out] a The first iterator. + * @param[in,out] b The second iterator. + */ DMNSN_INLINE void dmnsn_list_swap(dmnsn_list_iterator *a, dmnsn_list_iterator *b) { @@ -148,7 +223,13 @@ dmnsn_list_swap(dmnsn_list_iterator *a, dmnsn_list_iterator *b) b->ptr = temp; } -/* Insert `j' before `i' */ +/** + * Insert a detached iterator into a list. + * @param[in,out] list The list to insert into. + * @param[in,out] i The detached iterator to insert. + * @param[in,out] j The iterator before which to insert, or NULL for the end + * of the list. + */ DMNSN_INLINE void dmnsn_list_iterator_insert(dmnsn_list *list, dmnsn_list_iterator *i, dmnsn_list_iterator *j) @@ -170,7 +251,13 @@ dmnsn_list_iterator_insert(dmnsn_list *list, ++list->length; } -/* Insert an item before `i' (NULL means at the end) */ +/** + * Insert an object. + * @param[in,out] list The list to insert into. + * @param[in,out] i The iterator before which to insert, or NULL for the end + * of the list. + * @param[in] obj The location of the object to insert. + */ DMNSN_INLINE void dmnsn_list_insert(dmnsn_list *list, dmnsn_list_iterator *i, const void *obj) { @@ -178,7 +265,11 @@ dmnsn_list_insert(dmnsn_list *list, dmnsn_list_iterator *i, const void *obj) dmnsn_list_iterator_insert(list, i, j); } -/* Remove the given iterator */ +/** + * Detach an iterator from a list. + * @param[in,out] list The list to remove from. + * @param[in,out] i The iterator to detach. + */ DMNSN_INLINE void dmnsn_list_iterator_remove(dmnsn_list *list, dmnsn_list_iterator *i) { @@ -197,7 +288,11 @@ dmnsn_list_iterator_remove(dmnsn_list *list, dmnsn_list_iterator *i) --list->length; } -/* Remove the specified item */ +/** + * Remove the specified item from a list. + * @param[in,out] list The list to remove from. + * @param[in,out] i The iterator to delete. + */ DMNSN_INLINE void dmnsn_list_remove(dmnsn_list *list, dmnsn_list_iterator *i) { @@ -205,14 +300,22 @@ dmnsn_list_remove(dmnsn_list *list, dmnsn_list_iterator *i) dmnsn_delete_list_iterator(i); } -/* Push obj to the end of the list */ +/** + * Push an object to the end of the list. + * @param[in,out] list The list to append to. + * @param[in] obj The location of the object to push. + */ DMNSN_INLINE void dmnsn_list_push(dmnsn_list *list, const void *obj) { dmnsn_list_insert(list, NULL, obj); } -/* Pop obj from the end of the list */ +/** + * Pop an object from the end of the list. + * @param[in,out] list The list to extract from. + * @param[out] obj The location to store the extracted object. + */ DMNSN_INLINE void dmnsn_list_pop(dmnsn_list *list, void *obj) { @@ -221,11 +324,22 @@ dmnsn_list_pop(dmnsn_list *list, void *obj) dmnsn_list_remove(list, list->last); } -/* Splits a list in half, and returns the second half */ +/** + * Split a list in half, and return the second half. + * @param[in,out] list The list to split. + * @return A the second half of the list. + */ dmnsn_list *dmnsn_list_split(dmnsn_list *list); -/* Sort a list */ + +/** List object comparator function type */ typedef bool dmnsn_list_comparator_fn(dmnsn_list_iterator *l, dmnsn_list_iterator *r); + +/** + * Sort a list, with O(n*log(n)) comparisons. + * @param[in,out] list The list to sort. + * @param[in] comparator The comparator to use for comparisons. + */ void dmnsn_list_sort(dmnsn_list *list, dmnsn_list_comparator_fn *comparator); #endif /* DIMENSION_LIST_H */ diff --git a/libdimension/dimension/malloc.h b/libdimension/dimension/malloc.h index 3c9e84b..7a5295a 100644 --- a/libdimension/dimension/malloc.h +++ b/libdimension/dimension/malloc.h @@ -18,15 +18,41 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Seriously, how often does malloc fail? And how often can you do something - * better than bail out when it does? dmnsn_malloc() is like malloc in every - * way except it calls dmnsn_error() on failure. +/** + * @file + * Dynamic memory. dmnsn_malloc() and friends behave like their + * non-dmnsn_-prefixed counterparts, but never return NULL. If allocation + * fails, they instead call dmnsn_error(DMNSN_SEVERITY_HIGH). */ #include <stddef.h> /* For size_t */ +/** + * Allocate some memory. Always use dmnsn_free() to free this memory, never + * free(). + * @param[in] size The size of the memory block to allocate. + * @return The allocated memory area. + */ void *dmnsn_malloc(size_t size); + +/** + * Expand or shrink an allocation created by dmnsn_malloc(). + * @param[in] ptr The block to resize. + * @param[in] size The new size. + * @return The resized memory area. + */ void *dmnsn_realloc(void *ptr, size_t size); + +/** + * Duplicate a string. + * @param[in] s The string to duplicate. + * @return A string with the same contents as \p s, suitable for release by + * dmnsn_free(). + */ char *dmnsn_strdup(const char *s); -void dmnsn_free(void *ptr); + +/** + * Free memory allocated by dmnsn_malloc() or dmnsn_strdup(). + * @param[in] ptr The memory block to free, or NULL. + */ +void dmnsn_free(void *ptr); diff --git a/libdimension/dimension/object.h b/libdimension/dimension/object.h index 56cfacd..28682a2 100644 --- a/libdimension/dimension/object.h +++ b/libdimension/dimension/object.h @@ -18,7 +18,8 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* +/** + * @file * Objects. */ @@ -27,70 +28,104 @@ #include <stdbool.h> -/* A type to represent a ray-object intersection */ +/** A type to represent a ray-object intersection. */ typedef struct dmnsn_intersection { - /* The ray and point which intersected */ - dmnsn_line ray; - double t; + dmnsn_line ray; /**< The ray that intersected. */ + double t; /**< The line index that intersected */ - /* The surface normal at the intersection point */ - dmnsn_vector normal; + dmnsn_vector normal; /**< The surface normal at the intersection point */ - /* The object properties at the intersection point */ - const dmnsn_texture *texture; - const dmnsn_interior *interior; + const dmnsn_texture *texture; /**< The texture at the intersection point */ + const dmnsn_interior *interior; /**< The interior at the intersection point */ } dmnsn_intersection; /* Forward-declare dmnsn_object */ typedef struct dmnsn_object dmnsn_object; -/* Object callback types */ - +/** + * Object initialization callback. + * @param[in,out] object The object to initialize. + */ typedef void dmnsn_object_init_fn(dmnsn_object *object); + +/** + * Ray-object intersection callback. + * @param[in] object The object to test. + * @param[in] line The line to test. + * @param[out] intersection Where to store the intersection details of the + * closest (if any) intersection. + * @return Whether \p line intersected \p object. + */ typedef bool dmnsn_object_intersection_fn(const dmnsn_object *object, dmnsn_line line, dmnsn_intersection *intersection); + +/** + * Object inside callback. + * @param[in] object The object to test. + * @param[in] point The point to test. + * @return Whether \p point is inside \p object. + */ typedef bool dmnsn_object_inside_fn(const dmnsn_object *object, dmnsn_vector point); -/* dmnsn_object definition */ +/** An object. */ struct dmnsn_object { - /* Surface properties */ - dmnsn_texture *texture; - - /* Interior properties */ - dmnsn_interior *interior; + dmnsn_texture *texture; /**< Surface properties */ + dmnsn_interior *interior; /**< Interior properties */ - /* Transformation matrix */ - dmnsn_matrix trans, trans_inv; + dmnsn_matrix trans; /**< Transformation matrix */ + dmnsn_matrix trans_inv; /**< Inverse of the transformation matrix */ - /* Bounding box */ - dmnsn_bounding_box bounding_box; + dmnsn_bounding_box bounding_box; /**< Object bounding box */ - /* Child objects */ + /** Child objects. This array lists objects that can be split into + sub-objects for bounding purposes (for unions and meshes, for example). */ dmnsn_array *children; - /* Callback functions */ - dmnsn_object_init_fn *init_fn; - dmnsn_object_intersection_fn *intersection_fn; - dmnsn_object_inside_fn *inside_fn; - dmnsn_free_fn *free_fn; + dmnsn_object_init_fn *init_fn; /**< Initialization callback. */ + dmnsn_object_intersection_fn *intersection_fn; /**< Intersection callback. */ + dmnsn_object_inside_fn *inside_fn; /**< Inside callback. */ + dmnsn_free_fn *free_fn; /**< Destruction callback. */ - /* Generic pointer for object info */ + /** Generic pointer for object info */ void *ptr; }; -/* Allocate a dummy object */ +/** + * Allocate a dummy object. + * @return The allocated object. + */ dmnsn_object *dmnsn_new_object(void); -/* Free an object */ + +/** + * Free an object + * @param[in,out] object The object to destroy. + */ void dmnsn_delete_object(dmnsn_object *object); -/* Initialize an object and potentially its children */ +/** + * Initialize an object and potentially its children. + * @param[in,out] object The object to initialize. + */ void dmnsn_object_init(dmnsn_object *object); -/* Helpers for invoking object callbacks with correct transformations */ +/** + * Appropriately transform a ray, then test for an intersection. + * @param[in] object The object to test. + * @param[in] line The ray to test. + * @param[out] intersection Where to store the intersection details. + * @return Whether there was an intersection. + */ bool dmnsn_object_intersection(const dmnsn_object *object, dmnsn_line line, dmnsn_intersection *intersection); + +/** + * Appropriately transform a point, then test for containment. + * @param[in] object The object to test. + * @param[in] point The point to test. + * @return Whether \p point was inside \p object. + */ bool dmnsn_object_inside(const dmnsn_object *object, dmnsn_vector point); #endif /* DIMENSION_OBJECT_H */ diff --git a/libdimension/dimension/objects.h b/libdimension/dimension/objects.h index 41706a0..a98541b 100644 --- a/libdimension/dimension/objects.h +++ b/libdimension/dimension/objects.h @@ -18,8 +18,9 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Custom objects. +/** + * @file + * Pre-defined objects. */ #ifndef DIMENSION_OBJECTS_H @@ -27,19 +28,40 @@ #include <stdbool.h> -/* A plane through the origin, with the given normal */ +/** + * A plane. + * @param[in] normal The normal vector of the plane. + * @return A plane through the origin, with the given normal. + */ dmnsn_object *dmnsn_new_plane(dmnsn_vector normal); -/* A sphere object, of radius 1, centered at the origin. */ +/** + * A sphere. + * @return A sphere of radius 1, centered at the origin. + */ dmnsn_object *dmnsn_new_sphere(void); -/* A cube, axis-aligned, from (-1, -1, -1) to (1, 1, 1) */ +/** + * A cube. + * @return An axis-aligned cube, from (-1, -1, -1) to (1, 1, 1). + */ dmnsn_object *dmnsn_new_cube(void); -/* A cylinder/cone, from r = r1 at y = -1, to r = r2 at y = 1 */ -dmnsn_object *dmnsn_new_cylinder(double r1, double r2, bool open); +/** + * A cylinder/cone. + * @param[in] r1 The bottom radius. + * @param[in] r2 The top radius. + * @param[in] open Whether to render caps. + * @return A cone slice, from r = \p r1 at y = -1, to r = \p r2 at y = 1 + */ +dmnsn_object *dmnsn_new_cone(double r1, double r2, bool open); -/* A torus, centered at the origin and lying in the x-z plane */ +/** + * A torus. + * @param[in] major The major radius. + * @param[in] minor The minor radius. + * @return A torus, centered at the origin and lying in the x-z plane. + */ dmnsn_object *dmnsn_new_torus(double major, double minor); #endif /* DIMENSION_OBJECTS_H */ diff --git a/libdimension/dimension/pattern.h b/libdimension/dimension/pattern.h index 6301372..9636155 100644 --- a/libdimension/dimension/pattern.h +++ b/libdimension/dimension/pattern.h @@ -18,8 +18,10 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Patterns +/** + * @file + * Patterns. Patterns are functions which map vectors to scalars, which are + * used for pigments and normals. */ #ifndef DIMENSION_PATTERN_H @@ -28,28 +30,52 @@ /* Forward-declare dmnsn_pattern */ typedef struct dmnsn_pattern dmnsn_pattern; -/* Pattern callback */ +/** + * 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); -/* Generic pattern */ +/** A pattern. */ struct dmnsn_pattern { - /* Callbacks */ - dmnsn_pattern_fn *pattern_fn; - dmnsn_free_fn *free_fn; + dmnsn_pattern_fn *pattern_fn; /**< The pattern callback. */ + dmnsn_free_fn *free_fn; /**< The destructor callback. */ - /* Transformation matrix */ - dmnsn_matrix trans, trans_inv; + dmnsn_matrix trans; /**< The transformation matrix of the pattern */ + dmnsn_matrix trans_inv; /**< The inverse of the transformation matrix */ - /* Generic pointer */ - void *ptr; + void *ptr; /**< Generic pointer */ }; +/** + * Allocate an dummy pattern. + * @return A pattern with no callbacks set. + */ dmnsn_pattern *dmnsn_new_pattern(void); + +/** + * Delete a pattern. + * @param[in,out] pattern The pattern to destroy. + */ void dmnsn_delete_pattern(dmnsn_pattern *pattern); +/** + * Initialize a pattern. This precomputes some values that are used during + * ray-tracing; the pattern will not work until it has been initialized, but + * should not be modified after it has been initialized. Patterns are generally + * initialized for you. + * @param[in,out] pattern The pattern to initialize. + */ void dmnsn_pattern_init(dmnsn_pattern *pattern); -/* Invoke the pattern callback with the right transformation */ +/** + * Invoke the pattern callback with the right transformation. + * @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 /* DIMENSION_PATTERN_H */ diff --git a/libdimension/dimension/patterns.h b/libdimension/dimension/patterns.h index cd4aa35..5dd44bf 100644 --- a/libdimension/dimension/patterns.h +++ b/libdimension/dimension/patterns.h @@ -18,14 +18,27 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Custom patterns +/** + * @file + * Pre-defined patterns. */ #ifndef DIMENSION_PATTERNS_H #define DIMENSION_PATTERNS_H -dmnsn_pattern *dmnsn_new_checker_pattern(); +/** + * A checker pattern. The pattern is composed of tesselating unit cubes + * alternating between 0 and 1. + * @return A checker pattern. + */ +dmnsn_pattern *dmnsn_new_checker_pattern(void); + +/** + * A gradient. The value starts at 0 at the origin, and goes linearly to 1 in + * the direction of \p orientation, then repeats after a distance of 1. + * @param[in] orientation The direction of the gradient. + * @return A gradient pattern. + */ dmnsn_pattern *dmnsn_new_gradient_pattern(dmnsn_vector orientation); #endif /* DIMENSION_PATTERNS_H */ diff --git a/libdimension/dimension/pigments.h b/libdimension/dimension/pigments.h index 31c0598..68a9c66 100644 --- a/libdimension/dimension/pigments.h +++ b/libdimension/dimension/pigments.h @@ -18,28 +18,67 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Custom pigments. +/** + * @file + * Pre-defined pigments. */ #ifndef DIMENSION_PIGMENTS_H #define DIMENSION_PIGMENTS_H -/* A solid color */ +/** + * A solid color. + * @param[in] color The color of the pigment. + * @return A pigment with the color \p color everywhere. + */ dmnsn_pigment *dmnsn_new_solid_pigment(dmnsn_color color); -/* An image map */ + +/** + * An image map. The image (regardless of its real dimensions) is projected + * on the x-y plane in tesselating unit squares. + * @param[in] canvas The canvas holding the image. + * @return An image-mapped pigment. + */ dmnsn_pigment *dmnsn_new_canvas_pigment(dmnsn_canvas *canvas); -/* Color maps */ +/** Color map. */ typedef dmnsn_array dmnsn_color_map; -dmnsn_color_map *dmnsn_new_color_map(); +/** + * Create an empty color map. + * @return A color map with no entries. + */ +dmnsn_color_map *dmnsn_new_color_map(void); + +/** + * Delete a color map. + * @param[in,out] map The color map to delete. + */ void dmnsn_delete_color_map(dmnsn_color_map *map); +/** + * Add an entry (a scalar-color pair) to a color map. + * @param[in,out] map The color map to add to. + * @param[in] n The index of the entry. + * @param[in] c The value of the entry. + */ void dmnsn_add_color_map_entry(dmnsn_color_map *map, double n, dmnsn_color c); + +/** + * Evaluate a color map. + * @param[in] map The map to evaluate. + * @param[in] n The index to evaluate. + * @return The value of the gradient between the the two indicies closest to + * \p n. + */ dmnsn_color dmnsn_color_map_value(const dmnsn_color_map *map, double n); -/* Color-mapped pigments */ +/** + * A color-mapped pigment. + * @param[in,out] pattern The pattern of the pigment. + * @param[in,out] map The color map to apply to the pattern. + * @return A pigment mapping the pattern to color values. + */ dmnsn_pigment *dmnsn_new_color_map_pigment(dmnsn_pattern *pattern, dmnsn_color_map *map); diff --git a/libdimension/dimension/png.h b/libdimension/dimension/png.h index cf21116..296331a 100644 --- a/libdimension/dimension/png.h +++ b/libdimension/dimension/png.h @@ -18,8 +18,9 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Support for exporting/importing canvases to/from PNG files +/** + * @file + * PNG import/export of canvases */ #ifndef DIMENSION_PNG_H @@ -27,17 +28,46 @@ #include <stdio.h> -/* Optimize canvas for PNG exporting */ +/** + * Optimize a canvas for PNG exporting + * @param[in,out] canvas The canvas to optimize. + * @return Whether the canvas was successfully optimized. + */ int dmnsn_png_optimize_canvas(dmnsn_canvas *canvas); -/* Write canvas to file in PNG format. Returns 0 on success, nonzero on - failure */ +/** + * Write a canvas to a file in PNG format. + * @param[in] canvas The canvas to write. + * @param[in,out] file The file to write to. + * @return 0 on success, non-zero on failure. + */ int dmnsn_png_write_canvas(const dmnsn_canvas *canvas, FILE *file); + +/** + * Write a canvas to a PNG file in the background. + * @param[in] canvas The canvas to write. + * @param[in,out] file The file to write to. + * @return A \ref dmnsn_progress object, or NULL on failure. + */ dmnsn_progress *dmnsn_png_write_canvas_async(const dmnsn_canvas *canvas, FILE *file); -/* Read a canvas from a PNG file. Returns NULL on failure. */ +/** + * Read a canvas from a PNG file. + * @param[in,out] file The PNG file to read. + * @return The new canvas, or NULL on failure. + */ dmnsn_canvas *dmnsn_png_read_canvas(FILE *file); + +/** + * Read a canvas from a PNG file in the background. + * @param[out] canvas The address of a non-allocated canvas object. The + * canvas object will be allocated and filled with the + * contents of \p file. Do not read from this object + * until the background task has finished. + * @param[in,out] file The PNG file to read. + * @return A \ref dmnsn_progress object, or NULL on failure. + */ dmnsn_progress *dmnsn_png_read_canvas_async(dmnsn_canvas **canvas, FILE *file); #endif /* DIMENSION_PNG_H */ diff --git a/libdimension/dimension/polynomial.h b/libdimension/dimension/polynomial.h index 56e3ac0..b0a9357 100644 --- a/libdimension/dimension/polynomial.h +++ b/libdimension/dimension/polynomial.h @@ -18,7 +18,8 @@ * <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. @@ -30,6 +31,14 @@ #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_evaluate_polynomial(const double poly[], size_t degree, double x) { @@ -41,6 +50,12 @@ dmnsn_evaluate_polynomial(const double poly[], size_t degree, double x) 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_evaluate_polynomial_derivative(const double poly[], size_t degree, double x) @@ -53,11 +68,23 @@ dmnsn_evaluate_polynomial_derivative(const double poly[], size_t degree, return ret; } -/* Stores the positive roots of poly[] in x[], and returns the number of such - roots that were stored */ +/** + * 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_solve_polynomial(const double poly[], size_t degree, double x[]); -/* Helper function to print a polynomial */ +/** + * 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_print_polynomial(FILE *file, const double poly[], size_t degree); #endif /* DIMENSION_POLYNOMIAL_H */ diff --git a/libdimension/dimension/progress.h b/libdimension/dimension/progress.h index 043f014..89d0d25 100644 --- a/libdimension/dimension/progress.h +++ b/libdimension/dimension/progress.h @@ -18,7 +18,8 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* +/** + * @file * An interface for asynchronous tasks. *_async() versions of functions * return a dmnsn_progress* object which can indicate the progress of the * background task, and wait for task completion. The task's return value @@ -28,15 +29,30 @@ #ifndef DIMENSION_PROGRESS_H #define DIMENSION_PROGRESS_H +/** A progress object */ typedef struct dmnsn_progress dmnsn_progress; -/* Join the worker thread and return it's integer return value in addition to - deleting `progress' */ +/** + * Join the worker thread and return it's integer return value in addition to + * deleting \p progress. + * @param[in,out] progress The background task to finish. + * @return The return value of the background task. + */ int dmnsn_finish_progress(dmnsn_progress *progress); -/* Get the progress of the background task, out of 1.0 */ +/** + * Get the progress of the background task. + * @param[in] progress The background task to examine. + * @return The progress of the background task, out of 1.0. + */ double dmnsn_get_progress(const dmnsn_progress *progress); -/* Wait for the progress to be >= prog, in a better way than spinlocking */ + +/** + * Wait for a certain amount of progress. Always use this rather than + * spinlocking. + * @param[in] progress The background task to monitor. + * @param[in] prog The progress value to wait for. + */ void dmnsn_wait_progress(const dmnsn_progress *progress, double prog); #endif /* DIMENSION_PROGRESS_H */ diff --git a/libdimension/dimension/raytrace.h b/libdimension/dimension/raytrace.h index f145d5f..2fee879 100644 --- a/libdimension/dimension/raytrace.h +++ b/libdimension/dimension/raytrace.h @@ -18,15 +18,25 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * Render a scene by raytracing +/** + * @file + * Ray-trace a scene. */ #ifndef DIMENSION_RAYTRACE_H #define DIMENSION_RAYTRACE_H -/* Render a scene by raytracing */ +/** + * Render a scene by raytracing. + * @param[in,out] scene The scene to render. + */ void dmnsn_raytrace_scene(dmnsn_scene *scene); + +/** + * Render a scene in the background. + * @param[in,out] scene The scene to render. + * @return A \p dmnsn_progress object. + */ dmnsn_progress *dmnsn_raytrace_scene_async(dmnsn_scene *scene); #endif /* DIMENSION_RAYTRACE_H */ diff --git a/libdimension/dimension/scene.h b/libdimension/dimension/scene.h index 7e52859..36fe74e 100644 --- a/libdimension/dimension/scene.h +++ b/libdimension/dimension/scene.h @@ -18,60 +18,70 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * A scene. +/** + * @file + * Entire scenes. */ #ifndef DIMENSION_SCENE_H #define DIMENSION_SCENE_H -#include <stdbool.h> - +/** Render quality flags. */ enum { - DMNSN_RENDER_NONE = 0, - DMNSN_RENDER_PIGMENT = 1 << 0, - DMNSN_RENDER_LIGHTS = 1 << 1, - DMNSN_RENDER_FINISH = 1 << 2, - DMNSN_RENDER_TRANSLUCENCY = 1 << 3, - DMNSN_RENDER_REFLECTION = 1 << 4, - DMNSN_RENDER_FULL = ~DMNSN_RENDER_NONE + DMNSN_RENDER_NONE = 0, /**< Render nothing. */ + DMNSN_RENDER_PIGMENT = 1 << 0, /**< Render pigments. */ + DMNSN_RENDER_LIGHTS = 1 << 1, /**< Render lights and shadows. */ + DMNSN_RENDER_FINISH = 1 << 2, /**< Render object finishes. */ + DMNSN_RENDER_TRANSLUCENCY = 1 << 3, /**< Render translucency/refraction. */ + DMNSN_RENDER_REFLECTION = 1 << 4, /**< Render specular reflection. */ + DMNSN_RENDER_FULL = ~DMNSN_RENDER_NONE /**< Render everything. */ }; +/** Render quality. */ typedef unsigned int dmnsn_quality; -typedef struct { +/** An entire scene. */ +typedef struct dmnsn_scene { /* World attributes */ - dmnsn_color background; - dmnsn_texture *default_texture; + dmnsn_color background; /**< Background color. */ + dmnsn_texture *default_texture; /**< Default object texture. */ - /* Camera */ + /** Camera. */ dmnsn_camera *camera; - /* Canvas */ + /** Canvas. */ dmnsn_canvas *canvas; - /* Objects */ + /** Objects. */ dmnsn_array *objects; - /* Lights */ + /** Lights. */ dmnsn_array *lights; - /* Rendering quality */ + /** Render quality. */ dmnsn_quality quality; - /* Recursion limit */ + /** Recursion limit. */ unsigned int reclimit; - /* Number of parallel threads */ + /** Number of parallel threads. */ unsigned int nthreads; - /* Timers */ + /** Timers */ dmnsn_timer *bounding_timer; dmnsn_timer *render_timer; } dmnsn_scene; -/* Create a scene */ +/** + * Create a scene. + * @return A new empty scene. + */ dmnsn_scene *dmnsn_new_scene(void); + +/** + * Delete a scene. + * @param[in,out] scene The scene to delete. + */ void dmnsn_delete_scene(dmnsn_scene *scene); #endif /* DIMENSION_SCENE_H */ diff --git a/libdimension/dimension/texture.h b/libdimension/dimension/texture.h index 5586e24..f582351 100644 --- a/libdimension/dimension/texture.h +++ b/libdimension/dimension/texture.h @@ -18,7 +18,8 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* +/** + * @file * Object textures. */ @@ -32,31 +33,55 @@ /* Forward-declare dmnsn_pigment */ typedef struct dmnsn_pigment dmnsn_pigment; -/* Pigment callbacks */ +/** + * Pigment callback. + * @param[in] pigment The pigment itself. + * @param[in] v The point to color. + * @return The color of the pigment at \p v. + */ typedef dmnsn_color dmnsn_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v); + +/** + * Pigment initializer callback. + * @param[in,out] pigment The pigment to initialize. + */ typedef void dmnsn_pigment_init_fn(dmnsn_pigment *pigment); -/* dmnsn_pigment definition */ +/** A pigment */ struct dmnsn_pigment { - /* Callbacks */ - dmnsn_pigment_fn *pigment_fn; - dmnsn_pigment_init_fn *init_fn; - dmnsn_free_fn *free_fn; + dmnsn_pigment_fn *pigment_fn; /**< The pigment callback. */ + dmnsn_pigment_init_fn *init_fn; /**< The initializer callback. */ + dmnsn_free_fn *free_fn; /**< The destructor callback. */ - /* Transformation matrix */ - dmnsn_matrix trans, trans_inv; + dmnsn_matrix trans; /**< Transformation matrix. */ + dmnsn_matrix trans_inv; /**< The inverse of the transformation matrix. */ - /* Quick color */ + /** Quick color -- used for low-quality renders. */ dmnsn_color quick_color; - /* Generic pointer */ + /** Generic pointer */ void *ptr; }; +/** + * Allocate a new dummy pigment. + * @return The allocated pigment. + */ dmnsn_pigment *dmnsn_new_pigment(void); + +/** + * Delete a pigment. + * @param[in,out] pigment The pigment to delete. + */ void dmnsn_delete_pigment(dmnsn_pigment *pigment); +/** + * Initialize a pigment. Pigments should not be used before being initialized, + * but should not be modified after being initialized. Pigments are generally + * initialized for you. + * @param[in,out] pigment The pigment to initialize. + */ void dmnsn_pigment_init(dmnsn_pigment *pigment); /* @@ -66,56 +91,111 @@ void dmnsn_pigment_init(dmnsn_pigment *pigment); /* Forward-declare dmnsn_finish */ typedef struct dmnsn_finish dmnsn_finish; -/* Finish callbacks */ +/** + * Diffuse reflection callback. + * @param[in] finish The finish itself. + * @param[in] light The color of the light illuminating the object. + * @param[in] color The pigment of the object. + * @param[in] ray The direction of the light source. + * @param[in] normal The normal vector of the surface. + * @return The diffuse reflection component of the object's color. + */ typedef dmnsn_color dmnsn_diffuse_fn(const dmnsn_finish *finish, dmnsn_color light, dmnsn_color color, dmnsn_vector ray, dmnsn_vector normal); +/** + * Specular highlight callback. + * @param[in] finish The finish itself. + * @param[in] light The color of the light illuminating the object. + * @param[in] color The pigment of the object. + * @param[in] ray The direction of the light source. + * @param[in] normal The normal vector of the surface. + * @param[in] viewer The direction of the viewer. + * @return The specular reflection component of the object's color. + */ typedef dmnsn_color dmnsn_specular_fn(const dmnsn_finish *finish, dmnsn_color light, dmnsn_color color, dmnsn_vector ray, dmnsn_vector normal, dmnsn_vector viewer); +/** + * Ambient light callback. + * @param[in] finish The finish itself. + * @param[in] pigment The pigment of the object. + * @return The ambient contribution to the object's color. + */ typedef dmnsn_color dmnsn_ambient_fn(const dmnsn_finish *finish, dmnsn_color pigment); +/** + * Reflected light callback. + * @param[in] finish The finish itself. + * @param[in] reflect The color of the reflected ray. + * @param[in] color The pigment of the object. + * @param[in] ray The direction of the reflected ray. + * @param[in] normal The normal vector of the surface. + * @return The contribution of the reflected ray to the object's color. + */ typedef dmnsn_color dmnsn_reflection_fn(const dmnsn_finish *finish, dmnsn_color reflect, dmnsn_color color, dmnsn_vector ray, dmnsn_vector normal); -/* dmnsn_finish definition */ +/** A finish. */ struct dmnsn_finish { - /* Callbacks */ - dmnsn_diffuse_fn *diffuse_fn; - dmnsn_specular_fn *specular_fn; - dmnsn_ambient_fn *ambient_fn; - dmnsn_reflection_fn *reflection_fn; - dmnsn_free_fn *free_fn; - - /* Generic pointer */ + dmnsn_diffuse_fn *diffuse_fn; /**< The diffuse callback. */ + dmnsn_specular_fn *specular_fn; /**< The specular callback. */ + dmnsn_ambient_fn *ambient_fn; /**< The ambient callback. */ + dmnsn_reflection_fn *reflection_fn; /**< The reflection callback. */ + dmnsn_free_fn *free_fn; /**< The destruction callback. */ + + /** Generic pointer */ void *ptr; }; +/** + * Allocate a new dummy finish. + * @return The allocated finish. + */ dmnsn_finish *dmnsn_new_finish(void); + +/** + * Delete a finish. + * @param[in,out] finish The finish to delete. + */ void dmnsn_delete_finish(dmnsn_finish *finish); /* - * A complete texture + * Textures */ +/** A complete texture. */ typedef struct { - /* Texture components */ - dmnsn_pigment *pigment; - dmnsn_finish *finish; + dmnsn_pigment *pigment; /**< Pigment. */ + dmnsn_finish *finish; /**< Finish. */ - /* Transformation matrix */ - dmnsn_matrix trans, trans_inv; + dmnsn_matrix trans; /**< Transformation matrix. */ + dmnsn_matrix trans_inv; /**< The inverse of the transformation matrix. */ - /* Reference count */ - unsigned int *refcount; - bool should_init; + unsigned int *refcount; /**< @internal Reference count. */ + bool should_init; /**< @internal Whether to init the texture. */ } dmnsn_texture; +/** + * Create a blank texture. + * @return The new texture. + */ dmnsn_texture *dmnsn_new_texture(void); + +/** + * Delete a texture. + * @param[in,out] texture The texture to delete. + */ void dmnsn_delete_texture(dmnsn_texture *texture); +/** + * Initialize a texture. Textures should not be used before being initialized, + * but should not be modified after being initialized. Textures are generally + * initialized for you. + * @param[in,out] texture The texture to initialize. + */ void dmnsn_texture_init(dmnsn_texture *texture); #endif /* DIMENSION_TEXTURE_H */ diff --git a/libdimension/dimension/timer.h b/libdimension/dimension/timer.h index 0f3c61f..9e935c2 100644 --- a/libdimension/dimension/timer.h +++ b/libdimension/dimension/timer.h @@ -18,17 +18,43 @@ * <http://www.gnu.org/licenses/>. * *************************************************************************/ -/* - * A platform-agnostic timer abstraction +/** + * @file + * A platform-agnostic timer abstraction. */ +/** A platform-agnotic timer. */ typedef struct dmnsn_timer { - double real, user, system; + double real; /**< Wall-clock time. */ + double user; /**< Time spent executing. */ + double system; /**< Time spent waiting for the system. */ } dmnsn_timer; +/** A standard format string for timers. */ #define DMNSN_TIMER_FORMAT "%.2fs (user: %.2fs; system: %.2fs)" +/** + * The appropriate arguments to printf() a timer. For example: + * @code + * printf(DMNSN_TIMER_FORMAT "\n", DMNSN_TIMER_PRINTF(timer)); + * @endcode + * will print something like "1.00s (user: 0.99s; system: 0.01s)". + */ #define DMNSN_TIMER_PRINTF(t) (t)->real, (t)->user, (t)->system +/** + * Create a new timer. Timing starts right before this function returns. + * @return A new timer object. + */ dmnsn_timer *dmnsn_new_timer(void); + +/** + * Finish timing. The members of the timer struct will now contain timing data. + * @param[in,out] timer The timer to stop. + */ void dmnsn_complete_timer(dmnsn_timer *timer); + +/** + * Delete a timer. + * @param[in,out] timer The timer to delete. + */ void dmnsn_delete_timer(dmnsn_timer *timer); |