summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore24
-rw-r--r--Makefile.am7
-rw-r--r--README12
-rw-r--r--bench/libdimension/geometry.c6
-rw-r--r--configure.ac1
-rw-r--r--dimension/realize.c31
-rw-r--r--doc/Makefile.am4
-rw-r--r--doc/libdimension.texi1032
-rw-r--r--libdimension/Doxyfile.in43
-rw-r--r--libdimension/Makefile.am14
-rw-r--r--libdimension/ambient.c10
-rw-r--r--libdimension/camera.c14
-rw-r--r--libdimension/canvas.c22
-rw-r--r--libdimension/canvas_pigment.c41
-rw-r--r--libdimension/checker.c12
-rw-r--r--libdimension/color.c53
-rw-r--r--libdimension/color_map.c16
-rw-r--r--libdimension/cone.c (renamed from libdimension/cylinder.c)84
-rw-r--r--libdimension/csg.c55
-rw-r--r--libdimension/cube.c44
-rw-r--r--libdimension/diffuse.c10
-rw-r--r--libdimension/dimension-impl.h6
-rw-r--r--libdimension/dimension.h23
-rw-r--r--libdimension/dimension/array.h117
-rw-r--r--libdimension/dimension/camera.h40
-rw-r--r--libdimension/dimension/cameras.h19
-rw-r--r--libdimension/dimension/canvas.h79
-rw-r--r--libdimension/dimension/color.h98
-rw-r--r--libdimension/dimension/csg.h31
-rw-r--r--libdimension/dimension/error.h79
-rw-r--r--libdimension/dimension/finishes.h38
-rw-r--r--libdimension/dimension/geometry.h171
-rw-r--r--libdimension/dimension/gl.h27
-rw-r--r--libdimension/dimension/inline.h16
-rw-r--r--libdimension/dimension/interior.h23
-rw-r--r--libdimension/dimension/light.h29
-rw-r--r--libdimension/dimension/lights.h11
-rw-r--r--libdimension/dimension/list.h166
-rw-r--r--libdimension/dimension/malloc.h36
-rw-r--r--libdimension/dimension/object.h101
-rw-r--r--libdimension/dimension/objects.h38
-rw-r--r--libdimension/dimension/pattern.h50
-rw-r--r--libdimension/dimension/patterns.h19
-rw-r--r--libdimension/dimension/pigments.h53
-rw-r--r--libdimension/dimension/png.h42
-rw-r--r--libdimension/dimension/polynomial.h35
-rw-r--r--libdimension/dimension/progress.h26
-rw-r--r--libdimension/dimension/raytrace.h16
-rw-r--r--libdimension/dimension/scene.h56
-rw-r--r--libdimension/dimension/texture.h140
-rw-r--r--libdimension/dimension/timer.h32
-rw-r--r--libdimension/error.c13
-rw-r--r--libdimension/finish_combination.c14
-rw-r--r--libdimension/geometry.c46
-rw-r--r--libdimension/gl-stubs.c7
-rw-r--r--libdimension/gl.c21
-rw-r--r--libdimension/gradient.c10
-rw-r--r--libdimension/inline.c5
-rw-r--r--libdimension/interior.c5
-rw-r--r--libdimension/light.c5
-rw-r--r--libdimension/list.c5
-rw-r--r--libdimension/malloc.c5
-rw-r--r--libdimension/object.c5
-rw-r--r--libdimension/pattern.c5
-rw-r--r--libdimension/perspective.c62
-rw-r--r--libdimension/phong.c10
-rw-r--r--libdimension/plane.c9
-rw-r--r--libdimension/platform.c10
-rw-r--r--libdimension/platform.h11
-rw-r--r--libdimension/png-stubs.c7
-rw-r--r--libdimension/png.c38
-rw-r--r--libdimension/point_light.c10
-rw-r--r--libdimension/polynomial.c35
-rw-r--r--libdimension/progress-impl.h14
-rw-r--r--libdimension/progress.c18
-rw-r--r--libdimension/prtree.c45
-rw-r--r--libdimension/prtree.h17
-rw-r--r--libdimension/raytrace.c55
-rw-r--r--libdimension/reflective.c11
-rw-r--r--libdimension/scene.c5
-rw-r--r--libdimension/solid_pigment.c23
-rw-r--r--libdimension/sphere.c44
-rw-r--r--libdimension/texture.c5
-rw-r--r--libdimension/threads.c14
-rw-r--r--libdimension/threads.h23
-rw-r--r--libdimension/timer.c6
-rw-r--r--libdimension/torus.c66
-rw-r--r--tests/libdimension/render.c8
-rw-r--r--tests/libdimension/tests.c2
89 files changed, 1983 insertions, 1863 deletions
diff --git a/.gitignore b/.gitignore
index 7acf53d..afdc526 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,28 +15,8 @@ Makefile
Makefile.in
# Documentation files created by make
-/doc/*.aux
-/doc/*.cp
-/doc/*.cps
-/doc/*.dvi
-/doc/*.fn
-/doc/*.fns
-/doc/*.html/
-/doc/*.info
-/doc/*.ky
-/doc/*.kys
-/doc/*.log
-/doc/*.pdf
-/doc/*.pg
-/doc/*.pgs
-/doc/*.ps
-/doc/*.tmp
-/doc/*.toc
-/doc/*.tp
-/doc/*.tps
-/doc/*.vr
-/doc/*.vrs
-/doc/texinfo.tex
+/doc/libdimension
+Doxyfile
# pkg-config files
*.pc
diff --git a/Makefile.am b/Makefile.am
index 6c6848a..5f9bd53 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -28,7 +28,7 @@ EXTRA_DIST = autogen.sh
if PGO
-.PHONY: pgo bench
+.PHONY: pgo bench doc
pgo:
@if [ ! -d $(top_builddir)/libdimension/pgo/.libs ] || [ -z "$$(ls $(top_builddir)/libdimension/pgo/.libs/*.gcda 2>/dev/null)" ]; then \
$(MAKE) $(AM_MAKEFLAGS) -C libdimension libdimension-pgo.la && \
@@ -44,8 +44,11 @@ pgo:
all-recursive check-recursive install-recursive installcheck-recursive distdir: pgo
else ## PGO
-.PHONY: bench
+.PHONY: bench doc
endif ## PGO
bench: all-recursive
cd bench && $(MAKE) $(AM_MAKEFLAGS) bench
+
+doc:
+ cd libdimension && $(MAKE) $(AM_MAKEFLAGS) doc
diff --git a/README b/README
index b998a2e..8c4a22d 100644
--- a/README
+++ b/README
@@ -1,9 +1,5 @@
This is Dimension, a project to create a GPLed, POV-Ray compatible ray tracer.
-It is currently stable but lacking in features, to the point of unusability.
-But if you want to try it anyway, see the INSTALL file for how to compile and
-run it. For a quick demo, run ./autogen.sh && ./configure && make check, and
-look at tests/dimension/demo.{pov,png}.
-
-Documentation for the `dimension' program will eventually be in the doc/
-directory. (Out of date) API documentation for the ray tracing library
-libdimension is also in doc/.
+It is currently stable but lacking in features. But if you want to try it
+anyway, see the INSTALL file for how to compile and run it. For a quick demo,
+run ./autogen.sh && ./configure && make check, and look at
+tests/dimension/demo.{pov,png}.
diff --git a/bench/libdimension/geometry.c b/bench/libdimension/geometry.c
index bc351b5..99757ae 100644
--- a/bench/libdimension/geometry.c
+++ b/bench/libdimension/geometry.c
@@ -169,11 +169,5 @@ main(void)
});
printf("dmnsn_line_point(): %ld\n", sandglass.grains);
- /* dmnsn_line_index() */
- sandglass_bench_fine(&sandglass, {
- result = dmnsn_line_index(line, vector);
- });
- printf("dmnsn_line_index(): %ld\n", sandglass.grains);
-
return EXIT_SUCCESS;
}
diff --git a/configure.ac b/configure.ac
index 0170fa0..266e990 100644
--- a/configure.ac
+++ b/configure.ac
@@ -128,6 +128,7 @@ dnl Generate Makefiles
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_FILES([Makefile
libdimension/Makefile
+ libdimension/Doxyfile
libdimension/libdimension.pc
dimension/Makefile
tests/Makefile
diff --git a/dimension/realize.c b/dimension/realize.c
index e6de1a4..40ff114 100644
--- a/dimension/realize.c
+++ b/dimension/realize.c
@@ -435,7 +435,6 @@ dmnsn_realize_camera(dmnsn_astnode astnode)
);
camera = dmnsn_new_perspective_camera();
- dmnsn_set_perspective_camera_trans(camera, trans);
break;
}
@@ -443,6 +442,7 @@ dmnsn_realize_camera(dmnsn_astnode astnode)
dmnsn_assert(false, "Unsupported camera type.");
}
+ camera->trans = trans;
return camera;
}
@@ -990,7 +990,7 @@ dmnsn_realize_box(dmnsn_astnode astnode)
}
static dmnsn_object *
-dmnsn_realize_cylinder(dmnsn_astnode astnode)
+dmnsn_realize_cone(dmnsn_astnode astnode)
{
dmnsn_astnode pnode1, rnode1, pnode2, rnode2, open;
@@ -1021,28 +1021,27 @@ dmnsn_realize_cylinder(dmnsn_astnode astnode)
double theta1 = dmnsn_vector_axis_angle(dmnsn_y, dir, dmnsn_x);
double theta2 = dmnsn_vector_axis_angle(dmnsn_y, dir, dmnsn_z);
- dmnsn_object *cylinder
- = dmnsn_new_cylinder(r1, r2, dmnsn_realize_integer(open));
- /* Transformations: lift the cylinder to start at the origin, scale, rotate,
+ dmnsn_object *cone = dmnsn_new_cone(r1, r2, dmnsn_realize_integer(open));
+ /* Transformations: lift the cone to start at the origin, scale, rotate,
and translate properly */
- cylinder->trans = dmnsn_translation_matrix(dmnsn_new_vector(0.0, 1.0, 0.0));
- cylinder->trans = dmnsn_matrix_mul(
+ cone->trans = dmnsn_translation_matrix(dmnsn_new_vector(0.0, 1.0, 0.0));
+ cone->trans = dmnsn_matrix_mul(
dmnsn_scale_matrix(dmnsn_new_vector(1.0, l/2.0, 1.0)),
- cylinder->trans
+ cone->trans
);
- cylinder->trans = dmnsn_matrix_mul(
+ cone->trans = dmnsn_matrix_mul(
dmnsn_rotation_matrix(dmnsn_new_vector(theta1, 0.0, 0.0)),
- cylinder->trans
+ cone->trans
);
- cylinder->trans = dmnsn_matrix_mul(
+ cone->trans = dmnsn_matrix_mul(
dmnsn_rotation_matrix(dmnsn_new_vector(0.0, 0.0, theta2)),
- cylinder->trans
+ cone->trans
);
- cylinder->trans = dmnsn_matrix_mul(
+ cone->trans = dmnsn_matrix_mul(
dmnsn_translation_matrix(p1),
- cylinder->trans
+ cone->trans
);
- return cylinder;
+ return cone;
}
static dmnsn_object *
@@ -1210,7 +1209,7 @@ dmnsn_realize_object(dmnsn_astnode astnode, dmnsn_array *lights)
break;
case DMNSN_AST_CONE:
case DMNSN_AST_CYLINDER:
- object = dmnsn_realize_cylinder(onode);
+ object = dmnsn_realize_cone(onode);
break;
case DMNSN_AST_DIFFERENCE:
object = dmnsn_realize_difference(onode, modifiers, lights);
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 5f5c9db..7aed436 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -16,7 +16,3 @@
## You should have received a copy of the GNU General Public License ##
## along with this program. If not, see <http://www.gnu.org/licenses/>. ##
###########################################################################
-
-info_TEXINFOS = libdimension.texi
-
-libdimension_la_TEXI = libdimension.texi
diff --git a/doc/libdimension.texi b/doc/libdimension.texi
deleted file mode 100644
index 5939a20..0000000
--- a/doc/libdimension.texi
+++ /dev/null
@@ -1,1032 +0,0 @@
-\input texinfo @c -*- Texinfo -*-
-@c %**start of header
-@setfilename libdimension.info
-@settitle The Dimension 3-D Rendering Library
-@c %**end of header
-
-@c Combine variable and function indicies
-@syncodeindex vr fn
-
-@c Wrap code examples at 72 chars, please
-
-@copying
-Copyright @copyright{} 2009-2010 Tavian Barnes
-@end copying
-
-@titlepage
-@title The Dimension Library
-@page
-@vskip 0pt plus 1filll
-@insertcopying
-@end titlepage
-
-@contents
-
-@ifnottex
-@node Top
-@top The Dimension Library
-
-@insertcopying
-@end ifnottex
-
-@menu
-* Introduction:: An introduction to the Dimension Library
-* Error Handling:: How libdimension handles warnings and errors
-* Arrays:: A generic interface for arrays of arbitrary objects
-* Lists:: A generic interface for lists of arbitrary objects
-* Asynchronicity:: An interface for controlling background tasks
-* Geometry:: Geometric types like vectors, transformation matricies, and lines
-* Color:: Correct color handling
-* Canvases:: Where the results of rendering are stored
-* Objects:: Physical objects in a scene
-* Cameras:: How a 3-D image is seen in 2-D
-* Scenes:: Scene objects which hold everything needed to render an image
-* Type Index::
-* Function and Constant Index::
-* Concept Index::
-@end menu
-
-
-@node Introduction
-@chapter Introduction
-
-@cindex introduction
-@cindex overview
-The Dimension Library is a C library for rendering photo-realistic 3-D scenes.
-It is the workhorse for the ``dimension'' program.
-The Dimension Library is currently in the very early stages of development, but does support rendering scenes with transparency and reflection.
-
-The C library is probably not the interface you want to use; the ``dimension'' program will render scenes specified in POV-Ray's Scene Description Language.
-This documentation gives a bottom-up overview of the Dimension Library, to allow readers to have a full and complete understanding of the library, rather than a simple top-down overview.
-
-@menu
-* Common Definitions:: Definitions used across the Dimension Library
-* Memory Allocation:: Wrappers for malloc() and friends
-@end menu
-
-@node Common Definitions
-@section Common Definitions
-
-@example
-@tindex dmnsn_free_fn
-typedef void dmnsn_free_fn(void *ptr);
-@end example
-
-@code{dmnsn_free_fn} is a type whose signature matches that of @code{free()}, and which is used as a destructor callback type across the Dimension Library.
-
-@node Memory Allocation
-@section Memory Allocation
-@example
-@findex dmnsn_malloc()
-void *dmnsn_malloc(size_t size);
-@findex dmnsn_realloc()
-void *dmnsn_realloc(void *ptr, size_t size);
-@findex dmnsn_strdup()
-char *dmnsn_strdup(const char *s);
-@end example
-
-@code{dmnsn_malloc()} is a wrapper for @code{malloc()} which is guaranteed to have succeeded if it returns, hence eliminating the need for checking its return value for @code{NULL}.
-If @code{malloc()} should fail, @code{dmnsn_malloc()} reports an error with @code{dmnsn_error()}, which cancels the calling thread (@pxref{Error Handling}).
-@code{dmnsn_realloc()} and @code{dmnsn_strdup()} behave similarly, wrapping @code{realloc()} and @code{strdup()} respectively.
-
-
-@node Error Handling
-@chapter Error Handling
-
-@example
-@tindex dmnsn_severity
-typedef enum @{
- @vindex DMNSN_SEVERITY_LOW
- DMNSN_SEVERITY_LOW, /* Only die on low resilience */
- @vindex DMNSN_SEVERITY_MEDIUM
- DMNSN_SEVERITY_MEDIUM, /* Die on low or medium resilience */
- @vindex DMNSN_SEVERITY_HIGH
- DMNSN_SEVERITY_HIGH /* Always die */
-@} dmnsn_severity;
-
-@findex dmnsn_error()
-#define dmnsn_error(severity, str) /* ... */
-
-@findex dmnsn_assert()
-#define dmnsn_assert(expression, str) /* ... */
-
-@findex dmnsn_get_resilience()
-dmnsn_severity dmnsn_get_resilience();
-@findex dmnsn_set_resilience()
-void dmnsn_set_resilience(dmnsn_severity resilience);
-@end example
-
-@cindex errors
-@cindex warnings
-When it makes sense, libdimension reports errors by returning error codes from its functions.
-However, when errors are not severe, when said function should not fail, or when the error is very serious, libdimension reports errors using the macro @code{dmnsn_error()}.
-@code{dmnsn_error()} takes two parameters: the severity of the error, and a string description of the error.
-The macro will conveniently report the description, as well as the function name and code line where the error occured, to standard error.
-The severity can be either @code{DMNSN_SEVERITY_LOW}, @code{DMNSN_SEVERITY_MEDIUM}, or @code{DMNSN_SEVERITY_HIGH}.
-
-@code{dmnsn_assert()} is used for checking invariants.
-Like @code{assert()}, when @code{NDEBUG} is defined, this macro generates no code.
-However, when @code{NDEBUG} is not defined and @code{expression} evaluates to @code{false}, @code{dmnsn_assert()} will terminate the current thread with @code{dmnsn_error(DMNSN_SEVERITY_HIGH, str)}.
-
-@cindex resilience
-The Dimension Library has also has a user-settable resilience.
-The resilience controls the minimum severity at which the library considers an error to be fatal, and terminates the calling thread.
-As such, errors of severity @code{DMNSN_SEVERITY_HIGH} are always fatal.
-libdimension's resilience defaults to @code{DMNSN_SEVERITY_MEDIUM}, but can be inspected or changed thread-safely by @code{dmnsn_get_resilience()} or @code{dmnsn_set_resilience()}, respectively.
-Warnings (non-fatal errors) are formatted like this:
-
-@example
-Dimension WARNING: <function>, <file>:<line>: <description>
-@end example
-
-@noindent while errors are formatted like this:
-
-@example
-Dimension ERROR: <function>, <file>:<line>: <description>
-@end example
-
-@noindent possibly followed by a backtrace.
-
-
-@node Arrays
-@chapter Arrays
-
-@example
-@tindex dmnsn_array *
-typedef struct @{
- /* ... */
-@} dmnsn_array;
-
-/* Array allocation */
-@findex dmnsn_new_array()
-dmnsn_array *dmnsn_new_array(size_t obj_size);
-@findex dmnsn_delete_array()
-void dmnsn_delete_array(dmnsn_array *array);
-
-@findex dmnsn_array_push()
-void dmnsn_array_push(dmnsn_array *array, const void *obj);
-@findex dmnsn_array_pop()
-void dmnsn_array_pop(dmnsn_array *array, void *obj);
-@findex dmnsn_array_get()
-void dmnsn_array_get(const dmnsn_array *array, size_t i, void *obj);
-@findex dmnsn_array_set()
-void dmnsn_array_set(dmnsn_array *array, size_t i, const void *obj);
-
-@findex dmnsn_array_first()
-void *dmnsn_array_first(const dmnsn_array *array);
-@findex dmnsn_array_last()
-void *dmnsn_array_last(const dmnsn_array *array);
-@findex dmnsn_array_at()
-void *dmnsn_array_at(const dmnsn_array *array, size_t i);
-
-@findex dmnsn_array_insert()
-void dmnsn_array_insert(dmnsn_array *array, size_t i, const void *obj)
-@findex dmnsn_array_remove()
-void dmnsn_array_remove(dmnsn_array *array, size_t i)
-
-@findex dmnsn_array_size()
-size_t dmnsn_array_size(const dmnsn_array *array);
-@findex dmnsn_array_resize()
-void dmnsn_array_resize(dmnsn_array *array, size_t length);
-
-@findex DMNSN_ARRAY_FOREACH ()
-#define DMNSN_ARRAY_FOREACH (type, i, array) /* ... */
-@end example
-
-@cindex array
-The Dimension Library often has cause to work with adjustable-size arrays.
-It provides an interface for dynamically-allocated arrays of arbitrary objects.
-Arrays are allocated with the @code{dmnsn_new_array()} function, and freed with the @code{dmnsn_delete_array()} function, a pattern common in libdimension.
-@code{dmnsn_new_array()} takes the size of the new array's elements as its parameter.
-
-Arrays support the push, pop, get, set, insert, and remove operations for arrays, taking a pointer to an object to read or write as their last parameter, the array index (when applicable) as the second-last parameter, and the @code{dmnsn_array *} as the first parameter.
-The get, remove, and pop operations are bounds-checked; other operations dynamically resize the array as needed.
-The array's length may be queried with @code{dmnsn_array_size()}, or set with @code{dmnsn_array_resize()}.
-A pointer to the first object is returned by @code{dmnsn_array_first()}, the last object by @code{dmnsn_array_last()}, and a pointer to the @code{i}'th object may be obtained with @code{dmnsn_array_at()}.
-
-The @code{DMNSN_ARRAY_FOREACH ()} macro expands to an appropriate for loop iterating over an array.
-@code{type} should be a type that points to the type of objects in the array, @code{i} will be the name of the pointer which iterates over the array, and @code{array} is the array to iterate over. For example:
-
-@example
-DMNSN_ARRAY_FOREACH (int *, i, array) @{
- printf("%d\n", *i);
-@}
-@end example
-
-
-@node Lists
-@chapter Lists
-
-@example
-@tindex dmnsn_list *
-typedef struct @{
- /* ... */
-@} dmnsn_list;
-
-@tindex dmnsn_list_iterator *
-typedef struct @{
- /* ... */
-@} dmnsn_list_iterator;
-
-/* List allocation */
-@findex dmnsn_new_list()
-dmnsn_array *dmnsn_new_list(size_t obj_size);
-@findex dmnsn_delete_list()
-void dmnsn_delete_list(dmnsn_array *array);
-
-/* Construction to/from arrays */
-@findex dmnsn_list_from_array()
-dmnsn_list *dmnsn_list_from_array(const dmnsn_array *array);
-@findex dmnsn_array_from_list()
-dmnsn_array *dmnsn_array_from_list(const dmnsn_list *list);
-
-/* Iteration */
-
-@findex dmnsn_list_first()
-dmnsn_list_iterator *dmnsn_list_first(const dmnsn_list *list);
-@findex dmnsn_list_last()
-dmnsn_list_iterator *dmnsn_list_last(const dmnsn_list *list);
-@findex dmnsn_list_size()
-size_t dmnsn_list_size(const dmnsn_list *list);
-
-@findex dmnsn_list_prev()
-dmnsn_list_iterator *dmnsn_list_prev(const dmnsn_list_iterator *i);
-@findex dmnsn_list_next()
-dmnsn_list_iterator *dmnsn_list_next(const dmnsn_list_iterator *i);
-
-/* Element access */
-@findex dmnsn_list_get()
-void dmnsn_list_get(const dmnsn_list_iterator *i, void *obj);
-@findex dmnsn_list_set()
-void dmnsn_list_set(dmnsn_list_iterator *i, const void *obj);
-@findex dmnsn_list_swap()
-void dmnsn_list_swap(dmnsn_list_iterator *a, dmnsn_list_iterator *b);
-
-/* Insertion/removal */
-@findex dmnsn_list_push()
-void dmnsn_list_push(dmnsn_list *list, const void *obj);
-@findex dmnsn_list_pop()
-void dmnsn_list_pop(dmnsn_list *list, void *obj);
-@findex dmnsn_list_insert()
-void dmnsn_list_insert(dmnsn_list *list, dmnsn_list_iterator *i,
- const void *obj)
-@findex dmnsn_list_remove()
-void dmnsn_list_remove(dmnsn_list *list, dmnsn_list_iterator *i)
-
-/* Splits a list in half, and returns the second half */
-@findex dmnsn_list_split()
-dmnsn_list *dmnsn_list_split(dmnsn_list *list);
-
-/* Sort a list */
-@tindex dmnsn_list_comparator_fn
-typedef bool dmnsn_list_comparator_fn(dmnsn_list_iterator *l,
- dmnsn_list_iterator *r);
-@findex dmnsn_list_sort()
-void dmnsn_list_sort(dmnsn_list *list,
- dmnsn_list_comparator_fn *comparator);
-@end example
-
-@cindex list
-Generic doubly-linked lists are also provided by the Dimension Library.
-They are allocated and freed by @code{dmnsn_new_list()} and @code{dmnsn_delete_list()}, respectively.
-They can also be constructed from @code{dmnsn_array *}'s by @code{dmnsn_list_from_array()}, and converted to @code{dmnsn_array *}'s by @code{dmnsn_array_from_list()}.
-
-List elements are accessed with an iterator type, @code{dmnsn_list_iterator *}.
-The previous or next list element is found with @code{dmnsn_list_prev()} or @code{dmnsn_list_next()}, respectively.
-@code{NULL} indicates that you've fallen off the beginning or end of the list.
-An iterator to the first or last element of a list is obtained with @code{dmnsn_list_first()} or @code{dmnsn_list_last()}.
-The size of a list is given by @code{dmnsn_list_size()}.
-
-An object can be retrieved from a @code{dmnsn_list_iterator *} with @code{dmnsn_list_get()}, and set with @code{dmnsn_list_set()}. The objects of two list iterators can be swapped with @code{dmnsn_list_swap()}.
-
-Objects can be added or removed from the end of a list with @code{dmnsn_list_push()} and @code{dmnsn_list_pop()}.
-Elements can be added at arbitrary locations with @code{dmnsn_list_insert()}, which inserts the object before the iterator @code{i} (pass NULL to insert it at the end).
-The element at @code{i} can be removed with @code{dmnsn_list_remove()}.
-
-@code{dmnsn_list_split()} splits the given list in half, and returns the second, possibly smaller half.
-
-@code{dmnsn_list_sort()} sorts a given list, using a comparison function matching the signature of the @code{dmnsn_list_comparator_fn} type.
-
-
-@node Asynchronicity
-@chapter Asynchronicity
-
-@example
-@tindex dmnsn_progress *
-typedef struct @{
- /* ... */
-@} dmnsn_progress;
-
-/* Progress allocation */
-@findex dmnsn_new_progress()
-dmnsn_progress *dmnsn_new_progress();
-@findex dmnsn_delete_progress()
-void dmnsn_delete_progress(dmnsn_progress *progress);
-
-/* Ensures completion of the worker thread */
-@findex dmnsn_finish_progress()
-int dmnsn_finish_progress(dmnsn_progress *progress);
-
-/* Routines for users */
-@findex dmnsn_get_progress()
-double dmnsn_get_progress(const dmnsn_progress *progress);
-@findex dmnsn_wait_progress()
-void dmnsn_wait_progress(const dmnsn_progress *progress, double prog);
-
-/* Routines for worker threads */
-@findex dmnsn_new_progress_element()
-void dmnsn_new_progress_element(dmnsn_progress *progress,
- unsigned int total);
-@findex dmnsn_increment_progress()
-void dmnsn_increment_progress(dmnsn_progress *progress);
-@findex dmnsn_done_progress()
-void dmnsn_done_progress(dmnsn_progress *progress);
-@end example
-
-@cindex asynchronous task
-@cindex background task
-@cindex progress indicator
-As the Dimension Library is a raytracing engine, some routines are likely to take a long time.
-These routines may be run in a background thread, and controlled with a common interface.
-Routines supporting this interface end in @code{_async}, such as @code{dmnsn_raytrace_scene_async()}, and return a @code{dmnsn_progress *} object, so named because it allows an application to be query the progress of the background task.
-By necessity, all @code{dmnsn_progress *} operations are atomic and thread-safe.
-
-Progress objects are allocated and deallocated in the standard libdimension way, but also support a unique @code{dmnsn_finish_progress()} function.
-This function waits for the background thread to complete, and then destroys the @code{dmnsn_progress *} object.
-Never use the result of a background task before calling @code{dmnsn_finish_progress()}, even if the progress seems to be at 100%! @code{dmnsn_delete_progress()} should only be called from within failed @code{*_async()} functions, to deallocate a progress object before it is associated with a running thread.
-
-Users of these asynchronous tasks will mainly be interested in the functions @code{dmnsn_get_progress()} and @code{dmnsn_wait_progress()}.
-@code{dmnsn_get_progress()} returns the progress of the background task, a value between 0.0 and 1.0.
-@code{dmnsn_wait_progress()} simply waits for @code{dmnsn_get_progress()} to be >= @code{prog}, but in a much better way than spinlocking (internally, a condition variable is used).
-
-Background tasks themselves will be interested in three more functions.
-To indicate progress to the user, progress objects store one "element" for each level of loop nesting a task would like to report the progress of.
-Only the innermost loop need increment the progress counter, as in this example:
-
-@example
-dmnsn_new_progress_element(progress, i_max);
-for (i = 0; i < i_max; ++i) @{
- dmnsn_new_progress_element(progress, j_max);
- for (j = 0; j < j_max; ++j) @{
- /* Do stuff */
- dmnsn_increment_progress(progress);
- @}
-@}
-@end example
-
-For robustness, tasks should call @code{dmnsn_done_progress()} when they finish, even if they fail.
-This function immediately sets the progress to 100%, which wakes up all waiters.
-Otherwise, a user's application may hang calling @code{dmnsn_wait_progress()}.
-
-
-@node Geometry
-@chapter Geometry
-
-@example
-/* Vector and matrix types. */
-
-@tindex dmnsn_vector
-typedef struct @{
- double x, y, z;
-@} dmnsn_vector;
-
-@tindex dmnsn_matrix
-typedef struct @{
- double n[4][4];
-@} dmnsn_matrix;
-
-/* A line, or ray. */
-@tindex dmnsn_line
-typedef struct @{
- dmnsn_vector x0; /* A point on the line */
- dmnsn_vector n; /* A normal vector; the direction of the line */
-@} dmnsn_line;
-
-@tindex dmnsn_bounding_box
-typedef struct @{
- dmnsn_vector min;
- dmnsn_vector max;
-@} dmnsn_bounding_box;
-
-/* Vector/matrix construction */
-
-@findex dmnsn_new_vector()
-dmnsn_vector dmnsn_new_vector(double x, double y, double z);
-
-@findex dmnsn_new_matrix()
-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,
- double d0, double d1, double d2, double d3);
-
-@findex dmnsn_identity_matrix()
-dmnsn_matrix dmnsn_identity_matrix();
-@findex dmnsn_scale_matrix()
-dmnsn_matrix dmnsn_scale_matrix(dmnsn_vector s);
-@findex dmnsn_translation_matrix()
-dmnsn_matrix dmnsn_translation_matrix(dmnsn_vector d);
-@findex dmnsn_rotation_matrix()
-dmnsn_matrix dmnsn_rotation_matrix(dmnsn_vector theta);
-
-@findex dmnsn_new_line()
-dmnsn_line dmnsn_new_line(dmnsn_vector x0, dmnsn_vector n);
-
-/* Vector and matrix arithmetic */
-
-@findex dmnsn_vector_add()
-dmnsn_vector dmnsn_vector_add(dmnsn_vector lhs, dmnsn_vector rhs);
-@findex dmnsn_vector_sub()
-dmnsn_vector dmnsn_vector_sub(dmnsn_vector lhs, dmnsn_vector rhs);
-@findex dmnsn_vector_mul()
-dmnsn_vector dmnsn_vector_mul(double lhs, dmnsn_vector rhs);
-@findex dmnsn_vector_div()
-dmnsn_vector dmnsn_vector_div(dmnsn_vector lhs, double rhs);
-
-@findex dmnsn_vector_dot()
-double dmnsn_vector_dot(dmnsn_vector lhs, dmnsn_vector rhs);
-@findex dmnsn_vector_cross()
-dmnsn_vector dmnsn_vector_cross(dmnsn_vector lhs, dmnsn_vector rhs);
-
-@findex dmnsn_vector_norm()
-double dmnsn_vector_norm(dmnsn_vector n);
-@findex dmnsn_vector_normalize()
-dmnsn_vector dmnsn_vector_normalize(dmnsn_vector n);
-
-@findex dmnsn_matrix_inverse()
-dmnsn_matrix dmnsn_matrix_inverse(dmnsn_matrix A);
-@findex dmnsn_matrix_mul()
-dmnsn_matrix dmnsn_matrix_mul(dmnsn_matrix lhs, dmnsn_matrix rhs);
-@findex dmnsn_transform_vector()
-dmnsn_vector dmnsn_transform_vector(dmnsn_matrix lhs,
- dmnsn_vector rhs);
-@findex dmnsn_transform_bounding_box()
-dmnsn_bounding_box dmnsn_transform_bounding_box(dmnsn_matrix lhs,
- dmnsn_bounding_box rhs);
-@findex dmnsn_transform_line()
-dmnsn_line dmnsn_transform_line(dmnsn_matrix lhs, dmnsn_line rhs);
-
-@findex dmnsn_line_point()
-dmnsn_vector dmnsn_line_point(dmnsn_line l, double t);
-@findex dmnsn_line_index()
-double dmnsn_line_index(dmnsn_line l, dmnsn_vector x);
-@end example
-
-@cindex scalar
-@cindex vector
-@cindex matrix
-@cindex line
-@cindex ray
-For performing 3-D computational geometry, the Dimension Library supports geometric types and many operations on these types.
-libdimension defines the @code{dmnsn_vector}, @code{dmnsn_matrix}, and @code{dmnsn_line} geometric types.
-They may be easily constructed by the self-explanatory @code{dmnsn_new_vector()}, @code{dmnsn_new_matrix()}, or @code{dmnsn_new_line()}.
-
-@cindex transformation
-@cindex norm
-@cindex normalization
-@cindex dot product
-@cindex cross product
-Vectors support addition and subtraction, multiplication and division by a scalar, the dot and cross products, the norm and normalization operations, and transformation by a matrix (@code{dmnsn_transform_vector()}).
-
-@cindex matrix inversion
-Matricies support matrix multiplication, and inversion.
-Inversion uses a very fast partitioning algorithm.
-As well, there are four special matrix constructors.
-@code{dmnsn_identity_matrix()} simply returns the identity matrix.
-@code{dmnsn_scale_matrix(s)} returns a matrix which scales each dimension by a factor of the corresponding dimension of the @code{s}.
-@code{dmnsn_translate_matrix(d)} returns a matrix which translates by @code{d}.
-Finally, @code{dmnsn_rotation_matrix(theta)} returns a matrix which rotates by an angle of @code{dmnsn_vector_norm(theta)}, about the axis @code{dmnsn_vector_normalize(theta)}.
-
-Lines support transformation by a matrix (@code{dmnsn_transform_line(A, l) = dmnsn_new_line(A*l.x0, A*(l.x0 + l.n) - A*l.x0)}).
-Also, @code{dmnsn_line_point(l, t) = l.x0 + t*l.n} gives the point @code{t} on the line, and @code{dmnsn_line_index(l, x)} gives the @code{t} value such that @code{dmnsn_line_point(l, t) == x}.
-
-@cindex bounding boxes
-@cindex axis-aligned bounding boxes
-Axis-aligned bounding boxes are represented by the @code{dmnsn_bounding_box} type, with their minimum extent in the @code{.min} field, and their maximum extent in the @code{.max} field.
-They may be transformed by a matrix with @code{dmnsn_transform_bounding_box()}.
-
-
-@node Color
-@chapter Color
-
-@example
-@tindex dmnsn_color
-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. */
- /* ... */
-@} dmnsn_color;
-
-@tindex dmnsn_CIE_XYZ
-typedef struct @{
- double X, Y, Z; /* X, Y, and Z are tristimulus values, unbounded
- above zero.
-Diffuse white is (0.9505, 1,
- 1.089). */
-@} dmnsn_CIE_XYZ;
-
-@tindex dmnsn_CIE_xyY
-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 */
-@} dmnsn_CIE_xyY;
-
-@tindex dmnsn_CIE_Lab
-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. */
-@} dmnsn_CIE_Lab;
-
-@tindex dmnsn_CIE_Luv
-typedef struct @{
- double L, u, v; /* L is luminence (100 = diffuse white); u and v are
- chromaticity coordinates. */
-@} dmnsn_CIE_Luv;
-
-@tindex dmnsn_sRGB
-typedef struct @{
- double R, G, B; /* sRGB R, G, and B values */
-@} dmnsn_sRGB;
-
-/* Standard colors */
-@vindex dmnsn_black
-@vindex dmnsn_white
-@vindex dmnsn_red
-@vindex dmnsn_green
-@vindex dmnsn_blue
-@vindex dmnsn_magenta
-@vindex dmnsn_yellow
-@vindex dmnsn_cyan
-extern const dmnsn_color dmnsn_black, dmnsn_white, dmnsn_red,
- dmnsn_green, dmnsn_blue, dmnsn_magenta, dmnsn_yellow, dmnsn_cyan;
-
-/* Standard whitepoint, determined by the conversion of sRGB white to
- CIE XYZ */
-@vindex dmnsn_whitepoint
-extern const dmnsn_CIE_XYZ dmnsn_whitepoint;
-
-/* Color conversions */
-
-@findex dmnsn_color_from_XYZ()
-dmnsn_color dmnsn_color_from_XYZ(dmnsn_CIE_XYZ XYZ);
-@findex dmnsn_color_from_xyY()
-dmnsn_color dmnsn_color_from_xyY(dmnsn_CIE_xyY xyY);
-@findex dmnsn_color_from_Lab()
-dmnsn_color dmnsn_color_from_Lab(dmnsn_CIE_Lab Lab,
- dmnsn_CIE_XYZ white);
-@findex dmnsn_color_from_Luv()
-dmnsn_color dmnsn_color_from_Luv(dmnsn_CIE_Luv Luv,
- dmnsn_CIE_XYZ white);
-@findex dmnsn_color_from_sRGB()
-dmnsn_color dmnsn_color_from_sRGB(dmnsn_sRGB sRGB);
-
-@findex dmnsn_XYZ_from_color()
-dmnsn_CIE_XYZ dmnsn_XYZ_from_color(dmnsn_color color);
-@findex dmnsn_xyY_from_color()
-dmnsn_CIE_xyY dmnsn_xyY_from_color(dmnsn_color color);
-@findex dmnsn_Lab_from_color()
-dmnsn_CIE_Lab dmnsn_Lab_from_color(dmnsn_color color,
- dmnsn_CIE_XYZ white);
-@findex dmnsn_Luv_from_color()
-dmnsn_CIE_Luv dmnsn_Luv_from_color(dmnsn_color color,
- dmnsn_CIE_XYZ white);
-@findex dmnsn_sRGB_from_color()
-dmnsn_sRGB dmnsn_sRGB_from_color(dmnsn_color color);
-
-/* Is this color black? */
-@findex dmsnn_color_is_black()
-bool dmnsn_color_is_black(dmnsn_color color);
-
-/* Perceptual color manipulation */
-@findex dmnsn_color_add()
-dmnsn_color dmnsn_color_add(dmnsn_color color1, dmnsn_color color2);
-@findex dmnsn_color_mul()
-dmnsn_color dmnsn_color_mul(double n, dmnsn_color color);
-@findex dmnsn_color_gradient()
-dmnsn_color dmnsn_color_gradient(dmnsn_color c1, dmnsn_color c2,
- double n);
-@findex dmnsn_color_filter()
-dmnsn_color dmnsn_color_filter(dmnsn_color color, dmnsn_color filter);
-@findex dmnsn_color_illuminate()
-dmnsn_color dmnsn_color_illuminate(dmnsn_color light,
- dmnsn_color color);
-
-/* Perceptual color difference */
-@findex dmnsn_color_difference()
-double dmnsn_color_difference(dmnsn_color color1, dmnsn_color color2);
-@end example
-
-@cindex color
-@cindex CIE XYZ
-@cindex CIE xyY
-@cindex CIE L*a*b*
-@cindex CIE L*u*v*
-@cindex sRGB
-@cindex RGB
-The Dimension Library supports many different representations of color.
-The details of each representation are beyond the scope of this manual, but libdimension supports CIE XYZ, xyY, L*a*b*, L*u*v*, and sRGB color.
-CIE L*a*b* and L*u*v* are designed to be perceptually uniform, meaning changes in their color coordinates correspond to perceptual changes of equal magnitude.
-The @code{dmnsn_color} type is used by libdimension itself to represent colors, internally in the sRGB color space.
-The @code{.filter} field gives the color's filtered transparency, which lets same-colored light through, while the @code{.trans} field stores non-filtered transparency.
-
-The @code{dmnsn_color_from_*()} and @code{dmnsn_*_from_color()} functions are used to convert to and from the @code{dmnsn_color} type.
-The conversions to @code{dmnsn_color} set the @code{.filter} and @code{.trans} fields to zero, and those fields are ignored by the inverse conversions.
-Conversions to and from CIE L*a*b* and L*u*v* colors take an extra parameter, which specifies the absolute color value of the whitepoint the conversions are relative to.
-@code{dmnsn_whitepoint} is a good value for this parameter.
-
-@code{dmnsn_color_add()} adds two colors in a perceptually-correct way.
-@code{dmnsn_color_mul()} scales the brightness of a color.
-@code{dmnsn_color_gradient()} returns the color at point @code{n} on a gradient from @code{c1} at 0 to @code{c2} at 1.
-@code{dmnsn_color_filter()} returns the color obtained by filtering @code{color} through @code{filter}.
-@code{dmnsn_color_illuminate()} return the color obtained by illuminating @code{color} with @code{light}-colored light.
-@code{dmnsn_color_difference()} returns the magnatude of the perceptual difference between two colors.
-
-
-@node Canvases
-@chapter Canvases
-
-@example
-@tindex dmnsn_canvas *
-typedef struct @{
- /* width, height */
- unsigned int x, y;
-
- /* An array of dmnsn_canvas_optimizer's - see below */
- dmnsn_array *optimizers;
-
- /* ... */
-@} dmnsn_canvas;
-
-/* Allocate and free a canvas */
-@findex dmnsn_new_canvas()
-dmnsn_canvas *dmnsn_new_canvas(unsigned int x, unsigned int y);
-@findex dmnsn_delete_canvas()
-void dmnsn_delete_canvas(dmnsn_canvas *canvas);
-
-/* Pixel accessors */
-@findex dmnsn_get_pixel()
-dmnsn_color dmnsn_get_pixel(const dmnsn_canvas *canvas,
- unsigned int x, unsigned int y);
-@findex dmnsn_set_pixel()
-void dmnsn_set_pixel(dmnsn_canvas *canvas,
- unsigned int x, unsigned int y,
- dmnsn_color color);
-@end example
-
-@cindex canvas
-@cindex rendering target
-The target of a rendering operation in the Dimension Library is a canvas object, represented by the type @code{dmnsn_canvas *}.
-This type stores the dimensions of the canvas in the @code{->x} and @code{->y} fields.
-The pixel at (x,y) can be examined or set by the accessors @code{dmnsn_get_pixel()} and @code{dmnsn_set_pixel()}.
-
-Canvases may be imported from or exported to images.
-In the future, canvases will also be able to be treated as object textures, to support images as textures.
-
-@menu
-* PNG Import and Export:: Importing and exporting canvases to and from PNG files
-* OpenGL:: Drawing and reading canvases to and from OpenGL buffers
-* Canvas Optimization:: Optimizing a canvas for a later export
-@end menu
-
-@node PNG Import and Export
-@section PNG Import and Export
-
-@example
-/* Optimize canvas for PNG exporting */
-@findex dmnsn_png_optimize_canvas()
-int dmnsn_png_optimize_canvas(dmnsn_canvas *canvas);
-
-/* Write canvas to file in PNG format. Returns 0 on success, nonzero
- on failure */
-@findex dmnsn_png_write_canvas()
-int dmnsn_png_write_canvas(const dmnsn_canvas *canvas, FILE *file);
-@findex dmnsn_png_write_canvas_async()
-dmnsn_progress *
-dmnsn_png_write_canvas_async(const dmnsn_canvas *canvas, FILE *file);
-
-/* Read a canvas from a PNG file.
-Returns NULL on failure. */
-@findex dmnsn_png_read_canvas()
-dmnsn_canvas *dmnsn_png_read_canvas(FILE *file);
-@findex dmnsn_png_read_canvas_async()
-dmnsn_progress *dmnsn_png_read_canvas_async(dmnsn_canvas **canvas,
- FILE *file);
-@end example
-
-@cindex PNG
-The Dimension Library supports import and export of canvas to and from PNG files; this is currently the only supported image type.
-The interface is simple: @code{dmnsn_png_write_canvas()} writes the canvas in PNG format to the given file, at maximum quality; @code{dmnsn_png_read_canvas()} imports a PNG file to a canvas.
-The @code{*_async()} versions work as described in @ref{Asynchronicity}.
-If it is known in advance that a canvas will be exported to a PNG file, calling @code{dmnsn_png_optimize_canvas()} on it before it is written to will speed up the export process; see @ref{Canvas Optimization}.
-
-@node OpenGL
-@section OpenGL
-
-@example
-/* Optimize canvas for GL drawing */
-@findex dmnsn_gl_optimize_canvas()
-int dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas);
-
-/* Write canvas to GL framebuffer. Returns 0 on success, nonzero on
- failure. */
-@findex dmnsn_gl_write_canvas()
-int dmnsn_gl_write_canvas(const dmnsn_canvas *canvas);
-
-/* Read a canvas from a GL framebuffer.
-Returns NULL on failure. */
-@findex dmnsn_gl_read_canvas()
-dmnsn_canvas *dmnsn_gl_read_canvas(unsigned int x0, unsigned int y0,
- unsigned int width,
- unsigned int height);
-@end example
-
-@cindex GL
-@cindex OpenGL
-Canvases may be written to or read from an OpenGL buffer with the @code{dmnsn_gl_write_canvas()} and @code{dmnsn_gl_read_canvas()} functions, respectively.
-Writing uses the @code{glDrawPixels()} GL function, and reading uses the @code{glReadPixels()} function.
-@code{dmnsn_gl_read_canvas()} starts reading at (@code{x0}, @code{y0}), and reads a @code{width}*@code{height} sized image.
-These operations should be fast (especially if optimized), so no @code{..._async()} versions are supplied.
-If it is known in advance that a canvas will be drawn to an OpenGL buffer, calling @code{dmnsn_gl_optimize_canvas()} on it before it is written to will speed up the export process; see @ref{Canvas Optimization}.
-
-@node Canvas Optimization
-@section Canvas Optimization
-
-@example
-/* Canvas optimizer callback types */
-@tindex dmnsn_canvas_optimizer_fn
-typedef void dmnsn_canvas_optimizer_fn(dmnsn_canvas *canvas,
- dmnsn_canvas_optimizer optimizer,
- unsigned int x, unsigned int y);
-
-/* Canvas optimizer */
-@tindex dmnsn_canvas_optimizer
-typedef struct @{
- dmnsn_canvas_optimizer_fn *optimizer_fn;
- dmnsn_free_fn *free_fn;
- void *ptr;
-@} dmnsn_canvas_optimizer;
-
-/* Set a canvas optimizer */
-@findex dmnsn_optimize_canvas()
-int dmnsn_optimize_canvas(dmnsn_canvas *canvas,
- dmnsn_canvas_optimizer optimizer);
-@end example
-
-@cindex optimization, canvas
-@cindex optimization, export
-If a canvas is to be exported to a different format, the export process can be sped up if the pixels are stored in the target format as they are written to a canvas.
-This is what canvas optimizers do: they register callbacks that are triggered upon a @code{dmnsn_set_pixel()} call, generally storing the color in the appropriate format for the target (sRGB for PNG, for example) in some other buffer.
-Then the exporting process is a breeze, because the canvas doesn't have to be converted to another format.
-
-The @code{dmnsn_canvas_optimizer} type stores a pointer to a callback function to be executed upon calls to @code{dmnsn_set_pixel()} in its @code{.optimizer_fn} field.
-This function should match the signature of the @code{dmnsn_canvas_optimizer_fn} type.
-Its @code{.ptr} field stores a generic pointer to any type of data the optimizer may wish to store.
-This pointer will be provided to its @code{.free_fn} callback when @code{dmnsn_delete_canvas()} is called, and may simply point to the standard library @code{free} function.
-
-To register a new canvas optimizer, the program should first check that the same optimization hasn't already been applied by examining the @code{dmnsn_canvas *}'s @code{->optimizers} array, and testing each @code{dmnsn_canvas_optimizer}'s @code{.optimizer_fn} for equality with the address of the new callback.
-If the optimization hasn't yet been applied, the program should call @code{dmnsn_optimize_canvas()}, which returns 0 if it succeeded, and nonzero otherwise.
-Note that this function will fail if @code{dmnsn_set_pixel()} has ever been called on the target canvas, since pixels which have already been set would not be known to the optimizer.
-
-@node Objects
-@chapter Objects
-
-@example
-@tindex dmnsn_object *
-typedef struct @{
- /* Surface properties */
- dmnsn_texture *texture;
-
- /* Transformation matrix */
- dmnsn_matrix trans, trans_inv;
-
- /* Bounding box */
- dmnsn_vector min, max;
-
- /* Callback functions */
- dmnsn_object_intersection_fn *intersection_fn;
- dmnsn_object_inside_fn *inside_fn;
- dmnsn_free_fn *free_fn;
-
- /* Generic pointer for object info */
- void *ptr;
-@} dmnsn_object;
-
-/* Object callback types */
-@tindex dmnsn_object_intersections_fn
-typedef dmnsn_intersection *
-dmnsn_object_intersection_fn(const dmnsn_object *object,
- dmnsn_line line);
-@tindex dmnsn_object_inside_fn
-typedef bool dmnsn_object_inside_fn(const dmnsn_object *object,
- dmnsn_vector point);
-
-/* Allocate a dummy object */
-@findex dmnsn_new_object()
-dmnsn_object *dmnsn_new_object();
-@findex dmnsn_delete_object()
-void dmnsn_delete_object(dmnsn_object *object);
-@end example
-
-@cindex object
-The Dimension Library renders 3-D objects, represented by the @code{dmnsn_object *} type.
-This type has callback functions for determining if and where a ray intersects the object, and whether a point is inside the object.
-In the future, many more callbacks will be added.
-libdimension comes with a few simple object types like spheres and cubes, or you may create your own by customizing the object callbacks.
-The field @code{->ptr} is a void pointer which may be used to store additional information about an object.
-The @code{->trans} field is a transformation matrix, transforming the rays which intersect the object, rather than the object itself.
-Thus, @code{->trans} should be set to the inverse of the transformations you wish to apply to the object.
-
-@cindex object callbacks
-The @code{->intersection_fn} callback should point to a function with the same signature as the @code{dmnsn_object_intersection_fn} type.
-It should return a @code{dmnsn_intersection *} corresponding to the closest intersection, or @code{NULL} if the ray does not intersect the object.
-
-The @code{->inside_fn} callback should point to a function matching the signature of the @code{dmnsn_object_inside_fn} type.
-It should return 0 if the given @code{point} is outside the object, and nonzero when that point is inside the object.
-The callback is free to return any value in the case that the point lies directly on the surface of the object.
-
-@menu
-* Spheres:: Spheres
-* Cubes:: Cubes
-@end menu
-
-@node Spheres
-@section Spheres
-
-@example
-@findex dmnsn_new_sphere()
-dmnsn_object *dmnsn_new_sphere();
-@end example
-
-@cindex sphere
-The Dimension Library has a few built-in basic shape primitives.
-One of them is the sphere; @code{dmnsn_new_sphere()} returns a sphere of radius 1, centered at the origin.
-Use the object's transformation matrix to scale, translate, and/or rotate it.
-
-@node Cubes
-@section Cubes
-
-@example
-@findex dmnsn_new_cube()
-dmnsn_object *dmnsn_new_cube();
-@end example
-
-@cindex cube
-@code{dmnsn_new_cube()} returns a cube, axis-aligned, from (-1, -1, -1) to (1, 1, 1).
-Use its transformation matrix to scale, translate, and/or rotate it.
-
-
-@node Cameras
-@chapter Cameras
-
-@example
-@tindex dmnsn_camera *
-typedef struct @{
- /* Callback functions */
- dmnsn_camera_ray_fn *ray_fn;
- dmnsn_free_fn *free_fn;
-
- /* Generic pointer for camera info */
- void *ptr;
-@} dmnsn_camera;
-
-/* Camera callback types */
-@tindex dmnsn_camera_ray_fn
-typedef dmnsn_line dmnsn_camera_ray_fn(const dmnsn_camera *camera,
- double x, double y);
-
-@findex dmnsn_new_camera()
-dmnsn_camera *dmnsn_new_camera();
-@findex dmnsn_delete_camera()
-void dmnsn_delete_camera(dmnsn_camera *camera);
-@end example
-
-@cindex camera
-In order to project a 3-D scene onto a 2-D plane, the Dimension Library uses a generic camera type.
-A camera provides the Dimension Library the camera ray corresponding to each pixel in the canvas, by its @code{->ray_fn} callback.
-
-@code{->ray_fn} should point to a function matching the signature of the type @code{dmnsn_camera_ray_fn}, and should return the ray corresponding to the pixel at (@code{x}, @code{y}) in a hypothetical square canvas from (0, 0) to (1, 1).
-
-@menu
-* Perspective Cameras:: Simple perspective cameras
-@end menu
-
-@node Perspective Cameras
-@section Perspective Cameras
-
-@example
-@findex dmnsn_new_perspective_camera()
-dmnsn_camera *dmnsn_new_perspective_camera();
-
-/* 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);
-@end example
-
-@cindex perspective
-The function @code{dmnsn_new_perspective_camera} creates a perspective camera, situated at the origin, looking toward (0, 0, 1), and aiming at a screen from (-0.5, -0.5) to (0.5, 0.5) on the z = 1 plane.
-Camera rays may be transformed by a matrix set by @code{dmnsn_set_perspective_camera_trans()} and retrieved by @code{dmnsn_get_perspective_camera_trans()}.
-
-
-@node Scenes
-@chapter Scenes
-
-@example
-
-enum @{
- DMNSN_RENDER_NONE = /* ... */,
- DMNSN_RENDER_PIGMENT = /* ... */,
- DMNSN_RENDER_LIGHTS = /* ... */,
- DMNSN_RENDER_FINISH = /* ... */,
- DMNSN_RENDER_TRANSLUCENCY = /* ... */,
- DMNSN_RENDER_REFLECTION = /* ... */,
- DMNSN_RENDER_FULL = ~DMNSN_RENDER_NONE
-@};
-
-@tindex dmnsn_quality
-typedef unsigned int dmnsn_quality;
-
-@tindex dmnsn_scene *
-typedef struct @{
- /* World attributes */
- dmnsn_color background;
- dmnsn_texture *default_texture;
-
- /* Camera */
- dmnsn_camera *camera;
-
- /* Canvas */
- dmnsn_canvas *canvas;
-
- /* Objects */
- dmnsn_array *objects;
-
- /* Lights */
- dmnsn_array *lights;
-
- /* Rendering quality */
- dmnsn_quality quality;
-
- /* Recursion limit */
- unsigned int limit;
-
- /* Number of paralell threads */
- unsigned int nthreads;
-@} dmnsn_scene;
-
-@findex dmnsn_new_scene()
-dmnsn_scene *dmnsn_new_scene();
-@findex dmnsn_delete_scene()
-void dmnsn_delete_scene(dmnsn_scene *scene);
-@end example
-
-@cindex scene
-The @code{dmnsn_scene *} type ties all the components of a 3-D world together.
-A scene stores a background color in its @code{->background} field, a @code{dmnsn_array *} of @code{const dmnsn_object *}'s in its @code{->objects} field, a @code{dmnsn_camera *} in its @code{->camera} field, and a @code{dmnsn_canvas *} in its @code{->canvas} field.
-Scenes can be rendered, producing an image in their canvas field.
-
-@menu
-* Raytracing:: Rendering a scene by raytracing
-@end menu
-
-@node Raytracing
-@section Raytracing
-
-@example
-@findex dmnsn_raytrace_scene()
-int dmnsn_raytrace_scene(dmnsn_scene *scene);
-@findex dmnsn_raytrace_scene_async()
-dmnsn_progress *dmnsn_raytrace_scene_async(dmnsn_scene *scene);
-@end example
-
-@cindex raytracing
-The @code{dmnsn_raytrace_scene()} function renders a scene by raytracing - casting rays from the camera to objects in its view.
-The @code{..._async()} version works as described in @ref{Asynchronicity}.
-
-
-@node Type Index
-@unnumbered Type Index
-
-@printindex tp
-
-
-@node Function and Constant Index
-@unnumbered Function and Constant Index
-
-@printindex fn
-
-
-@node Concept Index
-@unnumbered Concept Index
-
-@printindex cp
-
-@bye
diff --git a/libdimension/Doxyfile.in b/libdimension/Doxyfile.in
new file mode 100644
index 0000000..23d7bfb
--- /dev/null
+++ b/libdimension/Doxyfile.in
@@ -0,0 +1,43 @@
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = libdimension
+PROJECT_NUMBER = @VERSION@
+OUTPUT_DIRECTORY = @top_builddir@/doc/libdimension
+OUTPUT_LANGUAGE = English
+FULL_PATH_NAMES = YES
+OPTIMIZE_OUTPUT_FOR_C = YES
+IGNORE_PREFIX = dmnsn_ DMNSN_
+JAVADOC_AUTOBRIEF = YES
+TYPEDEF_HIDES_STRUCT = YES
+EXTRACT_LOCAL_CLASSES = NO
+EXTRACT_STATIC = YES
+SORT_MEMBER_DOCS = NO
+ALWAYS_DETAILED_SEC = YES
+HIDE_UNDOC_MEMBERS = YES
+INPUT = dimension.h dimension
+INPUT_ENCODING = UTF-8
+# Hack to get DMNSN_INLINE documentation to show up.
+INPUT_FILTER = "sed 's/#ifndef DMNSN_INLINE/#if 1/g'"
+FILE_PATTERNS = *.h
+EXCLUDE_PATTERNS = *-stubs.c
+SOURCE_BROWSER = YES
+MACRO_EXPANSION = YES
+EXPAND_ONLY_PREDEF = YES
+EXPAND_AS_DEFINED = "DMNSN_INLINE"
+PREDEFINED = "__STDC_VERSION__=199901L" "__GNUC__"
+
+INTERNAL_DOCS = NO
+#INTERNAL_DOCS = YES
+#INPUT = . dimension
+#FILE_PATTERNS = *.c *.h
+#EXTRACT_LOCAL_CLASSES = YES
+#REFERENCED_BY_RELATION = YES
+#REFERENCES_RELATION = YES
+
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+
+GENERATE_LATEX = YES
+LATEX_OUTPUT = latex
+
+PREDEFINED = "__STDC_VERSION__=199901L" "__GNUC__"
diff --git a/libdimension/Makefile.am b/libdimension/Makefile.am
index 87742e0..542e684 100644
--- a/libdimension/Makefile.am
+++ b/libdimension/Makefile.am
@@ -31,6 +31,7 @@ nobase_include_HEADERS = dimension.h \
dimension/finishes.h \
dimension/geometry.h \
dimension/gl.h \
+ dimension/inline.h \
dimension/interior.h \
dimension/light.h \
dimension/lights.h \
@@ -42,6 +43,7 @@ nobase_include_HEADERS = dimension.h \
dimension/patterns.h \
dimension/pigments.h \
dimension/png.h \
+ dimension/polynomial.h \
dimension/progress.h \
dimension/raytrace.h \
dimension/scene.h \
@@ -58,9 +60,9 @@ libdimension_la_SOURCES = $(nobase_include_HEADERS) \
checker.c \
color.c \
color_map.c \
+ cone.c \
cube.c \
csg.c \
- cylinder.c \
diffuse.c \
dimension-impl.h \
error.c \
@@ -128,9 +130,17 @@ all-local: libdimension.la
true; \
done
-clean-local:
+clean-pgo:
rm -rf pgo
+clean-local: clean-docs clean-pgo
+else
+clean-local: clean-docs
endif
+doc:
+ doxygen Doxyfile
+clean-docs:
+ rm -rf $(top_builddir)/doc/libdimension
+
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libdimension.pc
diff --git a/libdimension/ambient.c b/libdimension/ambient.c
index 7c68b4c..d00b031 100644
--- a/libdimension/ambient.c
+++ b/libdimension/ambient.c
@@ -18,14 +18,16 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Ambient finish.
+ */
+
#include "dimension.h"
#include <math.h>
#include <stdlib.h>
-/*
- * Ambient finish
- */
-
+/** Ambient finish callback. */
static dmnsn_color
dmnsn_ambient_finish_fn(const dmnsn_finish *finish, dmnsn_color pigment)
{
diff --git a/libdimension/camera.c b/libdimension/camera.c
index 08c4e1a..d963d1b 100644
--- a/libdimension/camera.c
+++ b/libdimension/camera.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Cameras.
+ */
+
#include "dimension.h"
#include <stdlib.h>
@@ -27,6 +32,7 @@ dmnsn_new_camera()
{
dmnsn_camera *camera = dmnsn_malloc(sizeof(dmnsn_camera));
camera->free_fn = NULL;
+ camera->trans = dmnsn_identity_matrix();
return camera;
}
@@ -41,3 +47,11 @@ dmnsn_delete_camera(dmnsn_camera *camera)
dmnsn_free(camera);
}
}
+
+/* Invoke the camera ray function */
+dmnsn_line
+dmnsn_camera_ray(const dmnsn_camera *camera, double x, double y)
+{
+ dmnsn_line ray = (*camera->ray_fn)(camera, x, y);
+ return dmnsn_transform_line(camera->trans, ray);
+}
diff --git a/libdimension/canvas.c b/libdimension/canvas.c
index da4f1aa..53dd980 100644
--- a/libdimension/canvas.c
+++ b/libdimension/canvas.c
@@ -18,25 +18,30 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Canveses.
+ */
+
#include "dimension.h"
#include <stdlib.h> /* For dmnsn_free() */
/* Allocate a new canvas, of width x and height y */
dmnsn_canvas *
-dmnsn_new_canvas(size_t x, size_t y)
+dmnsn_new_canvas(size_t width, size_t height)
{
/* Allocate the dmnsn_canvas struct */
dmnsn_canvas *canvas = dmnsn_malloc(sizeof(dmnsn_canvas));
/* Set the width and height */
- canvas->x = x;
- canvas->y = y;
+ canvas->width = width;
+ canvas->height = height;
/* Allocate room for the optimizers */
canvas->optimizers = dmnsn_new_array(sizeof(dmnsn_canvas_optimizer));
/* Allocate the pixels */
- canvas->pixels = dmnsn_malloc(sizeof(dmnsn_color)*x*y);
+ canvas->pixels = dmnsn_malloc(sizeof(dmnsn_color)*width*height);
return canvas;
}
@@ -72,8 +77,11 @@ void
dmnsn_set_pixel(dmnsn_canvas *canvas, size_t x, size_t y,
dmnsn_color color)
{
+ dmnsn_assert(x < canvas->width && y < canvas->height,
+ "Canvas access out of bounds.");
+
/* Set the pixel */
- canvas->pixels[y*canvas->x + x] = color;
+ canvas->pixels[y*canvas->width + x] = color;
/* Call the optimizers */
DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) {
@@ -85,8 +93,8 @@ dmnsn_set_pixel(dmnsn_canvas *canvas, size_t x, size_t y,
void
dmnsn_clear_canvas(dmnsn_canvas *canvas, dmnsn_color color)
{
- for (size_t x = 0; x < canvas->x; ++x) {
- for (size_t y = 0; y < canvas->y; ++y) {
+ for (size_t x = 0; x < canvas->width; ++x) {
+ for (size_t y = 0; y < canvas->height; ++y) {
dmnsn_set_pixel(canvas, x, y, color);
}
}
diff --git a/libdimension/canvas_pigment.c b/libdimension/canvas_pigment.c
index c86fc66..a1820c4 100644
--- a/libdimension/canvas_pigment.c
+++ b/libdimension/canvas_pigment.c
@@ -18,25 +18,14 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension.h"
-
-/* Canvas color pigment callback */
-static dmnsn_color dmnsn_canvas_pigment_fn(const dmnsn_pigment *pigment,
- dmnsn_vector v);
-static void dmnsn_canvas_pigment_free_fn(void *ptr);
+/**
+ * @file
+ * Image maps.
+ */
-/* Create a canvas color */
-dmnsn_pigment *
-dmnsn_new_canvas_pigment(dmnsn_canvas *canvas)
-{
- dmnsn_pigment *pigment = dmnsn_new_pigment();
- pigment->pigment_fn = &dmnsn_canvas_pigment_fn;
- pigment->free_fn = &dmnsn_canvas_pigment_free_fn;
- pigment->ptr = canvas;
- return pigment;
-}
+#include "dimension.h"
-/* Canvas color callback */
+/** Canvas pigment color callback. */
static dmnsn_color
dmnsn_canvas_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v)
{
@@ -44,14 +33,26 @@ dmnsn_canvas_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v)
dmnsn_canvas *canvas = pigment->ptr;
- int x = (fmod(v.x, 1.0) + 1.0)*(canvas->x - 1) + 0.5;
- int y = (fmod(v.y, 1.0) + 1.0)*(canvas->y - 1) + 0.5;
- dmnsn_color c = dmnsn_get_pixel(canvas, x%canvas->x, y%canvas->y);
+ int x = (fmod(v.x, 1.0) + 1.0)*(canvas->width - 1) + 0.5;
+ int y = (fmod(v.y, 1.0) + 1.0)*(canvas->height - 1) + 0.5;
+ dmnsn_color c = dmnsn_get_pixel(canvas, x%canvas->width, y%canvas->height);
return c;
}
+/** Canvas pigment destructor. */
static void
dmnsn_canvas_pigment_free_fn(void *ptr)
{
dmnsn_delete_canvas(ptr);
}
+
+/* Create a canvas color */
+dmnsn_pigment *
+dmnsn_new_canvas_pigment(dmnsn_canvas *canvas)
+{
+ dmnsn_pigment *pigment = dmnsn_new_pigment();
+ pigment->pigment_fn = &dmnsn_canvas_pigment_fn;
+ pigment->free_fn = &dmnsn_canvas_pigment_free_fn;
+ pigment->ptr = canvas;
+ return pigment;
+}
diff --git a/libdimension/checker.c b/libdimension/checker.c
index 9c1de34..0424cd6 100644
--- a/libdimension/checker.c
+++ b/libdimension/checker.c
@@ -18,12 +18,14 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension.h"
-
-/*
- * Checker pattern
+/**
+ * @file
+ * Checker pattern.
*/
+#include "dimension.h"
+
+/** Checker pattern callback. */
static double
dmnsn_checker_pattern_fn(const dmnsn_pattern *checker, dmnsn_vector v)
{
@@ -50,7 +52,7 @@ dmnsn_checker_pattern_fn(const dmnsn_pattern *checker, dmnsn_vector v)
}
dmnsn_pattern *
-dmnsn_new_checker_pattern()
+dmnsn_new_checker_pattern(void)
{
dmnsn_pattern *checker = dmnsn_new_pattern();
checker->pattern_fn = &dmnsn_checker_pattern_fn;
diff --git a/libdimension/color.c b/libdimension/color.c
index eee1f0e..e91ebc1 100644
--- a/libdimension/color.c
+++ b/libdimension/color.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Color handling.
+ */
+
#include "dimension.h"
#include <math.h> /* For pow(), sqrt() */
@@ -97,7 +102,21 @@ dmnsn_color_is_black(dmnsn_color color)
return color.R == 0.0 && color.G == 0.0 && color.B == 0.0;
}
-/* sRGB's `C' function */
+/* Convert an sRGB color to a dmnsn_color (actually a no-op) */
+dmnsn_color
+dmnsn_color_from_sRGB(dmnsn_sRGB sRGB)
+{
+ dmnsn_color ret = {
+ .R = sRGB.R,
+ .G = sRGB.G,
+ .B = sRGB.B,
+ .filter = 0.0,
+ .trans = 0.0
+ };
+ return ret;
+}
+
+/** sRGB's `C' function. */
static double
dmnsn_sRGB_C(double Clinear)
{
@@ -144,7 +163,8 @@ dmnsn_color_from_xyY(dmnsn_CIE_xyY xyY)
return dmnsn_color_from_XYZ(ret);
}
-/* Inverse function of CIE L*a*b*'s `f' function, for the reverse conversion */
+/** Inverse function of CIE L*a*b*'s `f' function, for the reverse
+ conversion. */
static double
dmnsn_Lab_finv(double t)
{
@@ -195,21 +215,15 @@ dmnsn_color_from_Luv(dmnsn_CIE_Luv Luv, dmnsn_CIE_XYZ white)
return dmnsn_color_from_XYZ(ret);
}
-/* Convert an sRGB color to a dmnsn_color (actually a no-op) */
-dmnsn_color
-dmnsn_color_from_sRGB(dmnsn_sRGB sRGB)
+/* Convert a dmnsn_color to an sRGB color (actually a no-op) */
+dmnsn_sRGB
+dmnsn_sRGB_from_color(dmnsn_color color)
{
- dmnsn_color ret = {
- .R = sRGB.R,
- .G = sRGB.G,
- .B = sRGB.B,
- .filter = 0.0,
- .trans = 0.0
- };
- return ret;
+ dmnsn_sRGB sRGB = { .R = color.R, .G = color.G, .B = color.B };
+ return sRGB;
}
-/* Inverse function of sRGB's `C' function, for the reverse conversion */
+/** Inverse function of sRGB's `C' function, for the reverse conversion. */
static double
dmnsn_sRGB_Cinv(double CsRGB)
{
@@ -260,7 +274,7 @@ dmnsn_xyY_from_color(dmnsn_color color)
return ret;
}
-/* CIE L*a*b*'s `f' function */
+/** CIE L*a*b*'s `f' function. */
static double
dmnsn_Lab_f(double t)
{
@@ -305,14 +319,7 @@ dmnsn_Luv_from_color(dmnsn_color color, dmnsn_CIE_XYZ white)
return ret;
}
-/* Convert a dmnsn_color to an sRGB color (actually a no-op) */
-dmnsn_sRGB
-dmnsn_sRGB_from_color(dmnsn_color color)
-{
- dmnsn_sRGB sRGB = { .R = color.R, .G = color.G, .B = color.B };
- return sRGB;
-}
-
+/** Greyscale color intensity. */
static double
dmnsn_color_intensity(dmnsn_color color)
{
diff --git a/libdimension/color_map.c b/libdimension/color_map.c
index 1123789..f839335 100644
--- a/libdimension/color_map.c
+++ b/libdimension/color_map.c
@@ -18,19 +18,21 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension.h"
-
-/*
- * Color-mapped patterned pigments
+/**
+ * @file
+ * Color-mapped pigment patterns.
*/
+#include "dimension.h"
+
+/** An [index, color] pair. */
typedef struct dmnsn_color_map_entry {
double n;
dmnsn_color color;
} dmnsn_color_map_entry;
dmnsn_color_map *
-dmnsn_new_color_map()
+dmnsn_new_color_map(void)
{
return dmnsn_new_array(sizeof(dmnsn_color_map_entry));
}
@@ -84,11 +86,13 @@ dmnsn_color_map_value(const dmnsn_color_map *map, double n)
return c2;
}
+/** Payload for a color_map pigment */
typedef struct dmnsn_color_map_payload {
dmnsn_pattern *pattern;
dmnsn_color_map *map;
} dmnsn_color_map_payload;
+/** Free a color_map payload. */
static void
dmnsn_delete_color_map_payload(void *ptr)
{
@@ -98,6 +102,7 @@ dmnsn_delete_color_map_payload(void *ptr)
dmnsn_free(payload);
}
+/** color_map pigment callback. */
static dmnsn_color
dmnsn_color_map_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v)
{
@@ -106,6 +111,7 @@ dmnsn_color_map_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v)
dmnsn_pattern_value(payload->pattern, v));
}
+/** color_map initialization callback. */
static void
dmnsn_color_map_init_fn(dmnsn_pigment *pigment)
{
diff --git a/libdimension/cylinder.c b/libdimension/cone.c
index 9f5b7ff..9f5340a 100644
--- a/libdimension/cylinder.c
+++ b/libdimension/cone.c
@@ -18,52 +18,26 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension.h"
-#include <math.h>
-
-/*
- * Cylinder
+/**
+ * @file
+ * Cones/cylinders.
*/
-/* Cylinder callbacks */
-static bool dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder,
- dmnsn_line line,
- dmnsn_intersection *intersection);
-static bool dmnsn_cylinder_inside_fn(const dmnsn_object *cylinder,
- dmnsn_vector point);
+#include "dimension.h"
+#include <math.h>
-/* Payload type */
-typedef struct dmnsn_cylinder_payload {
+/** Cone payload type. */
+typedef struct dmnsn_cone_payload {
double r1, r2;
bool open;
-} dmnsn_cylinder_payload;
+} dmnsn_cone_payload;
-/* Allocate a new cylinder object */
-dmnsn_object *
-dmnsn_new_cylinder(double r1, double r2, bool open)
-{
- dmnsn_object *cylinder = dmnsn_new_object();
- cylinder->intersection_fn = &dmnsn_cylinder_intersection_fn;
- cylinder->inside_fn = &dmnsn_cylinder_inside_fn;
- cylinder->bounding_box.min = dmnsn_new_vector(-1.0, -1.0, -1.0);
- cylinder->bounding_box.max = dmnsn_new_vector(1.0, 1.0, 1.0);
-
- dmnsn_cylinder_payload *payload
- = dmnsn_malloc(sizeof(dmnsn_cylinder_payload));
- payload->r1 = r1;
- payload->r2 = r2;
- payload->open = open;
- cylinder->ptr = payload;
- cylinder->free_fn = &dmnsn_free;
- return cylinder;
-}
-
-/* Intersections callback for a cylinder */
+/** Intersection callback for a cone. */
static bool
-dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line l,
- dmnsn_intersection *intersection)
+dmnsn_cone_intersection_fn(const dmnsn_object *cone, dmnsn_line l,
+ dmnsn_intersection *intersection)
{
- const dmnsn_cylinder_payload *payload = cylinder->ptr;
+ const dmnsn_cone_payload *payload = cone->ptr;
double r1 = payload->r1, r2 = payload->r2;
/* Solve (x0 + nx*t)^2 + (z0 + nz*t)^2
@@ -130,8 +104,8 @@ dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line l,
intersection->ray = l;
intersection->t = tcap;
intersection->normal = norm;
- intersection->texture = cylinder->texture;
- intersection->interior = cylinder->interior;
+ intersection->texture = cone->texture;
+ intersection->interior = cone->interior;
return true;
}
}
@@ -143,8 +117,8 @@ dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line l,
intersection->ray = l;
intersection->t = t;
intersection->normal = norm;
- intersection->texture = cylinder->texture;
- intersection->interior = cylinder->interior;
+ intersection->texture = cone->texture;
+ intersection->interior = cone->interior;
return true;
}
}
@@ -152,13 +126,33 @@ dmnsn_cylinder_intersection_fn(const dmnsn_object *cylinder, dmnsn_line l,
return false;
}
-/* Inside callback for a cylinder */
+/** Inside callback for a cone. */
static bool
-dmnsn_cylinder_inside_fn(const dmnsn_object *cylinder, dmnsn_vector point)
+dmnsn_cone_inside_fn(const dmnsn_object *cone, dmnsn_vector point)
{
- const dmnsn_cylinder_payload *payload = cylinder->ptr;
+ const dmnsn_cone_payload *payload = cone->ptr;
double r1 = payload->r1, r2 = payload->r2;
double r = (point.y*(r2 - r1) + r1 + r2)/2.0;
return point.x*point.x + point.z*point.z < r*r
&& point.y > -1.0 && point.y < 1.0;
}
+
+/* Allocate a new cone object */
+dmnsn_object *
+dmnsn_new_cone(double r1, double r2, bool open)
+{
+ dmnsn_object *cone = dmnsn_new_object();
+ cone->intersection_fn = &dmnsn_cone_intersection_fn;
+ cone->inside_fn = &dmnsn_cone_inside_fn;
+ double rmax = dmnsn_max(r1, r2);
+ cone->bounding_box.min = dmnsn_new_vector(-rmax, -1.0, -rmax);
+ cone->bounding_box.max = dmnsn_new_vector(rmax, 1.0, rmax);
+
+ dmnsn_cone_payload *payload = dmnsn_malloc(sizeof(dmnsn_cone_payload));
+ payload->r1 = r1;
+ payload->r2 = r2;
+ payload->open = open;
+ cone->ptr = payload;
+ cone->free_fn = &dmnsn_free;
+ return cone;
+}
diff --git a/libdimension/csg.c b/libdimension/csg.c
index 58104ff..ff45158 100644
--- a/libdimension/csg.c
+++ b/libdimension/csg.c
@@ -18,10 +18,15 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Constructive solid geometry.
+ */
+
#include "dimension-impl.h"
#include <stdlib.h>
-/* Apply the properties of `csg' to its children */
+/** Apply the properties of \p csg to its children. */
static void
dmnsn_csg_cascade(const dmnsn_object *csg, dmnsn_object *object)
{
@@ -38,8 +43,11 @@ dmnsn_csg_cascade(const dmnsn_object *csg, dmnsn_object *object)
object->trans = dmnsn_matrix_mul(csg->trans, object->trans);
}
-/* Unions */
+/*
+ * Unions
+ */
+/** CSG union intersection callback. */
static bool
dmnsn_csg_union_intersection_fn(const dmnsn_object *csg,
dmnsn_line line,
@@ -49,6 +57,7 @@ dmnsn_csg_union_intersection_fn(const dmnsn_object *csg,
return dmnsn_prtree_intersection(prtree, line, intersection);
}
+/** CSG union inside callback. */
static bool
dmnsn_csg_union_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
{
@@ -56,6 +65,7 @@ dmnsn_csg_union_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
return dmnsn_prtree_inside(prtree, point);
}
+/** CSG union initialization callback. */
static void
dmnsn_csg_union_init_fn(dmnsn_object *csg)
{
@@ -70,6 +80,7 @@ dmnsn_csg_union_init_fn(dmnsn_object *csg)
csg->bounding_box = prtree->bounding_box;
}
+/** CSG union destruction callback. */
static void
dmnsn_csg_union_free_fn(void *ptr)
{
@@ -78,7 +89,7 @@ dmnsn_csg_union_free_fn(void *ptr)
/* Bulk-load a union */
dmnsn_object *
-dmnsn_new_csg_union(dmnsn_array *objects)
+dmnsn_new_csg_union(const dmnsn_array *objects)
{
dmnsn_object *csg = dmnsn_new_object();
@@ -94,7 +105,7 @@ dmnsn_new_csg_union(dmnsn_array *objects)
return csg;
}
-/* Generic CSG free function */
+/** Generic CSG destruction callback. */
static void
dmnsn_csg_free_fn(void *ptr)
{
@@ -104,15 +115,22 @@ dmnsn_csg_free_fn(void *ptr)
dmnsn_free(ptr);
}
-/* Generic CSG intersection function */
+/**
+ * Generic CSG intersection callback.
+ * @param[in] csg The CSG object.
+ * @param[in] line The intersection ray.
+ * @param[out] intersection The intersection data.
+ * @param[in] inside1 Whether the first object is allowed inside the
+ * second object.
+ * @param[in] inside2 Whether the second object is allowed inside the
+ * first object.
+ * @return Whether \p line intersected \p csg.
+ */
static bool
dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line,
dmnsn_intersection *intersection,
bool inside1, bool inside2)
{
- /* inside1 is whether the second object is allowed inside the first object;
- respectively for inside2 */
-
const dmnsn_object **params = csg->ptr;
dmnsn_intersection i1, i2;
@@ -170,8 +188,11 @@ dmnsn_csg_intersection_fn(const dmnsn_object *csg, dmnsn_line line,
return true;
}
-/* Intersections */
+/*
+ * Intersections
+ */
+/** CSG intersection intersection callback. */
static bool
dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg,
dmnsn_line line,
@@ -180,6 +201,7 @@ dmnsn_csg_intersection_intersection_fn(const dmnsn_object *csg,
return dmnsn_csg_intersection_fn(csg, line, intersection, true, true);
}
+/** CSG intersection inside callback. */
static bool
dmnsn_csg_intersection_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
{
@@ -188,6 +210,7 @@ dmnsn_csg_intersection_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
&& dmnsn_object_inside(params[1], point);
}
+/** CSG intersection initialization callback. */
static void
dmnsn_csg_intersection_init_fn(dmnsn_object *csg)
{
@@ -226,8 +249,11 @@ dmnsn_new_csg_intersection(dmnsn_object *A, dmnsn_object *B)
return csg;
}
-/* Differences */
+/*
+ * Differences
+ */
+/** CSG difference intersection callback. */
static bool
dmnsn_csg_difference_intersection_fn(const dmnsn_object *csg,
dmnsn_line line,
@@ -236,6 +262,7 @@ dmnsn_csg_difference_intersection_fn(const dmnsn_object *csg,
return dmnsn_csg_intersection_fn(csg, line, intersection, true, false);
}
+/** CSG difference inside callback. */
static bool
dmnsn_csg_difference_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
{
@@ -244,6 +271,7 @@ dmnsn_csg_difference_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
&& !dmnsn_object_inside(params[1], point);
}
+/** CSG difference initialization callback. */
static void
dmnsn_csg_difference_init_fn(dmnsn_object *csg)
{
@@ -279,8 +307,11 @@ dmnsn_new_csg_difference(dmnsn_object *A, dmnsn_object *B)
return csg;
}
-/* Merges */
+/*
+ * Merges
+ */
+/** CSG merge intersection callback. */
static bool
dmnsn_csg_merge_intersection_fn(const dmnsn_object *csg,
dmnsn_line line,
@@ -289,6 +320,7 @@ dmnsn_csg_merge_intersection_fn(const dmnsn_object *csg,
return dmnsn_csg_intersection_fn(csg, line, intersection, false, false);
}
+/** CSG merge inside callback. */
static bool
dmnsn_csg_merge_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
{
@@ -297,6 +329,7 @@ dmnsn_csg_merge_inside_fn(const dmnsn_object *csg, dmnsn_vector point)
|| dmnsn_object_inside(params[1], point);
}
+/** CSG merge initialization callback. */
static void
dmnsn_csg_merge_init_fn(dmnsn_object *csg)
{
diff --git a/libdimension/cube.c b/libdimension/cube.c
index c70ebf6..6e3120e 100644
--- a/libdimension/cube.c
+++ b/libdimension/cube.c
@@ -18,33 +18,15 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension.h"
-#include <math.h>
-
-/*
- * Cube
+/**
+ * @file
+ * Cubes.
*/
-/* Cube callbacks */
-static bool dmnsn_cube_intersection_fn(const dmnsn_object *cube,
- dmnsn_line line,
- dmnsn_intersection *intersection);
-static bool dmnsn_cube_inside_fn(const dmnsn_object *cube,
- dmnsn_vector point);
-
-/* Allocate a new cube object */
-dmnsn_object *
-dmnsn_new_cube()
-{
- dmnsn_object *cube = dmnsn_new_object();
- cube->intersection_fn = &dmnsn_cube_intersection_fn;
- cube->inside_fn = &dmnsn_cube_inside_fn;
- cube->bounding_box.min = dmnsn_new_vector(-1.0, -1.0, -1.0);
- cube->bounding_box.max = dmnsn_new_vector(1.0, 1.0, 1.0);
- return cube;
-}
+#include "dimension.h"
+#include <math.h>
-/* Intersections callback for a cube */
+/** Intersection callback for a cube. */
static bool
dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line,
dmnsn_intersection *intersection)
@@ -141,7 +123,7 @@ dmnsn_cube_intersection_fn(const dmnsn_object *cube, dmnsn_line line,
}
}
-/* Inside callback for a cube */
+/** Inside callback for a cube. */
static bool
dmnsn_cube_inside_fn(const dmnsn_object *cube, dmnsn_vector point)
{
@@ -149,3 +131,15 @@ dmnsn_cube_inside_fn(const dmnsn_object *cube, dmnsn_vector point)
&& point.y > -1.0 && point.y < 1.0
&& point.z > -1.0 && point.z < 1.0;
}
+
+/* Allocate a new cube object */
+dmnsn_object *
+dmnsn_new_cube()
+{
+ dmnsn_object *cube = dmnsn_new_object();
+ cube->intersection_fn = &dmnsn_cube_intersection_fn;
+ cube->inside_fn = &dmnsn_cube_inside_fn;
+ cube->bounding_box.min = dmnsn_new_vector(-1.0, -1.0, -1.0);
+ cube->bounding_box.max = dmnsn_new_vector(1.0, 1.0, 1.0);
+ return cube;
+}
diff --git a/libdimension/diffuse.c b/libdimension/diffuse.c
index beafbd8..64a2953 100644
--- a/libdimension/diffuse.c
+++ b/libdimension/diffuse.c
@@ -18,14 +18,16 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Diffuse finish.
+ */
+
#include "dimension.h"
#include <math.h>
#include <stdlib.h>
-/*
- * Diffuse finish
- */
-
+/** Diffuse finish callback. */
static dmnsn_color
dmnsn_diffuse_finish_fn(const dmnsn_finish *finish,
dmnsn_color light, dmnsn_color color,
diff --git a/libdimension/dimension-impl.h b/libdimension/dimension-impl.h
index 7d1f943..2746b1c 100644
--- a/libdimension/dimension-impl.h
+++ b/libdimension/dimension-impl.h
@@ -18,6 +18,12 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * The internal libdimension API. These functions and types are used to
+ * implement libdimension, but are not part of its public API.
+ */
+
#ifndef DIMENSION_IMPL_H
#define DIMENSION_IMPL_H
diff --git a/libdimension/dimension.h b/libdimension/dimension.h
index 5f84054..55b3b87 100644
--- a/libdimension/dimension.h
+++ b/libdimension/dimension.h
@@ -18,8 +18,22 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-/*
- * libdimension - a library for photo-realistic 3-D rendering
+/**
+ * @file
+ * The main #include file for libdimension. This file declares all public
+ * functions and types used by the Dimension library. You should never attempt
+ * to include any of the component headers in the dimension/ subdirectory
+ * directly; only this file.
+ */
+
+/**
+ * @mainpage libdimension - A library for photo-realistic 3-D rendering
+ *
+ * The Dimension library (libdimension) is the ray-tracing library that handles
+ * all rendering-related tasks for Dimension. It is written in C and designed
+ * with performance and concurrency in mind. It is also generic enough to be
+ * used for applications other than Dimension, though that is its primary
+ * purpose.
*/
#ifndef DIMENSION_H
@@ -31,6 +45,11 @@ extern "C" {
#endif
/* Common types */
+
+/**
+ * Destructor callback type.
+ * @param[in,out] ptr The pointer to free.
+ */
typedef void dmnsn_free_fn(void *ptr);
/* Include all the libdimension headers */
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);
diff --git a/libdimension/error.c b/libdimension/error.c
index 31d1606..f87c655 100644
--- a/libdimension/error.c
+++ b/libdimension/error.c
@@ -18,17 +18,28 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Error handling.
+ */
+
#include "dimension-impl.h"
#include <pthread.h>
#include <stdio.h> /* For fprintf() */
#include <stdlib.h> /* For exit() */
+/** The default fatal error handler. */
static void dmnsn_default_fatal_error_fn(void);
+
+/** The current fatal error handler. */
static dmnsn_fatal_error_fn *dmnsn_fatal = &dmnsn_default_fatal_error_fn;
+/** Mutex which protects \c dmnsn_fatal. */
+static pthread_mutex_t dmnsn_fatal_mutex = PTHREAD_MUTEX_INITIALIZER;
+/** The current resilience. */
static dmnsn_severity dmnsn_resilience = DMNSN_SEVERITY_MEDIUM;
+/** Mutex which protexts \c dmnsn_resilience. */
static pthread_mutex_t dmnsn_resilience_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t dmnsn_fatal_mutex = PTHREAD_MUTEX_INITIALIZER;
/* Called by dmnsn_error macro (don't call directly). */
void
diff --git a/libdimension/finish_combination.c b/libdimension/finish_combination.c
index 1a54d22..49908bd 100644
--- a/libdimension/finish_combination.c
+++ b/libdimension/finish_combination.c
@@ -18,14 +18,16 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Finish combinations.
+ */
+
#include "dimension.h"
#include <math.h>
#include <stdlib.h>
-/*
- * Finish combinations
- */
-
+/** Diffuse combination callback. */
static dmnsn_color
dmnsn_finish_combination_diffuse_fn(const dmnsn_finish *finish,
dmnsn_color light, dmnsn_color color,
@@ -46,6 +48,7 @@ dmnsn_finish_combination_diffuse_fn(const dmnsn_finish *finish,
}
}
+/** Specular combination callback. */
static dmnsn_color
dmnsn_finish_combination_specular_fn(const dmnsn_finish *finish,
dmnsn_color light, dmnsn_color color,
@@ -69,6 +72,7 @@ dmnsn_finish_combination_specular_fn(const dmnsn_finish *finish,
}
}
+/** Ambient combination callback. */
static dmnsn_color
dmnsn_finish_combination_ambient_fn(const dmnsn_finish *finish,
dmnsn_color pigment)
@@ -86,6 +90,7 @@ dmnsn_finish_combination_ambient_fn(const dmnsn_finish *finish,
}
}
+/** Reflection combination callback. */
static dmnsn_color
dmnsn_finish_combination_reflection_fn(const dmnsn_finish *finish,
dmnsn_color reflect, dmnsn_color color,
@@ -106,6 +111,7 @@ dmnsn_finish_combination_reflection_fn(const dmnsn_finish *finish,
}
}
+/** Finish combination destructor callback. */
static void
dmnsn_finish_combination_free_fn(void *ptr)
{
diff --git a/libdimension/geometry.c b/libdimension/geometry.c
index 6d3652f..9f198b8 100644
--- a/libdimension/geometry.c
+++ b/libdimension/geometry.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Geometrical function implementations.
+ */
+
#include "dimension.h"
#include <math.h>
@@ -58,7 +63,7 @@ dmnsn_rotation_matrix(dmnsn_vector theta)
/* Two trig calls, 25 multiplications, 13 additions */
double angle = dmnsn_vector_norm(theta);
- if (angle == 0.0) {
+ if (fabs(angle) < dmnsn_epsilon) {
return dmnsn_identity_matrix();
}
dmnsn_vector axis = dmnsn_vector_div(theta, angle);
@@ -88,14 +93,14 @@ dmnsn_vector_axis_angle(dmnsn_vector v1, dmnsn_vector v2, dmnsn_vector axis)
dmnsn_vector proj = dmnsn_vector_add(dmnsn_vector_proj(d, axis), v2);
double projn = dmnsn_vector_norm(proj);
- if (!projn)
+ if (fabs(projn) < dmnsn_epsilon)
return 0.0;
double c = dmnsn_vector_dot(dmnsn_vector_normalize(v1),
dmnsn_vector_div(proj, projn));
double angle = acos(c);
- if (dmnsn_vector_dot(dmnsn_vector_cross(v1, proj), axis) > 0) {
+ if (dmnsn_vector_dot(dmnsn_vector_cross(v1, proj), axis) > 0.0) {
return angle;
} else {
return -angle;
@@ -104,16 +109,25 @@ dmnsn_vector_axis_angle(dmnsn_vector v1, dmnsn_vector v2, dmnsn_vector axis)
/* Matrix inversion helper functions */
+/** A 2x2 matrix for inversion by partitioning. */
typedef struct { double n[2][2]; } dmnsn_matrix2;
+/** Construct a 2x2 matrix. */
static dmnsn_matrix2 dmnsn_new_matrix2(double a1, double a2,
double b1, double b2);
+/** Invert a 2x2 matrix. */
static dmnsn_matrix2 dmnsn_matrix2_inverse(dmnsn_matrix2 A);
+/** Negate a 2x2 matrix. */
static dmnsn_matrix2 dmnsn_matrix2_negate(dmnsn_matrix2 A);
+/** Subtract two 2x2 matricies. */
static dmnsn_matrix2 dmnsn_matrix2_sub(dmnsn_matrix2 lhs, dmnsn_matrix2 rhs);
+/** Add two 2x2 matricies. */
static dmnsn_matrix2 dmnsn_matrix2_mul(dmnsn_matrix2 lhs, dmnsn_matrix2 rhs);
+/** Invert a matrix with the slower cofactor algorithm, if partitioning
+ failed. */
static dmnsn_matrix dmnsn_matrix_inverse_generic(dmnsn_matrix A);
+/** Get the [\p row, \p col] cofactor of A */
static double dmnsn_matrix_cofactor(dmnsn_matrix A,
unsigned int row, unsigned int col);
@@ -395,29 +409,3 @@ dmnsn_transform_bounding_box(dmnsn_matrix trans, dmnsn_bounding_box box)
return ret;
}
-
-/* Solve for the t value such that x0 + t*n = x */
-double
-dmnsn_line_index(dmnsn_line l, dmnsn_vector x)
-{
- /* nz + 1 divisions, nz additions */
- double d = 0.0;
- unsigned int nz = 0;
-
- if (l.n.x != 0.0) {
- d += (x.x - l.x0.x)/l.n.x;
- ++nz;
- }
-
- if (l.n.y != 0.0) {
- d += (x.y - l.x0.y)/l.n.y;
- ++nz;
- }
-
- if (l.n.z != 0.0) {
- d += (x.z - l.x0.z)/l.n.z;
- ++nz;
- }
-
- return d/nz;
-}
diff --git a/libdimension/gl-stubs.c b/libdimension/gl-stubs.c
index 1d6946d..656b6a8 100644
--- a/libdimension/gl-stubs.c
+++ b/libdimension/gl-stubs.c
@@ -18,11 +18,14 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Stubs for GL functions when compiled with --disable-gl.
+ */
+
#include "dimension.h"
#include <errno.h>
-/* Stubs for GL functions when compiled with --disable-gl */
-
int
dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas)
{
diff --git a/libdimension/gl.c b/libdimension/gl.c
index b09509e..2b26938 100644
--- a/libdimension/gl.c
+++ b/libdimension/gl.c
@@ -18,13 +18,18 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * OpenGL import/export.
+ */
+
#include "dimension.h"
#include <GL/gl.h>
#include <stdlib.h>
#include <stdint.h>
-/* GL optimizer callback */
-static void dmnsn_gl_optimizer_fn(dmnsn_canvas *canvas,
+/** GL optimizer callback. */
+static void dmnsn_gl_optimizer_fn(const dmnsn_canvas *canvas,
dmnsn_canvas_optimizer optimizer,
size_t x, size_t y);
@@ -44,7 +49,7 @@ dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas)
optimizer.free_fn = &dmnsn_free;
/* Allocate a buffer to hold RGB values */
- optimizer.ptr = dmnsn_malloc(4*canvas->x*canvas->y*sizeof(GLushort));
+ optimizer.ptr = dmnsn_malloc(4*canvas->width*canvas->height*sizeof(GLushort));
/* Set a new optimizer */
dmnsn_optimize_canvas(canvas, optimizer);
@@ -60,8 +65,8 @@ dmnsn_gl_write_canvas(const dmnsn_canvas *canvas)
dmnsn_sRGB sRGB;
dmnsn_color color;
- size_t width = canvas->x;
- size_t height = canvas->y;
+ size_t width = canvas->width;
+ size_t height = canvas->height;
/* Check if we can optimize this */
DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) {
@@ -160,12 +165,12 @@ dmnsn_gl_read_canvas(size_t x0, size_t y0,
/* GL optimizer callback */
static void
-dmnsn_gl_optimizer_fn(dmnsn_canvas *canvas, dmnsn_canvas_optimizer optimizer,
- size_t x, size_t y)
+dmnsn_gl_optimizer_fn(const dmnsn_canvas *canvas,
+ dmnsn_canvas_optimizer optimizer, size_t x, size_t y)
{
dmnsn_color color;
dmnsn_sRGB sRGB;
- GLushort *pixel = (GLushort *)optimizer.ptr + 4*(y*canvas->x + x);
+ GLushort *pixel = (GLushort *)optimizer.ptr + 4*(y*canvas->width + x);
color = dmnsn_get_pixel(canvas, x, y);
sRGB = dmnsn_sRGB_from_color(color);
diff --git a/libdimension/gradient.c b/libdimension/gradient.c
index 6bcb3b8..47e6c6b 100644
--- a/libdimension/gradient.c
+++ b/libdimension/gradient.c
@@ -18,12 +18,14 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension.h"
-
-/*
- * Gradient pattern
+/**
+ * @file
+ * Gradient pattern.
*/
+#include "dimension.h"
+
+/** Gradient pattern callback. */
static double
dmnsn_gradient_pattern_fn(const dmnsn_pattern *gradient, dmnsn_vector v)
{
diff --git a/libdimension/inline.c b/libdimension/inline.c
index adffd6c..a1b4694 100644
--- a/libdimension/inline.c
+++ b/libdimension/inline.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Emit definitions of inline functions, if necessary.
+ */
+
/* Set DMNSN_INLINE to produce definitions of inline functions, emitted here,
if needed */
#ifdef __cplusplus
diff --git a/libdimension/interior.c b/libdimension/interior.c
index 6bf76e4..035a7f6 100644
--- a/libdimension/interior.c
+++ b/libdimension/interior.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Interiors.
+ */
+
#include "dimension.h"
#include <stdlib.h>
diff --git a/libdimension/light.c b/libdimension/light.c
index 4e0f850..445a9d3 100644
--- a/libdimension/light.c
+++ b/libdimension/light.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Lights.
+ */
+
#include "dimension.h"
#include <stdlib.h>
diff --git a/libdimension/list.c b/libdimension/list.c
index 15051d6..3ccc6b8 100644
--- a/libdimension/list.c
+++ b/libdimension/list.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Doubly-linked lists.
+ */
+
#include "dimension.h"
dmnsn_list *
diff --git a/libdimension/malloc.c b/libdimension/malloc.c
index 605de8b..f5666a0 100644
--- a/libdimension/malloc.c
+++ b/libdimension/malloc.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Dynamic memory.
+ */
+
#include "dimension.h"
#include <stdlib.h>
#include <string.h>
diff --git a/libdimension/object.c b/libdimension/object.c
index d710304..bb4eeb1 100644
--- a/libdimension/object.c
+++ b/libdimension/object.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Objects.
+ */
+
#include "dimension.h"
#include <stdlib.h>
diff --git a/libdimension/pattern.c b/libdimension/pattern.c
index 0be017f..9e8dacb 100644
--- a/libdimension/pattern.c
+++ b/libdimension/pattern.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Patterns.
+ */
+
#include "dimension.h"
/* Allocate a dummy pattern */
diff --git a/libdimension/perspective.c b/libdimension/perspective.c
index cc602eb..0fa5567 100644
--- a/libdimension/perspective.c
+++ b/libdimension/perspective.c
@@ -18,60 +18,30 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Perspective cameras.
+ */
+
#include "dimension.h"
#include <stdlib.h>
-/*
- * Perspective camera
- */
-
-/* Perspective camera ray callback */
-static dmnsn_line dmnsn_perspective_camera_ray_fn(const dmnsn_camera *camera,
- double x, double y);
+/** Perspective camera ray callback. */
+static dmnsn_line
+dmnsn_perspective_camera_ray_fn(const dmnsn_camera *camera, double x, double y)
+{
+ dmnsn_line l = dmnsn_new_line(
+ dmnsn_zero,
+ dmnsn_new_vector(x - 0.5, y - 0.5, 1.0)
+ );
+ return l;
+}
-/* Create a new perspective camera. Rays are aimed from the origin to a screen
- located on the z = 1 plane, from (-0.5, -0.5) to (0.5, 0.5). Rays are then
- transformed by the camera's transformation matrix. */
+/* Create a new perspective camera. */
dmnsn_camera *
dmnsn_new_perspective_camera()
{
dmnsn_camera *camera = dmnsn_new_camera();
-
- dmnsn_matrix *ptr = dmnsn_malloc(sizeof(dmnsn_matrix));
- *ptr = dmnsn_identity_matrix();
-
camera->ray_fn = &dmnsn_perspective_camera_ray_fn;
- camera->free_fn = &dmnsn_free;
- camera->ptr = ptr;
-
return camera;
}
-
-/* Get the transformation matrix */
-dmnsn_matrix
-dmnsn_get_perspective_camera_trans(const dmnsn_camera *camera)
-{
- dmnsn_matrix *trans = camera->ptr;
- return *trans;
-}
-
-/* Set the transformation matrix */
-void
-dmnsn_set_perspective_camera_trans(dmnsn_camera *camera, dmnsn_matrix T)
-{
- dmnsn_matrix *trans = camera->ptr;
- *trans = T;
-}
-
-/* Perspective camera ray callback */
-static dmnsn_line
-dmnsn_perspective_camera_ray_fn(const dmnsn_camera *camera,
- double x, double y)
-{
- dmnsn_matrix *trans = camera->ptr;
- dmnsn_line l = dmnsn_new_line(
- dmnsn_zero,
- dmnsn_new_vector(x - 0.5, y - 0.5, 1.0)
- );
- return dmnsn_transform_line(*trans, l);
-}
diff --git a/libdimension/phong.c b/libdimension/phong.c
index f0fb3bb..e2afd15 100644
--- a/libdimension/phong.c
+++ b/libdimension/phong.c
@@ -18,13 +18,15 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Phong highlights.
+ */
+
#include "dimension.h"
#include <stdlib.h>
-/*
- * Phong finish
- */
-
+/** Phong specular highlight callback. */
static dmnsn_color
dmnsn_phong_specular_fn(const dmnsn_finish *finish,
dmnsn_color light, dmnsn_color color,
diff --git a/libdimension/plane.c b/libdimension/plane.c
index be3d91a..c941cd1 100644
--- a/libdimension/plane.c
+++ b/libdimension/plane.c
@@ -18,14 +18,15 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Planes.
+ */
+
#include "dimension.h"
#include <math.h>
#include <stdlib.h>
-/*
- * Plane
- */
-
/* Plane object callbacks */
static bool dmnsn_plane_intersection_fn(const dmnsn_object *plane,
diff --git a/libdimension/platform.c b/libdimension/platform.c
index 0317bd5..9ae579a 100644
--- a/libdimension/platform.c
+++ b/libdimension/platform.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Platform abstractions.
+ */
+
#include "dimension-impl.h"
#if HAVE_UNISTD_H
#include <unistd.h>
@@ -40,7 +45,10 @@ dmnsn_backtrace(FILE *file)
void *buffer[size];
int nptrs = backtrace(buffer, size);
- backtrace_symbols_fd(buffer, nptrs, fileno(file));
+ int fd = fileno(file);
+ if (fd != -1) {
+ backtrace_symbols_fd(buffer, nptrs, fd);
+ }
#endif
}
diff --git a/libdimension/platform.h b/libdimension/platform.h
index a5d4dc6..a339ced 100644
--- a/libdimension/platform.h
+++ b/libdimension/platform.h
@@ -18,8 +18,13 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#ifndef DIMENSION_IMPL_UTILITIES_H
-#define DIMENSION_IMPL_UTILITIES_H
+/**
+ * @file
+ * Platform abstractions.
+ */
+
+#ifndef DIMENSION_IMPL_PLATFORM_H
+#define DIMENSION_IMPL_PLATFORM_H
#include <stdbool.h>
#include <stddef.h>
@@ -37,4 +42,4 @@ bool dmnsn_is_little_endian(void);
/* Return the number of CPUs available to dimension */
size_t dmnsn_ncpus(void);
-#endif /* DIMENSION_IMPL_UTILITIES_H */
+#endif /* DIMENSION_IMPL_PLATFORM_H */
diff --git a/libdimension/png-stubs.c b/libdimension/png-stubs.c
index db4a19d..04fe608 100644
--- a/libdimension/png-stubs.c
+++ b/libdimension/png-stubs.c
@@ -18,11 +18,14 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Stubs for PNG functions when compiled with --disable-png.
+ */
+
#include "dimension.h"
#include <errno.h>
-/* Stubs for PNG functions when compiled with --disable-png */
-
int
dmnsn_png_optimize_canvas(dmnsn_canvas *canvas)
{
diff --git a/libdimension/png.c b/libdimension/png.c
index ec2b980..63cb71e 100644
--- a/libdimension/png.c
+++ b/libdimension/png.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * PNG import/export.
+ */
+
#include "dimension-impl.h"
#include <pthread.h>
#include <png.h>
@@ -26,8 +31,8 @@
#include <stdlib.h>
#include <stdint.h>
-/* PNG optimizer callback */
-static void dmnsn_png_optimizer_fn(dmnsn_canvas *canvas,
+/** PNG optimizer callback. */
+static void dmnsn_png_optimizer_fn(const dmnsn_canvas *canvas,
dmnsn_canvas_optimizer optimizer,
size_t x, size_t y);
@@ -46,7 +51,7 @@ dmnsn_png_optimize_canvas(dmnsn_canvas *canvas)
optimizer.optimizer_fn = &dmnsn_png_optimizer_fn;
optimizer.free_fn = &dmnsn_free;
- optimizer.ptr = dmnsn_malloc(4*canvas->x*canvas->y*sizeof(uint16_t));
+ optimizer.ptr = dmnsn_malloc(4*canvas->width*canvas->height*sizeof(uint16_t));
dmnsn_optimize_canvas(canvas, optimizer);
return 0;
@@ -54,12 +59,12 @@ dmnsn_png_optimize_canvas(dmnsn_canvas *canvas)
/* PNG optimizer callback */
static void
-dmnsn_png_optimizer_fn(dmnsn_canvas *canvas, dmnsn_canvas_optimizer optimizer,
- size_t x, size_t y)
+dmnsn_png_optimizer_fn(const dmnsn_canvas *canvas,
+ dmnsn_canvas_optimizer optimizer, size_t x, size_t y)
{
dmnsn_color color;
dmnsn_sRGB sRGB;
- uint16_t *pixel = (uint16_t *)optimizer.ptr + 4*(y*canvas->x + x);
+ uint16_t *pixel = (uint16_t *)optimizer.ptr + 4*(y*canvas->width + x);
color = dmnsn_get_pixel(canvas, x, y);
sRGB = dmnsn_sRGB_from_color(color);
@@ -100,22 +105,23 @@ dmnsn_png_optimizer_fn(dmnsn_canvas *canvas, dmnsn_canvas_optimizer optimizer,
}
}
-/* Payload to store function arguments for thread callbacks */
-
+/** Payload type for PNG write thread callback. */
typedef struct {
dmnsn_progress *progress;
const dmnsn_canvas *canvas;
FILE *file;
} dmnsn_png_write_payload;
+/** Payload type for PNG read thread callback. */
typedef struct {
dmnsn_progress *progress;
dmnsn_canvas **canvas;
FILE *file;
} dmnsn_png_read_payload;
-/* Thread callbacks */
+/** PNG write thread callback. */
static int dmnsn_png_write_canvas_thread(void *ptr);
+/** PNG read thread callback. */
static int dmnsn_png_read_canvas_thread(void *ptr);
/* Write a canvas to a png file, using libpng. Return 0 on success, nonzero on
@@ -140,7 +146,7 @@ dmnsn_png_write_canvas_async(const dmnsn_canvas *canvas, FILE *file)
payload->file = file;
/* Create the worker thread */
- dmnsn_new_thread(progress, NULL, &dmnsn_png_write_canvas_thread, payload);
+ dmnsn_new_thread(progress, &dmnsn_png_write_canvas_thread, payload);
return progress;
}
@@ -168,7 +174,7 @@ dmnsn_png_read_canvas_async(dmnsn_canvas **canvas, FILE *file)
payload->file = file;
/* Create the worker thread */
- dmnsn_new_thread(progress, NULL, &dmnsn_png_read_canvas_thread, payload);
+ dmnsn_new_thread(progress, &dmnsn_png_read_canvas_thread, payload);
return progress;
}
@@ -190,8 +196,8 @@ dmnsn_png_write_canvas_thread(void *ptr)
return -1;
}
- png_uint_32 width = payload->canvas->x;
- png_uint_32 height = payload->canvas->y;
+ png_uint_32 width = payload->canvas->width;
+ png_uint_32 height = payload->canvas->height;
dmnsn_new_progress_element(payload->progress, height);
@@ -321,11 +327,11 @@ dmnsn_png_write_canvas_thread(void *ptr)
return 0;
}
-/* Thread-specific pointer to the appropriate dmnsn_progress* for
- dmnsn_png_read_row_callback */
+/** Thread-specific pointer to the appropriate dmnsn_progress* for
+ dmnsn_png_read_row_callback. */
static __thread dmnsn_progress *dmnsn_tl_png_read_progress;
-/* Callback to increment the progress after a row has been read */
+/** Callback to increment the progress after a row has been read. */
static void
dmnsn_png_read_row_callback(png_structp png_ptr, png_uint_32 row, int pass)
{
diff --git a/libdimension/point_light.c b/libdimension/point_light.c
index f12df62..ba15f57 100644
--- a/libdimension/point_light.c
+++ b/libdimension/point_light.c
@@ -18,13 +18,15 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Point lights.
+ */
+
#include "dimension.h"
#include <stdlib.h>
-/*
- * Point light source
- */
-
+/** Point light callback. */
static dmnsn_color
dmnsn_point_light_fn(const dmnsn_light *light, dmnsn_vector v)
{
diff --git a/libdimension/polynomial.c b/libdimension/polynomial.c
index 20c3423..0ca31ab 100644
--- a/libdimension/polynomial.c
+++ b/libdimension/polynomial.c
@@ -18,10 +18,15 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Polynomials.
+ */
+
#include "dimension.h"
#include <math.h>
-/* Get the real degree of a polynomial, ignoring leading zeros */
+/** Get the real degree of a polynomial, ignoring leading zeros. */
static inline size_t
dmnsn_real_degree(const double poly[], size_t degree)
{
@@ -34,7 +39,7 @@ dmnsn_real_degree(const double poly[], size_t degree)
return 0;
}
-/* Divide each coefficient by the leading coefficient */
+/** Divide each coefficient by the leading coefficient. */
static inline void
dmnsn_normalize_polynomial(double poly[], size_t degree)
{
@@ -44,7 +49,7 @@ dmnsn_normalize_polynomial(double poly[], size_t degree)
poly[degree] = 1.0;
}
-/* Eliminate trivial zero roots from poly[] */
+/** Eliminate trivial zero roots from \p poly[]. */
static inline void
dmnsn_eliminate_zero_roots(double poly[], size_t *degree)
{
@@ -60,7 +65,7 @@ dmnsn_eliminate_zero_roots(double poly[], size_t *degree)
*degree -= i;
}
-/* Returns the number of sign changes between coefficients of `poly' */
+/** Returns the number of sign changes between coefficients of \p poly[]. */
static inline size_t
dmnsn_descartes_rule(const double poly[], size_t degree)
{
@@ -85,7 +90,10 @@ dmnsn_descartes_rule(const double poly[], size_t degree)
return changes;
}
+/** How many levels of Pascal's triangle to precompute. */
#define DMNSN_NBINOM 11
+
+/** Pre-computed values of Pascal's triangle. */
static const double dmnsn_pascals_triangle[DMNSN_NBINOM][DMNSN_NBINOM] = {
{ 1.0 },
{ 1.0, 1.0 },
@@ -100,7 +108,7 @@ static const double dmnsn_pascals_triangle[DMNSN_NBINOM][DMNSN_NBINOM] = {
{ 1.0, 10.0, 45.0, 120.0, 210.0, 252.0, 210.0, 120.0, 45.0, 10.0, 1.0 }
};
-/* Get the (n k) binomial coefficient */
+/** Compute the (n k) binomial coefficient. */
static inline double
dmnsn_binom(size_t n, size_t k)
{
@@ -117,7 +125,7 @@ dmnsn_binom(size_t n, size_t k)
return ret;
}
-/* Find all ranges that contain a single root, with Uspensky's algorithm */
+/** Find ranges that contain a single root, with Uspensky's algorithm. */
static size_t
dmnsn_uspensky_bounds(const double poly[], size_t degree, double bounds[][2],
size_t max_roots)
@@ -201,7 +209,7 @@ dmnsn_uspensky_bounds(const double poly[], size_t degree, double bounds[][2],
}
}
-/* Calculate a finite upper bound for the roots of poly[] */
+/** Calculate a finite upper bound for the roots of \p poly[]. */
static inline double
dmnsn_root_bound(double poly[], size_t degree)
{
@@ -214,7 +222,7 @@ dmnsn_root_bound(double poly[], size_t degree)
return bound;
}
-/* Improve a root with Newton's method */
+/** Improve a root with Newton's method. */
static inline double
dmnsn_improve_root(const double poly[], size_t degree, double x)
{
@@ -234,8 +242,8 @@ dmnsn_improve_root(const double poly[], size_t degree, double x)
return x;
}
-/* Use the false position method to find a root in a range that contains exactly
- one root */
+/** Use the false position method to find a root in a range that contains
+ exactly one root. */
static inline double
dmnsn_bisect_root(const double poly[], size_t degree, double min, double max)
{
@@ -293,7 +301,7 @@ dmnsn_bisect_root(const double poly[], size_t degree, double min, double max)
return mid;
}
-/* Use synthetic division to eliminate the root `r' from poly[] */
+/** Use synthetic division to eliminate the root \p r from \p poly[]. */
static inline void
dmnsn_eliminate_root(double poly[], size_t *degree, double r)
{
@@ -307,8 +315,7 @@ dmnsn_eliminate_root(double poly[], size_t *degree, double r)
--*degree;
}
-/* Basic solving methods -- assuming normalized polynomial */
-
+/** Solve a normalized linear polynomial algebraically. */
static inline size_t
dmnsn_solve_linear(const double poly[2], double x[1])
{
@@ -316,6 +323,7 @@ dmnsn_solve_linear(const double poly[2], double x[1])
return (x[0] >= dmnsn_epsilon) ? 1 : 0;
}
+/** Solve a normalized quadratic polynomial algebraically. */
static inline size_t
dmnsn_solve_quadratic(const double poly[3], double x[2])
{
@@ -386,6 +394,7 @@ dmnsn_solve_polynomial(const double poly[], size_t degree, double x[])
return i;
}
+/* Print a polynomial */
void
dmnsn_print_polynomial(FILE *file, const double poly[], size_t degree)
{
diff --git a/libdimension/progress-impl.h b/libdimension/progress-impl.h
index ef5ad42..bfb74f6 100644
--- a/libdimension/progress-impl.h
+++ b/libdimension/progress-impl.h
@@ -18,17 +18,23 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Progress object implementation.
+ */
+
#ifndef DIMENSION_IMPL_PROGRESS_H
#define DIMENSION_IMPL_PROGRESS_H
-/* Allocate a new progress object */
+/** Allocate a new progress object. */
dmnsn_progress *dmnsn_new_progress(void);
-/* Create a new level of loop nesting */
+/** Create a new level of loop nesting. */
void dmnsn_new_progress_element(dmnsn_progress *progress, unsigned int total);
-/* Increment the progress counter; should only be called from innermost loop */
+/** Increment the progress counter; should only be called from the innermost
+ loop. */
void dmnsn_increment_progress(dmnsn_progress *progress);
-/* Instantly complete the progress */
+/** Instantly complete the progress. */
void dmnsn_done_progress(dmnsn_progress *progress);
struct dmnsn_progress {
diff --git a/libdimension/progress.c b/libdimension/progress.c
index 51e7992..243b7e6 100644
--- a/libdimension/progress.c
+++ b/libdimension/progress.c
@@ -18,31 +18,39 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Progress objects.
+ */
+
#include "dimension-impl.h"
#include <pthread.h>
-/* A single element in an array for dmnsn_progress. Progress of this item is
- progress/total. */
+/** A single element in an array for dmnsn_progress. Progress of this item is
+ \p progress/\p total. */
typedef struct {
unsigned int progress, total;
} dmnsn_progress_element;
-/* For thread synchronization */
-
+/** Read-lock a progress object. */
static void dmnsn_progress_rdlock_impl(const dmnsn_progress *progress);
+/** Write-lock a progress object. */
static void dmnsn_progress_wrlock_impl(dmnsn_progress *progress);
+/** Unlock a progress object. */
static void dmnsn_progress_unlock_impl(void *arg);
+/** Read-lock a progress object and ensure that it will unlock upon error. */
#define dmnsn_progress_rdlock(progress) \
dmnsn_progress_rdlock_impl(progress); \
pthread_cleanup_push(&dmnsn_progress_unlock_impl, (void *)progress);
+/** Write-lock a progress object and ensure that it will unlock upon error. */
#define dmnsn_progress_wrlock(progress) \
dmnsn_progress_wrlock_impl(progress); \
pthread_cleanup_push(&dmnsn_progress_unlock_impl, (void *)progress);
+/** Unlock a progress object. */
#define dmnsn_progress_unlock(progress) \
pthread_cleanup_pop(1);
-
/* Allocate a new dmnsn_progress* */
dmnsn_progress *
dmnsn_new_progress()
diff --git a/libdimension/prtree.c b/libdimension/prtree.c
index 73c2484..88aba73 100644
--- a/libdimension/prtree.c
+++ b/libdimension/prtree.c
@@ -18,13 +18,21 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Priority R-tree implementation. These are the hottest code paths in
+ * libdimension.
+ */
+
#include "dimension-impl.h"
#include <stdlib.h>
-/* Number of children per node */
+/** Number of children per PR-node. */
#define DMNSN_PRTREE_B 6
+/** Number of children per pseudo-PR-node (must be 2*ndimensions) */
#define DMNSN_PSEUDO_PRTREE_B 6
+/** Pseudo PR-tree node. */
struct dmnsn_prtree_node {
dmnsn_bounding_box bounding_box;
@@ -34,6 +42,7 @@ struct dmnsn_prtree_node {
dmnsn_bounding_box bounding_boxes[DMNSN_PRTREE_B];
};
+/** Pseudo PR-tree leaf node. */
typedef struct dmnsn_pseudo_prleaf {
void *children[DMNSN_PRTREE_B];
bool is_leaf;
@@ -42,11 +51,13 @@ typedef struct dmnsn_pseudo_prleaf {
typedef struct dmnsn_pseudo_prtree dmnsn_pseudo_prtree;
+/** Pseudo PR-tree internal node. */
typedef struct dmnsn_pseudo_prnode {
dmnsn_pseudo_prtree *left, *right;
dmnsn_pseudo_prleaf children[DMNSN_PSEUDO_PRTREE_B];
} dmnsn_pseudo_prnode;
+/** Pseudo PR-tree. */
struct dmnsn_pseudo_prtree {
bool is_leaf;
union {
@@ -55,7 +66,7 @@ struct dmnsn_pseudo_prtree {
} pseudo;
};
-/* Expand node to contain the bounding box from min to max */
+/** Expand a node to contain the bounding box \p box. */
static void
dmnsn_pseudo_prleaf_swallow(dmnsn_pseudo_prleaf *leaf, dmnsn_bounding_box box)
{
@@ -63,7 +74,7 @@ dmnsn_pseudo_prleaf_swallow(dmnsn_pseudo_prleaf *leaf, dmnsn_bounding_box box)
leaf->bounding_box.max = dmnsn_vector_max(leaf->bounding_box.max, box.max);
}
-/* Comparator types */
+/** Comparator types. */
enum {
DMNSN_XMIN,
DMNSN_YMIN,
@@ -73,6 +84,7 @@ enum {
DMNSN_ZMAX
};
+/** Get a coordinate of the bounding box of a node. */
static inline double
dmnsn_priority_get(dmnsn_list_iterator *i, bool is_object, int comparator)
{
@@ -205,6 +217,7 @@ dmnsn_zmax_prnode_comp(dmnsn_list_iterator *l, dmnsn_list_iterator *r)
return lval < rval;
}
+/** Leaf node comparators. */
static dmnsn_list_comparator_fn *dmnsn_object_comparators[6] = {
[DMNSN_XMIN] = &dmnsn_xmin_object_comp,
[DMNSN_YMIN] = &dmnsn_ymin_object_comp,
@@ -214,6 +227,7 @@ static dmnsn_list_comparator_fn *dmnsn_object_comparators[6] = {
[DMNSN_ZMAX] = &dmnsn_zmax_object_comp
};
+/** Internal node comparators. */
static dmnsn_list_comparator_fn *dmnsn_prnode_comparators[6] = {
[DMNSN_XMIN] = &dmnsn_xmin_prnode_comp,
[DMNSN_YMIN] = &dmnsn_ymin_prnode_comp,
@@ -223,6 +237,7 @@ static dmnsn_list_comparator_fn *dmnsn_prnode_comparators[6] = {
[DMNSN_ZMAX] = &dmnsn_zmax_prnode_comp
};
+/** Select an extreme node based on a comparator. */
static dmnsn_list_iterator *
dmnsn_priority_search(dmnsn_list *leaves, bool are_objects, int comparator)
{
@@ -245,7 +260,7 @@ dmnsn_priority_search(dmnsn_list *leaves, bool are_objects, int comparator)
return i;
}
-/* Build a pseudo PR-tree */
+/** Build a pseudo PR-tree. */
static dmnsn_pseudo_prtree *
dmnsn_new_pseudo_prtree(dmnsn_list *leaves, bool are_objects, int comparator)
{
@@ -349,6 +364,7 @@ dmnsn_new_pseudo_prtree(dmnsn_list *leaves, bool are_objects, int comparator)
return pseudo;
}
+/** Delete a pseudo-PR-tree. */
static void
dmnsn_delete_pseudo_prtree(dmnsn_pseudo_prtree *pseudo)
{
@@ -361,7 +377,7 @@ dmnsn_delete_pseudo_prtree(dmnsn_pseudo_prtree *pseudo)
}
}
-/* Construct a node from a pseudo leaf */
+/** Construct a node from a pseudo leaf. */
static dmnsn_prtree_node *
dmnsn_new_prtree_node(const dmnsn_pseudo_prleaf *leaf)
{
@@ -386,6 +402,7 @@ dmnsn_new_prtree_node(const dmnsn_pseudo_prleaf *leaf)
return node;
}
+/** Add a pseudo leaf to a list of leaves. */
static void
dmnsn_pseudo_prtree_add_leaf(const dmnsn_pseudo_prleaf *leaf,
dmnsn_list *leaves)
@@ -397,6 +414,7 @@ dmnsn_pseudo_prtree_add_leaf(const dmnsn_pseudo_prleaf *leaf,
}
}
+/** Recursively extract the leaves of a pseudo-PR-tree. */
static void
dmnsn_pseudo_prtree_leaves_recursive(const dmnsn_pseudo_prtree *node,
dmnsn_list *leaves)
@@ -412,7 +430,7 @@ dmnsn_pseudo_prtree_leaves_recursive(const dmnsn_pseudo_prtree *node,
}
}
-/* Extract the leaves of a pseudo PR-tree */
+/** Extract the leaves of a pseudo PR-tree. */
static dmnsn_list *
dmnsn_pseudo_prtree_leaves(const dmnsn_pseudo_prtree *pseudo)
{
@@ -427,8 +445,7 @@ dmnsn_pseudo_prtree_leaves(const dmnsn_pseudo_prtree *pseudo)
return leaves;
}
-/* Add objects from an array to a list, splitting unions etc. */
-
+/** Add an object or its children, if any, to a list. */
static void
dmnsn_list_add_object(dmnsn_list *objects, const dmnsn_object *object)
{
@@ -441,6 +458,7 @@ dmnsn_list_add_object(dmnsn_list *objects, const dmnsn_object *object)
}
}
+/** Add objects from an array to a list, splitting unions etc. */
static dmnsn_list *
dmnsn_object_list(const dmnsn_array *objects)
{
@@ -451,7 +469,7 @@ dmnsn_object_list(const dmnsn_array *objects)
return list;
}
-/* Split the unbounded objects into a new list */
+/** Split unbounded objects into a new list. */
static dmnsn_list *
dmnsn_split_unbounded(dmnsn_list *objects)
{
@@ -516,7 +534,7 @@ dmnsn_new_prtree(const dmnsn_array *objects)
return prtree;
}
-/* Free a PR-tree node */
+/** Free a PR-tree node. */
static void
dmnsn_delete_prtree_node(dmnsn_prtree_node *node)
{
@@ -541,12 +559,13 @@ dmnsn_delete_prtree(dmnsn_prtree *tree)
}
}
+/** A line with pre-calculated reciprocals to avoid divisions. */
typedef struct dmnsn_optimized_line {
dmnsn_line line;
dmnsn_vector n_inv;
} dmnsn_optimized_line;
-/* Precompute inverses for faster ray-box intersection tests */
+/** Precompute inverses for faster ray-box intersection tests. */
static inline dmnsn_optimized_line
dmnsn_optimize_line(dmnsn_line line)
{
@@ -557,7 +576,7 @@ dmnsn_optimize_line(dmnsn_line line)
return optline;
}
-/* Ray-AABB intersection test, by the slab method */
+/** Ray-AABB intersection test, by the slab method. Highly optimized. */
static inline bool
dmnsn_ray_box_intersection(dmnsn_optimized_line optline,
dmnsn_bounding_box box, double t)
@@ -592,6 +611,7 @@ dmnsn_ray_box_intersection(dmnsn_optimized_line optline,
return tmax >= dmnsn_max(0.0, tmin) && tmin < t;
}
+/** Recursive component of PR-tree intersection traversal. */
static void
dmnsn_prtree_intersection_recursive(const dmnsn_prtree_node *node,
dmnsn_optimized_line ray,
@@ -657,6 +677,7 @@ dmnsn_prtree_intersection(const dmnsn_prtree *tree, dmnsn_line ray,
return !isinf(t);
}
+/** Recursive component of PR-tree containment traversal. */
static bool
dmnsn_prtree_inside_recursive(const dmnsn_prtree_node *node, dmnsn_vector point)
{
diff --git a/libdimension/prtree.h b/libdimension/prtree.h
index 7ab616d..a0f7651 100644
--- a/libdimension/prtree.h
+++ b/libdimension/prtree.h
@@ -18,11 +18,12 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-/*
- * Priority R-Trees for storing bounding box hierarchies. PR-trees are a data
- * structure introduced by Arge, de Berg, Haverkort, and Yi, which provides
- * asymptotically optimal worst-case lookup, while remaining efficient with
- * real-world data. Their structure is derived from B-trees.
+/**
+ * @file.
+ * Priority R-trees. PR-trees are a data structure introduced by Arge, de Berg,
+ * Haverkort, and Yi, which provides asymptotically optimal worst-case lookup,
+ * while remaining efficient with real-world data. Their structure is derived
+ * from B-trees.
*/
#ifndef DIMENSION_IMPL_PRTREE_H
@@ -30,19 +31,25 @@
#include <stdbool.h>
+/** A PR-tree node. */
typedef struct dmnsn_prtree_node dmnsn_prtree_node;
+/** A priority R-tree. */
typedef struct dmnsn_prtree {
dmnsn_bounding_box bounding_box;
dmnsn_prtree_node *root;
dmnsn_array *unbounded;
} dmnsn_prtree;
+/** Create a PR-tree. */
dmnsn_prtree *dmnsn_new_prtree(const dmnsn_array *objects);
+/** Delete a PR-tree. */
void dmnsn_delete_prtree(dmnsn_prtree *tree);
+/** Find the closest ray-object intersection in the tree. */
bool dmnsn_prtree_intersection(const dmnsn_prtree *tree, dmnsn_line ray,
dmnsn_intersection *intersection);
+/** Determine whether a point is inside any object in the tree. */
bool dmnsn_prtree_inside(const dmnsn_prtree *tree, dmnsn_vector point);
#endif /* DIMENSION_IMPL_PRTREE_H */
diff --git a/libdimension/raytrace.c b/libdimension/raytrace.c
index 2d93c86..ca489ef 100644
--- a/libdimension/raytrace.c
+++ b/libdimension/raytrace.c
@@ -18,15 +18,20 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * The ray-tracing algorithm.
+ */
+
#include "dimension-impl.h"
#include <stdlib.h>
+#include <pthread.h>
/*
* Boilerplate for multithreading
*/
-/* Payload type for passing arguments to worker thread */
-
+/** Payload type for passing arguments to worker threads. */
typedef struct {
dmnsn_progress *progress;
dmnsn_scene *scene;
@@ -36,7 +41,7 @@ typedef struct {
unsigned int index, threads;
} dmnsn_raytrace_payload;
-/* Thread callback */
+/** Background thread callback. */
static int dmnsn_raytrace_scene_thread(void *ptr);
/* Raytrace a scene */
@@ -58,12 +63,12 @@ dmnsn_raytrace_scene_async(dmnsn_scene *scene)
payload->progress = progress;
payload->scene = scene;
- dmnsn_new_thread(progress, NULL, &dmnsn_raytrace_scene_thread, payload);
+ dmnsn_new_thread(progress, &dmnsn_raytrace_scene_thread, payload);
return progress;
}
-/* Thread callback */
+/** Worker thread callback. */
static void *dmnsn_raytrace_scene_multithread_thread(void *ptr);
/* Thread callback -- set up the multithreaded engine */
@@ -95,7 +100,7 @@ dmnsn_raytrace_scene_thread(void *ptr)
/* Set up the progress object */
dmnsn_new_progress_element(payload->progress,
- payload->scene->canvas->y);
+ payload->scene->canvas->height);
/* Create the payloads */
for (int i = 0; i < nthreads; ++i) {
@@ -136,7 +141,7 @@ dmnsn_raytrace_scene_thread(void *ptr)
return 0;
}
-/* Actual raytracing implementation */
+/** Actual raytracing implementation. */
static void dmnsn_raytrace_scene_impl(dmnsn_progress *progress,
dmnsn_scene *scene,
dmnsn_prtree *prtree,
@@ -156,6 +161,7 @@ dmnsn_raytrace_scene_multithread_thread(void *ptr)
* Raytracing algorithm
*/
+/** The current state of the ray-tracing engine. */
typedef struct dmnsn_raytrace_state {
const struct dmnsn_raytrace_state *parent;
@@ -175,7 +181,7 @@ typedef struct dmnsn_raytrace_state {
double ior;
} dmnsn_raytrace_state;
-/* Main helper for dmnsn_raytrace_scene_impl - shoot a ray */
+/** Main helper for dmnsn_raytrace_scene_impl - shoot a ray. */
static dmnsn_color dmnsn_raytrace_shoot(dmnsn_raytrace_state *state,
dmnsn_line ray);
@@ -192,21 +198,18 @@ dmnsn_raytrace_scene_impl(dmnsn_progress *progress, dmnsn_scene *scene,
.ior = 1.0
};
- size_t width = scene->canvas->x;
- size_t height = scene->canvas->y;
-
/* Iterate through each pixel */
- for (size_t y = index; y < height; y += threads) {
- for (size_t x = 0; x < width; ++x) {
+ for (size_t y = index; y < scene->canvas->height; y += threads) {
+ for (size_t x = 0; x < scene->canvas->width; ++x) {
/* Set the pixel to the background color */
dmnsn_color color = scene->background;
if (scene->quality) {
/* Get the ray corresponding to the (x,y)'th pixel */
- dmnsn_line ray = (*scene->camera->ray_fn)(
+ dmnsn_line ray = dmnsn_camera_ray(
scene->camera,
- ((double)x)/(scene->canvas->x - 1),
- ((double)y)/(scene->canvas->y - 1)
+ ((double)x)/(scene->canvas->width - 1),
+ ((double)y)/(scene->canvas->height - 1)
);
/* Shoot a ray */
@@ -221,20 +224,24 @@ dmnsn_raytrace_scene_impl(dmnsn_progress *progress, dmnsn_scene *scene,
}
}
+/** Get the intersection texture. */
#define ITEXTURE(state) (state->intersection->texture)
+/** Get the default texture. */
#define DTEXTURE(state) (state->scene->default_texture)
+/** Can a texture element be accessed? */
#define CAN_ACCESS(texture, telem) \
((texture) && (texture)->telem)
+/** Can a texture element callback be called? */
#define CAN_CALL(texture, telem, fn) \
(CAN_ACCESS(texture, telem) && (texture)->telem->fn)
-/* Determine whether a callback may be called */
+/** Determine whether a callback may be called. */
#define TEXTURE_HAS_CALLBACK(state, telem, fn) \
(CAN_CALL(ITEXTURE(state), telem, fn) \
|| CAN_CALL(DTEXTURE(state), telem, fn))
-/* Call the appropriate overloaded texture callback */
+/** Call the appropriate overloaded texture callback. */
#define TEXTURE_CALLBACK(state, telem, fn, def, ...) \
(CAN_CALL(ITEXTURE(state), telem, fn) \
? (*ITEXTURE(state)->telem->fn)(ITEXTURE(state)->telem, __VA_ARGS__) \
@@ -242,7 +249,7 @@ dmnsn_raytrace_scene_impl(dmnsn_progress *progress, dmnsn_scene *scene,
? (*DTEXTURE(state)->telem->fn)(DTEXTURE(state)->telem, __VA_ARGS__) \
: def));
-/* Get a property from a texture element */
+/** Get a property from a texture element. */
#define TEXTURE_PROPERTY(state, telem, prop, def) \
(CAN_ACCESS(ITEXTURE(state), telem) \
? ITEXTURE(state)->telem->prop \
@@ -250,11 +257,13 @@ dmnsn_raytrace_scene_impl(dmnsn_progress *progress, dmnsn_scene *scene,
? DTEXTURE(state)->telem->prop \
: def))
+/** Get the current index of refraction. */
#define IOR(state) \
((state)->intersection->interior \
? (state)->intersection->interior->ior \
: 1.0)
+/** Calculate the base pigment at the intersection. */
static void
dmnsn_raytrace_pigment(dmnsn_raytrace_state *state)
{
@@ -267,7 +276,7 @@ dmnsn_raytrace_pigment(dmnsn_raytrace_state *state)
state->diffuse = state->pigment;
}
-/* Get the color of a light ray at an intersection point */
+/** Get the color of a light ray at an intersection point. */
static dmnsn_color
dmnsn_raytrace_light_ray(const dmnsn_raytrace_state *state,
const dmnsn_light *light)
@@ -315,6 +324,7 @@ dmnsn_raytrace_light_ray(const dmnsn_raytrace_state *state,
return color;
}
+/** Handle light, shadow, and shading. */
static void
dmnsn_raytrace_lighting(dmnsn_raytrace_state *state)
{
@@ -357,6 +367,7 @@ dmnsn_raytrace_lighting(dmnsn_raytrace_state *state)
}
}
+/** Trace a reflected ray. */
static dmnsn_color
dmnsn_raytrace_reflection(const dmnsn_raytrace_state *state)
{
@@ -379,7 +390,7 @@ dmnsn_raytrace_reflection(const dmnsn_raytrace_state *state)
return reflected;
}
-/* Handle translucency - must be called last to work correctly */
+/** Handle translucency - must be called last to work correctly. */
static void
dmnsn_raytrace_translucency(dmnsn_raytrace_state *state)
{
@@ -435,7 +446,7 @@ dmnsn_raytrace_translucency(dmnsn_raytrace_state *state)
}
}
-/* Shoot a ray, and calculate the color, using `color' as the background */
+/* Shoot a ray, and calculate the color */
static dmnsn_color
dmnsn_raytrace_shoot(dmnsn_raytrace_state *state, dmnsn_line ray)
{
diff --git a/libdimension/reflective.c b/libdimension/reflective.c
index 6800ac7..cc89534 100644
--- a/libdimension/reflective.c
+++ b/libdimension/reflective.c
@@ -18,19 +18,22 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Reflective finish.
+ */
+
#include "dimension.h"
#include <math.h>
#include <stdlib.h>
-/*
- * Reflective finish
- */
-
+/** Reflective finish payload. */
typedef struct dmnsn_reflection_params {
dmnsn_color min, max;
double falloff;
} dmnsn_reflection_params;
+/** Reflective finish callback. */
static dmnsn_color
dmnsn_reflective_finish_fn(const dmnsn_finish *finish,
dmnsn_color reflect, dmnsn_color color,
diff --git a/libdimension/scene.c b/libdimension/scene.c
index f56236f..fc5bb92 100644
--- a/libdimension/scene.c
+++ b/libdimension/scene.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Scenes.
+ */
+
#include "dimension-impl.h"
#include <stdlib.h>
diff --git a/libdimension/solid_pigment.c b/libdimension/solid_pigment.c
index 2b878c7..14bdffe 100644
--- a/libdimension/solid_pigment.c
+++ b/libdimension/solid_pigment.c
@@ -18,12 +18,21 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Solid color pigments.
+ */
+
#include "dimension.h"
#include <stdlib.h>
-/* Solid color pigment callback */
-static dmnsn_color dmnsn_solid_pigment_fn(const dmnsn_pigment *pigment,
- dmnsn_vector v);
+/** Solid color pigment callback. */
+static dmnsn_color
+dmnsn_solid_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v)
+{
+ dmnsn_color *color = pigment->ptr;
+ return *color;
+}
/* Create a solid color */
dmnsn_pigment *
@@ -41,11 +50,3 @@ dmnsn_new_solid_pigment(dmnsn_color color)
return pigment;
}
-
-/* Solid color callback */
-static dmnsn_color
-dmnsn_solid_pigment_fn(const dmnsn_pigment *pigment, dmnsn_vector v)
-{
- dmnsn_color *color = pigment->ptr;
- return *color;
-}
diff --git a/libdimension/sphere.c b/libdimension/sphere.c
index 7ff2292..53ceef9 100644
--- a/libdimension/sphere.c
+++ b/libdimension/sphere.c
@@ -18,34 +18,14 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension.h"
-#include <math.h> /* For sqrt */
-
-/*
- * Sphere
+/**
+ * @file
+ * Spheres.
*/
-/* Sphere object callbacks */
-
-static bool dmnsn_sphere_intersection_fn(const dmnsn_object *sphere,
- dmnsn_line line,
- dmnsn_intersection *intersection);
-static bool dmnsn_sphere_inside_fn(const dmnsn_object *sphere,
- dmnsn_vector point);
-
-/* Allocate a new sphere */
-dmnsn_object *
-dmnsn_new_sphere()
-{
- dmnsn_object *sphere = dmnsn_new_object();
- sphere->intersection_fn = &dmnsn_sphere_intersection_fn;
- sphere->inside_fn = &dmnsn_sphere_inside_fn;
- sphere->bounding_box.min = dmnsn_new_vector(-1.0, -1.0, -1.0);
- sphere->bounding_box.max = dmnsn_new_vector(1.0, 1.0, 1.0);
- return sphere;
-}
+#include "dimension.h"
-/* Returns the closest intersection of `line' with `sphere' */
+/** Sphere intersection callback. */
static bool
dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line l,
dmnsn_intersection *intersection)
@@ -73,9 +53,21 @@ dmnsn_sphere_intersection_fn(const dmnsn_object *sphere, dmnsn_line l,
}
}
-/* Return whether a point is inside a sphere (x**2 + y**2 + z**2 < 1.0) */
+/** Sphere inside callback. */
static bool
dmnsn_sphere_inside_fn(const dmnsn_object *sphere, dmnsn_vector point)
{
return point.x*point.x + point.y*point.y + point.z*point.z < 1.0;
}
+
+/* Allocate a new sphere */
+dmnsn_object *
+dmnsn_new_sphere()
+{
+ dmnsn_object *sphere = dmnsn_new_object();
+ sphere->intersection_fn = &dmnsn_sphere_intersection_fn;
+ sphere->inside_fn = &dmnsn_sphere_inside_fn;
+ sphere->bounding_box.min = dmnsn_new_vector(-1.0, -1.0, -1.0);
+ sphere->bounding_box.max = dmnsn_new_vector(1.0, 1.0, 1.0);
+ return sphere;
+}
diff --git a/libdimension/texture.c b/libdimension/texture.c
index 00b8682..f69f748 100644
--- a/libdimension/texture.c
+++ b/libdimension/texture.c
@@ -18,6 +18,11 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Textures, pigments, and finishes.
+ */
+
#include "dimension.h"
#include <stdlib.h>
diff --git a/libdimension/threads.c b/libdimension/threads.c
index 2c00cc8..5e39fdc 100644
--- a/libdimension/threads.c
+++ b/libdimension/threads.c
@@ -18,15 +18,22 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Background threading.
+ */
+
#include "dimension-impl.h"
#include <pthread.h>
+/** The payload to pass to the pthread callback. */
typedef struct dmnsn_thread_payload {
dmnsn_thread_fn *thread_fn;
void *arg;
dmnsn_progress *progress;
} dmnsn_thread_payload;
+/** Clean up after a thread. */
static void
dmnsn_thread_cleanup(void *arg)
{
@@ -37,6 +44,7 @@ dmnsn_thread_cleanup(void *arg)
dmnsn_done_progress(progress);
}
+/** pthread callback -- call the real thread callback. */
static void *
dmnsn_thread(void *arg)
{
@@ -51,15 +59,15 @@ dmnsn_thread(void *arg)
}
void
-dmnsn_new_thread(dmnsn_progress *progress, const pthread_attr_t *attr,
- dmnsn_thread_fn *thread_fn, void *arg)
+dmnsn_new_thread(dmnsn_progress *progress, dmnsn_thread_fn *thread_fn,
+ void *arg)
{
dmnsn_thread_payload *payload = dmnsn_malloc(sizeof(dmnsn_thread_payload));
payload->thread_fn = thread_fn;
payload->arg = arg;
payload->progress = progress;
- if (pthread_create(&progress->thread, attr, &dmnsn_thread, payload) != 0) {
+ if (pthread_create(&progress->thread, NULL, &dmnsn_thread, payload) != 0) {
dmnsn_error(DMNSN_SEVERITY_HIGH, "Couldn't start thread.");
}
}
diff --git a/libdimension/threads.h b/libdimension/threads.h
index 00be0a9..7ae6288 100644
--- a/libdimension/threads.h
+++ b/libdimension/threads.h
@@ -18,15 +18,28 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Background threading interface.
+ */
+
#ifndef DIMENSION_IMPL_THREADS_H
#define DIMENSION_IMPL_THREADS_H
-#include <pthread.h>
-
+/**
+ * Thread callback type.
+ * @param[in,out] ptr An arbitrary pointer.
+ * @return 0 on success, non-zero on failure.
+ */
typedef int dmnsn_thread_fn(void *ptr);
-/* Creates a thread that cleans up after itself on errors */
-void dmnsn_new_thread(dmnsn_progress *progress, const pthread_attr_t *attr,
- dmnsn_thread_fn *thread_fn, void *arg);
+/**
+ * Create a thread that cleans up after itself on errors.
+ * @param[in,out] progress The progress object to associate with the thread.
+ * @param[in] thread_fn The thread callback.
+ * @param[in,out] arg The pointer to pass to the thread callback.
+ */
+void dmnsn_new_thread(dmnsn_progress *progress, dmnsn_thread_fn *thread_fn,
+ void *arg);
#endif /* DIMENSION_IMPL_THREADS_H */
diff --git a/libdimension/timer.c b/libdimension/timer.c
index eb15357..daf0c00 100644
--- a/libdimension/timer.c
+++ b/libdimension/timer.c
@@ -18,10 +18,16 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
+/**
+ * @file
+ * Performance counter.
+ */
+
#include "dimension.h"
#include <sys/times.h>
#include <unistd.h>
+/** Clock ticks per second. */
static long clk_tck = 0;
dmnsn_timer *
diff --git a/libdimension/torus.c b/libdimension/torus.c
index 702404b..244f174 100644
--- a/libdimension/torus.c
+++ b/libdimension/torus.c
@@ -18,47 +18,19 @@
* <http://www.gnu.org/licenses/>. *
*************************************************************************/
-#include "dimension.h"
-
-/*
- * Torus - special case of a quartic
+/**
+ * @file
+ * Torii. A special case of a quartic.
*/
-/* Torus object callbacks */
-static bool dmnsn_torus_intersection_fn(const dmnsn_object *torus,
- dmnsn_line line,
- dmnsn_intersection *intersection);
-static bool dmnsn_torus_inside_fn(const dmnsn_object *torus,
- dmnsn_vector point);
+#include "dimension.h"
-/* Payload type */
+/** Torus payload type. */
typedef struct dmnsn_torus_payload {
double major, minor;
} dmnsn_torus_payload;
-/* Allocate a new torus */
-dmnsn_object *
-dmnsn_new_torus(double major, double minor)
-{
- dmnsn_object *torus = dmnsn_new_object();
- torus->intersection_fn = &dmnsn_torus_intersection_fn;
- torus->inside_fn = &dmnsn_torus_inside_fn;
- torus->bounding_box.min = dmnsn_new_vector(-(major + minor),
- -minor,
- -(major + minor));
- torus->bounding_box.max = dmnsn_new_vector(major + minor,
- minor,
- major + minor);
-
- dmnsn_torus_payload *payload = dmnsn_malloc(sizeof(dmnsn_torus_payload));
- payload->major = major;
- payload->minor = minor;
- torus->ptr = payload;
- torus->free_fn = &dmnsn_free;
- return torus;
-}
-
-/* Bound the torus in a cylindrical shell */
+/** Bound the torus in a cylindrical shell. */
static inline bool
dmnsn_torus_bound_intersection(const dmnsn_torus_payload *payload, dmnsn_line l)
{
@@ -103,7 +75,7 @@ dmnsn_torus_bound_intersection(const dmnsn_torus_payload *payload, dmnsn_line l)
return true;
}
-/* Returns the closest intersection of `line' with `torus' */
+/** Torus intersection callback. */
static bool
dmnsn_torus_intersection_fn(const dmnsn_object *torus, dmnsn_line l,
dmnsn_intersection *intersection)
@@ -159,7 +131,7 @@ dmnsn_torus_intersection_fn(const dmnsn_object *torus, dmnsn_line l,
return true;
}
-/* Return whether a point is inside a torus */
+/** Torus inside callback. */
static bool
dmnsn_torus_inside_fn(const dmnsn_object *torus, dmnsn_vector point)
{
@@ -167,3 +139,25 @@ dmnsn_torus_inside_fn(const dmnsn_object *torus, dmnsn_vector point)
double dmajor = payload->major - sqrt(point.x*point.x + point.z*point.z);
return dmajor*dmajor + point.y*point.y < payload->minor*payload->minor;
}
+
+/* Allocate a new torus */
+dmnsn_object *
+dmnsn_new_torus(double major, double minor)
+{
+ dmnsn_object *torus = dmnsn_new_object();
+ torus->intersection_fn = &dmnsn_torus_intersection_fn;
+ torus->inside_fn = &dmnsn_torus_inside_fn;
+ torus->bounding_box.min = dmnsn_new_vector(-(major + minor),
+ -minor,
+ -(major + minor));
+ torus->bounding_box.max = dmnsn_new_vector(major + minor,
+ minor,
+ major + minor);
+
+ dmnsn_torus_payload *payload = dmnsn_malloc(sizeof(dmnsn_torus_payload));
+ payload->major = major;
+ payload->minor = minor;
+ torus->ptr = payload;
+ torus->free_fn = &dmnsn_free;
+ return torus;
+}
diff --git a/tests/libdimension/render.c b/tests/libdimension/render.c
index 1de9fba..440333c 100644
--- a/tests/libdimension/render.c
+++ b/tests/libdimension/render.c
@@ -45,7 +45,7 @@ dmnsn_new_test_scene(void)
/* Set up the transformation matrix for the perspective camera */
dmnsn_matrix trans = dmnsn_scale_matrix(
dmnsn_new_vector(
- ((double)scene->canvas->x)/scene->canvas->y, 1.0, 1.0
+ ((double)scene->canvas->width)/scene->canvas->height, 1.0, 1.0
)
);
trans = dmnsn_matrix_mul(
@@ -63,7 +63,7 @@ dmnsn_new_test_scene(void)
/* Create a perspective camera */
scene->camera = dmnsn_new_perspective_camera();
- dmnsn_set_perspective_camera_trans(scene->camera, trans);
+ scene->camera->trans = trans;
/* Background color */
scene->background = dmnsn_color_from_sRGB((dmnsn_sRGB){ 0.0, 0.1, 0.2 });
@@ -106,11 +106,11 @@ dmnsn_new_test_scene(void)
dmnsn_array *arrow_array = dmnsn_new_array(sizeof(dmnsn_object *));
- dmnsn_object *cylinder = dmnsn_new_cylinder(0.1, 0.1, false);
+ dmnsn_object *cylinder = dmnsn_new_cone(0.1, 0.1, false);
cylinder->trans = dmnsn_scale_matrix(dmnsn_new_vector(1.0, 1.25, 1.0));
dmnsn_array_push(arrow_array, &cylinder);
- dmnsn_object *cone = dmnsn_new_cylinder(0.1, 0.0, true);
+ dmnsn_object *cone = dmnsn_new_cone(0.1, 0.0, true);
cone->trans =
dmnsn_matrix_mul(
dmnsn_translation_matrix(dmnsn_new_vector(0.0, 1.375, 0.0)),
diff --git a/tests/libdimension/tests.c b/tests/libdimension/tests.c
index 9d1d38c..e2e0d18 100644
--- a/tests/libdimension/tests.c
+++ b/tests/libdimension/tests.c
@@ -86,7 +86,7 @@ dmnsn_new_display(const dmnsn_canvas *canvas)
swa.event_mask = StructureNotifyMask;
display->win = XCreateWindow(display->dpy,
RootWindow(display->dpy, display->vi->screen),
- 0, 0, canvas->x, canvas->y,
+ 0, 0, canvas->width, canvas->height,
0, display->vi->depth, InputOutput,
display->vi->visual,
CWBorderPixel|CWColormap|CWEventMask, &swa);