Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

vp_context.c

Go to the documentation of this file.
00001 /*
00002  * vp_context.c
00003  *
00004  * Routines to create, modify and destroy vpContext objects.
00005  *
00006  * Copyright (c) 1994 The Board of Trustees of The Leland Stanford
00007  * Junior University.  All rights reserved.
00008  *
00009  * Permission to use, copy, modify and distribute this software and its
00010  * documentation for any purpose is hereby granted without fee, provided
00011  * that the above copyright notice and this permission notice appear in
00012  * all copies of this software and that you do not sell the software.
00013  * Commercial licensing is available by contacting the author.
00014  * 
00015  * THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
00016  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
00017  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
00018  *
00019  * Author:
00020  *    Phil Lacroute
00021  *    Computer Systems Laboratory
00022  *    Electrical Engineering Dept.
00023  *    Stanford University
00024  */
00025 
00026 /*
00027  * $Date: 2001/12/17 16:16:22 $
00028  * $Revision: 1.1 $
00029  */
00030 
00031 #include "vp_global.h"
00032 
00033 static void InitContext ANSI_ARGS((vpContext *vpc));
00034 #ifdef HAVE_HIRES_TIMER
00035 static void StartHiResTimer ANSI_ARGS((vpContext *vpc));
00036 #endif
00037 
00038 #ifdef STATISTICS
00039 int vpResampleCount = 0;
00040 int vpCompositeCount = 0;
00041 int vpERTSkipCount = 0;
00042 int vpERTSkipAgainCount = 0;
00043 int vpERTUpdateCount = 0;
00044 int vpSpecialZeroSkipCount = 0;
00045 int vpRunFragmentCount = 0;
00046 #endif
00047 
00048 /*
00049  * InitContext
00050  *
00051  * Initialize the fields of a context that have defaults.
00052  */
00053 
00054 static void
00055 InitContext(vpc)
00056 vpContext *vpc;
00057 {
00058     extern int read(), write();
00059     int m, l;
00060 
00061     vpc->xlen = 0;
00062     vpc->ylen = 0;
00063     vpc->zlen = 0;
00064     vpc->raw_bytes_per_voxel = 0;
00065     vpc->num_voxel_fields = 0;
00066     vpc->num_shade_fields = 0;
00067     vpc->min_opacity = 0.0;
00068     vpc->num_clsfy_params = 0;
00069     vpc->color_channels = 1;
00070     vpc->shading_mode = LOOKUP_SHADER;
00071     vpc->num_materials = 1;
00072     vpc->color_field = 0;
00073     vpc->weight_field = 0;
00074     for (m = 0; m < VP_MAX_MATERIAL; m++) {
00075         vpc->matl_props[m][EXT_SURFACE][MATL_AMB_R] = DEFAULT_AMBIENT;
00076         vpc->matl_props[m][EXT_SURFACE][MATL_DIFF_R] = DEFAULT_DIFFUSE;
00077         vpc->matl_props[m][EXT_SURFACE][MATL_SPEC_R] = DEFAULT_SPECULAR;
00078         vpc->matl_props[m][EXT_SURFACE][MATL_AMB_G] = DEFAULT_AMBIENT;
00079         vpc->matl_props[m][EXT_SURFACE][MATL_DIFF_G] = DEFAULT_DIFFUSE;
00080         vpc->matl_props[m][EXT_SURFACE][MATL_SPEC_G] = DEFAULT_SPECULAR;
00081         vpc->matl_props[m][EXT_SURFACE][MATL_AMB_B] = DEFAULT_AMBIENT;
00082         vpc->matl_props[m][EXT_SURFACE][MATL_DIFF_B] = DEFAULT_DIFFUSE;
00083         vpc->matl_props[m][EXT_SURFACE][MATL_SPEC_B] = DEFAULT_SPECULAR;
00084         vpc->matl_props[m][EXT_SURFACE][MATL_SHINY] = DEFAULT_SHINYNESS;
00085 
00086         vpc->matl_props[m][INT_SURFACE][MATL_AMB_R] = DEFAULT_AMBIENT;
00087         vpc->matl_props[m][INT_SURFACE][MATL_DIFF_R] = DEFAULT_DIFFUSE;
00088         vpc->matl_props[m][INT_SURFACE][MATL_SPEC_R] = DEFAULT_SPECULAR;
00089         vpc->matl_props[m][INT_SURFACE][MATL_AMB_G] = DEFAULT_AMBIENT;
00090         vpc->matl_props[m][INT_SURFACE][MATL_DIFF_G] = DEFAULT_DIFFUSE;
00091         vpc->matl_props[m][INT_SURFACE][MATL_SPEC_G] = DEFAULT_SPECULAR;
00092         vpc->matl_props[m][INT_SURFACE][MATL_AMB_B] = DEFAULT_AMBIENT;
00093         vpc->matl_props[m][INT_SURFACE][MATL_DIFF_B] = DEFAULT_DIFFUSE;
00094         vpc->matl_props[m][INT_SURFACE][MATL_SPEC_B] = DEFAULT_SPECULAR;
00095         vpc->matl_props[m][INT_SURFACE][MATL_SHINY] = DEFAULT_SHINYNESS;
00096     }
00097     for (l = 0; l < VP_MAX_LIGHTS; l++) {
00098         vpc->light_enable[l] = 0;
00099         vpSetVector4(vpc->light_vector[l], 0.57735, 0.57735, 0.57735, 1.);
00100         vpSetVector3(vpc->light_color[l], 1., 1., 1.);
00101     }
00102     vpc->light_enable[0] = 1;
00103     vpc->light_both_sides = 0;
00104     vpc->reverse_surface_sides = 0;
00105     vpc->dc_enable = 0;
00106     vpc->dc_front_factor = 1.;
00107     vpc->dc_density = 1.;
00108     vpc->dc_quantization = DEFAULT_DC_QUANTIZATION;
00109     vpIdentity4(vpc->transforms[VP_MODEL]);
00110     vpIdentity4(vpc->transforms[VP_VIEW]);
00111     vpIdentity4(vpc->transforms[VP_PROJECT]);
00112     vpWindow(vpc, VP_PARALLEL, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5);
00113     vpc->current_matrix = VP_MODEL;
00114     vpc->concat_left = 0;
00115     vpc->axis_override = VP_NO_AXIS;
00116     vpc->max_opacity = 1.0;
00117     vpc->factored_view_ready = 0;
00118     vpc->int_image_width_hint = 0;
00119     vpc->int_image_height_hint = 0;
00120     vpc->clamp_shade_table = 1;
00121     vpc->enable_shadows = 0;
00122     vpc->shadow_light_num = VP_LIGHT0;
00123     vpc->shadow_width_hint = 0;
00124     vpc->shadow_height_hint = 0;
00125     vpc->shadow_bias = 4;
00126     vpc->write_func = write;
00127     vpc->read_func = read;
00128     vpc->mmap_func = NULL;
00129     vpc->log_alloc_func = NULL;
00130     vpc->log_free_func = NULL;
00131     vpc->status_func = NULL;
00132     vpc->client_data = NULL;
00133     vpc->error_code = VP_OK;
00134 #ifdef DEBUG
00135     bzero(vpc->debug_enable, VPDEBUG_COUNT * sizeof(short));
00136     vpc->trace_u = -1;
00137     vpc->trace_v = -1;
00138     vpc->trace_shadow_k = 0;
00139 #endif
00140 
00141 #ifdef USE_TIMER
00142     bzero(vpc->timer_ticks, VPTIMER_COUNT * sizeof(unsigned));
00143 #ifdef HAVE_LORES_TIMER
00144     vpc->timer_usec_per_tick = 1.0;
00145 #endif
00146 #ifdef HAVE_HIRES_TIMER
00147     StartHiResTimer(vpc);
00148 #endif
00149 #endif /* USE_TIMER */
00150 }
00151 
00152 /*
00153  * vpCreateContext
00154  *
00155  * Create a rendering context.
00156  */
00157 
00158 vpContext *
00159 vpCreateContext()
00160 {
00161     vpContext *vpc;
00162 
00163     /* NOTE: cannot use Alloc() to allocate a context since it
00164        requires a context as an argument */
00165     if ((vpc = (vpContext *)malloc(sizeof(vpContext))) == NULL)
00166         VPBug("out of memory");
00167     bzero(vpc, sizeof(vpContext));
00168     InitContext(vpc);
00169     return(vpc);
00170 }
00171 
00172 /*
00173  * vpDestroyContext
00174  *
00175  * Destroy a rendering context.
00176  */
00177 
00178 void
00179 vpDestroyContext(vpc)
00180 vpContext *vpc;
00181 {
00182     VPResizeDepthCueTable(vpc, 0, 0);
00183     VPResizeRenderBuffers(vpc, 0, 0, 0);
00184     vpDestroyClassifiedVolume(vpc);
00185     vpDestroyMinMaxOctree(vpc);
00186     if (vpc->sum_table != NULL)
00187         Dealloc(vpc, vpc->sum_table);
00188     VPResizeShadowBuffer(vpc, 0, 0);
00189 
00190     /* NOTE: don't use Dealloc() to deallocate a context since
00191        it wasn't created with Alloc() */
00192     free((void *)vpc);
00193 }
00194 
00195 /*
00196  * vpSetVolumeSize
00197  *
00198  * Set the size of the volume.
00199  */
00200 
00201 vpResult
00202 vpSetVolumeSize(vpc, xlen, ylen, zlen)
00203 vpContext *vpc;
00204 int xlen, ylen, zlen;
00205 {
00206     vpc->xlen = xlen;
00207     vpc->ylen = ylen;
00208     vpc->zlen = zlen;
00209     vpc->factored_view_ready = 0;
00210     vpDestroyClassifiedVolume(vpc);
00211     vpDestroyMinMaxOctree(vpc);
00212     return(VP_OK);
00213 }
00214 
00215 /*
00216  * vpSetVoxelSize
00217  *
00218  * Set the size of a voxel.
00219  */
00220 
00221 vpResult
00222 vpSetVoxelSize(vpc, bytes_per_voxel, num_voxel_fields, num_shade_fields,
00223                num_clsfy_fields)
00224 vpContext *vpc;
00225 int bytes_per_voxel;
00226 int num_voxel_fields;
00227 int num_shade_fields;
00228 int num_clsfy_fields;
00229 {
00230     if (num_voxel_fields >= VP_MAX_FIELDS)
00231         return(VPSetError(vpc, VPERROR_LIMIT_EXCEEDED));
00232     if (num_clsfy_fields < 0 || num_clsfy_fields > num_voxel_fields)
00233         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00234     if (num_shade_fields < 0 || num_shade_fields > num_voxel_fields)
00235         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00236     vpc->raw_bytes_per_voxel = bytes_per_voxel;
00237     vpc->num_voxel_fields = num_voxel_fields;
00238     vpc->num_shade_fields = num_shade_fields;
00239     vpc->num_clsfy_params = num_clsfy_fields;
00240     vpDestroyClassifiedVolume(vpc);
00241     vpDestroyMinMaxOctree(vpc);
00242     return(VP_OK);
00243 }
00244 
00245 /*
00246  * vpSetVoxelField
00247  *
00248  * Set the size and position of a voxel field.
00249  */
00250 
00251 vpResult
00252 vpSetVoxelField(vpc, field_num, field_size, field_offset, field_max)
00253 vpContext *vpc;
00254 int field_num;
00255 int field_size;
00256 int field_offset;
00257 int field_max;
00258 {
00259     if (field_num < 0 || field_num >= vpc->num_voxel_fields)
00260         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00261     if (field_size != 1 && field_size != 2 && field_size != 4)
00262         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00263     if (field_offset < 0 || field_offset >= vpc->raw_bytes_per_voxel)
00264         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00265     vpc->field_size[field_num] = field_size;
00266     vpc->field_offset[field_num] = field_offset;
00267     vpc->field_max[field_num] = field_max;
00268     vpDestroyClassifiedVolume(vpc);
00269     vpDestroyMinMaxOctree(vpc);
00270     return(VP_OK);
00271 }
00272 
00273 /*
00274  * vpSetRawVoxels
00275  *
00276  * Set the array of unclassified voxels.
00277  */
00278 
00279 vpResult
00280 vpSetRawVoxels(vpc, raw_voxels, raw_voxels_size, xstride, ystride, zstride)
00281 vpContext *vpc;
00282 int xstride, ystride, zstride;
00283 void *raw_voxels;
00284 int raw_voxels_size;
00285 {
00286     vpc->raw_voxels = raw_voxels;
00287     vpc->raw_voxels_size = raw_voxels_size;
00288     vpc->xstride = xstride;
00289     vpc->ystride = ystride;
00290     vpc->zstride = zstride;
00291     if (raw_voxels_size != 0)
00292         vpDestroyClassifiedVolume(vpc);
00293     vpDestroyMinMaxOctree(vpc);
00294     return(VP_OK);
00295 }
00296 
00297 /*
00298  * vpSetClassifierTable
00299  *
00300  * Specify a lookup table for one of the classification function's
00301  * parameters.
00302  */
00303 
00304 vpResult
00305 vpSetClassifierTable(vpc, param_num, param_field, table, table_size)
00306 vpContext *vpc;
00307 int param_num;
00308 int param_field;
00309 float *table;
00310 int table_size;
00311 {
00312     if (param_num < 0 || param_num >= vpc->num_clsfy_params)
00313         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00314     if (param_field < 0 || param_field >= vpc->num_voxel_fields)
00315         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00316     vpc->param_field[param_num] = param_field;
00317     vpc->clsfy_table[param_num] = table;
00318     vpc->clsfy_table_size[param_num] = table_size;
00319     return(VP_OK);
00320 }
00321 
00322 /*
00323  * vpSetLookupShader
00324  *
00325  * Define a lookup shader.
00326  */
00327 
00328 vpResult
00329 vpSetLookupShader(vpc, color_channels, num_materials,
00330                   color_field, color_table, color_table_size,
00331                   weight_field, weight_table, weight_table_size)
00332 vpContext *vpc;
00333 int color_channels;
00334 int num_materials;
00335 int color_field;
00336 float *color_table;
00337 int color_table_size;
00338 int weight_field;
00339 float *weight_table;
00340 int weight_table_size;
00341 {
00342     if (color_channels != 1 && color_channels != 3)
00343         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00344     if (num_materials <= 0 || num_materials >= VP_MAX_MATERIAL)
00345         return(VPSetError(vpc, VPERROR_LIMIT_EXCEEDED));
00346     if (color_field < 0 || color_field >= vpc->num_voxel_fields ||
00347         color_table == NULL || color_table_size == 0)
00348         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00349     if (num_materials > 1) {
00350         if (weight_field < 0 || weight_field >= vpc->num_voxel_fields ||
00351             weight_table == NULL || weight_table_size == 0)
00352             return(VPSetError(vpc, VPERROR_BAD_VALUE));
00353     }
00354     vpc->color_channels = color_channels;
00355     vpc->shading_mode = LOOKUP_SHADER;
00356     vpc->shade_color_table = color_table;
00357     vpc->shade_color_table_size = color_table_size;
00358     vpc->shade_weight_table = weight_table;
00359     vpc->shade_weight_table_size = weight_table_size;
00360     vpc->num_materials = num_materials;
00361     vpc->color_field = color_field;
00362     vpc->weight_field = weight_field;
00363     return(VP_OK);
00364 }
00365 
00366 /*
00367  * vpSetShadowLookupShader
00368  *
00369  * Define a lookup shader that support shadows.
00370  */
00371 
00372 vpResult
00373 vpSetShadowLookupShader(vpc, color_channels, num_materials,
00374                         color_field, color_table, color_table_size,
00375                         weight_field, weight_table, weight_table_size,
00376                         shadow_table, shadow_table_size)
00377 vpContext *vpc;
00378 int color_channels;
00379 int num_materials;
00380 int color_field;
00381 float *color_table;
00382 int color_table_size;
00383 int weight_field;
00384 float *weight_table;
00385 int weight_table_size;
00386 float *shadow_table;
00387 int shadow_table_size;
00388 {
00389     if (color_channels != 1 && color_channels != 3)
00390         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00391     if (num_materials <= 0 || num_materials >= VP_MAX_MATERIAL)
00392         return(VPSetError(vpc, VPERROR_LIMIT_EXCEEDED));
00393     if (color_field < 0 || color_field >= vpc->num_voxel_fields ||
00394         color_table == NULL || color_table_size == 0)
00395         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00396     if (num_materials > 1) {
00397         if (weight_field < 0 || weight_field >= vpc->num_voxel_fields ||
00398             weight_table == NULL || weight_table_size == 0)
00399             return(VPSetError(vpc, VPERROR_BAD_VALUE));
00400     }
00401     if (shadow_table_size != color_table_size)
00402         return(VPSetError(vpc, VPERROR_BAD_SIZE));
00403     vpc->color_channels = color_channels;
00404     vpc->shading_mode = LOOKUP_SHADER;
00405     vpc->shade_color_table = color_table;
00406     vpc->shade_color_table_size = color_table_size;
00407     vpc->shade_weight_table = weight_table;
00408     vpc->shade_weight_table_size = weight_table_size;
00409     vpc->num_materials = num_materials;
00410     vpc->color_field = color_field;
00411     vpc->weight_field = weight_field;
00412     vpc->shadow_color_table = shadow_table;
00413     vpc->shadow_color_table_size = shadow_table_size;
00414     return(VP_OK);
00415 }
00416 
00417 /*
00418  * vpSetMaterial
00419  *
00420  * Set material parameters.
00421  */
00422 
00423 vpResult
00424 vpSetMaterial(vpc, material, property, surface_side, r, g, b)
00425 vpContext *vpc;
00426 int material;
00427 int property;
00428 int surface_side;
00429 double r, g, b;
00430 {
00431     material -= VP_MATERIAL0;
00432     if (material < 0 || material >= vpc->num_materials)
00433         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00434     if (surface_side == 0 || (surface_side & ~VP_BOTH_SIDES) != 0)
00435         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00436     if (property != VP_SHINYNESS) {
00437         if (r < 0. || g < 0. || b < 0.)
00438             return(VPSetError(vpc, VPERROR_BAD_VALUE));
00439     }
00440     switch (property) {
00441     case VP_AMBIENT:
00442         if (surface_side & VP_EXTERIOR) {
00443             vpc->matl_props[material][EXT_SURFACE][MATL_AMB_R] = r * 255.;
00444             vpc->matl_props[material][EXT_SURFACE][MATL_AMB_G] = g * 255.;
00445             vpc->matl_props[material][EXT_SURFACE][MATL_AMB_B] = b * 255.;
00446         }
00447         if (surface_side & VP_INTERIOR) {
00448             vpc->matl_props[material][INT_SURFACE][MATL_AMB_R] = r * 255.;
00449             vpc->matl_props[material][INT_SURFACE][MATL_AMB_G] = g * 255.;
00450             vpc->matl_props[material][INT_SURFACE][MATL_AMB_B] = b * 255.;
00451         }
00452         break;
00453     case VP_DIFFUSE:
00454         if (surface_side & VP_EXTERIOR) {
00455             vpc->matl_props[material][EXT_SURFACE][MATL_DIFF_R] = r * 255.;
00456             vpc->matl_props[material][EXT_SURFACE][MATL_DIFF_G] = g * 255.;
00457             vpc->matl_props[material][EXT_SURFACE][MATL_DIFF_B] = b * 255.;
00458         }
00459         if (surface_side & VP_INTERIOR) {
00460             vpc->matl_props[material][INT_SURFACE][MATL_DIFF_R] = r * 255.;
00461             vpc->matl_props[material][INT_SURFACE][MATL_DIFF_G] = g * 255.;
00462             vpc->matl_props[material][INT_SURFACE][MATL_DIFF_B] = b * 255.;
00463         }
00464         break;
00465     case VP_SPECULAR:
00466         if (surface_side & VP_EXTERIOR) {
00467             vpc->matl_props[material][EXT_SURFACE][MATL_SPEC_R] = r * 255.;
00468             vpc->matl_props[material][EXT_SURFACE][MATL_SPEC_G] = g * 255.;
00469             vpc->matl_props[material][EXT_SURFACE][MATL_SPEC_B] = b * 255.;
00470         }
00471         if (surface_side & VP_INTERIOR) {
00472             vpc->matl_props[material][INT_SURFACE][MATL_SPEC_R] = r * 255.;
00473             vpc->matl_props[material][INT_SURFACE][MATL_SPEC_G] = g * 255.;
00474             vpc->matl_props[material][INT_SURFACE][MATL_SPEC_B] = b * 255.;
00475         }
00476         break;
00477     case VP_SHINYNESS:
00478         if (surface_side & VP_EXTERIOR)
00479             vpc->matl_props[material][EXT_SURFACE][MATL_SHINY] = r;
00480         if (surface_side & VP_INTERIOR)
00481             vpc->matl_props[material][INT_SURFACE][MATL_SHINY] = r;
00482         break;
00483     default:
00484         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00485     }
00486     return(VP_OK);
00487 }
00488 
00489 /*
00490  * vpSetLight
00491  *
00492  * Set the properties of a directional light source.
00493  */
00494 
00495 vpResult
00496 vpSetLight(vpc, light_num, property, n0, n1, n2)
00497 vpContext *vpc;
00498 int light_num;
00499 int property;
00500 double n0, n1, n2;
00501 {
00502     vpVector4 v1, v2;
00503 
00504     light_num -= VP_LIGHT0;
00505     if (light_num < 0 || light_num >= VP_MAX_LIGHTS)
00506         return(VPSetError(vpc, VPERROR_LIMIT_EXCEEDED));
00507     switch (property) {
00508     case VP_DIRECTION:
00509         vpSetVector4(v1, n0, n1, n2, 1.);
00510         if (vpNormalize3(v1) != VP_OK)
00511             return(VPSetError(vpc, VPERROR_SINGULAR));
00512         vpMatrixVectorMult4(v2, vpc->transforms[VP_MODEL], v1);
00513         vpc->light_vector[light_num][0] = v2[0];
00514         vpc->light_vector[light_num][1] = v2[1];
00515         vpc->light_vector[light_num][2] = v2[2];
00516         vpc->light_vector[light_num][3] = v2[3];
00517         break;
00518     case VP_COLOR:
00519         if (n0 < 0. || n0 > 1. || n1 < 0. || n1 > 1. || n2 < 0. || n2 > 1.)
00520             return(VPSetError(vpc, VPERROR_BAD_VALUE));
00521         vpc->light_color[light_num][0] = n0;
00522         vpc->light_color[light_num][1] = n1;
00523         vpc->light_color[light_num][2] = n2;
00524         break;
00525     default:
00526         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00527     }
00528     return(VP_OK);
00529 }
00530 
00531 /*
00532  * vpEnable
00533  *
00534  * Enable or disable an option.
00535  */
00536 
00537 vpResult
00538 vpEnable(vpc, option, value)
00539 vpContext *vpc;
00540 int option;
00541 int value;
00542 {
00543     switch (option) {
00544     case VP_LIGHT0:
00545     case VP_LIGHT1:
00546     case VP_LIGHT2:
00547     case VP_LIGHT3:
00548     case VP_LIGHT4:
00549     case VP_LIGHT5:
00550         if (value == 0)
00551             vpc->light_enable[option - VP_LIGHT0] = 0;
00552         else
00553             vpc->light_enable[option - VP_LIGHT0] = 1;
00554         break;
00555     case VP_LIGHT_BOTH_SIDES:
00556         if (value == 0)
00557             vpc->light_both_sides = 0;
00558         else
00559             vpc->light_both_sides = 1;
00560         break;
00561     case VP_REVERSE_SURFACE_SIDES:
00562         if (value == 0)
00563             vpc->reverse_surface_sides = 0;
00564         else
00565             vpc->reverse_surface_sides = 1;
00566         break;
00567     case VP_DEPTH_CUE:
00568         if (value == 0)
00569             vpc->dc_enable = 0;
00570         else
00571             vpc->dc_enable = 1;
00572         break;
00573     case VP_VIEW_X_AXIS:
00574         if (value == 0)
00575             vpc->skip_rle_x = 1;
00576         else
00577             vpc->skip_rle_x = 0;
00578         break;
00579     case VP_VIEW_Y_AXIS:
00580         if (value == 0)
00581             vpc->skip_rle_y = 1;
00582         else
00583             vpc->skip_rle_y = 0;
00584         break;
00585     case VP_VIEW_Z_AXIS:
00586         if (value == 0)
00587             vpc->skip_rle_z = 1;
00588         else
00589             vpc->skip_rle_z = 0;
00590         break;
00591     case VP_SHADOW:
00592         if (value == 0) {
00593             vpc->enable_shadows = 0;
00594         } else {
00595             vpc->enable_shadows = 1;
00596         }
00597         vpc->factored_view_ready = 0;
00598         break;
00599     case VP_CLAMP_SHADE_TABLE:
00600         if (value == 0)
00601             vpc->clamp_shade_table = 0;
00602         else
00603             vpc->clamp_shade_table = 1;
00604         break;
00605     default:
00606         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00607     }
00608     return(VP_OK);
00609 }
00610 
00611 /*
00612  * vpSetDepthCueing
00613  *
00614  * Set depth cueing parameters.
00615  */
00616 
00617 vpResult
00618 vpSetDepthCueing(vpc, front_factor, density)
00619 vpContext *vpc;
00620 double front_factor;
00621 double density;
00622 {
00623     if (front_factor <= 0.)
00624         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00625     vpc->dc_front_factor = front_factor;
00626     vpc->dc_density = density;
00627     if (vpc->dc_table_len > 0)
00628         VPComputeDepthCueTable(vpc, 0, vpc->dc_table_len-1);
00629     return(VP_OK);
00630 }
00631 
00632 /*
00633  * vpCurrentMatrix
00634  *
00635  * Set the current matrix.
00636  */
00637 
00638 vpResult
00639 vpCurrentMatrix(vpc, option)
00640 vpContext *vpc;
00641 int option;
00642 {
00643     switch (option) {
00644     case VP_MODEL:
00645     case VP_VIEW:
00646     case VP_PROJECT:
00647         vpc->current_matrix = option;
00648         break;
00649     default:
00650         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00651     }
00652     return(VP_OK);
00653 }
00654 
00655 /*
00656  * vpIdentityMatrix
00657  *
00658  * Load the identity into the current matrix.
00659  */
00660 
00661 vpResult
00662 vpIdentityMatrix(vpc)
00663 vpContext *vpc;
00664 {
00665     vpIdentity4(vpc->transforms[vpc->current_matrix]);
00666     vpc->factored_view_ready = 0;
00667     return(VP_OK);
00668 }
00669 
00670 /*
00671  * vpSetMatrix
00672  *
00673  * Load the elements of the current matrix.
00674  */
00675 
00676 vpResult
00677 vpSetMatrix(vpc, matrix)
00678 vpContext *vpc;
00679 vpMatrix4 matrix;
00680 {
00681     bcopy(matrix, vpc->transforms[vpc->current_matrix], sizeof(vpMatrix4));
00682     vpc->factored_view_ready = 0;
00683     return(VP_OK);
00684 }
00685 
00686 /*
00687  * vpGetMatrix
00688  *
00689  * Get the elements of the indicated matrix.
00690  */
00691 
00692 vpResult
00693 vpGetMatrix(vpc, matrix_code, matrix)
00694 vpContext *vpc;
00695 int matrix_code;
00696 vpMatrix4 matrix;
00697 {
00698     switch (matrix_code) {
00699     case VP_MODEL:
00700     case VP_VIEW:
00701     case VP_PROJECT:
00702         bcopy(vpc->transforms[matrix_code], matrix, sizeof(vpMatrix4));
00703         break;
00704     case VP_SCREEN:
00705         VPComputeViewTransform(vpc, matrix);
00706         break;
00707     default:
00708         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00709     }
00710     return(VP_OK);
00711 }
00712 
00713 /*
00714  * vpMultMatrix
00715  *
00716  * Multiply the current matrix by the given matrix.
00717  */
00718 
00719 vpResult
00720 vpMultMatrix(vpc, matrix)
00721 vpContext *vpc;
00722 vpMatrix4 matrix;
00723 {
00724     vpMatrix4 tmp;
00725 
00726     if (vpc->concat_left)
00727         vpMatrixMult4(tmp, matrix, vpc->transforms[vpc->current_matrix]);
00728     else
00729         vpMatrixMult4(tmp, vpc->transforms[vpc->current_matrix], matrix);
00730     bcopy(tmp, vpc->transforms[vpc->current_matrix], sizeof(vpMatrix4));
00731     vpc->factored_view_ready = 0;
00732     return(VP_OK);
00733 }
00734 
00735 /*
00736  * vpTranslate
00737  *
00738  * Multiply the current matrix by a translation matrix.
00739  */
00740 
00741 vpResult
00742 vpTranslate(vpc, tx, ty, tz)
00743 vpContext *vpc;
00744 double tx, ty, tz;
00745 {
00746     vpMatrix4 t, tmp;
00747 
00748     VPLoadTranslation(t, tx, ty, tz);
00749     if (vpc->concat_left)
00750         vpMatrixMult4(tmp, t, vpc->transforms[vpc->current_matrix]);
00751     else
00752         vpMatrixMult4(tmp, vpc->transforms[vpc->current_matrix], t);
00753     bcopy(tmp, vpc->transforms[vpc->current_matrix], sizeof(vpMatrix4));
00754     vpc->factored_view_ready = 0;
00755     return(VP_OK);
00756 }    
00757 
00758 /*
00759  * vpRotate
00760  *
00761  * Multiply the current matrix by a rotation matrix.
00762  */
00763 
00764 vpResult
00765 vpRotate(vpc, axis, degrees)
00766 vpContext *vpc;
00767 int axis;
00768 double degrees;
00769 {
00770     vpMatrix4 r, tmp;
00771 
00772     if (axis != VP_X_AXIS && axis != VP_Y_AXIS && axis != VP_Z_AXIS)
00773         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00774     VPLoadRotation(r, axis, degrees);
00775     if (vpc->concat_left)
00776         vpMatrixMult4(tmp, r, vpc->transforms[vpc->current_matrix]);
00777     else
00778         vpMatrixMult4(tmp, vpc->transforms[vpc->current_matrix], r);
00779     bcopy(tmp, vpc->transforms[vpc->current_matrix], sizeof(vpMatrix4));
00780     vpc->factored_view_ready = 0;
00781     return(VP_OK);
00782 }
00783 
00784 /*
00785  * vpScale
00786  *
00787  * Multiply the current matrix by a scale matrix.
00788  */
00789 
00790 vpResult
00791 vpScale(vpc, sx, sy, sz)
00792 vpContext *vpc;
00793 double sx, sy, sz;
00794 {
00795     vpMatrix4 s, tmp;
00796 
00797     VPLoadScale(s, sx, sy, sz);
00798     if (vpc->concat_left)
00799         vpMatrixMult4(tmp, s, vpc->transforms[vpc->current_matrix]);
00800     else
00801         vpMatrixMult4(tmp, vpc->transforms[vpc->current_matrix], s);
00802     bcopy(tmp, vpc->transforms[vpc->current_matrix], sizeof(vpMatrix4));
00803     vpc->factored_view_ready = 0;
00804     return(VP_OK);
00805 }
00806 
00807 /*
00808  * vpWindow
00809  *
00810  * Set the projection matrix for a perspective or
00811  * orthographic viewing volume.
00812  */
00813 
00814 vpResult
00815 vpWindow(vpc, type, left, right, bottom, top, near, far)
00816 vpContext *vpc;
00817 int type;
00818 double left, right, bottom, top, near, far;
00819 {
00820     vpMatrix4 projectm, tmp;
00821 
00822     if (left >= right || bottom >= top || near >= far)
00823         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00824     if (type == VP_PERSPECTIVE) {
00825         if (near <= 0 || far <= 0)
00826             return(VPSetError(vpc, VPERROR_BAD_VALUE));
00827     } else if (type != VP_PARALLEL) {
00828         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00829     }
00830 
00831     vpIdentity4(projectm);
00832     if (type == VP_PARALLEL) {
00833         projectm[0][0] = 2. / (right - left);
00834         projectm[1][1] = 2. / (top - bottom);
00835         projectm[2][2] = 2. / (far - near);
00836         projectm[0][3] = (left + right) / (left - right);
00837         projectm[1][3] = (bottom + top) / (bottom - top);
00838         projectm[2][3] = (near + far) / (near - far);
00839     } else {
00840         /* XXX perspective rendering not available yet */
00841         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00842 #ifdef notdef
00843         projectm[0][0] = 2. * near / (right - left);
00844         projectm[1][1] = 2. * near / (top - bottom);
00845         projectm[2][2] = (near + far) / (near - far);
00846         projectm[0][2] = (right + left) / (right - left);
00847         projectm[1][2] = (top + bottom) / (top - bottom);
00848         projectm[3][2] = -1.;
00849         projectm[2][3] = 2. * far * near / (near - far);
00850 #endif
00851     }
00852     if (vpc->concat_left)
00853         vpMatrixMult4(tmp, projectm, vpc->transforms[VP_PROJECT]);
00854     else
00855         vpMatrixMult4(tmp, vpc->transforms[VP_PROJECT], projectm);
00856     bcopy(tmp, vpc->transforms[VP_PROJECT], sizeof(vpMatrix4));
00857     vpc->factored_view_ready = 0;
00858     return(VP_OK);
00859 }
00860 
00861 /*
00862  * vpWindowPHIGS
00863  *
00864  * Setting the projection matrix using a PHIGS view specification.
00865  */
00866 
00867 vpResult
00868 vpWindowPHIGS(vpc, vrp, vpn, vup, prp, viewport_umin, viewport_umax,
00869               viewport_vmin, viewport_vmax, viewport_front, viewport_back,
00870               projection_type)
00871 vpContext *vpc;
00872 vpVector3 vrp;
00873 vpVector3 vpn;
00874 vpVector3 vup;
00875 vpVector3 prp;
00876 double viewport_umin;
00877 double viewport_umax;
00878 double viewport_vmin;
00879 double viewport_vmax;
00880 double viewport_front;
00881 double viewport_back;
00882 int projection_type;
00883 {
00884     vpMatrix4 m1, m2, m3;
00885     double cw_x, cw_y;  /* center of window */
00886     double newz;
00887 
00888     if (viewport_umax <= viewport_umin || viewport_vmax <= viewport_vmin ||
00889         viewport_front <= viewport_back)
00890         return(VPSetError(vpc, VPERROR_BAD_VALUE));
00891     if (projection_type != VP_PARALLEL && projection_type != VP_PERSPECTIVE)
00892         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00893 
00894     /* perspective rendering not available yet */
00895     if (projection_type == VP_PERSPECTIVE)
00896         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00897 
00898     /* translate view reference point to the origin */
00899     VPLoadTranslation(m1, -vrp[0], -vrp[1], -vrp[2]);
00900 
00901     /* rotate VRC axes into world coordinate axes */
00902     vpIdentity4(m2);
00903     m2[2][0] = vpn[0];
00904     m2[2][1] = vpn[1];
00905     m2[2][2] = vpn[2];
00906     if (vpNormalize3(m2[2]) != VP_OK)
00907         return(VPSetError(vpc, VPERROR_SINGULAR));
00908     vpCrossProduct(m2[0], vup, m2[2]);
00909     if (vpNormalize3(m2[0]) != VP_OK)
00910         return(VPSetError(vpc, VPERROR_SINGULAR));
00911     vpCrossProduct(m2[1], m2[2], m2[0]);
00912     vpMatrixMult4(m3, m2, m1);
00913 
00914     if (projection_type == VP_PERSPECTIVE) {
00915         /* translate center of projection to the origin */
00916         VPLoadTranslation(m1, -prp[0], -prp[1], -prp[2]);
00917         vpMatrixMult4(m2, m1, m3);
00918         bcopy(m2, m3, sizeof(vpMatrix4));
00919     }
00920 
00921     /* shear to make DOP equal to the z axis */
00922     if (fabs(prp[2]) < VP_EPS)
00923         return(VPSetError(vpc, VPERROR_SINGULAR));
00924     vpIdentity4(m1);
00925     cw_x = 0.5 * (viewport_umin + viewport_umax);
00926     cw_y = 0.5 * (viewport_vmin + viewport_vmax);
00927     m1[0][2] = (cw_x - prp[0]) / prp[2];
00928     m1[1][2] = (cw_y - prp[1]) / prp[2];
00929     vpMatrixMult4(m2, m1, m3);
00930 
00931     if (projection_type == VP_PARALLEL) {
00932         /* translate to clip origin */
00933         VPLoadTranslation(m3, -cw_x, -cw_y, -viewport_back);
00934         vpMatrixMult4(m1, m3, m2);
00935 
00936         /* scale to clip coordinates */
00937         VPLoadScale(m2, 2. / (viewport_umax - viewport_umin),
00938                     2. / (viewport_vmax - viewport_vmin),
00939                     1. / (viewport_front - viewport_back));
00940         vpMatrixMult4(m3, m2, m1);
00941     } else {
00942         /* scale into canonical perspective view volume */
00943         if (fabs(prp[2] - viewport_back) < VP_EPS)
00944             return(VPSetError(vpc, VPERROR_SINGULAR));
00945         vpIdentity4(m3);
00946         m3[0][0] = 2*prp[2] / ((viewport_umax - viewport_umin) *
00947                                (prp[2] - viewport_back));
00948         m3[1][1] = 2*prp[2] / ((viewport_vmax - viewport_vmin) *
00949                                (prp[2] - viewport_back));
00950         m3[2][2] = 1. / (prp[2] - viewport_back);
00951         vpMatrixMult4(m1, m3, m2);
00952 
00953         /* transform into clip coordinates */
00954         vpIdentity4(m2);
00955         newz = (prp[2] - viewport_front) / (viewport_back - prp[2]);
00956         m2[2][2] = 1. / (1. + newz);
00957         m2[2][3] = newz / (-1. - newz);
00958         m2[3][2] = -1.;
00959         m2[3][3] = 0.;
00960         vpMatrixMult4(m3, m2, m1);
00961     }
00962     if (vpc->concat_left)
00963         vpMatrixMult4(m1, m3, vpc->transforms[VP_PROJECT]);
00964     else
00965         vpMatrixMult4(m1, vpc->transforms[VP_PROJECT], m3);
00966     bcopy(m1, vpc->transforms[VP_PROJECT], sizeof(vpMatrix4));
00967     vpc->factored_view_ready = 0;
00968     return(VP_OK);
00969 }
00970 
00971 /*
00972  * vpSetImage
00973  *
00974  * Set the buffer to store the image into.
00975  */
00976 
00977 vpResult
00978 vpSetImage(vpc, image, width, height, bytes_per_scan, pixel_type)
00979 vpContext *vpc;
00980 unsigned char *image;
00981 int width, height;
00982 int bytes_per_scan;
00983 int pixel_type;
00984 {
00985     int bytes_per_pixel;
00986 
00987     /* check for errors */
00988     switch (pixel_type) {
00989     case VP_ALPHA:
00990     case VP_LUMINANCE:
00991         bytes_per_pixel = 1;
00992         break;
00993     case VP_LUMINANCEA:
00994         bytes_per_pixel = 2;
00995         break;
00996     case VP_RGB:
00997     case VP_BGR:
00998         bytes_per_pixel = 3;
00999         break;
01000     case VP_RGBA:
01001     case VP_ABGR:
01002         bytes_per_pixel = 4;
01003         break;
01004     default:
01005         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01006     }
01007     if (bytes_per_scan < width * bytes_per_pixel)
01008         return(VPSetError(vpc, VPERROR_BAD_SIZE));
01009 
01010     /* update context */
01011     if (width != vpc->image_width || height != vpc->image_height) {
01012         vpc->image_width = width;
01013         vpc->image_height = height;
01014         vpc->factored_view_ready = 0;
01015     }
01016     vpc->image = image;
01017     vpc->image_bytes_per_scan = bytes_per_scan;
01018     vpc->pixel_type = pixel_type;
01019     return(VP_OK);
01020 }
01021 
01022 /*
01023  * vpSeti
01024  *
01025  * Set a rendering option with an integer value.
01026  */
01027 
01028 vpResult
01029 vpSeti(vpc, option, value)
01030 vpContext *vpc;
01031 int option;
01032 int value;
01033 {
01034     switch (option) {
01035     case VP_CONCAT_MODE:
01036         if (value == VP_CONCAT_LEFT)
01037             vpc->concat_left = 1;
01038         else if (value == VP_CONCAT_RIGHT)
01039             vpc->concat_left = 0;
01040         else
01041             return(VPSetError(vpc, VPERROR_BAD_OPTION));
01042         break;
01043     case VP_DEPTH_CUE_SIZE_HINT:
01044         if (value < 0)
01045             return(VPSetError(vpc, VPERROR_BAD_VALUE));
01046         vpc->dc_table_len_hint = value;
01047         break;
01048     case VP_INT_WIDTH_HINT:
01049         if (value < 0)
01050             return(VPSetError(vpc, VPERROR_BAD_VALUE));
01051         vpc->int_image_width_hint = value;
01052         break;
01053     case VP_INT_HEIGHT_HINT:
01054         if (value < 0)
01055             return(VPSetError(vpc, VPERROR_BAD_VALUE));
01056         vpc->int_image_height_hint = value;
01057         break;
01058     case VP_SHADOW_LIGHT:
01059         if (value < VP_LIGHT0 || value > VP_LIGHT5)
01060             return(VPSetError(vpc, VPERROR_BAD_OPTION));
01061         vpc->shadow_light_num = value;
01062         break;
01063     case VP_SHADOW_WIDTH_HINT:
01064         if (value < 0)
01065             return(VPSetError(vpc, VPERROR_BAD_VALUE));
01066         vpc->shadow_width_hint = value;
01067         break;
01068     case VP_SHADOW_HEIGHT_HINT:
01069         if (value < 0)
01070             return(VPSetError(vpc, VPERROR_BAD_VALUE));
01071         vpc->shadow_height_hint = value;
01072         break;
01073     case VP_SHADOW_BIAS:
01074         if (value < 0)
01075             return(VPSetError(vpc, VPERROR_BAD_VALUE));
01076         vpc->shadow_bias = value;
01077         vpc->factored_view_ready = 0;
01078         break;
01079     case VP_AXIS_OVERRIDE:
01080         switch (value) {
01081         case VP_X_AXIS:
01082         case VP_Y_AXIS:
01083         case VP_Z_AXIS:
01084         case VP_NO_AXIS:
01085             vpc->axis_override = value;
01086             break;
01087         default:
01088             return(VPSetError(vpc, VPERROR_BAD_OPTION));
01089             break;
01090         }
01091         vpc->factored_view_ready = 0;
01092         break;
01093     case VP_TRACE_SHADOW_K:
01094 #ifdef DEBUG
01095         vpc->trace_shadow_k = value;
01096 #endif
01097         break;
01098     default:
01099         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01100     }
01101     return(VP_OK);
01102 }
01103 
01104 /*
01105  * vpSetd
01106  *
01107  * Set a rendering option with a double-precision value.
01108  */
01109 
01110 vpResult
01111 vpSetd(vpc, option, value)
01112 vpContext *vpc;
01113 int option;
01114 double value;
01115 {
01116     switch (option) {
01117     case VP_DEPTH_CUE_QUANTIZATION:
01118         if (value <= 0. || value >= 1.)
01119             return(VPSetError(vpc, VPERROR_BAD_VALUE));
01120         vpc->dc_quantization = value;
01121         VPResizeDepthCueTable(vpc, 0, 0);
01122         break;
01123     case VP_MAX_RAY_OPACITY:
01124         if (value < 0. || value > 1.)
01125             return(VPSetError(vpc, VPERROR_BAD_VALUE));
01126         vpc->max_opacity = value;
01127         break;
01128     case VP_MIN_VOXEL_OPACITY:
01129         if ((value < 0. || value > 1.) && value != -1.0)
01130             return(VPSetError(vpc, VPERROR_BAD_VALUE));
01131         vpc->min_opacity = value;
01132         break;
01133     default:
01134         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01135     }
01136     return(VP_OK);
01137 }
01138 
01139 /*
01140  * vpMinMaxOctreeThreshold
01141  *
01142  * Set the threshold of a parameter for constructing the min-max octree.
01143  */
01144 
01145 vpResult
01146 vpMinMaxOctreeThreshold(vpc, param, range)
01147 vpContext *vpc;
01148 int param;
01149 int range;
01150 {
01151     if (param >= vpc->num_clsfy_params)
01152         return(VPSetError(vpc, VPERROR_BAD_VALUE));
01153     vpc->param_maxrange[param] = range;
01154     return(VP_OK);
01155 }
01156 
01157 /*
01158  * vpSetCallback
01159  *
01160  * Set one of the callback functions.
01161  */
01162 
01163 vpResult
01164 vpSetCallback(vpc, option, func)
01165 vpContext *vpc;
01166 int option;
01167 void *func;
01168 {
01169     extern int read(), write();
01170 
01171     switch (option) {
01172     case VP_LOG_ALLOC_FUNC:
01173         vpc->log_alloc_func = func;
01174         break;
01175     case VP_LOG_FREE_FUNC:
01176         vpc->log_free_func = func;
01177         break;
01178     case VP_STATUS_FUNC:
01179         vpc->status_func = func;
01180         break;
01181     case VP_READ_FUNC:
01182         if (func == NULL)
01183             vpc->read_func = read;
01184         else
01185             vpc->read_func = func;
01186         break;
01187     case VP_WRITE_FUNC:
01188         if (func == NULL)
01189             vpc->write_func = write;
01190         else
01191             vpc->write_func = func;
01192         break;
01193     case VP_MMAP_FUNC:
01194         vpc->mmap_func = func;
01195         break;
01196     case VP_GRAY_SHADE_FUNC:
01197         if (func == NULL) {
01198             vpc->shading_mode = LOOKUP_SHADER;
01199         } else {
01200             vpc->color_channels = 1;
01201             vpc->shading_mode = CALLBACK_SHADER;
01202             vpc->shade_func = func;
01203         }
01204         break;
01205     case VP_RGB_SHADE_FUNC:
01206         if (func == NULL) {
01207             vpc->shading_mode = LOOKUP_SHADER;
01208         } else {
01209             vpc->color_channels = 3;
01210             vpc->shading_mode = CALLBACK_SHADER;
01211             vpc->shade_func = func;
01212         }
01213         break;
01214     default:
01215         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01216     }
01217     return(VP_OK);
01218 }
01219 
01220 /*
01221  * vpSetClientData
01222  *
01223  * Set the client_data hook.
01224  */
01225 
01226 vpResult
01227 vpSetClientData(vpc, client_data)
01228 vpContext *vpc;
01229 void *client_data;
01230 {
01231     vpc->client_data = client_data;
01232     return(VP_OK);
01233 }
01234 
01235 /*
01236  * vpSetDebug
01237  *
01238  * Set the value of a debugging flag.
01239  */
01240 
01241 vpResult
01242 vpSetDebug(vpc, flag, value)
01243 vpContext *vpc;
01244 int flag;
01245 int value;
01246 {
01247     if (flag < 0 || flag >= VPDEBUG_COUNT)
01248         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01249 #ifdef DEBUG
01250     vpc->debug_enable[flag] = value;
01251 #endif
01252     return(VP_OK);
01253 }
01254 
01255 /*
01256  * vpTracePixel
01257  *
01258  * Trace one pixel of the intermediate image.
01259  */
01260 
01261 vpResult
01262 vpTracePixel(vpc, trace_u, trace_v)
01263 vpContext *vpc;
01264 int trace_u, trace_v;   /* pixel coordinates */
01265 {
01266 #ifdef DEBUG
01267     vpc->trace_u = trace_u;
01268     vpc->trace_v = trace_v;
01269 #endif
01270     return(VP_OK);
01271 }
01272 
01273 /*
01274  * vpGeti
01275  *
01276  * Retrieve an integer-valued piece of state.
01277  */
01278 
01279 vpResult
01280 vpGeti(vpc, option, iptr)
01281 vpContext *vpc;
01282 int option;
01283 int *iptr;
01284 {
01285     int c;
01286     int retcode;
01287 
01288     switch (option) {
01289     case VP_XLEN:
01290         *iptr = vpc->xlen;
01291         break;
01292     case VP_YLEN:
01293         *iptr = vpc->ylen;
01294         break;
01295     case VP_ZLEN:
01296         *iptr = vpc->zlen;
01297         break;
01298     case VP_BYTES_PER_VOXEL:
01299         *iptr = vpc->raw_bytes_per_voxel;
01300         break;
01301     case VP_VOXEL_FIELD_COUNT:
01302         *iptr = vpc->num_voxel_fields;
01303         break;
01304     case VP_SHADE_FIELD_COUNT:
01305         *iptr = vpc->num_shade_fields;
01306         break;
01307     case VP_FIELD_SIZES:
01308         for (c = 0; c < vpc->num_voxel_fields; c++)
01309             iptr[c] = vpc->field_size[c];
01310         break;
01311     case VP_FIELD_OFFSETS:
01312         for (c = 0; c < vpc->num_voxel_fields; c++)
01313             iptr[c] = vpc->field_offset[c];
01314         break;
01315     case VP_FIELD_MAXES:
01316         for (c = 0; c < vpc->num_voxel_fields; c++)
01317             iptr[c] = vpc->field_max[c];
01318         break;
01319     case VP_VOXEL_DATA_SIZE:
01320         *iptr = vpc->raw_voxels_size;
01321         break;
01322     case VP_VOXEL_XSTRIDE:
01323         *iptr = vpc->xstride;
01324         break;
01325     case VP_VOXEL_YSTRIDE:
01326         *iptr = vpc->ystride;
01327         break;
01328     case VP_VOXEL_ZSTRIDE:
01329         *iptr = vpc->zstride;
01330         break;
01331     case VP_CLASSIFY_FIELD_COUNT:
01332         *iptr = vpc->num_clsfy_params;
01333         break;
01334     case VP_CLASSIFY_FIELDS:
01335         for (c = 0; c < vpc->num_clsfy_params; c++)
01336             iptr[c] = vpc->param_field[c];
01337         break;
01338     case VP_CLASSIFY_TABLE_SIZES:
01339         for (c = 0; c < vpc->num_clsfy_params; c++)
01340             iptr[c] = vpc->clsfy_table_size[c];
01341         break;
01342     case VP_COLOR_CHANNELS:
01343         *iptr = vpc->color_channels;
01344         break;
01345     case VP_SHADE_COLOR_SIZE:
01346         *iptr = vpc->shade_color_table_size;
01347         break;
01348     case VP_SHADE_WEIGHT_SIZE:
01349         *iptr = vpc->shade_weight_table_size;
01350         break;
01351     case VP_MATERIAL_COUNT:
01352         *iptr = vpc->num_materials;
01353         break;
01354     case VP_SHADE_COLOR_FIELD:
01355         *iptr = vpc->color_field;
01356         break;
01357     case VP_SHADE_WEIGHT_FIELD:
01358         *iptr = vpc->weight_field;
01359         break;
01360     case VP_LIGHT0:
01361     case VP_LIGHT1:
01362     case VP_LIGHT2:
01363     case VP_LIGHT3:
01364     case VP_LIGHT4:
01365     case VP_LIGHT5:
01366         *iptr = vpc->light_enable[option - VP_LIGHT0];
01367         break;
01368     case VP_LIGHT_BOTH_SIDES:
01369         *iptr = vpc->light_both_sides;
01370         break;
01371     case VP_REVERSE_SURFACE_SIDES:
01372         *iptr = vpc->reverse_surface_sides;
01373         break;
01374     case VP_DEPTH_CUE:
01375         *iptr = vpc->dc_enable;
01376         break;
01377     case VP_DEPTH_CUE_TABLE_SIZE:
01378         *iptr = vpc->dc_table_len;
01379         break;
01380     case VP_DEPTH_CUE_SIZE_HINT:
01381         *iptr = vpc->dc_table_len_hint;
01382         break;
01383     case VP_CURRENT_MATRIX:
01384         *iptr = vpc->current_matrix;
01385         break;
01386     case VP_CONCAT_MODE:
01387         if (vpc->concat_left)
01388             *iptr = VP_CONCAT_LEFT;
01389         else
01390             *iptr = VP_CONCAT_RIGHT;
01391         break;
01392     case VP_IMAGE_WIDTH:
01393         *iptr = vpc->image_width;
01394         break;
01395     case VP_IMAGE_HEIGHT:
01396         *iptr = vpc->image_height;
01397         break;
01398     case VP_IMAGE_SCAN_SIZE:
01399         *iptr = vpc->image_bytes_per_scan;
01400         break;
01401     case VP_VIEW_AXIS:
01402         if ((retcode = VPFactorView(vpc)) != VP_OK)
01403             return(retcode);
01404         *iptr = vpc->best_view_axis;
01405         break;
01406     case VP_INTERMEDIATE_WIDTH:
01407         if ((retcode = VPFactorView(vpc)) != VP_OK)
01408             return(retcode);
01409         *iptr = vpc->intermediate_width;
01410         break;
01411     case VP_INTERMEDIATE_HEIGHT:
01412         if ((retcode = VPFactorView(vpc)) != VP_OK)
01413             return(retcode);
01414         *iptr = vpc->intermediate_height;
01415         break;
01416     case VP_INTERMEDIATE_COLOR:
01417         if ((retcode = VPFactorView(vpc)) != VP_OK)
01418             return(retcode);
01419         *iptr = vpc->intermediate_color_channels;
01420         break;
01421     case VP_INT_WIDTH_HINT:
01422         *iptr = vpc->int_image_width_hint;
01423         break;
01424     case VP_INT_HEIGHT_HINT:
01425         *iptr = vpc->int_image_height_hint;
01426         break;
01427     case VP_VIEW_X_AXIS:
01428         *iptr = !vpc->skip_rle_x;
01429         break;
01430     case VP_VIEW_Y_AXIS:
01431         *iptr = !vpc->skip_rle_y;
01432         break;
01433     case VP_VIEW_Z_AXIS:
01434         *iptr = !vpc->skip_rle_z;
01435         break;
01436     case VP_VIEW_X_SIZE:
01437         if (vpc->rle_x == NULL) {
01438             *iptr = 0;
01439         } else {
01440             *iptr = sizeof(RLEVoxels) + vpc->rle_x->run_count +
01441                     vpc->rle_x->data_count*vpc->rle_bytes_per_voxel +
01442                     vpc->rle_x->klen*vpc->rle_x->scan_offsets_per_slice*
01443                         sizeof(ScanOffset);
01444         }
01445         break;
01446     case VP_VIEW_Y_SIZE:
01447         if (vpc->rle_y == NULL) {
01448             *iptr = 0;
01449         } else {
01450             *iptr = sizeof(RLEVoxels) + vpc->rle_y->run_count +
01451                     vpc->rle_y->data_count*vpc->rle_bytes_per_voxel +
01452                     vpc->rle_y->klen*vpc->rle_y->scan_offsets_per_slice*
01453                         sizeof(ScanOffset);
01454         }
01455         break;
01456     case VP_VIEW_Z_SIZE:
01457         if (vpc->rle_z == NULL) {
01458             *iptr = 0;
01459         } else {
01460             *iptr = sizeof(RLEVoxels) + vpc->rle_z->run_count +
01461                     vpc->rle_z->data_count*vpc->rle_bytes_per_voxel +
01462                     vpc->rle_z->klen*vpc->rle_z->scan_offsets_per_slice*
01463                         sizeof(ScanOffset);
01464         }
01465         break;
01466     case VP_MMOCTREE_THRESHOLDS:
01467         for (c = 0; c < vpc->num_clsfy_params; c++)
01468             iptr[c] = vpc->param_maxrange[c];
01469         break;
01470     case VP_MMOCTREE_SIZE:
01471         if (vpc->mm_octree == NULL)
01472             *iptr = 0;
01473         else
01474             *iptr = sizeof(MinMaxOctree) + vpc->mm_octree->octree_bytes;
01475         break;
01476     case VP_SHADOW:
01477         *iptr = vpc->enable_shadows;
01478         break;
01479     case VP_SHADOW_LIGHT:
01480         *iptr = vpc->shadow_light_num;
01481         break;
01482     case VP_SHADOW_WIDTH_HINT:
01483         *iptr = vpc->shadow_width_hint;
01484         break;
01485     case VP_SHADOW_HEIGHT_HINT:
01486         *iptr = vpc->shadow_height_hint;
01487         break;
01488     case VP_SHADOW_WIDTH:
01489         if ((retcode = VPFactorView(vpc)) != VP_OK)
01490             return(retcode);
01491         *iptr = vpc->shadow_width;
01492         break;
01493     case VP_SHADOW_HEIGHT:
01494         if ((retcode = VPFactorView(vpc)) != VP_OK)
01495             return(retcode);
01496         *iptr = vpc->shadow_height;
01497         break;
01498     case VP_SHADOW_COLOR_SIZE:
01499         *iptr = vpc->shadow_color_table_size;
01500         break;
01501     case VP_SHADOW_BIAS:
01502         *iptr = vpc->shadow_bias;
01503         break;
01504     case VP_PIXEL_TYPE:
01505         *iptr = vpc->pixel_type;
01506         break;
01507     case VP_CLAMP_SHADE_TABLE:
01508         *iptr = vpc->clamp_shade_table;
01509         break;
01510     case VP_COMPOSITE_ORDER:
01511         if ((retcode = VPFactorView(vpc)) != VP_OK)
01512             return(retcode);
01513         if (vpc->reverse_slice_order)
01514             *iptr = -1;
01515         else
01516             *iptr = 1;
01517         break;
01518     default:
01519         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01520     }
01521     return(VP_OK);
01522 }
01523 
01524 /*
01525  * vpGetd
01526  *
01527  * Retrieve a double-precision-valued piece of state.
01528  */
01529 
01530 vpResult
01531 vpGetd(vpc, option, dptr)
01532 vpContext *vpc;
01533 int option;
01534 double *dptr;
01535 {
01536     int c;
01537 
01538     switch (option) {
01539     case VP_MIN_VOXEL_OPACITY:
01540         *dptr = vpc->min_opacity;
01541         break;
01542     case VP_DEPTH_CUE_FRONT:
01543         *dptr = vpc->dc_front_factor;
01544         break;
01545     case VP_DEPTH_CUE_DENSITY:
01546         *dptr = vpc->dc_density;
01547         break;
01548     case VP_DEPTH_CUE_QUANTIZATION:
01549         *dptr = vpc->dc_quantization;
01550         break;
01551     case VP_MAX_RAY_OPACITY:
01552         *dptr = vpc->max_opacity;
01553         break;
01554     default:
01555         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01556     }
01557     return(VP_OK);
01558 }
01559 
01560 /*
01561  * vpGetp
01562  *
01563  * Retrieve a pointer-valued piece of state.
01564  */
01565 
01566 vpResult
01567 vpGetp(vpc, option, pptr)
01568 vpContext *vpc;
01569 int option;
01570 void **pptr;
01571 {
01572     int c;
01573 
01574     switch (option) {
01575     case VP_VOXEL_DATA:
01576         *pptr = vpc->raw_voxels;
01577         break;
01578     case VP_CLASSIFY_TABLES:
01579         for (c = 0; c < vpc->num_clsfy_params; c++)
01580             pptr[c] = vpc->clsfy_table[c];
01581         break;
01582     case VP_SHADE_FUNC:
01583         *pptr = vpc->shade_func;
01584         break;
01585     case VP_SHADE_COLOR_TABLE:
01586         *pptr = vpc->shade_color_table;
01587         break;
01588     case VP_SHADE_WEIGHT_TABLE:
01589         *pptr = vpc->shade_weight_table;
01590         break;
01591     case VP_SHADOW_COLOR_TABLE:
01592         *pptr = vpc->shadow_color_table;
01593         break;
01594     case VP_IMAGE:
01595         *pptr = vpc->image;
01596         break;
01597     case VP_LOG_ALLOC_FUNC:
01598         *pptr = vpc->log_alloc_func;
01599         break;
01600     case VP_LOG_FREE_FUNC:
01601         *pptr = vpc->log_free_func;
01602         break;
01603     case VP_STATUS_FUNC:
01604         *pptr = vpc->status_func;
01605         break;
01606     case VP_READ_FUNC:
01607         *pptr = vpc->read_func;
01608         break;
01609     case VP_WRITE_FUNC:
01610         *pptr = vpc->write_func;
01611         break;
01612     case VP_MMAP_FUNC:
01613         *pptr = vpc->mmap_func;
01614         break;
01615     case VP_CLIENT_DATA:
01616         *pptr = vpc->client_data;
01617         break;
01618     default:
01619         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01620     }
01621     return(VP_OK);
01622 }
01623 
01624 /*
01625  * vpGetMaterial
01626  *
01627  * Get material parameters.
01628  */
01629 
01630 vpResult
01631 vpGetMaterial(vpc, material, property, surface_side, r, g, b)
01632 vpContext *vpc;
01633 int material;
01634 int property;
01635 int surface_side;
01636 double *r, *g, *b;
01637 {
01638     material -= VP_MATERIAL0;
01639     if (material < 0 || material >= vpc->num_materials)
01640         return(VPSetError(vpc, VPERROR_BAD_VALUE));
01641     if (surface_side != VP_EXTERIOR && surface_side != VP_INTERIOR)
01642         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01643     switch (property) {
01644     case VP_AMBIENT:
01645         if (surface_side == VP_EXTERIOR) {
01646             *r = vpc->matl_props[material][EXT_SURFACE][MATL_AMB_R] / 255.;
01647             *g = vpc->matl_props[material][EXT_SURFACE][MATL_AMB_G] / 255.;
01648             *b = vpc->matl_props[material][EXT_SURFACE][MATL_AMB_B] / 255.;
01649         } else {
01650             *r = vpc->matl_props[material][INT_SURFACE][MATL_AMB_R] / 255.;
01651             *g = vpc->matl_props[material][INT_SURFACE][MATL_AMB_G] / 255.;
01652             *b = vpc->matl_props[material][INT_SURFACE][MATL_AMB_B] / 255.;
01653         }
01654         break;
01655     case VP_DIFFUSE:
01656         if (surface_side == VP_EXTERIOR) {
01657             *r = vpc->matl_props[material][EXT_SURFACE][MATL_DIFF_R] / 255.;
01658             *g = vpc->matl_props[material][EXT_SURFACE][MATL_DIFF_G] / 255.;
01659             *b = vpc->matl_props[material][EXT_SURFACE][MATL_DIFF_B] / 255.;
01660         } else {
01661             *r = vpc->matl_props[material][INT_SURFACE][MATL_DIFF_R] / 255.;
01662             *g = vpc->matl_props[material][INT_SURFACE][MATL_DIFF_G] / 255.;
01663             *b = vpc->matl_props[material][INT_SURFACE][MATL_DIFF_B] / 255.;
01664         }
01665         break;
01666     case VP_SPECULAR:
01667         if (surface_side == VP_EXTERIOR) {
01668             *r = vpc->matl_props[material][EXT_SURFACE][MATL_SPEC_R] / 255.;
01669             *g = vpc->matl_props[material][EXT_SURFACE][MATL_SPEC_G] / 255.;
01670             *b = vpc->matl_props[material][EXT_SURFACE][MATL_SPEC_B] / 255.;
01671         } else {
01672             *r = vpc->matl_props[material][INT_SURFACE][MATL_SPEC_R] / 255.;
01673             *g = vpc->matl_props[material][INT_SURFACE][MATL_SPEC_G] / 255.;
01674             *b = vpc->matl_props[material][INT_SURFACE][MATL_SPEC_B] / 255.;
01675         }
01676         break;
01677     case VP_SHINYNESS:
01678         if (surface_side & VP_EXTERIOR)
01679             *r = vpc->matl_props[material][EXT_SURFACE][MATL_SHINY];
01680         else
01681             *r = vpc->matl_props[material][INT_SURFACE][MATL_SHINY];
01682         break;
01683     default:
01684         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01685     }
01686     return(VP_OK);
01687 }
01688 
01689 /*
01690  * vpGetLight
01691  *
01692  * Get the properties of a directional light source.
01693  */
01694 
01695 vpResult
01696 vpGetLight(vpc, light_num, property, n0, n1, n2)
01697 vpContext *vpc;
01698 int light_num;
01699 int property;
01700 double *n0, *n1, *n2;
01701 {
01702     light_num -= VP_LIGHT0;
01703     if (light_num < 0 || light_num >= VP_MAX_LIGHTS)
01704         return(VPSetError(vpc, VPERROR_LIMIT_EXCEEDED));
01705     switch (property) {
01706     case VP_DIRECTION:
01707         *n0 = vpc->light_vector[light_num][0];
01708         *n1 = vpc->light_vector[light_num][1];
01709         *n2 = vpc->light_vector[light_num][2];
01710         break;
01711     case VP_COLOR:
01712         *n0 = vpc->light_color[light_num][0];
01713         *n1 = vpc->light_color[light_num][1];
01714         *n2 = vpc->light_color[light_num][2];
01715         break;
01716     default:
01717         return(VPSetError(vpc, VPERROR_BAD_OPTION));
01718     }
01719     return(VP_OK);
01720 }
01721 
01722 /*
01723  * vpGetImage
01724  *
01725  * Get one of the intermediate rendering buffers.
01726  */
01727 
01728 vpResult
01729 vpGetImage(vpc, image, width, height, scan_bytes, pixel_type, image_type)
01730 vpContext *vpc;         /* context */
01731 void *image;            /* buffer for storing result */
01732 int width;              /* expected width of image in buffer */
01733 int height;             /* expected height of image in buffer */
01734 int scan_bytes;         /* bytes per scanline in buffer */
01735 int pixel_type;         /* type of pixel to store in buffer */
01736 int image_type;         /* rendering buffer to extract from
01737                            (VP_IMAGE_BUFFER or VP_SHADOW_BUFFER) */
01738 {
01739     int x, y;
01740     unsigned char *dst_ptr;
01741     GrayIntPixel *gray_pixel;
01742     RGBIntPixel *rgb_pixel;
01743     int value;
01744     int color_channels;
01745 
01746     switch (image_type) {
01747     case VP_IMAGE_BUFFER:
01748         if (width != vpc->intermediate_width ||
01749             height != vpc->intermediate_height)
01750             return(VPSetError(vpc, VPERROR_BAD_SIZE));
01751         color_channels = vpc->intermediate_color_channels;
01752         dst_ptr = image;
01753         switch (pixel_type) {
01754         case VP_ALPHA:
01755             if (scan_bytes < width)
01756                 return(VPSetError(vpc, VPERROR_BAD_SIZE));
01757             if (color_channels == 1) {
01758                 for (y = 0; y < height; y++) {
01759                     gray_pixel = vpc->int_image.gray_intim +
01760                         (vpc->pad_int_to_maxwidth ?
01761                          vpc->max_intermediate_width*y :
01762                          vpc->intermediate_width*y);
01763                     dst_ptr = (unsigned char *)image + y * scan_bytes;
01764                     for (x = 0; x < width; x++) {
01765                         value = (int)rint(gray_pixel->opcflt * 255.);
01766                         if (value > 255)
01767                             *dst_ptr = 255;
01768                         else
01769                             *dst_ptr = value;
01770                         dst_ptr++;
01771                         gray_pixel++;
01772                     }
01773                 }
01774             } else {
01775                 for (y = 0; y < height; y++) {
01776                     rgb_pixel = vpc->int_image.rgb_intim +
01777                         (vpc->pad_int_to_maxwidth ?
01778                          vpc->max_intermediate_width*y :
01779                          vpc->intermediate_width*y);
01780                     dst_ptr = (unsigned char *)image + y * scan_bytes;
01781                     for (x = 0; x < width; x++) {
01782                         value = (int)rint(rgb_pixel->opcflt * 255.);
01783                         if (value > 255)
01784                             *dst_ptr = 255;
01785                         else
01786                             *dst_ptr = value;
01787                         dst_ptr++;
01788                         rgb_pixel++;
01789                     }
01790                 }
01791             }
01792             break;
01793         case VP_LUMINANCE:
01794             if (color_channels != 1)
01795                 return(VPSetError(vpc, VPERROR_BAD_OPTION));
01796             if (scan_bytes < width)
01797                 return(VPSetError(vpc, VPERROR_BAD_SIZE));
01798             for (y = 0; y < height; y++) {
01799                 gray_pixel = vpc->int_image.gray_intim +
01800                     (vpc->pad_int_to_maxwidth ?
01801                      vpc->max_intermediate_width*y :
01802                      vpc->intermediate_width*y);
01803                 dst_ptr = (unsigned char *)image + y * scan_bytes;
01804                 for (x = 0; x < width; x++) {
01805                     value = (int)rint(gray_pixel->clrflt);
01806                     if (value > 255)
01807                         *dst_ptr = 255;
01808                     else
01809                         *dst_ptr = value;
01810                     dst_ptr++;
01811                     gray_pixel++;
01812                 }
01813             }
01814             break;
01815         case VP_LUMINANCEA:
01816             if (color_channels != 1)
01817                 return(VPSetError(vpc, VPERROR_BAD_OPTION));
01818             if (scan_bytes < 2*width)
01819                 return(VPSetError(vpc, VPERROR_BAD_SIZE));
01820             for (y = 0; y < height; y++) {
01821                 gray_pixel = vpc->int_image.gray_intim +
01822                     (vpc->pad_int_to_maxwidth ?
01823                      vpc->max_intermediate_width*y :
01824                      vpc->intermediate_width*y);
01825                 dst_ptr = (unsigned char *)image + y * scan_bytes;
01826                 for (x = 0; x < width; x++) {
01827                     value = (int)rint(gray_pixel->clrflt);
01828                     if (value > 255)
01829                         *dst_ptr = 255;
01830                     else
01831                         *dst_ptr = value;
01832                     dst_ptr++;
01833                     value = (int)rint(gray_pixel->opcflt * 255.);
01834                     if (value > 255)
01835                         *dst_ptr = 255;
01836                     else
01837                         *dst_ptr = value;
01838                     dst_ptr++;
01839                     gray_pixel++;
01840                 }
01841             }
01842             break;
01843         case VP_RGB:
01844             if (color_channels != 3)
01845                 return(VPSetError(vpc, VPERROR_BAD_OPTION));
01846             if (scan_bytes < 3*width)
01847                 return(VPSetError(vpc, VPERROR_BAD_SIZE));
01848             for (y = 0; y < height; y++) {
01849                 rgb_pixel = vpc->int_image.rgb_intim +
01850                     (vpc->pad_int_to_maxwidth ?
01851                      vpc->max_intermediate_width*y :
01852                      vpc->intermediate_width*y);
01853                 dst_ptr = (unsigned char *)image + y * scan_bytes;
01854                 for (x = 0; x < width; x++) {
01855                     value = (int)rint(rgb_pixel->rclrflt);
01856                     if (value > 255)
01857                         *dst_ptr = 255;
01858                     else
01859                         *dst_ptr = value;
01860                     dst_ptr++;
01861                     value = (int)rint(rgb_pixel->gclrflt);
01862                     if (value > 255)
01863                         *dst_ptr = 255;
01864                     else
01865                         *dst_ptr = value;
01866                     dst_ptr++;
01867                     value = (int)rint(rgb_pixel->bclrflt);
01868                     if (value > 255)
01869                         *dst_ptr = 255;
01870                     else
01871                         *dst_ptr = value;
01872                     dst_ptr++;
01873                     rgb_pixel++;
01874                 }
01875             }
01876             break;
01877         case VP_RGBA:
01878             if (color_channels != 3)
01879                 return(VPSetError(vpc, VPERROR_BAD_OPTION));
01880             if (scan_bytes < 4*width)
01881                 return(VPSetError(vpc, VPERROR_BAD_SIZE));
01882             for (y = 0; y < height; y++) {
01883                 rgb_pixel = vpc->int_image.rgb_intim +
01884                     (vpc->pad_int_to_maxwidth ?
01885                      vpc->max_intermediate_width*y :
01886                      vpc->intermediate_width*y);
01887                 dst_ptr = (unsigned char *)image + y * scan_bytes;
01888                 for (x = 0; x < width; x++) {
01889                     value = (int)rint(rgb_pixel->rclrflt);
01890                     if (value > 255)
01891                         *dst_ptr = 255;
01892                     else
01893                         *dst_ptr = value;
01894                     dst_ptr++;
01895                     value = (int)rint(rgb_pixel->gclrflt);
01896                     if (value > 255)
01897                         *dst_ptr = 255;
01898                     else
01899                         *dst_ptr = value;
01900                     dst_ptr++;
01901                     value = (int)rint(rgb_pixel->bclrflt);
01902                     if (value > 255)
01903                         *dst_ptr = 255;
01904                     else
01905                         *dst_ptr = value;
01906                     dst_ptr++;
01907                     value = (int)rint(rgb_pixel->opcflt*255.);
01908                     if (value > 255)
01909                         *dst_ptr = 255;
01910                     else
01911                         *dst_ptr = value;
01912                     dst_ptr++;
01913                     rgb_pixel++;
01914                 }
01915             }
01916             break;
01917         case VP_BGR:
01918             if (color_channels != 3)
01919                 return(VPSetError(vpc, VPERROR_BAD_OPTION));
01920             if (scan_bytes < 3*width)
01921                 return(VPSetError(vpc, VPERROR_BAD_SIZE));
01922             for (y = 0; y < height; y++) {
01923                 rgb_pixel = vpc->int_image.rgb_intim +
01924                     (vpc->pad_int_to_maxwidth ?
01925                      vpc->max_intermediate_width*y :
01926                      vpc->intermediate_width*y);
01927                 dst_ptr = (unsigned char *)image + y * scan_bytes;
01928                 for (x = 0; x < width; x++) {
01929                     value = (int)rint(rgb_pixel->bclrflt);
01930                     if (value > 255)
01931                         *dst_ptr = 255;
01932                     else
01933                         *dst_ptr = value;
01934                     dst_ptr++;
01935                     value = (int)rint(rgb_pixel->gclrflt);
01936                     if (value > 255)
01937                         *dst_ptr = 255;
01938                     else
01939                         *dst_ptr = value;
01940                     dst_ptr++;
01941                     value = (int)rint(rgb_pixel->rclrflt);
01942                     if (value > 255)
01943                         *dst_ptr = 255;
01944                     else
01945                         *dst_ptr = value;
01946                     dst_ptr++;
01947                     rgb_pixel++;
01948                 }
01949             }
01950             break;
01951         case VP_ABGR:
01952             if (color_channels != 3)
01953                 return(VPSetError(vpc, VPERROR_BAD_OPTION));
01954             if (scan_bytes < 4*width)
01955                 return(VPSetError(vpc, VPERROR_BAD_SIZE));
01956             for (y = 0; y < height; y++) {
01957                 rgb_pixel = vpc->int_image.rgb_intim +
01958                     (vpc->pad_int_to_maxwidth ?
01959                      vpc->max_intermediate_width*y :
01960                      vpc->intermediate_width*y);
01961                 dst_ptr = (unsigned char *)image + y * scan_bytes;
01962                 for (x = 0; x < width; x++) {
01963                     value = (int)rint(rgb_pixel->opcflt*255.);
01964                     if (value > 255)
01965                         *dst_ptr = 255;
01966                     else
01967                         *dst_ptr = value;
01968                     dst_ptr++;
01969                     value = (int)rint(rgb_pixel->bclrflt);
01970                     if (value > 255)
01971                         *dst_ptr = 255;
01972                     else
01973                         *dst_ptr = value;
01974                     dst_ptr++;
01975                     value = (int)rint(rgb_pixel->gclrflt);
01976                     if (value > 255)
01977                         *dst_ptr = 255;
01978                     else
01979                         *dst_ptr = value;
01980                     dst_ptr++;
01981                     value = (int)rint(rgb_pixel->rclrflt);
01982                     if (value > 255)
01983                         *dst_ptr = 255;
01984                     else
01985                         *dst_ptr = value;
01986                     dst_ptr++;
01987                     rgb_pixel++;
01988                 }
01989             }
01990             break;
01991         default:
01992             return(VPSetError(vpc, VPERROR_BAD_OPTION));
01993         }
01994         break;
01995     case VP_SHADOW_BUFFER:
01996         if (pixel_type != VP_ALPHA)
01997             return(VPSetError(vpc, VPERROR_BAD_OPTION));
01998         if (width != vpc->shadow_width || height != vpc->shadow_height)
01999             return(VPSetError(vpc, VPERROR_BAD_SIZE));
02000         if (scan_bytes < width)
02001             return(VPSetError(vpc, VPERROR_BAD_SIZE));
02002         for (y = 0; y < height; y++) {
02003             gray_pixel = vpc->shadow_buffer + (vpc->pad_shadow_to_maxwidth ?
02004                         vpc->max_shadow_width*y : vpc->shadow_width*y);
02005             dst_ptr = (unsigned char *)image + y * scan_bytes;
02006             for (x = 0; x < width; x++) {
02007                 value = (int)rint(gray_pixel->opcflt * 255.);
02008                 if (value > 255)
02009                     *dst_ptr = 255;
02010                 else
02011                     *dst_ptr = value;
02012                 dst_ptr++;
02013                 gray_pixel++;
02014             }
02015         }
02016         break;
02017     default:
02018         return(VPSetError(vpc, VPERROR_BAD_OPTION));
02019     }
02020     return(VP_OK);
02021 }
02022 
02023 /*
02024  * vpGetTimer
02025  *
02026  * Get the value of one of the timers.
02027  */
02028 
02029 vpResult
02030 vpGetTimer(vpc, option, iptr)
02031 vpContext *vpc;
02032 int option;
02033 int *iptr;
02034 {
02035     if (option < 0 || option >= VPTIMER_COUNT)
02036         return(VPSetError(vpc, VPERROR_BAD_OPTION));
02037 #ifdef USE_TIMER
02038     *iptr = (int)(vpc->timer_ticks[option] * vpc->timer_usec_per_tick);
02039 #else
02040     *iptr = 0;
02041 #endif
02042     return(VP_OK);
02043 }
02044 
02045 /*
02046  * vpClearTimer
02047  *
02048  * Reset the value of one of the timers to zero.
02049  */
02050 
02051 vpResult
02052 vpClearTimer(vpc, option)
02053 vpContext *vpc;
02054 int option;
02055 {
02056     if (option < 0 || option >= VPTIMER_COUNT)
02057         return(VPSetError(vpc, VPERROR_BAD_OPTION));
02058 #ifdef USE_TIMER
02059     vpc->timer_ticks[option] = 0;
02060 #endif
02061     return(VP_OK);
02062 }
02063 
02064 #ifdef HAVE_HIRES_TIMER
02065 /*
02066  * StartHiResTimer
02067  *
02068  * Initialize the high-resolution memory mapped timer (available on
02069  * some models of SGI hardware).  On machines with a 64-bit timer
02070  * (e.g. Challenge or ONYX), HAVE_64BIT_TIMER must be defined for
02071  * proper operation.
02072  */
02073 
02074 static void
02075 StartHiResTimer(vpc)
02076 vpContext *vpc;
02077 {
02078     volatile unsigned timer_resolution; /* resolution of timer in psec. */
02079     unsigned phys_addr;         /* hardware address of timer */
02080     unsigned page_addr;         /* address of page containing timer */
02081     int fd;                     /* file descriptor for file to be mapped */
02082     volatile unsigned *timer_addr; /* memory-mapped address of timer */
02083 
02084 
02085     /* set values to harmless defaults in case hardware doesn't really
02086        support a high-resolution timer */
02087     vpc->timer_usec_per_tick = 0.;
02088     vpc->timer_addr = &vpc->dummy_timer;
02089     vpc->dummy_timer = 0;
02090 
02091     phys_addr = syssgi(SGI_QUERY_CYCLECNTR, &timer_resolution);
02092     if ((int)phys_addr == -1)
02093         return;
02094     if ((fd = open("/dev/mmem", O_RDONLY)) < 0)
02095         return;
02096     page_addr = phys_addr & ~POFFMASK;
02097     timer_addr = (volatile unsigned *)mmap(0, POFFMASK, PROT_READ,
02098                                            MAP_PRIVATE, fd, (int)page_addr);
02099     close(fd);
02100     if ((int)timer_addr == -1)
02101         return;
02102     vpc->timer_addr = (unsigned *)((unsigned)timer_addr + poff(phys_addr));
02103 #ifdef HAVE_64BIT_TIMER
02104     vpc->timer_addr++;
02105     printf("Timer configured for 64 bits.\n");
02106 #endif
02107     vpc->timer_usec_per_tick = timer_resolution * 1.0e-6;
02108     printf("Timer resolution is %d psec.\n", timer_resolution);
02109 }
02110 #endif /* HAVE_HIRES_TIMER */
 

Powered by Plone

This site conforms to the following standards: