/*
* vp_check.c
*
* Consistency and error checking routines.
*
* Copyright (c) 1994 The Board of Trustees of The Leland Stanford
* Junior University. All rights reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation for any purpose is hereby granted without fee, provided
* that the above copyright notice and this permission notice appear in
* all copies of this software and that you do not sell the software.
* Commercial licensing is available by contacting the author.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* Author:
* Phil Lacroute
* Computer Systems Laboratory
* Electrical Engineering Dept.
* Stanford University
*/
/*
* $Date: 2001/12/17 16:16:20 $
* $Revision: 1.1 $
*/
#include "vp_global.h"
/* error strings for vpGetErrorString() */
static char *ErrorString[] = {
"limit exceeded",
"singular matrix or vector",
"I/O error",
"invalid buffer size",
"invalid image definition",
"invalid shader definition",
"invalid classifier definition",
"invalid volume definition",
"invalid voxel definition",
"invalid option",
"argument out of range",
"invalid file",
"cannot compute shadow buffer",
};
/*
* VPCheckVoxelFields
*
* Check the voxel field information for validity.
*/
vpResult
VPCheckVoxelFields(vpc)
vpContext *vpc;
{
int f;
int size, offset;
if (vpc->raw_bytes_per_voxel <= 0)
return(VPSetError(vpc, VPERROR_BAD_VOXEL));
if (vpc->num_voxel_fields <= 0)
return(VPSetError(vpc, VPERROR_BAD_VOXEL));
for (f = 0; f < vpc->num_voxel_fields; f++) {
size = vpc->field_size[f];
offset = vpc->field_offset[f];
if (size != 1 && size != 2 && size != 4)
return(VPSetError(vpc, VPERROR_BAD_VOXEL));
if (offset < 0 || offset + size > vpc->raw_bytes_per_voxel)
return(VPSetError(vpc, VPERROR_BAD_VOXEL));
if (f > 0 && offset < vpc->field_size[f-1] + vpc->field_offset[f-1])
return(VPSetError(vpc, VPERROR_BAD_VOXEL));
}
return(VP_OK);
}
/*
* VPCheckRawVolume
*
* Check the raw volume for consistency.
*/
vpResult
VPCheckRawVolume(vpc)
vpContext *vpc;
{
int size, offset, retcode;
if ((retcode = VPCheckVoxelFields(vpc)) != VP_OK)
return(retcode);
if (vpc->xlen <= 0 || vpc->ylen <= 0 || vpc->zlen <= 0)
return(VPSetError(vpc, VPERROR_BAD_VOLUME));
if (vpc->raw_voxels == NULL)
return(VPSetError(vpc, VPERROR_BAD_VOLUME));
if (vpc->raw_bytes_per_voxel * vpc->xlen * vpc->ylen * vpc->zlen !=
vpc->raw_voxels_size)
return(VPSetError(vpc, VPERROR_BAD_VOLUME));
return(VP_OK);
}
/*
* VPCheckClassifiedVolume
*
* Check the classified volume for consistency.
*/
vpResult
VPCheckClassifiedVolume(vpc, axis)
vpContext *vpc;
int axis;
{
int retcode;
if ((retcode = VPCheckVoxelFields(vpc)) != VP_OK)
return(retcode);
if (vpc->xlen <= 0 || vpc->ylen <= 0 || vpc->zlen <= 0)
return(VPSetError(vpc, VPERROR_BAD_VOLUME));
if (vpc->rle_bytes_per_voxel == 0)
return(VPSetError(vpc, VPERROR_BAD_VOLUME));
switch (axis) {
case VP_X_AXIS:
if (vpc->rle_x == NULL)
return(VPSetError(vpc, VPERROR_BAD_VOLUME));
ASSERT(vpc->rle_x->ilen == vpc->ylen);
ASSERT(vpc->rle_x->jlen == vpc->zlen);
ASSERT(vpc->rle_x->klen == vpc->xlen);
break;
case VP_Y_AXIS:
if (vpc->rle_y == NULL)
return(VPSetError(vpc, VPERROR_BAD_VOLUME));
ASSERT(vpc->rle_y->ilen == vpc->zlen);
ASSERT(vpc->rle_y->jlen == vpc->xlen);
ASSERT(vpc->rle_y->klen == vpc->ylen);
break;
case VP_Z_AXIS:
if (vpc->rle_z == NULL)
return(VPSetError(vpc, VPERROR_BAD_VOLUME));
ASSERT(vpc->rle_z->ilen == vpc->xlen);
ASSERT(vpc->rle_z->jlen == vpc->ylen);
ASSERT(vpc->rle_z->klen == vpc->zlen);
break;
default:
VPBug("bad axis in VPCheckClassifiedVolume");
}
return(VP_OK);
}
/*
* VPCheckClassifier
*
* Check the classification parameters for consistency.
*/
vpResult
VPCheckClassifier(vpc)
vpContext *vpc;
{
int p, f;
int size, offset, retcode;
if ((retcode = VPCheckVoxelFields(vpc)) != VP_OK)
return(retcode);
if (vpc->num_shade_fields <= 0 ||
vpc->num_shade_fields > vpc->num_voxel_fields)
return(VPSetError(vpc, VPERROR_BAD_VOXEL));
if (vpc->num_clsfy_params <= 0 ||
vpc->num_clsfy_params > vpc->num_voxel_fields)
return(VPSetError(vpc, VPERROR_BAD_VOXEL));
for (p = 0; p < vpc->num_clsfy_params; p++) {
f = vpc->param_field[p];
if (f < 0 || f >= vpc->num_voxel_fields)
return(VPSetError(vpc, VPERROR_BAD_CLASSIFIER));
if (vpc->clsfy_table[p] == NULL || vpc->clsfy_table_size[p] !=
(vpc->field_max[f]+1)*sizeof(float))
return(VPSetError(vpc, VPERROR_BAD_CLASSIFIER));
if (p > 0 && f <= vpc->param_field[p-1])
return(VPSetError(vpc, VPERROR_BAD_CLASSIFIER));
}
return(VP_OK);
}
/*
* VPCheckShader
*
* Check the shading parameters for consistency.
*/
vpResult
VPCheckShader(vpc)
vpContext *vpc;
{
if (vpc->shading_mode == LOOKUP_SHADER) {
if (vpc->color_field < 0 ||
vpc->color_field >= vpc->num_voxel_fields ||
vpc->color_field >= vpc->num_shade_fields)
return(VPSetError(vpc, VPERROR_BAD_SHADER));
if (vpc->shade_color_table == NULL)
return(VPSetError(vpc, VPERROR_BAD_SHADER));
if (vpc->shade_color_table_size != vpc->color_channels*sizeof(float)*
(vpc->field_max[vpc->color_field]+1)*vpc->num_materials)
return(VPSetError(vpc, VPERROR_BAD_SHADER));
if (vpc->field_size[vpc->color_field] != 2)
return(VPSetError(vpc, VPERROR_BAD_SHADER));
if (vpc->num_materials < 1)
return(VPSetError(vpc, VPERROR_BAD_SHADER));
if (vpc->num_materials > 1) {
if (vpc->weight_field < 0 ||
vpc->weight_field >= vpc->num_voxel_fields ||
vpc->weight_field >= vpc->num_shade_fields)
return(VPSetError(vpc, VPERROR_BAD_SHADER));
if (vpc->shade_weight_table == NULL)
return(VPSetError(vpc, VPERROR_BAD_SHADER));
if (vpc->shade_weight_table_size !=
(vpc->field_max[vpc->weight_field]+1) * sizeof(float) *
vpc->num_materials)
return(VPSetError(vpc, VPERROR_BAD_SHADER));
if (vpc->field_size[vpc->weight_field] != 1)
return(VPSetError(vpc, VPERROR_BAD_SHADER));
}
}
return(VP_OK);
}
/*
* VPCheckImage
*
* Check the image buffer for validity.
*/
vpResult
VPCheckImage(vpc)
vpContext *vpc;
{
if (vpc->image == NULL || vpc->image_width <= 0 || vpc->image_height <= 0)
return(VPSetError(vpc, VPERROR_BAD_IMAGE));
switch (vpc->pixel_type) {
case VP_ALPHA:
break;
case VP_LUMINANCE:
case VP_LUMINANCEA:
if (vpc->color_channels != 1)
return(VPSetError(vpc, VPERROR_BAD_OPTION));
break;
case VP_RGB:
case VP_BGR:
case VP_RGBA:
case VP_ABGR:
if (vpc->color_channels != 3)
return(VPSetError(vpc, VPERROR_BAD_OPTION));
break;
default:
return(VPSetError(vpc, VPERROR_BAD_OPTION));
}
return(VP_OK);
}
/*
* VPCheckShadows
*
* Check the shadow specification for validity.
*/
vpResult
VPCheckShadows(vpc)
vpContext *vpc;
{
if (vpc->enable_shadows) {
if (vpc->shadow_light_num < VP_LIGHT0 ||
vpc->shadow_light_num > VP_LIGHT5)
return(VPSetError(vpc, VPERROR_BAD_OPTION));
if (!vpc->light_enable[vpc->shadow_light_num - VP_LIGHT0])
vpc->enable_shadows = 0;
if (vpc->shadow_color_table_size != vpc->shade_color_table_size ||
vpc->shadow_color_table == NULL)
return(VPSetError(vpc, VPERROR_BAD_SIZE));
}
return(VP_OK);
}
/*
* vpGetError
*
* Return the error code from the first invalid command since the last
* call to vpGetError().
*/
vpResult
vpGetError(vpc)
vpContext *vpc;
{
vpResult code;
code = vpc->error_code;
vpc->error_code = VP_OK;
return(code);
}
/*
* vpGetErrorString
*
* Return a descriptive string for an error code.
*/
char *
vpGetErrorString(code)
vpResult code;
{
if (code == VP_OK)
return("no error");
else if (code < VPERROR_FIRST || code > VPERROR_LAST)
return(NULL);
else
return(ErrorString[code - VPERROR_FIRST]);
}
/*
* VPSetError
*
* Set the error code in vpc.
*/
vpResult
VPSetError(vpc, code)
vpContext *vpc;
vpResult code;
{
if (vpc->error_code == VP_OK)
vpc->error_code = code;
return(code);
}
syntax highlighted by Code2HTML, v. 0.9.1