diff options
Diffstat (limited to 'doc/libdimension.texi')
-rw-r--r-- | doc/libdimension.texi | 1032 |
1 files changed, 0 insertions, 1032 deletions
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 |