1 /*
2  * vp_check.c
3  *
4  * Consistency and error checking routines.
5  *
6  * Copyright (c) 1994 The Board of Trustees of The Leland Stanford
7  * Junior University.  All rights reserved.
8  *
9  * Permission to use, copy, modify and distribute this software and its
10  * documentation for any purpose is hereby granted without fee, provided
11  * that the above copyright notice and this permission notice appear in
12  * all copies of this software and that you do not sell the software.
13  * Commercial licensing is available by contacting the author.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * Author:
20  *    Phil Lacroute
21  *    Computer Systems Laboratory
22  *    Electrical Engineering Dept.
23  *    Stanford University
24  */
25 
26 /*
27  * $Date: 1994/12/30 23:52:38 $
28  * $Revision: 1.18 $
29  */
30 
31 #include "vp_global.h"
32 
33 /* error strings for vpGetErrorString() */
34 static char *ErrorString[] = {
35     "limit exceeded",
36     "singular matrix or vector",
37     "I/O error",
38     "invalid buffer size",
39     "invalid image definition",
40     "invalid shader definition",
41     "invalid classifier definition",
42     "invalid volume definition",
43     "invalid voxel definition",
44     "invalid option",
45     "argument out of range",
46     "invalid file",
47     "cannot compute shadow buffer",
48 };
49 
50 /*
51  * VPCheckVoxelFields
52  *
53  * Check the voxel field information for validity.
54  */
55 
56 vpResult
VPCheckVoxelFields(vpc)57 VPCheckVoxelFields(vpc)
58 vpContext *vpc;
59 {
60     int f;
61     int size, offset;
62 
63     if (vpc->raw_bytes_per_voxel <= 0)
64 	return(VPSetError(vpc, VPERROR_BAD_VOXEL));
65     if (vpc->num_voxel_fields <= 0)
66 	return(VPSetError(vpc, VPERROR_BAD_VOXEL));
67     for (f = 0; f < vpc->num_voxel_fields; f++) {
68 	size = vpc->field_size[f];
69 	offset = vpc->field_offset[f];
70 	if (size != 1 && size != 2 && size != 4)
71 	    return(VPSetError(vpc, VPERROR_BAD_VOXEL));
72 	if (offset < 0 || offset + size > vpc->raw_bytes_per_voxel)
73 	    return(VPSetError(vpc, VPERROR_BAD_VOXEL));
74 	if (f > 0 && offset < vpc->field_size[f-1] + vpc->field_offset[f-1])
75 	    return(VPSetError(vpc, VPERROR_BAD_VOXEL));
76     }
77     return(VP_OK);
78 }
79 
80 /*
81  * VPCheckRawVolume
82  *
83  * Check the raw volume for consistency.
84  */
85 
86 vpResult
VPCheckRawVolume(vpc)87 VPCheckRawVolume(vpc)
88 vpContext *vpc;
89 {
90     int size, offset, retcode;
91 
92     if ((retcode = VPCheckVoxelFields(vpc)) != VP_OK)
93 	return(retcode);
94     if (vpc->xlen <= 0 || vpc->ylen <= 0 || vpc->zlen <= 0)
95 	return(VPSetError(vpc, VPERROR_BAD_VOLUME));
96     if (vpc->raw_voxels == NULL)
97 	return(VPSetError(vpc, VPERROR_BAD_VOLUME));
98     if (vpc->raw_bytes_per_voxel * vpc->xlen * vpc->ylen * vpc->zlen !=
99 	vpc->raw_voxels_size)
100 	return(VPSetError(vpc, VPERROR_BAD_VOLUME));
101     return(VP_OK);
102 }
103 
104 /*
105  * VPCheckClassifiedVolume
106  *
107  * Check the classified volume for consistency.
108  */
109 
110 vpResult
VPCheckClassifiedVolume(vpc,axis)111 VPCheckClassifiedVolume(vpc, axis)
112 vpContext *vpc;
113 int axis;
114 {
115     int retcode;
116 
117     if ((retcode = VPCheckVoxelFields(vpc)) != VP_OK)
118 	return(retcode);
119     if (vpc->xlen <= 0 || vpc->ylen <= 0 || vpc->zlen <= 0)
120 	return(VPSetError(vpc, VPERROR_BAD_VOLUME));
121     if (vpc->rle_bytes_per_voxel == 0)
122 	return(VPSetError(vpc, VPERROR_BAD_VOLUME));
123     switch (axis) {
124     case VP_X_AXIS:
125 	if (vpc->rle_x == NULL)
126 	    return(VPSetError(vpc, VPERROR_BAD_VOLUME));
127 	ASSERT(vpc->rle_x->ilen == vpc->ylen);
128 	ASSERT(vpc->rle_x->jlen == vpc->zlen);
129 	ASSERT(vpc->rle_x->klen == vpc->xlen);
130 	break;
131     case VP_Y_AXIS:
132 	if (vpc->rle_y == NULL)
133 	    return(VPSetError(vpc, VPERROR_BAD_VOLUME));
134 	ASSERT(vpc->rle_y->ilen == vpc->zlen);
135 	ASSERT(vpc->rle_y->jlen == vpc->xlen);
136 	ASSERT(vpc->rle_y->klen == vpc->ylen);
137 	break;
138     case VP_Z_AXIS:
139 	if (vpc->rle_z == NULL)
140 	    return(VPSetError(vpc, VPERROR_BAD_VOLUME));
141 	ASSERT(vpc->rle_z->ilen == vpc->xlen);
142 	ASSERT(vpc->rle_z->jlen == vpc->ylen);
143 	ASSERT(vpc->rle_z->klen == vpc->zlen);
144 	break;
145     default:
146 	VPBug("bad axis in VPCheckClassifiedVolume");
147     }
148     return(VP_OK);
149 }
150 
151 /*
152  * VPCheckClassifier
153  *
154  * Check the classification parameters for consistency.
155  */
156 
157 vpResult
VPCheckClassifier(vpc)158 VPCheckClassifier(vpc)
159 vpContext *vpc;
160 {
161     int p, f;
162     int size, offset, retcode;
163 
164     if ((retcode = VPCheckVoxelFields(vpc)) != VP_OK)
165 	return(retcode);
166     if (vpc->num_shade_fields <= 0 ||
167 	vpc->num_shade_fields > vpc->num_voxel_fields)
168 	return(VPSetError(vpc, VPERROR_BAD_VOXEL));
169     if (vpc->num_clsfy_params <= 0 ||
170 	vpc->num_clsfy_params > vpc->num_voxel_fields)
171 	return(VPSetError(vpc, VPERROR_BAD_VOXEL));
172     for (p = 0; p < vpc->num_clsfy_params; p++) {
173 	f = vpc->param_field[p];
174 	if (f < 0 || f >= vpc->num_voxel_fields)
175 	    return(VPSetError(vpc, VPERROR_BAD_CLASSIFIER));
176 	if (vpc->clsfy_table[p] == NULL || vpc->clsfy_table_size[p] !=
177 	    (vpc->field_max[f]+1)*sizeof(float))
178 	    return(VPSetError(vpc, VPERROR_BAD_CLASSIFIER));
179 	if (p > 0 && f <= vpc->param_field[p-1])
180 	    return(VPSetError(vpc, VPERROR_BAD_CLASSIFIER));
181     }
182     return(VP_OK);
183 }
184 
185 /*
186  * VPCheckShader
187  *
188  * Check the shading parameters for consistency.
189  */
190 
191 vpResult
VPCheckShader(vpc)192 VPCheckShader(vpc)
193 vpContext *vpc;
194 {
195     if (vpc->shading_mode == LOOKUP_SHADER) {
196 	if (vpc->color_field < 0 ||
197 	    vpc->color_field >= vpc->num_voxel_fields ||
198 	    vpc->color_field >= vpc->num_shade_fields)
199 	    return(VPSetError(vpc, VPERROR_BAD_SHADER));
200 	if (vpc->shade_color_table == NULL)
201 	    return(VPSetError(vpc, VPERROR_BAD_SHADER));
202 	if (vpc->shade_color_table_size != vpc->color_channels*sizeof(float)*
203 		(vpc->field_max[vpc->color_field]+1)*vpc->num_materials)
204 	    return(VPSetError(vpc, VPERROR_BAD_SHADER));
205 	if (vpc->field_size[vpc->color_field] != 2)
206 	    return(VPSetError(vpc, VPERROR_BAD_SHADER));
207 	if (vpc->num_materials < 1)
208 	    return(VPSetError(vpc, VPERROR_BAD_SHADER));
209 	if (vpc->num_materials > 1) {
210 	    if (vpc->weight_field < 0 ||
211 		vpc->weight_field >= vpc->num_voxel_fields ||
212 		vpc->weight_field >= vpc->num_shade_fields)
213 		return(VPSetError(vpc, VPERROR_BAD_SHADER));
214 	    if (vpc->shade_weight_table == NULL)
215 		return(VPSetError(vpc, VPERROR_BAD_SHADER));
216 	    if (vpc->shade_weight_table_size !=
217 		(vpc->field_max[vpc->weight_field]+1) * sizeof(float) *
218 		vpc->num_materials)
219 		return(VPSetError(vpc, VPERROR_BAD_SHADER));
220 	    if (vpc->field_size[vpc->weight_field] != 1)
221 		return(VPSetError(vpc, VPERROR_BAD_SHADER));
222 	}
223     }
224     return(VP_OK);
225 }
226 
227 /*
228  * VPCheckImage
229  *
230  * Check the image buffer for validity.
231  */
232 
233 vpResult
VPCheckImage(vpc)234 VPCheckImage(vpc)
235 vpContext *vpc;
236 {
237     if (vpc->image == NULL || vpc->image_width <= 0 || vpc->image_height <= 0)
238 	return(VPSetError(vpc, VPERROR_BAD_IMAGE));
239     switch (vpc->pixel_type) {
240     case VP_ALPHA:
241 	break;
242     case VP_LUMINANCE:
243     case VP_LUMINANCEA:
244 	if (vpc->color_channels != 1)
245 	    return(VPSetError(vpc, VPERROR_BAD_OPTION));
246 	break;
247     case VP_RGB:
248     case VP_BGR:
249     case VP_RGBA:
250     case VP_ABGR:
251 	if (vpc->color_channels != 3)
252 	    return(VPSetError(vpc, VPERROR_BAD_OPTION));
253 	break;
254     default:
255 	return(VPSetError(vpc, VPERROR_BAD_OPTION));
256     }
257     return(VP_OK);
258 }
259 
260 /*
261  * VPCheckShadows
262  *
263  * Check the shadow specification for validity.
264  */
265 
266 vpResult
VPCheckShadows(vpc)267 VPCheckShadows(vpc)
268 vpContext *vpc;
269 {
270     if (vpc->enable_shadows) {
271 	if (vpc->shadow_light_num < VP_LIGHT0 ||
272 	    vpc->shadow_light_num > VP_LIGHT5)
273 	    return(VPSetError(vpc, VPERROR_BAD_OPTION));
274 	if (!vpc->light_enable[vpc->shadow_light_num - VP_LIGHT0])
275 	    vpc->enable_shadows = 0;
276 	if (vpc->shadow_color_table_size != vpc->shade_color_table_size ||
277 	    vpc->shadow_color_table == NULL)
278 	    return(VPSetError(vpc, VPERROR_BAD_SIZE));
279     }
280     return(VP_OK);
281 }
282 
283 /*
284  * vpGetError
285  *
286  * Return the error code from the first invalid command since the last
287  * call to vpGetError().
288  */
289 
290 vpResult
vpGetError(vpc)291 vpGetError(vpc)
292 vpContext *vpc;
293 {
294     vpResult code;
295 
296     code = vpc->error_code;
297     vpc->error_code = VP_OK;
298     return(code);
299 }
300 
301 /*
302  * vpGetErrorString
303  *
304  * Return a descriptive string for an error code.
305  */
306 
307 char *
vpGetErrorString(code)308 vpGetErrorString(code)
309 vpResult code;
310 {
311     if (code == VP_OK)
312 	return("no error");
313     else if (code < VPERROR_FIRST || code > VPERROR_LAST)
314 	return(NULL);
315     else
316 	return(ErrorString[code - VPERROR_FIRST]);
317 }
318 
319 /*
320  * VPSetError
321  *
322  * Set the error code in vpc.
323  */
324 
325 vpResult
VPSetError(vpc,code)326 VPSetError(vpc, code)
327 vpContext *vpc;
328 vpResult code;
329 {
330     if (vpc->error_code == VP_OK)
331 	vpc->error_code = code;
332     return(code);
333 }
334