00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
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 
00050 
00051 
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 
00150 }
00151 
00152 
00153 
00154 
00155 
00156 
00157 
00158 vpContext *
00159 vpCreateContext()
00160 {
00161     vpContext *vpc;
00162 
00163     
00164 
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 
00174 
00175 
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     
00191 
00192     free((void *)vpc);
00193 }
00194 
00195 
00196 
00197 
00198 
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 
00217 
00218 
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 
00247 
00248 
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 
00275 
00276 
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 
00299 
00300 
00301 
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 
00324 
00325 
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 
00368 
00369 
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 
00419 
00420 
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 
00491 
00492 
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 
00533 
00534 
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 
00613 
00614 
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 
00634 
00635 
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 
00657 
00658 
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 
00672 
00673 
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 
00688 
00689 
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 
00715 
00716 
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 
00737 
00738 
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 
00760 
00761 
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 
00786 
00787 
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 
00809 
00810 
00811 
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         
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 
00863 
00864 
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;  
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     
00895     if (projection_type == VP_PERSPECTIVE)
00896         return(VPSetError(vpc, VPERROR_BAD_OPTION));
00897 
00898     
00899     VPLoadTranslation(m1, -vrp[0], -vrp[1], -vrp[2]);
00900 
00901     
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         
00916         VPLoadTranslation(m1, -prp[0], -prp[1], -prp[2]);
00917         vpMatrixMult4(m2, m1, m3);
00918         bcopy(m2, m3, sizeof(vpMatrix4));
00919     }
00920 
00921     
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         
00933         VPLoadTranslation(m3, -cw_x, -cw_y, -viewport_back);
00934         vpMatrixMult4(m1, m3, m2);
00935 
00936         
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         
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         
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 
00973 
00974 
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     
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     
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 
01024 
01025 
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 
01106 
01107 
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 
01141 
01142 
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 
01159 
01160 
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 
01222 
01223 
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 
01237 
01238 
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 
01257 
01258 
01259 
01260 
01261 vpResult
01262 vpTracePixel(vpc, trace_u, trace_v)
01263 vpContext *vpc;
01264 int trace_u, trace_v;   
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 
01275 
01276 
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 
01526 
01527 
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 
01562 
01563 
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 
01626 
01627 
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 
01691 
01692 
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 
01724 
01725 
01726 
01727 
01728 vpResult
01729 vpGetImage(vpc, image, width, height, scan_bytes, pixel_type, image_type)
01730 vpContext *vpc;         
01731 void *image;            
01732 int width;              
01733 int height;             
01734 int scan_bytes;         
01735 int pixel_type;         
01736 int image_type;         
01737 
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 
02025 
02026 
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 
02047 
02048 
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 
02067 
02068 
02069 
02070 
02071 
02072 
02073 
02074 static void
02075 StartHiResTimer(vpc)
02076 vpContext *vpc;
02077 {
02078     volatile unsigned timer_resolution; 
02079     unsigned phys_addr;         
02080     unsigned page_addr;         
02081     int fd;                     
02082     volatile unsigned *timer_addr; 
02083 
02084 
02085     
02086 
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