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