1 /*
2  * vp_global.h
3  *
4  * Non-exported global declarations for VolPack.
5  *
6  * Copyright (c) 1994 The Board of Trustees of The Leland Stanford
7  * Junior University.  All rights reserved.
8  *
9  * Permission to use, copy, modify and distribute this software and its
10  * documentation for any purpose is hereby granted without fee, provided
11  * that the above copyright notice and this permission notice appear in
12  * all copies of this software and that you do not sell the software.
13  * Commercial licensing is available by contacting the author.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * Author:
20  *    Phil Lacroute
21  *    Computer Systems Laboratory
22  *    Electrical Engineering Dept.
23  *    Stanford University
24  */
25 
26 /*
27  * $Date: 1994/12/30 23:52:38 $
28  * $Revision: 1.27 $
29  */
30 
31 /*******************************************************************
32  * Include files.                                                  *
33  *******************************************************************/
34 
35 #include "config.h"
36 #include "volpack.h"
37 
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <math.h>
41 extern double rint ANSI_ARGS((double x)); /* missing from Ultrix math.h */
42 
43 #ifdef ANSI_C
44 #include <stdarg.h>
45 #else
46 #include <varargs.h>
47 #endif
48 
49 #if STDC_HEADERS || HAVE_STRING_H
50 #include <string.h>
51 /* An ANSI string.h and pre-ANSI memory.h might conflict.  */
52 #if !STDC_HEADERS && HAVE_MEMORY_H
53 #include <memory.h>
54 #endif /* not STDC_HEADERS and HAVE_MEMORY_H */
55 #define index strchr
56 #define rindex strrchr
57 #define bcopy(s, d, n) memcpy ((d), (s), (n))
58 #define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
59 #define bzero(s, n) memset ((s), 0, (n))
60 #else /* not STDC_HEADERS and not HAVE_STRING_H */
61 #include <strings.h>
62 /* memory.h and strings.h conflict on some systems.  */
63 #endif /* not STDC_HEADERS and not HAVE_STRING_H */
64 
65 #ifdef HAVE_LORES_TIMER
66 /* use the low-resolution interval timer system call to collect timings */
67 #   define USE_TIMER
68 #   include <sys/time.h>
69 #   define DECLARE_TIME(t)	struct timeval t
70 #   define GET_TIME(vpc, t)	gettimeofday(&t)
71 #   define STORE_TIME(vpc, code, t0, t1)	\
72     vpc->timer_ticks[code] += ((t1).tv_usec < (t0).tv_usec) ? \
73 	(((t1).tv_sec - (t0).tv_sec)*1000000 - ((t0).tv_usec - (t1).tv_usec)):\
74 	(((t1).tv_sec - (t0).tv_sec)*1000000 + ((t1).tv_usec - (t0).tv_usec));
75 #endif
76 
77 #ifdef HAVE_HIRES_TIMER
78 /* use the high-resolution memory-mapped timer to collect timings
79    (available only on certain SGI architectures) */
80 #   define USE_TIMER
81 #   include <fcntl.h>
82 #   include <sys/mman.h>
83 #   include <sys/syssgi.h>
84 #   include <sys/immu.h>
85 #   define DECLARE_TIME(t)	unsigned t
86 #   define GET_TIME(vpc, t)	t = *vpc->timer_addr
87 #   define STORE_TIME(vpc, code, t0, t1)	\
88     vpc->timer_ticks[code] += ((t1) < (t0)) ? \
89 	((0xFFFFFFFF - (t0)) + (t1)) : ((t1) - (t0));
90 #   define DECLARE_HIRES_TIME(t)	DECLARE_TIME(t)
91 #   define GET_HIRES_TIME(vpc, t)	GET_TIME(vpc, t)
92 #   define STORE_HIRES_TIME(vpc, code, t0, t1)	STORE_TIME(vpc, code, t0, t1)
93 #   define COPY_HIRES_TIME(t0, t1)	t0 = t1
94 #else
95 #   define DECLARE_HIRES_TIME(t)
96 #   define GET_HIRES_TIME(vpc, t)
97 #   define STORE_HIRES_TIME(vpc, code, t0, t1)
98 #   define COPY_HIRES_TIME(t0, t1)
99 #endif
100 
101 #ifndef USE_TIMER
102 #   define DECLARE_TIME(t)
103 #   define GET_TIME(vpc, t)
104 #   define STORE_TIME(vpc, code, t0, t1)
105 #endif
106 
107 /*******************************************************************
108  * Constants.                                                      *
109  *******************************************************************/
110 
111 /* rendering algorithms */
112 #define USE_RLEVOLUME	10	/* use classified, run-length encoded volume */
113 #define USE_RAWVOLUME	11	/* use raw volume (with octree if present) */
114 
115 /* shading modes */
116 #define CALLBACK_SHADER	20
117 #define LOOKUP_SHADER	21
118 
119 /* surfaces */
120 #define EXT_SURFACE	0
121 #define INT_SURFACE	1
122 
123 /* material property indexes */
124 #define MATL_AMB_R	0		/* ambient red coefficient */
125 #define MATL_DIFF_R	1		/* diffuse red coefficient */
126 #define MATL_SPEC_R	2		/* specular red coefficient */
127 #define MATL_AMB_G	3		/* ambient green coefficient */
128 #define MATL_DIFF_G	4		/* diffuse green coefficient */
129 #define MATL_SPEC_G	5		/* specular green coefficient */
130 #define MATL_AMB_B	6		/* ambient blue coefficient */
131 #define MATL_DIFF_B	7		/* diffuse blue coefficient */
132 #define MATL_SPEC_B	8		/* specular blue coefficient */
133 #define MATL_SHINY	9		/* specular exponent */
134 #define NUM_MATL_PROPS	10
135 
136 /* default material properties */
137 #define DEFAULT_AMBIENT		(0.1*255.0)
138 #define DEFAULT_DIFFUSE		(0.4*255.0)
139 #define DEFAULT_SPECULAR	(0.5*255.0)
140 #define DEFAULT_SHINYNESS	10.0
141 
142 /* default depth cueing parameters */
143 #define DEFAULT_DC_QUANTIZATION	(1./255.) /* quantization */
144 
145 /* size of lookup table for filter kernel used in the 2D warp */
146 #define WARP_WEIGHT_INDEX_BITS	6
147 #define WARP_WEIGHT_ENTRIES	(1 << WARP_WEIGHT_INDEX_BITS)
148 
149 /* constants for MinMaxOctree and fast classification */
150 #define VP_MAX_OCTREE_LEVELS	16	/* maximum number of levels in octree;
151 					   each side of volume can be at most
152 					   (2^VP_MAX_OCTREE_LEVELS)*
153 					   base_node_size */
154 
155 #define MM_K_BIT	4		/* bits in child_octant field of */
156 #define MM_J_BIT	2		/* MMOctreeLevel */
157 #define MM_I_BIT	1
158 
159 #define MM_EMPTY	0		/* node is transparent */
160 #define MM_FULL		1		/* node is non-transparent */
161 #define MM_PARTFULL	2		/* node is neither transparent
162 					   nor opaque and is not a leaf */
163 
164 #define INDEX_RUN_IS_ZERO 0x7000	/* bit to indicate a run in an
165 					   index volume is a zero run */
166 
167 /*******************************************************************
168  * Macros.                                                         *
169  *******************************************************************/
170 
171 /* #define NULL 0 */
172 
173 #define MAX(a,b)        (((a)<(b)) ? (b) : (a))
174 #define MIN(a,b)        (((a)>(b)) ? (b) : (a))
175 
176 /* Alloc: allocate memory */
177 #define Alloc(context, ptr, type, size, use)                            \
178 {                                                                       \
179     (ptr) = (type)malloc((unsigned)(size));		                \
180     if ((ptr) == NULL)							\
181 	VPBug("out of memory");						\
182     if ((context)->log_alloc_func != NULL)                              \
183         (context)->log_alloc_func((ptr),(size),(use),			\
184 		   __LINE__,__FILE__,(context)->client_data);		\
185 }
186 
187 /* Dealloc: free memory */
188 #define Dealloc(context, ptr)						\
189 {									\
190     if ((context)->log_free_func != NULL)                               \
191         (context)->log_free_func(ptr, (context)->client_data);		\
192     free((void *)ptr);							\
193 }
194 
195 /* Debug: print debugging information */
196 #ifdef DEBUG
197 #define Debug(x)        VPDebug x
198 #else
199 #define Debug(x)
200 #endif
201 
202 /* assertions */
203 #ifdef ASSERTIONS
204 #define ASSERT(expr)                                                    \
205     if (!(expr))                                                        \
206 	VPBug("assertion failed on line %d of file %s",                 \
207 	      __LINE__, __FILE__)
208 #else
209 #define ASSERT(expr)
210 #endif
211 
212 /* ReportStatus: call a callback to give a progress report */
213 #define ReportStatus(context, frac)      				\
214     if ((context)->status_func != NULL)					\
215 	(context)->status_func(frac, (context)->client_data)
216 
217 /* macros for accessing the fields of a voxel */
218 #define ByteField(voxel, offset)   (*((unsigned char *)(voxel) + (offset)))
219 #define ShortField(voxel, offset)  (*((unsigned short *)((char *)(voxel)+\
220 				      (offset))))
221 #define IntField(voxel, offset)    (*((unsigned *)((char *)(voxel)+(offset))))
222 #define VoxelField(voxel, offset, size) 			\
223     (((size) == 1) ? ByteField(voxel, offset) :			\
224      ((size) == 2) ? ShortField(voxel, offset) : 		\
225 		     IntField(voxel, offset))
226 
227 /*******************************************************************
228  * Type definitions.                                               *
229  *******************************************************************/
230 
231 /* ScanOffset: offsets to beginning of a run-length encoded voxel scanline */
232 typedef struct {		/* ScanOffset */
233     int first_len;		/*   byte offset to first run length */
234     int first_data;		/*   byte offset to first voxel data */
235 } ScanOffset;
236 
237 #ifdef INDEX_VOLUME
238 /* VoxelLocation: pointer to the run containing a voxel and the position
239    of the voxel in the run */
240 typedef struct {		/* VoxelLocation */
241     unsigned char run_count;	/*   number of voxels in run starting from
242 				     this voxel (run_count = run_len for
243 				     first voxel in run, run_count = 1 for
244 				     last voxel in run) */
245     unsigned char len_offset;	/*   offset in bytes from first run length
246 				     for scanline to run length for voxel */
247     short data_offset;		/*   offset in bytes from first voxel data
248 				     for scanline to data for voxel, or -1
249 				     if voxel has no data (zero run) */
250 } VoxelLocation;
251 #endif /* INDEX_VOLUME */
252 
253 /* RLEVoxels: a run-length encoding of a classified volume for one of the
254 	      three principal viewing axes */
255 typedef struct {		/* RLEVoxels */
256     int ilen, jlen, klen;	/*   size of each dimension */
257     int run_count;		/*   number of runs */
258     unsigned char *run_lengths;	/*   length of each run */
259     int data_count;		/*   number of entries in data */
260     void *data;			/*   data */
261     int scan_offsets_per_slice;	/*   number of entries in scan_offsets for
262 				     each slice of voxel data */
263     ScanOffset *scan_offsets;	/*   array of offsets to scanlines */
264     int mmapped;		/*   true if pointers point to memory-mapped
265 				     data */
266 #ifdef INDEX_VOLUME
267     VoxelLocation *voxel_index;	/*   index for experimental ERT code */
268 #endif
269 } RLEVoxels;
270 
271 /* RunData: statistics about the runs in a scanline of voxels */
272 typedef struct {		/* RunData */
273     short run_length;		/*   length of current run */
274     short next_index;		/*   index of next voxel in current scanline */
275     union {
276 	struct {		/*   data for pass 1 (ClassifyRawScanline) */
277 	    short run_count;	/*   number of runs in scanline */
278 	    short non_zero_count; /* number of nontransparent voxels in
279 				     scanline */
280 	} p1;
281 	struct {		/*   data for pass 2 (RepackClassifiedVolume)*/
282 	    unsigned data_offset; /* byte offset for storage for voxel */
283 	    unsigned length_offset; /* byte offset for storage for runlength */
284 	} p2;
285     } p;
286 } RunData;
287 
288 /* GBuffer: growable buffer (a singly-linked list of buffers) */
289 #define GBUFFER_SIZE	1024	/* number of bytes per list element
290 				   (to optimize memory performance, size
291 				   should be small enough so that at
292 				   least two buffers fit in the cache) */
293 
294 typedef struct _gbuffer {	/* GBuffer */
295     int bytes_left;		/*   size of unallocated space */
296     char *data_ptr;		/*   pointer to next available byte */
297     struct _gbuffer *next;	/*   next buffer in list */
298     char data[GBUFFER_SIZE];	/*   data */
299 } GBuffer;
300 
301 /* ConstructionBuffer: buffer for storing data while constructing a
302                        classified volume */
303 typedef struct {		/* ConstructionBuffer */
304     RunData *rundata_y;		/*   statistics for y-axis runs (2D array)
305 				     index: x*zlen + z */
306     RunData *rundata_z;		/*   statistics for z-axis runs (2D array)
307 				     index: y*xlen + x */
308     GBuffer *data_buf_head;	/*   first buffer for storing voxels */
309     GBuffer *data_buf_tail;	/*   last buffer in list */
310     GBuffer *lengths_buf_head;	/*   first buffer for storing run lengths */
311     GBuffer *lengths_buf_tail;	/*   last buffer in list */
312     int non_zero_count;		/*   number of nonzero voxels in data bufs */
313     int x_run_count;		/*   number of z-axis runs seen so far */
314     unsigned char octree_runs[VP_MAX_VOLUME_DIM];
315     				/*   estimated run lengths from octree */
316     int octree_scans_left;	/*   number of scanlines until octree_runs
317 				     must be recomputed */
318     int next_z;			/*   z coordinate of next scanline */
319     int next_y;			/*   y coordinate of next scanline */
320 } ConstructionBuffer;
321 
322 /* MinMaxOctree: min-max octree representation of the volume for
323    fast classification */
324 typedef struct {		/* MinMaxOctree */
325     int levels;			/*   number of levels in octree
326 				     level 0 = root = lowest detail
327 				     level levels-1 = base = finest detail */
328     int root_node_size;		/*   voxels/side for root level */
329     int base_node_size;		/*   voxels/side for base level */
330     int range_bytes_per_node;	/*   bytes/node for min/max data */
331     int base_bytes_per_node;	/*   bytes/node for base level
332 				     (min/max data + status) */
333     int nonbase_bytes_per_node; /*   bytes/node for non-base level
334 				     (min/max data + status + ptr to child) */
335     int node_offset[VP_MAX_FIELDS]; /* offset to min/max data for each
336 				       parameter in a node; min comes first */
337     int status_offset;		/*   offset to status field */
338     int child_offset;		/*   offset to child field */
339     void *root;			/*   storage for the octree, and a pointer
340 				     to the root node */
341     int octree_bytes;		/*   bytes of storage for the octree */
342 
343     /*
344      * Layout of an octree node:
345      *
346      * Nodes at level 0 (root) through levels-2 are nonbase_bytes_per_node
347      * bytes long.  This space is divided into a number of fields as follows:
348      *
349      *    minimum value for parameter 0 of the classification function
350      *    maximum value for parameter 0
351      *    minimum value for parameter 1
352      *    maximum value for parameter 1
353      *    .
354      *    .
355      *    .
356      *    minimum value for parameter num_clsfy_params-1
357      *    maximum value for parameter num_clsfy_params-1
358      *    status field
359      *    child field
360      *
361      * The min/max fields are the same size as the corresponding
362      * classification parameters (one or two bytes; four bytes not allowed).
363      * Node_offset[] gives offsets to the min field for each parameter.
364      *
365      * The status field is a one byte field which is filled in during
366      * classification of the volume (VPClassifyOctree).  The possible
367      * values are MM_EMPTY (node is transparent), MM_FULL (node has
368      * no transparent children), or MM_PARTFULL.  Status_offset
369      * gives the offset to this field from the beginning of the node.
370      *
371      * The child field is a one word field which gives the number of
372      * bytes from the root of the octree to the first child node of
373      * this node.  The remaining 7 children follow right after the
374      * first child.  Child_offset gives the offset to this field
375      * from the beginning of the node.
376      *
377      * There may be additional bytes of padding in between fields
378      * to satisfy alignment restrictions.  This could make the code
379      * non-portable on machines with bizarre requirements.
380      *
381      * Nodes at level levels-1 are base_bytes_per_node long and contain
382      * the same fields except there is no child field.
383      *
384      * NOTE: As you can probably tell, I'm simulating a C structure here.
385      * Unfortunately I can't use a real structure because I don't know the
386      * number of fields in advance: it depends on the number and
387      * size of the classification parameters.
388      */
389 } MinMaxOctree;
390 
391 /* MMOctreeLevel: data associated with one level of the min-max octree during
392  *     a depth first traversal; this data is used to compute which octree
393  *     nodes intersect the current scanline of interest */
394 typedef struct {		/* MMOctreeLevel */
395     int level_size;		/*   voxels/side for a node at this level */
396     int child_octant;		/*   octant number of first child to visit
397 				     when a scanline intersects a node at
398 				     this level */
399     int child_offset1;		/*   offset (in bytes) of first child to
400 				     visit relative to child 0 */
401     int child_offset2;		/*   offset (in bytes) of second child to
402 				     visit relative to child 0 */
403     void *child2;		/*   points to 2nd child if first is
404 				     begin visit; NULL otherwise */
405 } MMOctreeLevel;
406 
407 /* GrayIntPixel: grayscale intermediate image pixel */
408 typedef struct {		/* GrayIntPixel */
409     float clrflt;		/*   color */
410     float opcflt;		/*   opacity */
411     short lnk;			/*   early-ray termination link */
412     unsigned char zratio;	/*   integer part of opacity correction
413 				       exponent (perspective only) */
414     unsigned char zfrac;	/*   fractional part of opacity correction
415 				       exponent (perspective only) */
416 } GrayIntPixel;
417 
418 /* RGBIntPixel: RGB intermediate image pixel */
419 typedef struct {		/* RGBIntPixel */
420     float rclrflt;		/*   color (red channel) */
421     float gclrflt;		/*   color (green channel) */
422     float bclrflt;		/*   color (blue channel) */
423     float opcflt;		/*   opacity */
424     short lnk;			/*   early-ray termination link */
425     unsigned char zratio;	/*   integer part of opacity correction
426 				       exponent (perspective only) */
427     unsigned char zfrac;	/*   fractional part of opacity correction
428 				       exponent (perspective only) */
429 } RGBIntPixel;
430 
431 /* Trapezoid: a trapezoidal region of the output image (used to record
432  *            intersection of the intermediate and final images) */
433 typedef struct {
434     /* all coordinates are in the coordinate system of the final image */
435     int miny;		/* first scanline of the final image which
436 			   overlaps the trapezoid */
437     int maxy;		/* last scanline of the final image which
438 			   overlaps the trapezoid */
439     double x_top_lft;	/* left edge of the trapezoid at y = miny */
440     double x_top_rgt;	/* right edge of the trapezoid at y = miny */
441     double x_incr_lft;	/* increment to add to x_top_lft to get the
442 			   left edge of the trapezoid at the next y */
443     double x_incr_rgt;	/* increment to add to x_top_rgt to get the
444 			   right edge of the trapezoid at the next y */
445 } Trapezoid;
446 
447 /* vpContext: rendering context */
448 struct _vp_context {			/* vpContext */
449 
450     /* *** USER-SPECIFIED PARAMETERS *** */
451 
452     /* raw volume data layout */
453     int xlen, ylen, zlen;		/* voxels in each dimension */
454     short raw_bytes_per_voxel;		/* size of raw voxel in bytes */
455     short num_voxel_fields;		/* number of fields in the voxel */
456     short num_shade_fields;		/* # of voxel fields for shading */
457     short field_size[VP_MAX_FIELDS];	/* size of each field in bytes */
458     short field_offset[VP_MAX_FIELDS];	/* byte offset for each field */
459     int field_max[VP_MAX_FIELDS];	/* maximum value of each field */
460     void *raw_voxels;			/* voxel data */
461     int raw_voxels_size;		/* size of raw_voxels in bytes */
462     int xstride, ystride, zstride;	/* byte stride for each dimension */
463 
464     /* classification specification */
465     double min_opacity;			/* low opacity threshold (0.0-1.0) */
466     int num_clsfy_params;		/* # of params for classification */
467     int param_field[VP_MAX_FIELDS];	/* voxel field # for each param */
468     float *clsfy_table[VP_MAX_FIELDS];	/* lookup table for each parameter */
469     int clsfy_table_size[VP_MAX_FIELDS]; /* size of each table in bytes */
470 
471     /* shading specification */
472     int color_channels;			/* number of color channels */
473     int shading_mode;			/* type of shader to use */
474     float *shade_color_table;		/* lookup table for LOOKUP_SHADER */
475     int shade_color_table_size;		/* size of shade table in bytes */
476     float *shade_weight_table;		/* lookup table for LOOKUP_SHADER */
477     int shade_weight_table_size;	/* size of weight table in bytes */
478     short num_materials;		/* # of material types in tables */
479     short color_field;			/* voxel field # for color index */
480     short weight_field;			/* field # for weight index */
481 
482     /* material properties for each material and surface side */
483     double matl_props[VP_MAX_MATERIAL][2][NUM_MATL_PROPS]; /* 0.0-255.0 */
484 
485     /* lighting properties */
486     short light_enable[VP_MAX_LIGHTS];	/* enable each light */
487     vpVector4 light_vector[VP_MAX_LIGHTS]; /* normalized light direction
488 					      vectors (in eye coordinates) */
489     vpVector3 light_color[VP_MAX_LIGHTS];  /* light colors (0.0-1.0) */
490     int light_both_sides;		/* use two-sided lighting */
491     int reverse_surface_sides;		/* reverse interior and exterior */
492 
493     /* depth cueing parameters */
494     short dc_enable;			/* true to enable depth cueing */
495     double dc_front_factor;		/* front depth cueing factor */
496     double dc_density;			/* fog density for depth cueing */
497     int dc_table_len_hint;		/* hint for dc_table_len */
498     double dc_quantization;		/* minimum resolvable depth */
499 
500     /* view specification */
501     vpMatrix4 transforms[3];		/* transformation matrices (VP_MODEL,
502 					   VP_VIEW and VP_PROJECT) */
503     short current_matrix;		/* current matrix */
504     int concat_left;			/* if true, concatenate matrices
505 					   on left instead of on right */
506     int axis_override;			/* if not equal to VP_NO_AXIS then
507 					   this is an axis number (e.g.
508 					   VP_X_AXIS) that overrides the
509 					   computed value of best_view_axis */
510 
511     /* result image */
512     void *image;			/* memory for image */
513     int image_width;			/* image dimensions */
514     int image_height;
515     short image_bytes_per_scan;		/* size of scanline (with padding) */
516     int pixel_type;			/* format for pixels (e.g. VP_RGB) */
517 
518     /* rendering parameters */
519     double max_opacity;			/* high opacity threshold */
520     short int_image_width_hint;		/* hint for size of int. image */
521     short int_image_height_hint;
522     short clamp_shade_table;		/* clamp shade table entries */
523 
524     /* min-max octree parameters */
525     int param_maxrange[VP_MAX_FIELDS];	/* max. range of values allowed in an
526 					   mm_octree node w/o subdividing it */
527 
528     /* preclassified volume parameters */
529     short rle_bytes_per_voxel;		/* bytes per voxel in RLEVoxels */
530     int skip_rle_x;			/* if true, don't compute rle_x */
531     int skip_rle_y;			/* if true, don't compute rle_y */
532     int skip_rle_z;			/* if true, don't compute rle_z */
533 
534     /* parameters for rendering shadows */
535     short enable_shadows;		/* if true, enable shadows */
536     short shadow_light_num;		/* light source id (VP_LIGHT#) for
537 					   the light producing the shadows */
538     short shadow_width_hint;		/* hint for width of shadow buffer */
539     short shadow_height_hint;		/* hint for height of shadow buffer */
540     float *shadow_color_table;		/* lookup table for LOOKUP_SHADER */
541     int shadow_color_table_size;	/* size of shade table in bytes */
542     int shadow_bias;			/* shadow bias distance */
543 
544     /* *** USER-SPECIFIED PARAMETERS THAT ARE NOT STORED IN CONTEXT FILE *** */
545 
546     /* dummy variable marking the boundary between state variables stored
547        in volpack context files and those that are not; the value
548        of this variable is never used or set */
549     int end_of_parameters;
550 
551     /* callback functions */
552     void (*shade_func)();		/* shade a voxel */
553     int (*write_func) ANSI_ARGS((int, void *, unsigned)); /* write to file */
554     int (*read_func) ANSI_ARGS((int, void *, unsigned));  /* read from file */
555     void *(*mmap_func) ANSI_ARGS((int, unsigned, void *));/* memory map file */
556     void (*log_alloc_func) ANSI_ARGS((void *,int,char *,int,char *,void *));
557     					/* log memory allocation */
558     void (*log_free_func) ANSI_ARGS((void *, void *));
559 					/* log memory deallocation */
560     void (*status_func) ANSI_ARGS((double, void *)); /* give progress report */
561 
562     /* client data */
563     void *client_data;			/* hook for client data structure */
564 
565     /* resampling filter for vpResample */
566     int filter_num_taps;		/* number of filter taps */
567     int filter_num_phases;		/* number of filter phases */
568     float *filter_weights;		/* table of filter weights
569 					   (weights[num_phases][num_taps]) */
570 
571     /* *** INTERNAL DATA STRUCTURES *** */
572 
573     /* data structures for fast classification */
574     MinMaxOctree *mm_octree;		/* min-max octree version of volume */
575     unsigned *sum_table;		/* summed area table */
576     int sum_table_size;			/* size of summed area table (bytes) */
577 
578     /* classified, run-length encoded volume data */
579     RLEVoxels *rle_x;			/* RLE data for X viewing axis */
580     RLEVoxels *rle_y;			/* RLE data for Y viewing axis */
581     RLEVoxels *rle_z;			/* RLE data for Z viewing axis */
582     ConstructionBuffer *cbuf;		/* buffer for constructing volume */
583 
584     /* factored viewing parameters */
585     short factored_view_ready;		/* true if factored view is current */
586     short affine_view;			/* true for affine transformation */
587     short best_view_axis;		/* principal viewing axis */
588     short reverse_slice_order;		/* compositing direction */
589     short intermediate_width;		/* size of intermediate image */
590     short intermediate_height;
591     double shear_i;			/* shear coefficients */
592     double shear_j;
593     double trans_i;			/* translation coefficients */
594     double trans_j;
595     vpMatrix3 warp_2d;			/* final 2D transformation */
596     double depth_000;			/* depth of first voxel in volume */
597     double depth_di;			/* change in depth per unit i */
598     double depth_dj;			/* change in depth per unit j */
599     double depth_dk;			/* change in depth per unit k */
600 
601     /* work buffers for rendering */
602     short max_intermediate_width;	/* size of intermediate image buffer */
603     short max_intermediate_height;
604     short max_scan_length;		/* size of scanline buffers */
605     short intermediate_color_channels;	/* color channels in int. image */
606     short pad_int_to_maxwidth;		/* pad intermediate image scanlines */
607     union {				/* intermediate image (2D array) */
608 	GrayIntPixel *gray_intim;
609 	RGBIntPixel *rgb_intim;
610     } int_image;
611 
612     /* parameters and data structures for shadows */
613     double shadow_shear_i;		/* shear coeffs for light vector */
614     double shadow_shear_j;
615     double shadow_trans_i;		/* trans. coeffs for light vector */
616     double shadow_trans_j;
617     short shadow_width;			/* size of image in shadow buffer */
618     short shadow_height;
619     short max_shadow_width;		/* size of shadow buffer */
620     short max_shadow_height;
621     short pad_shadow_to_maxwidth;	/* pad shadow buffer scanlines */
622     GrayIntPixel *shadow_buffer;	/* 2D shadow buffer */
623 
624     /* depth cueing */
625     float *dc_table;			/* depth cueing lookup table */
626     int dc_table_len;			/* number of entries in dc_table */
627 
628     /* opacity correction */
629     float affine_opac_correct[VP_OPACITY_MAX+1];
630     					/* maps opacity (0-255) to opacity
631 					   corrected for view (0.0-1.0) */
632     float shadow_opac_correct[VP_OPACITY_MAX+1];
633 					/* opacity correction for shadow
634 					   buffer calculation */
635 
636     /* debugging info */
637     vpResult error_code;		/* result code from first invalid
638 					   command since last call to
639 					   vpGetError() */
640 #ifdef DEBUG
641     short debug_enable[VPDEBUG_COUNT];	/* flags to enable messages */
642     int trace_u, trace_v;		/* intermediate image pixel to trace */
643     int trace_shadow_k;			/* slice of interest for tracing
644 					   shadow opacity values */
645 #endif
646 
647 #ifdef USE_TIMER
648     unsigned timer_ticks[VPTIMER_COUNT];/* timer values in ticks */
649     double timer_usec_per_tick;		/* microseconds per tick */
650 #ifdef HAVE_HIRES_TIMER
651     volatile unsigned *timer_addr;	/* address of the timer */
652     unsigned dummy_timer;		/* dummy location */
653 #endif
654 #endif
655 
656 };
657 
658 /*******************************************************************
659  * Function prototypes.                                            *
660  *******************************************************************/
661 
662 /* vp_context.c */
663 
664 /* vp_check.c */
665 extern vpResult		    VPCheckVoxelFields ANSI_ARGS((vpContext *vpc));
666 extern vpResult		    VPCheckRawVolume ANSI_ARGS((vpContext *vpc));
667 extern vpResult		    VPCheckClassifiedVolume ANSI_ARGS((
668 				vpContext *vpc, int axis));
669 extern vpResult		    VPCheckClassifier ANSI_ARGS((vpContext *vpc));
670 extern vpResult		    VPCheckShader ANSI_ARGS((vpContext *vpc));
671 extern vpResult		    VPCheckImage ANSI_ARGS((vpContext *vpc));
672 extern vpResult		    VPCheckShadows ANSI_ARGS((vpContext *vpc));
673 extern vpResult		    VPSetError ANSI_ARGS((vpContext *vpc,
674 				vpResult code));
675 
676 /* vp_extract.c */
677 extern vpResult		    VPClassifyBlock ANSI_ARGS((vpContext *vpc,
678 				int correct, int x0, int y0, int z0,
679 				int x1, int y1, int z1, float *opc,
680 				int dst_xstride, int dst_ystride,
681 				int dst_zstride));
682 extern float		    VPClassifyVoxel ANSI_ARGS((vpContext *vpc,
683 				void *voxel));
684 extern vpResult		    VPShadeBlock ANSI_ARGS((vpContext *vpc,
685 				int x0, int y0, int z0, int x1, int y1, int z1,
686 				float *shd, int dst_xstride, int dst_ystride,
687 				int dst_zstride));
688 extern void		    VPQuantize ANSI_ARGS((float *src, int xlen,
689 				int ylen, int zlen, double scale, int maxvalue,
690 				unsigned char *dst, int dst_xstride,
691 				int dst_ystride, int dst_zstride));
692 
693 /* vp_linalg.c */
694 extern void		    VPLoadTranslation ANSI_ARGS((vpMatrix4 m,
695 				double tx, double ty, double tz));
696 extern void		    VPLoadRotation ANSI_ARGS((vpMatrix4 m,
697 				int axis, double degrees));
698 extern void		    VPLoadScale ANSI_ARGS((vpMatrix4 m,
699 				double sx, double sy, double sz));
700 
701 /* vp_view.c */
702 extern vpResult		    VPFactorView ANSI_ARGS((vpContext *vpc));
703 extern void		    VPComputeViewTransform ANSI_ARGS((vpContext *vpc,
704 				vpMatrix4 vm));
705 extern void		    VPResizeRenderBuffers ANSI_ARGS((vpContext *vpc,
706 				int max_width, int max_height, int max_scan));
707 extern void		    VPResizeDepthCueTable ANSI_ARGS((vpContext *vpc,
708 				int entries, int copy));
709 extern void		    VPComputeDepthCueTable ANSI_ARGS((vpContext *vpc,
710 				int first, int last));
711 extern float		    VPSliceDepthCueRatio ANSI_ARGS((vpContext *vpc));
712 extern void		    VPDepthCueIntImage ANSI_ARGS((vpContext *vpc,
713 				int slicenum));
714 extern void		    VPResizeShadowBuffer ANSI_ARGS((vpContext *vpc,
715 				int max_width, int max_height));
716 
717 /* vp_util.c */
718 extern void		    VPBug ANSI_ARGS((char *fmt, ...));
719 #ifdef DEBUG
720 extern void		    VPDebug ANSI_ARGS((vpContext *vpc, int debug_code,
721 				char *fmt, ...));
722 #endif /* DEBUG */
723 
724 /* vp_rle.c */
725 extern RLEVoxels *	    VPCreateRLEVoxels ANSI_ARGS((vpContext *vpc,
726 				int ilen, int jlen, int klen, int data_count,
727 				int run_count, int rle_bytes_per_voxel));
728 extern void		    VPDestroyRLEVoxels ANSI_ARGS((vpContext *vpc,
729 				RLEVoxels *rle_voxels));
730 #ifdef INDEX_VOLUME
731 extern vpResult		    VPComputeRLEScanOffsets ANSI_ARGS((
732 				vpContext *vpc));
733 #endif
734 #ifdef DEBUG
735 extern void		    VPCheckScanOffsets ANSI_ARGS((
736 				RLEVoxels *rle_voxels,
737 				int rle_bytes_per_voxel));
738 extern void		    VPValidateClassifiedVolume ANSI_ARGS((
739 				vpContext *vpc));
740 extern void		    VPDumpView ANSI_ARGS((vpContext *vpc));
741 extern void		    VPDumpClassifier ANSI_ARGS((vpContext *vpc));
742 #endif
743 
744 
745 /* vp_renderA.c */
746 extern void		    VPRenderAffine ANSI_ARGS((vpContext *vpc,
747 				int algorithm, void (*composite_func)()));
748 
749 /* vp_octree.c */
750 extern void		    VPComputeSummedAreaTable ANSI_ARGS((
751 				vpContext *vpc));
752 extern void		    VPClassifyOctree ANSI_ARGS((vpContext *vpc));
753 extern void		    VPInitOctreeLevelStack ANSI_ARGS((vpContext *vpc,
754 			       MMOctreeLevel level_stack[VP_MAX_OCTREE_LEVELS],
755 			       int axis, int k));
756 extern int		    VPComputeScanRuns ANSI_ARGS((vpContext *vpc,
757 			       MMOctreeLevel level_stack[VP_MAX_OCTREE_LEVELS],
758 			       unsigned char *run_lengths, int axis,
759 			       int j, int icount));
760 extern int		    VPCheckRuns ANSI_ARGS((vpContext *vpc,
761 				unsigned char *run_lengths, int axis,
762 				int k, int j));
763 extern void		    VPTestMinMaxOctree ANSI_ARGS((vpContext *vpc));
764 
765 /* vp_warp.c */
766 extern void		    VPComputeWarpTables ANSI_ARGS((void));
767 extern void		    VPAffineImageOverlap ANSI_ARGS((int in_width,
768 				int in_height, int out_width, int out_height,
769 				vpMatrix3 warp_matrix, double filter_width,
770 				Trapezoid full_overlap[9],
771 				Trapezoid part_overlap[9]));
772