1 //////////////////////////////////////////////////////////////////////
2 //
3 //                             Pixie
4 //
5 // Copyright � 1999 - 2003, Okan Arikan
6 //
7 // Contact: okan@cs.utexas.edu
8 //
9 //	This library is free software; you can redistribute it and/or
10 //	modify it under the terms of the GNU Lesser General Public
11 //	License as published by the Free Software Foundation; either
12 //	version 2.1 of the License, or (at your option) any later version.
13 //
14 //	This library is distributed in the hope that it will be useful,
15 //	but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 //	Lesser General Public License for more details.
18 //
19 //	You should have received a copy of the GNU Lesser General Public
20 //	License along with this library; if not, write to the Free Software
21 //	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22 //
23 ///////////////////////////////////////////////////////////////////////
24 ///////////////////////////////////////////////////////////////////////
25 //
26 //  File				:	ribOut.cpp
27 //  Classes				:	CRibOut
28 //  Description			:
29 //
30 ////////////////////////////////////////////////////////////////////////
31 #include <string.h>
32 #include <time.h>
33 #include <math.h>
34 
35 #include "ribOut.h"
36 #include "common/os.h"
37 #include "ri.h"
38 #include "error.h"
39 #include "variable.h"
40 
41 // This is the size of the temporary buffer we use before going to the file
42 const	int	ribOutScratchSize	=	1000;
43 
44 // Options for rib
45 int	preferCompressedRibOut		=	FALSE;
46 
47 
getFilter(float (* function)(float,float,float,float))48 static	const char	*getFilter(float (*function)(float,float,float,float)) {
49 	if (function == RiGaussianFilter) {
50 		return	RI_GAUSSIANFILTER;
51 	} else if (function == RiBoxFilter) {
52 		return	RI_BOXFILTER;
53 	} else if (function == RiTriangleFilter) {
54 		return	RI_TRIANGLEFILTER;
55 	} else if (function == RiCatmullRomFilter) {
56 		return	RI_CATMULLROMFILTER;
57 	} else if (function == RiBlackmanHarrisFilter) {
58 		return	RI_BLACKMANHARRISFILTER;
59 	} else if (function == RiMitchellFilter) {
60 		return	RI_MITCHELLFILTER;
61 	} else if (function == RiSincFilter) {
62 		return	RI_SINCFILTER;
63 	} else if (function == RiBesselFilter) {
64 		return  RI_BESSELFILTER;
65 	} else if (function == RiDiskFilter) {
66 		return  RI_DISKFILTER;
67 	} else {
68 		return	RI_GAUSSIANFILTER;
69 	}
70 }
71 
CRibAttributes()72 CRibOut::CRibAttributes::CRibAttributes() {
73 	uStep	=	3;
74 	vStep	=	3;
75 	next	=	NULL;
76 }
77 
CRibAttributes(CRibAttributes * a)78 CRibOut::CRibAttributes::CRibAttributes(CRibAttributes *a) {
79 	this[0]		=	a[0];
80 	this->next	=	a;
81 }
82 
~CRibAttributes()83 CRibOut::CRibAttributes::~CRibAttributes() {
84 }
85 
CRibOut(const char * n)86 CRibOut::CRibOut(const char *n) : CRiInterface() {
87 	struct tm	*newtime;
88 	time_t		aclock;
89 
90 	time( &aclock );
91 	newtime				=	localtime( &aclock );
92 
93 	outName				=	strdup(n);
94 	if (*outName == '|') {
95 		outFile				=	popen(outName+1,"w");
96 		outputCompressed	=	FALSE;
97 		outputIsPipe		=	TRUE;
98 	} else {
99 
100 #ifdef HAVE_ZLIB
101 
102 		if (	(strstr(outName,".Z") != NULL)		||
103 				(strstr(outName,".zip") != NULL)	||
104 				(strstr(outName,".z") != NULL)		||
105 				(preferCompressedRibOut == TRUE) ) {
106 			outFile				=	(FILE *) gzopen(outName,"wb");
107 			outputCompressed	=	TRUE;
108 		} else {
109 			outFile				=	fopen(outName,"w");
110 			outputCompressed	=	FALSE;
111 		}
112 #else
113 		outFile				=	fopen(outName,"w");
114 		outputCompressed	=	FALSE;
115 #endif
116 
117 		outputIsPipe		=	FALSE;
118 	}
119 	declaredVariables	=	new CTrie<CVariable *>;
120 	numLightSources		=	1;
121 	numObjects			=	1;
122 	attributes			=	new CRibAttributes;
123 	scratch				=	new char[ribOutScratchSize];
124 
125 	// Write a header
126 	out("## Pixie %d.%d.%d\n",VERSION_RELEASE,VERSION_BETA,VERSION_ALPHA);
127 	out("## Generated %s\n",asctime(newtime));
128 
129 	declareDefaultVariables();
130 }
131 
CRibOut(FILE * o)132 CRibOut::CRibOut(FILE *o) : CRiInterface() {
133 	struct tm	*newtime;
134 	time_t		aclock;
135 
136 	time( &aclock );
137 	newtime				=	localtime( &aclock );
138 
139 	outName				=	NULL;
140 	outFile				=	o;
141 	outputCompressed	=	FALSE;
142 	outputIsPipe		=	FALSE;
143 	declaredVariables	=	new CTrie<CVariable *>;
144 	numLightSources		=	1;
145 	numObjects			=	1;
146 	attributes			=	new CRibAttributes;
147 	scratch				=	new char[ribOutScratchSize];
148 
149 	// Write a header
150 	out("## Pixie %d.%d.%d\n",VERSION_RELEASE,VERSION_BETA,VERSION_ALPHA);
151 	out("## Generated %s\n",asctime(newtime));
152 
153 	declareDefaultVariables();
154 }
155 
~CRibOut()156 CRibOut::~CRibOut() {
157 
158 	if (outName != NULL) {
159 		if (outputIsPipe) {
160 			pclose(outFile);
161 		} else {
162 
163 #ifdef HAVE_ZLIB
164 			if (outputCompressed) {
165 				gzclose((gzFile)outFile);
166 			} else {
167 				fclose(outFile);
168 			}
169 #else
170 			fclose(outFile);
171 #endif
172 		}
173 
174 		free((void *) outName);
175 	}
176 
177 	assert(attributes->next == NULL);
178 
179 	delete attributes;
180 	declaredVariables->destroy();
181 
182 	delete [] scratch;
183 }
184 
RiDeclare(const char * name,const char * type)185 void		CRibOut::RiDeclare(const char *name,const char *type) {
186 	out("Declare \"%s\" \"%s\"\n",name,type);
187 	declareVariable(name,type);
188 }
189 
RiFrameBegin(int number)190 void		CRibOut::RiFrameBegin(int number) {
191 	out("FrameBegin %d\n",number);
192 }
193 
RiFrameEnd(void)194 void		CRibOut::RiFrameEnd(void) {
195 	out("FrameEnd\n");
196 }
197 
RiWorldBegin(void)198 void		CRibOut::RiWorldBegin(void) {
199 	out("WorldBegin\n");
200 }
201 
RiWorldEnd(void)202 void		CRibOut::RiWorldEnd(void) {
203 	out("WorldEnd\n");
204 }
205 
RiFormat(int xres,int yres,float aspect)206 void		CRibOut::RiFormat(int xres,int yres,float aspect) {
207 	out("Format %d %d %g\n",xres,yres,aspect);
208 }
209 
RiFrameAspectRatio(float aspect)210 void		CRibOut::RiFrameAspectRatio(float aspect) {
211 	out("FrameAspectRatio %g\n",aspect);
212 }
213 
RiScreenWindow(float left,float right,float bot,float top)214 void		CRibOut::RiScreenWindow(float left,float right,float bot,float top) {
215 	out("ScreenWindow %g %g %g %g\n",left,right,bot,top);
216 }
217 
RiCropWindow(float xmin,float xmax,float ymin,float ymax)218 void		CRibOut::RiCropWindow(float xmin,float xmax,float ymin,float ymax) {
219 	out("CropWindow %g %g %g %g\n",xmin,xmax,ymin,ymax);
220 }
221 
RiProjectionV(const char * name,int n,const char * tokens[],const void * params[])222 void		CRibOut::RiProjectionV(const char *name,int n,const char *tokens[],const void *params[]) {
223 	out("Projection \"%s\" ",name);
224 	writePL(n,tokens,params);
225 }
226 
RiClipping(float hither,float yon)227 void		CRibOut::RiClipping(float hither,float yon) {
228 	out("Clipping %g %g\n",hither,yon);
229 }
230 
RiClippingPlane(float x,float y,float z,float nx,float ny,float nz)231 void		CRibOut::RiClippingPlane(float x,float y,float z,float nx,float ny,float nz) {
232 	out("ClippingPlane %g %g %g %g %g %g\n",x,y,z,nx,ny,nz);
233 }
234 
RiDepthOfField(float fstop,float focallength,float focaldistance)235 void		CRibOut::RiDepthOfField(float fstop,float focallength,float focaldistance) {
236 	out("DepthOfField %g %g %g\n",fstop,focallength,focaldistance);
237 }
238 
RiShutter(float smin,float smax)239 void		CRibOut::RiShutter(float smin,float smax) {
240 	out("Shutter %g %g\n",smin,smax);
241 }
242 
RiPixelVariance(float variance)243 void		CRibOut::RiPixelVariance(float variance) {
244 	out("PixelVariance %g\n",variance);
245 }
246 
RiPixelSamples(float xsamples,float ysamples)247 void		CRibOut::RiPixelSamples(float xsamples,float ysamples) {
248 	out("PixelSamples %g %g\n",xsamples,ysamples);
249 }
250 
RiPixelFilter(float (* function)(float,float,float,float),float xwidth,float ywidth)251 void		CRibOut::RiPixelFilter(float (*function)(float,float,float,float),float xwidth,float ywidth) {
252 	if (function == RiGaussianFilter) {
253 		out("PixelFilter \"%s\" %g %g\n",RI_GAUSSIANFILTER,xwidth,ywidth);
254 	} else if (function == RiBoxFilter) {
255 		out("PixelFilter \"%s\" %g %g\n",RI_BOXFILTER,xwidth,ywidth);
256 	} else if (function == RiTriangleFilter) {
257 		out("PixelFilter \"%s\" %g %g\n",RI_TRIANGLEFILTER,xwidth,ywidth);
258 	} else if (function == RiCatmullRomFilter) {
259 		out("PixelFilter \"%s\" %g %g\n",RI_CATMULLROMFILTER,xwidth,ywidth);
260 	} else if (function == RiBlackmanHarrisFilter) {
261 		out("PixelFilter \"%s\" %g %g\n",RI_BLACKMANHARRISFILTER,xwidth,ywidth);
262 	} else if (function == RiMitchellFilter) {
263 		out("PixelFilter \"%s\" %g %g\n",RI_MITCHELLFILTER,xwidth,ywidth);
264 	} else if (function == RiSincFilter) {
265 		out("PixelFilter \"%s\" %g %g\n",RI_SINCFILTER,xwidth,ywidth);
266 	} else if (function == RiBesselFilter) {
267 		out("PixelFilter \"%s\" %g %g\n",RI_BESSELFILTER,xwidth,ywidth);
268 	} else if (function == RiDiskFilter) {
269 		out("PixelFilter \"%s\" %g %g\n",RI_DISKFILTER,xwidth,ywidth);
270 	} else {
271 		errorHandler(RIE_BADHANDLE,RIE_ERROR,"Failed to write custom filter function\n");
272 	}
273 }
274 
RiExposure(float gain,float gamma)275 void		CRibOut::RiExposure(float gain,float gamma) {
276 	out("Exposure %g %g\n",gain,gamma);
277 }
278 
RiImagerV(const char * name,int n,const char * tokens[],const void * params[])279 void		CRibOut::RiImagerV(const char *name,int n,const char *tokens[],const void *params[]) {
280 	out("Imager \"%s\" ",name);
281 	writePL(n,tokens,params);
282 }
283 
RiQuantize(const char * type,int one,int qmin,int qmax,float ampl)284 void		CRibOut::RiQuantize(const char * type,int one,int qmin,int qmax,float ampl) {
285 	out("Quantize \"%s\" %d %d %d %g\n",type,one,qmin,qmax,ampl);
286 }
287 
RiDisplayV(const char * name,const char * type,const char * mode,int n,const char * tokens[],const void * params[])288 void		CRibOut::RiDisplayV(const char *name,const char * type,const char * mode,int n,const char *tokens[],const void *params[]) {
289 	out("Display \"%s\" \"%s\" \"%s\" ",name,type,mode);
290 	writePL(n,tokens,params);
291 }
292 
RiCustomDisplayV(const char * name,RtToken mode,RtDisplayStartFunction,RtDisplayDataFunction,RtDisplayFinishFunction,RtInt n,RtToken tokens[],RtPointer params[])293 void		CRibOut::RiCustomDisplayV(const char *name, RtToken mode, RtDisplayStartFunction, RtDisplayDataFunction, RtDisplayFinishFunction, RtInt n, RtToken tokens[], RtPointer params[]) {
294 	error(CODE_INCAPABLE,"Can not serialize custom displays.\n");
295 }
296 
RiDisplayChannelV(const char * channel,int n,const char * tokens[],const void * params[])297 void		CRibOut::RiDisplayChannelV(const char *channel,int n,const char *tokens[],const void *params[]) {
298 	out("Display \"%s\" ",channel);
299 	writePL(n,tokens,params);
300 }
301 
RiHiderV(const char * type,int n,const char * tokens[],const void * params[])302 void		CRibOut::RiHiderV(const char * type,int n,const char *tokens[],const void *params[]) {
303 	out("Hider \"%s\" ",type);
304 	writePL(n,tokens,params);
305 }
306 
RiColorSamples(int N,float * nRGB,float * RGBn)307 void		CRibOut::RiColorSamples(int N,float *nRGB,float *RGBn) {
308 	int	i;
309 
310 	out("ColorSamples [ ");
311 
312 	for (i=0;i<N*3;i++) {
313 		out("%g ",nRGB[i]);
314 	}
315 
316 	out("] [ ");
317 
318 	for (i=0;i<N*3;i++) {
319 		out("%g ",RGBn[i]);
320 	}
321 
322 	out("]\n");
323 }
324 
RiRelativeDetail(float relativedetail)325 void		CRibOut::RiRelativeDetail(float relativedetail) {
326 	out("RelativeDetail %g\n",relativedetail);
327 }
328 
329 
330 
331 #define	optionCheckInt(__name,__num)																		\
332 	} else if (strcmp(tokens[i],__name) == 0) {																\
333 		const int		*val	=	(const int *) params[i];																\
334 		int		k;																							\
335 		out("Option \"%s\" \"%s\" [%i",name,tokens[i],val[0]);									\
336 		for (k=1;k<__num;k++) {																				\
337 			out(" %i",val[k]);																	\
338 		}																									\
339 		out("]\n");
340 
341 
342 #define	optionCheckFloat(__name,__num)																		\
343 	} else if (strcmp(tokens[i],__name) == 0) {																\
344 		const float	*val	=	(const float *) params[i];															\
345 		int		k;																							\
346 		out("Option \"%s\" \"%s\" [%g",name,tokens[i],val[0]);									\
347 		for (k=1;k<__num;k++) {																				\
348 			out(" %g",val[k]);																	\
349 		}																									\
350 		out("]\n");
351 
352 
353 #define	optionCheckString(__name)																			\
354 	} else if (strcmp(tokens[i],__name) == 0) {																\
355 		const char	*val	=	((const char **) params[i])[0];														\
356 		out("Option \"%s\" \"%s\" \"%s\"\n",name,tokens[i],val);
357 
358 #define	optionEndCheck																						\
359 	} else {																								\
360 		CVariable	var;																					\
361 		if (parseVariable(&var,NULL,tokens[i]) == TRUE) {													\
362 			RiOption(name,var.name,params[i],RI_NULL);														\
363 		} else {																							\
364 			error(CODE_BADTOKEN,"Unknown %s option: \"%s\"\n",name,tokens[i]);								\
365 		}																									\
366 	}
367 
368 
369 
370 
371 
RiOptionV(const char * name,int n,const char * tokens[],const void * params[])372 void		CRibOut::RiOptionV(const char *name,int n,const char *tokens[],const void *params[]) {
373 	int	i;
374 
375 	// Check the searchpath options
376 	if (strcmp(name,RI_SEARCHPATH) == 0) {
377 		for (i=0;i<n;i++) {
378 			if (FALSE) {
379 			optionCheckString(RI_ARCHIVE)
380 			optionCheckString(RI_PROCEDURAL)
381 			optionCheckString(RI_TEXTURE)
382 			optionCheckString(RI_SHADER)
383 			optionCheckString(RI_DISPLAY)
384 			optionCheckString(RI_RESOURCE)
385 			optionEndCheck
386 		}
387 
388 	// Check the limit options
389 	} else if (strcmp(name,RI_LIMITS) == 0) {
390 		for (i=0;i<n;i++) {
391 			if (FALSE) {
392 			optionCheckInt(RI_BUCKETSIZE,2)
393 			optionCheckInt(RI_METABUCKETS,2)
394 			optionCheckInt(RI_INHERITATTRIBUTES,1)
395 			optionCheckInt(RI_GRIDSIZE,1)
396 			optionCheckInt(RI_EYESPLITS,1)
397 			optionCheckInt(RI_TEXTUREMEMORY,1)
398 			optionCheckInt(RI_BRICKMEMORY,1)
399 			optionEndCheck
400 		}
401 	// Check the hider options
402 	} else if (strcmp(name,RI_HIDER) == 0) {
403 		for (i=0;i<n;i++) {
404 			if (FALSE) {
405 			optionCheckFloat(RI_JITTER,1)	//GSHTODO: should be INT
406 			optionCheckInt(RI_FALSECOLOR,1)
407 			optionCheckInt(RI_EMIT,1)
408 			optionCheckString(RI_DEPTHFILTER)
409 			optionEndCheck
410 		}
411 
412 	// Check the trace options
413 	} else if (strcmp(name,RI_TRACE) == 0) {
414 		for (i=0;i<n;i++) {
415 			if (FALSE) {
416 			optionCheckInt(RI_MAXDEPTH,1)
417 			optionEndCheck
418 		}
419 
420 	// Check the io options
421 	} else if (strcmp(name,RI_STATISTICS) == 0) {
422 		for (i=0;i<n;i++) {
423 			if (FALSE) {
424 			optionCheckInt(RI_ENDOFFRAME,1)
425 			optionCheckString(RI_FILELOG)
426 			optionCheckInt(RI_PROGRESS,1)
427 			optionEndCheck
428 		}
429 	// Check for rib compression / output options
430 	} else if (strcmp(name,RI_RIB) == 0) {
431 		for (i=0;i<n;i++) {
432 			if (FALSE) {
433 			} else if (strcmp(tokens[i],RI_COMPRESSION) == 0) {
434 				const char	*val	=	((const char **) params[i])[0];
435 				if (strcmp(val,"gzip") == 0) {
436 					preferCompressedRibOut	=	TRUE;
437 				} else if (strcmp(val,"none") == 0) {
438 					preferCompressedRibOut	=	FALSE;
439 				} else {
440 					error(CODE_BADTOKEN,"Unknown compression type \"%s\"\n",val);
441 				}
442 			optionEndCheck
443 		}
444 	} else {
445 		error(CODE_BADTOKEN,"Unknown option: \"%s\"\n",name);
446 	}
447 }
448 
449 #undef optionCheckInt
450 #undef optionCheckFloat
451 #undef optionCheckString
452 #undef optionEnd
453 
454 
455 void		CRibOut::RiAttributeBegin(void) {
456 	out("AttributeBegin\n");
457 
458 	attributes	=	new CRibAttributes(attributes);
459 }
460 
461 void		CRibOut::RiAttributeEnd(void) {
462 	CRibAttributes	*old	=	attributes;
463 
464 	out("AttributeEnd\n");
465 
466 	attributes		=	attributes->next;
467 	delete old;
468 }
469 
470 void		CRibOut::RiColor(float *Cs) {
471 	out("Color [%g %g %g]\n",Cs[0],Cs[1],Cs[2]);
472 }
473 
474 void		CRibOut::RiOpacity(float *Cs) {
475 	out("Opacity [%g %g %g]\n",Cs[0],Cs[1],Cs[2]);
476 }
477 
478 void		CRibOut::RiTextureCoordinates(float s1,float t1,float s2,float t2,float s3,float t3,float s4,float t4) {
479 	out("TextureCoordinates [%g %g %g %g %g %g %g %g]\n",s1,t1,s2,t2,s3,t3,s4,t4);
480 }
481 
482 void		*CRibOut::RiLightSourceV(const char *name,int n,const char *tokens[],const void *params[]) {
483 	out("LightSource \"%s\" %d ",name,numLightSources);
484 	writePL(n,tokens,params);
485 
486 	return (void *) (uintptr_t) numLightSources++;
487 }
488 
489 void		*CRibOut::RiAreaLightSourceV(const char *name,int n,const char *tokens[],const void *params[]) {
490 	out("AreaLightSource \"%s\" %d ",name,numLightSources);
491 	writePL(n,tokens,params);
492 
493 	return (void *) (uintptr_t) numLightSources++;
494 }
495 
496 void		CRibOut::RiIlluminate(const void *light,int onoff) {
497 	out("Illuminate %d %d\n",light,onoff);
498 }
499 
500 void		CRibOut::RiSurfaceV(const char *name,int n,const char *tokens[],const void *params[]) {
501 	out("Surface \"%s\" ",name);
502 	writePL(n,tokens,params);
503 }
504 
505 void		CRibOut::RiAtmosphereV(const char *name,int n,const char *tokens[],const void *params[]) {
506 	out("Atmosphere \"%s\" ",name);
507 	writePL(n,tokens,params);
508 }
509 
510 void		CRibOut::RiInteriorV(const char *name,int n,const char *tokens[],const void *params[]) {
511 	out("Interior \"%s\" ",name);
512 	writePL(n,tokens,params);
513 }
514 
515 void		CRibOut::RiExteriorV(const char *name,int n,const char *tokens[],const void *params[]) {
516 	out("Exterior \"%s\" ",name);
517 	writePL(n,tokens,params);
518 }
519 
520 void		CRibOut::RiShadingRate(float size) {
521 	out("ShadingRate %g\n",size);
522 }
523 
524 void		CRibOut::RiShadingInterpolation(const char * type) {
525 	out("ShadingInterpolation \"%s\"\n",type);
526 }
527 
528 void		CRibOut::RiMatte(int onoff) {
529 	out("Matte %d\n",onoff);
530 }
531 
532 void		CRibOut::RiBound(float *bound) {
533 	out("Bound [%g %g %g %g %g %g]\n",bound[0],bound[1],bound[2],bound[3],bound[4],bound[5]);
534 }
535 
536 void		CRibOut::RiDetail(float *bound) {
537 	out("Detail [%g %g %g %g %g %g]\n",bound[0],bound[1],bound[2],bound[3],bound[4],bound[5]);
538 }
539 
540 void		CRibOut::RiDetailRange(float minvis,float lowtran,float uptran,float maxvis) {
541 	out("DetailRange %g %g %g %g\n",minvis,lowtran,uptran,maxvis);
542 }
543 
544 void		CRibOut::RiGeometricApproximation(const char * type,float value) {
545 	out("GeometricApproximation \"%s\" %g\n",type,value);
546 }
547 
548 void		CRibOut::RiGeometricRepresentation(const char * type) {
549 	out("GeometricRepresentation \"%s\"\n",type);
550 }
551 
552 void		CRibOut::RiOrientation(const char * orientation) {
553 	out("Orientation \"%s\"\n",orientation);
554 }
555 
556 void		CRibOut::RiReverseOrientation(void) {
557 	out("ReverseOrientation\n");
558 }
559 
560 void		CRibOut::RiSides(int nsides) {
561 	out("Sides %d\n",nsides);
562 }
563 
564 void		CRibOut::RiIdentity(void) {
565 	out("Identity\n");
566 }
567 
568 void		CRibOut::RiTransform(float transform[][4]) {
569 	out("Transform [%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g]\n",transform[0][0],transform[0][1],transform[0][2],transform[0][3]
570 																					,transform[1][0],transform[1][1],transform[1][2],transform[1][3]
571 																					,transform[2][0],transform[2][1],transform[2][2],transform[2][3]
572 																					,transform[3][0],transform[3][1],transform[3][2],transform[3][3]);
573 }
574 
575 void		CRibOut::RiConcatTransform(float transform[][4]) {
576 	out("ConcatTransform [%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g]\n",transform[0][0],transform[0][1],transform[0][2],transform[0][3]
577 																					,transform[1][0],transform[1][1],transform[1][2],transform[1][3]
578 																					,transform[2][0],transform[2][1],transform[2][2],transform[2][3]
579 																					,transform[3][0],transform[3][1],transform[3][2],transform[3][3]);
580 }
581 
582 void		CRibOut::RiPerspective(float fov) {
583 	out("Perspective %g\n",fov);
584 }
585 
586 void		CRibOut::RiTranslate(float dx,float dy,float dz) {
587 		out("Translate %g %g %g\n",dx,dy,dz);
588 }
589 
590 void		CRibOut::RiRotate(float angle,float dx,float dy,float dz) {
591 	out("Rotate %g %g %g %g\n",angle,dx,dy,dz);
592 }
593 
594 void		CRibOut::RiScale(float dx,float dy,float dz) {
595 	out("Scale %g %g %g\n",dx,dy,dz);
596 }
597 
598 void		CRibOut::RiSkew(float angle,float dx1,float dy1,float dz1,float dx2,float dy2,float dz2) {
599 	out("Skew %g %g %g %g %g %g %g\n",angle,dx1,dy1,dz1,dx2,dy2,dz2);
600 }
601 
602 void		CRibOut::RiDeformationV(const char *name,int n,const char *tokens[],const void *params[]) {
603 	out("Deformation \"%s\" ",name);
604 	writePL(n,tokens,params);
605 }
606 
607 void		CRibOut::RiDisplacementV(const char *name,int n,const char *tokens[],const void *params[]) {
608 	out("Displacement \"%s\" ",name);
609 	writePL(n,tokens,params);
610 }
611 
612 void		CRibOut::RiCoordinateSystem(const char * space) {
613 	out("CoordinateSystem \"%s\"\n",space);
614 }
615 
616 void		CRibOut::RiCoordSysTransform(const char * space) {
617 	out("CoordSysTransform \"%s\"\n",space);
618 }
619 
620 RtPoint *		CRibOut::RiTransformPoints(const char * fromspace,const char * tospace,int npoints,RtPoint *points) {
621 	errorHandler(RIE_SYSTEM,RIE_ERROR,"Failed to output TransformPoints\n");
622 	return NULL;
623 }
624 
625 void		CRibOut::RiTransformBegin(void) {
626 	out("TransformBegin\n");
627 }
628 
629 void		CRibOut::RiTransformEnd(void) {
630 	out("TransformEnd\n");
631 }
632 
633 
634 #define	attributeCheckInt(__name,__num)																		\
635 	} else if (strcmp(tokens[i],__name) == 0) {																\
636 		const int	*val	=	(const int *) params[i];																\
637 		int			k;																							\
638 		out("Attribute \"%s\" \"%s\" [%i",name,tokens[i],val[0]);								\
639 		for (k=1;k<__num;k++) {																				\
640 			out(" %i",val[k]);																	\
641 		}																									\
642 		out("]\n");
643 
644 
645 #define	attributeCheckFloat(__name,__num)																	\
646 	} else if (strcmp(tokens[i],__name) == 0) {																\
647 		const float	*val	=	(const float *) params[i];															\
648 		int			k;																							\
649 		out("Attribute \"%s\" \"%s\" [%g",name,tokens[i],val[0]);								\
650 		for (k=1;k<__num;k++) {																				\
651 			out(" %g",val[k]);																	\
652 		}																									\
653 		out("]\n");
654 
655 
656 #define	attributeCheckString(__name)																		\
657 	} else if (strcmp(tokens[i],__name) == 0) {																\
658 		const char	*val	=	((const char **) params[i])[0];														\
659 		out("Attribute \"%s\" \"%s\" \"%s\"\n",name,tokens[i],val);
660 
661 #define	attributeEndCheck																					\
662 	} else {																								\
663 		CVariable	var;																					\
664 		if (parseVariable(&var,NULL,tokens[i]) == TRUE) {													\
665 			RiAttribute(name,var.name,params[i],RI_NULL);													\
666 		} else {																							\
667 			error(CODE_BADTOKEN,"Unknown %s option: \"%s\"\n",name,tokens[i]);								\
668 		}																									\
669 	}
670 
671 
672 
673 void		CRibOut::RiAttributeV(const char *name,int n,const char *tokens[],const void *params[]) {
674 	int	i;
675 
676 	if (strcmp(name,RI_DICE) == 0) {
677 		for (i=0;i<n;i++) {
678 			if (FALSE) {
679 			attributeCheckInt(RI_NUMPROBES,2)
680 			attributeCheckInt(RI_MINSUBDIVISION,1)
681 			attributeCheckInt(RI_MAXSUBDIVISION,1)
682 			attributeCheckInt(RI_MINSPLITS,1)
683 			attributeCheckFloat(RI_BOUNDEXPAND,1)
684 			attributeCheckInt(RI_BINARY,1)
685 			attributeCheckInt(RI_RASTERORIENT,1)
686 			attributeEndCheck
687 		}
688 	} else if (strcmp(name,RI_DISPLACEMENTBOUND) == 0) {
689 		for (i=0;i<n;i++) {
690 			if (FALSE) {
691 			attributeCheckFloat(RI_SPHERE,1)
692 			attributeCheckString(RI_COORDINATESYSYTEM)
693 			attributeEndCheck
694 		}
695 	} else if (strcmp(name,RI_TRACE) == 0) {
696 		for (i=0;i<n;i++) {
697 			if (FALSE) {
698 			attributeCheckInt(RI_DISPLACEMENTS,1)
699 			attributeCheckFloat(RI_BIAS,1)
700 			attributeCheckInt(RI_MAXDIFFUSEDEPTH,1)
701 			attributeCheckInt(RI_MAXSPECULARDEPTH,1)
702 			attributeEndCheck
703 		}
704 	// Check the irradiance cache options
705 	} else if (strcmp(name,RI_IRRADIANCE) == 0) {
706 		for (i=0;i<n;i++) {
707 			if (FALSE) {
708 			attributeCheckString(RI_HANDLE)
709 			attributeCheckString(RI_FILEMODE)
710 			attributeCheckFloat(RI_MAXERROR,1)
711 			attributeEndCheck
712 		}
713 	} else if (strcmp(name,RI_PHOTON) == 0) {
714 		for (i=0;i<n;i++) {
715 			if (FALSE) {
716 			attributeCheckString(RI_GLOBALMAP)
717 			attributeCheckString(RI_CAUSTICMAP)
718 			attributeCheckString(RI_SHADINGMODEL)
719 			attributeCheckFloat(RI_IOR,1)
720 			attributeCheckInt(RI_ESTIMATOR,1)
721 			attributeCheckInt(RI_ILLUMINATEFRONT,1)
722 			attributeEndCheck
723 		}
724 	} else if (strcmp(name,RI_VISIBILITY) == 0) {
725 		for (i=0;i<n;i++) {
726 			if (FALSE) {
727 			attributeCheckInt(RI_TRANSMISSION,1)
728 			attributeCheckInt(RI_DIFFUSE,1)
729 			attributeCheckInt(RI_SPECULAR,1)
730 			attributeCheckInt(RI_CAMERA,1)
731 			attributeCheckInt(RI_TRACE,1)
732 			attributeCheckInt(RI_PHOTON,1)
733 			attributeEndCheck
734 		}
735 	} else if (strcmp(name,RI_SHADE) == 0) {
736 		for (i=0;i<n;i++) {
737 			if (FALSE) {
738 			attributeCheckString(RI_TRANSMISSIONHITMODE)
739 			attributeCheckString(RI_DIFFUSEHITMODE)
740 			attributeCheckString(RI_SPECULARHITMODE)
741 			attributeEndCheck
742 		}
743 	} else if (strcmp(name,RI_IDENTIFIER) == 0) {
744 		for (i=0;i<n;i++) {
745 			if (FALSE) {
746 			attributeCheckString(RI_NAME)
747 			attributeEndCheck
748 		}
749 	} else if (strcmp(name,RI_CULL) == 0) {
750 		for (i=0;i<n;i++) {
751 			if (FALSE) {
752 			attributeCheckInt(RI_HIDDEN,1)
753 			attributeCheckInt(RI_BACKFACING,1)
754 			attributeEndCheck
755 		}
756 	}
757 }
758 
759 
760 #undef	attributeCheckInt
761 #undef	attributeCheckFloat
762 #undef	attributeCheckString
763 #undef	attributeEndCheck
764 
765 
766 void		CRibOut::RiPolygonV(int nvertices,int n,const char *tokens[],const void *params[]) {
767 	out("Polygon ");
768 	writePL(nvertices,nvertices,nvertices,1,n,tokens,params);
769 }
770 
771 void		CRibOut::RiGeneralPolygonV(int nloops,int *nverts,int n,const char *tokens[],const void *params[]) {
772 	int	i;
773 	int	nvertices=0;
774 
775 	out("GeneralPolygon [");
776 	for (i=0;i<nloops;i++) {
777 		nvertices	+=	nverts[i];
778 		out("%d ",nverts[i]);
779 	}
780 	out("] ");
781 
782 	writePL(nvertices,nvertices,nvertices,1,n,tokens,params);
783 }
784 
785 void		CRibOut::RiPointsPolygonsV(int npolys,int *nverts,int *verts,int n,const char *tokens[],const void *params[]) {
786 	int	i;
787 	int	nvertices		=	0;
788 	int	mvertex			=	0;
789 
790 	out("PointsPolygons [");
791 
792 	for (i=0;i<npolys;i++) {
793 		nvertices	+=	nverts[i];
794 		out("%d ",nverts[i]);
795 	}
796 	out("] ");
797 
798 	out("[");
799 	for (i=0;i<nvertices;i++) {
800 		mvertex		=	max(mvertex,verts[i]);
801 		out("%d ",verts[i]);
802 	}
803 	out("] ");
804 	mvertex++;
805 
806 	writePL(mvertex,mvertex,nvertices,npolys,n,tokens,params);
807 }
808 
809 void		CRibOut::RiPointsGeneralPolygonsV(int npolys,int *nloops,int *nverts,int *verts,int n,const char *tokens[],const void *params[]) {
810 	int	i,j;
811 	int	snverts		=	0;
812 	int	sverts		=	0;
813 	int	nvertices	=	0;
814 	int	k			=	0;
815 
816 	out("PointsGeneralPolygons [");
817 	for (i=0;i<npolys;i++) {
818 		snverts	+=	nloops[i];
819 		out("%d ",nloops[i]);
820 		for (j=0;j<nloops[i];j++,k++) {
821 			sverts	+=	nverts[k];
822 		}
823 	}
824 	out("] ");
825 
826 	out("[");
827 	for (k=0,i=0;i<npolys;i++) {
828 		for (j=0;j<nloops[i];j++,k++) {
829 			out("%d ",nverts[k]);
830 		}
831 	}
832 	out("] ");
833 
834 	out("[");
835 	for (i=0;i<sverts;i++) {
836 		nvertices	=	max(nvertices,verts[i]+1);
837 		out("%d ",verts[i]);
838 	}
839 	out("] ");
840 
841 	writePL(nvertices,nvertices,sverts,npolys,n,tokens,params);
842 }
843 
844 void		CRibOut::RiBasis(float ubasis[][4],int ustep,float vbasis[][4],int vstep) {
845 	if ((ubasis == RiBezierBasis || ubasis == RiBSplineBasis || ubasis == RiCatmullRomBasis || ubasis == RiHermiteBasis || ubasis == RiPowerBasis) &&
846 		(vbasis == RiBezierBasis || vbasis == RiBSplineBasis || vbasis == RiCatmullRomBasis || vbasis == RiHermiteBasis || vbasis == RiPowerBasis)) {
847 
848 		const char *ubasis_str;
849 		if (ubasis == RiBezierBasis)
850 			ubasis_str = "bezier";
851 		else if (ubasis == RiBSplineBasis)
852 			ubasis_str = "b-spline";
853 		else if (ubasis == RiCatmullRomBasis)
854 			ubasis_str = "catmull-rom";
855 		else if (ubasis == RiHermiteBasis)
856 			ubasis_str = "hermite";
857 		else if (ubasis == RiPowerBasis)
858 			ubasis_str = "power";
859 
860 		const char *vbasis_str;
861 		if (vbasis == RiBezierBasis)
862 			vbasis_str = "bezier";
863 		else if (vbasis == RiBSplineBasis)
864 			vbasis_str = "b-spline";
865 		else if (vbasis == RiCatmullRomBasis)
866 			vbasis_str = "catmull-rom";
867 		else if (vbasis == RiHermiteBasis)
868 			vbasis_str = "hermite";
869 		else if (vbasis == RiPowerBasis)
870 			vbasis_str = "power";
871 
872 		out("Basis \"%s\" %d \"%s\" %d\n",
873 			ubasis_str,ustep,
874 			vbasis_str,vstep);
875 		attributes->uStep	=	ustep;
876 		attributes->vStep	=	vstep;
877 		return;
878 	}
879 	out("Basis [%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g] %d [%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g] %d\n"
880 		,ubasis[0][0],ubasis[0][1],ubasis[0][2],ubasis[0][3]
881 		,ubasis[1][0],ubasis[1][1],ubasis[1][2],ubasis[1][3]
882 		,ubasis[2][0],ubasis[2][1],ubasis[2][2],ubasis[2][3]
883 		,ubasis[3][0],ubasis[3][1],ubasis[3][2],ubasis[3][3],ustep
884 		,vbasis[0][0],vbasis[0][1],vbasis[0][2],vbasis[0][3]
885 		,vbasis[1][0],vbasis[1][1],vbasis[1][2],vbasis[1][3]
886 		,vbasis[2][0],vbasis[2][1],vbasis[2][2],vbasis[2][3]
887 		,vbasis[3][0],vbasis[3][1],vbasis[3][2],vbasis[3][3],vstep);
888 	attributes->uStep	=	ustep;
889 	attributes->vStep	=	vstep;
890 }
891 
892 void		CRibOut::RiPatchV(const char * type,int n,const char *tokens[],const void *params[]) {
893 	int	uver,vver;
894 
895 	if (strcmp(type,RI_BILINEAR) == 0)		{	uver	=	2;	vver	=	2;	}
896 	else if (strcmp(type,RI_BICUBIC) == 0)	{	uver	=	4;	vver	=	4;	}
897 	else {
898 		char	tmp[512];
899 
900 		sprintf(tmp,"Unknown patch type: \"%s\"\n",type);
901 		errorHandler(RIE_BADTOKEN,RIE_ERROR,tmp);
902 		return;
903 	}
904 
905 	out("Patch \"%s\" ",type);
906 	writePL(uver*vver,4,4,1,n,tokens,params);
907 }
908 
909 void		CRibOut::RiPatchMeshV(const char *type,int nu,const char * uwrap,int nv,const char * vwrap,int n,const char *tokens[],const void *params[]) {
910 	int	uw,vw;
911 	int	uver,vver;
912 	int	upatches,vpatches;
913 
914 	if (strcmp(uwrap,RI_PERIODIC) == 0) {
915 		uw	=	TRUE;
916 	} else if ((strcmp(uwrap,RI_NONPERIODIC) == 0) || (strcmp(uwrap,RI_NOWRAP) == 0)) {
917 		uw	=	FALSE;
918 	} else {
919 		errorHandler(RIE_BADTOKEN,RIE_ERROR,"Wrapping mode unrecognized\n");
920 		return;
921 	}
922 
923 	if (strcmp(vwrap,RI_PERIODIC) == 0) {
924 		vw	=	TRUE;
925 	} else if ((strcmp(vwrap,RI_NONPERIODIC) == 0) || (strcmp(vwrap,RI_NOWRAP) == 0)) {
926 		vw	=	FALSE;
927 	} else {
928 		errorHandler(RIE_BADTOKEN,RIE_ERROR,"Wrapping mode unrecognized\n");
929 		return;
930 	}
931 
932 	uver	=	nu;
933 	vver	=	nv;
934 
935 	if (strcmp(type,RI_BICUBIC) == 0) {
936 		if (uw)		{
937 			if ((uver % attributes->uStep) != 0) {
938 				errorHandler(RIE_CONSISTENCY,RIE_ERROR,"Unexpected number of u vertices\n");
939 				return;
940 			}
941 
942 			upatches	=	(uver ) / attributes->uStep;
943 		} else {
944 			if (((uver - 4) % attributes->uStep) != 0) {
945 				errorHandler(RIE_CONSISTENCY,RIE_ERROR,"Unexpected number of u vertices\n");
946 				return;
947 			}
948 
949 			upatches	=	((uver - 4) / attributes->uStep)+1;
950 		}
951 
952 		if (vw)		{
953 			if ((vver % attributes->vStep) != 0) {
954 				errorHandler(RIE_CONSISTENCY,RIE_ERROR,"Unexpected number of v vertices\n");
955 				return;
956 			}
957 
958 			vpatches	=	(vver) / attributes->vStep;
959 		} else {
960 			if (((vver - 4) % attributes->vStep) != 0) {
961 				errorHandler(RIE_CONSISTENCY,RIE_ERROR,"Unexpected number of v vertices\n");
962 				return;
963 			}
964 
965 			vpatches	=	((vver - 4) / attributes->vStep)+1;
966 		}
967 	} else {
968 		if (uw)
969 			upatches	=	uver;
970 		else
971 			upatches	=	uver-1;
972 
973 		if (vw)
974 			vpatches	=	vver;
975 		else
976 			vpatches	=	vver-1;
977 	}
978 
979 	out("PatchMesh \"%s\" %i \"%s\" %i \"%s\" ",type,nu,uwrap,nv,vwrap);
980 	writePL(uver*vver,uver*vver,uver*vver,upatches*vpatches,n,tokens,params);
981 }
982 
983 void		CRibOut::RiNuPatchV(int nu,int uorder,float *uknot,float umin,float umax,int nv,int vorder,float *vknot,float vmin,float vmax,int n,const char *tokens[],const void *params[]) {
984 	int	upatches		=	nu - uorder + 1;
985 	int	vpatches		=	nv - vorder + 1;
986 	int	i,uk,vk;
987 
988 	out("NuPatch ");
989 
990 	// Print the knot sequence
991 	uk = nu + uorder;
992 	vk = nv + vorder;
993 	out("%i %i [%g",nu,uorder,uknot[0]);
994 	for (i=1;i<uk;i++) out(" %g",uknot[i]);
995 	out("] %g %g ",umin,umax);
996 
997 	out("%i %i [%g",nv,vorder,vknot[0]);
998 	for (i=1;i<vk;i++) out(" %g",vknot[i]);
999 	out("] %g %g ",vmin,vmax);
1000 
1001 	writePL(nu*nv,(nu-uorder+2)*(nv-vorder+2),(nu-uorder+2)*(nv-vorder+2),upatches*vpatches,n,tokens,params);
1002 }
1003 
1004 void		CRibOut::RiTrimCurve(int nloops,int *ncurves,int *order,float *knot,float *amin,float *amax,int *n,float *u,float *v,float *w) {
1005 	int	i,j,k,numCurves;
1006 
1007 	// Write the ncurves
1008 	out("TrimCurve [%d",ncurves[0]);
1009 	numCurves	=	ncurves[0];
1010 	for (i=1;i<nloops;i++) {
1011 		out(" %d",ncurves[i]);
1012 		numCurves	+=	ncurves[i];
1013 	}
1014 
1015 	// Print the order for each curve
1016 	out("] [%d",order[0]);
1017 	for (i=1;i<numCurves;i++) out(" %d",order[i]);
1018 
1019 	// Print the knot vector for each curve
1020 	out("] [");
1021 	for (k=0,i=0;i<numCurves;i++) {
1022 
1023 		for (j=n[i]+order[i];j>0;j--,k++) {
1024 			if (k == 0) {
1025 				out("%g",knot[k]);
1026 			} else {
1027 				out(" %g",knot[k]);
1028 			}
1029 		}
1030 	}
1031 
1032 	// Print the parametric range for each curve
1033 	out("] [%g",amin[0]);
1034 	for (i=1;i<numCurves;i++) {
1035 		out(" %g",amin[i]);
1036 	}
1037 
1038 	out("] [%g",amax[0]);
1039 	for (i=1;i<numCurves;i++) {
1040 		out(" %g",amax[i]);
1041 	}
1042 
1043 	// Print the number of vertices for each curve
1044 	out("] [%d",n[0]);
1045 	for (i=1;i<numCurves;i++) {
1046 		out(" %d",n[i]);
1047 	}
1048 
1049 	// Print the vertices for each curve
1050 	out("] [");
1051 	for (k=0,i=0;i<numCurves;i++) {
1052 
1053 		for (j=n[i];j>0;j--,k++) {
1054 			if (k == 0) {
1055 				out("%g",u[k]);
1056 			} else {
1057 				out(" %g",u[k]);
1058 			}
1059 		}
1060 	}
1061 
1062 	out("] [");
1063 	for (k=0,i=0;i<numCurves;i++) {
1064 
1065 		for (j=n[i];j>0;j--,k++) {
1066 			if (k == 0) {
1067 				out("%g",v[k]);
1068 			} else {
1069 				out(" %g",v[k]);
1070 			}
1071 		}
1072 	}
1073 
1074 	out("] [");
1075 	for (k=0,i=0;i<numCurves;i++) {
1076 
1077 		for (j=n[i];j>0;j--,k++) {
1078 			if (k == 0) {
1079 				out("%g",w[k]);
1080 			} else {
1081 				out(" %g",w[k]);
1082 			}
1083 		}
1084 	}
1085 
1086 	out("]\n");
1087 }
1088 
1089 void		CRibOut::RiSphereV(float radius,float zmin,float zmax,float thetamax,int n,const char *tokens[],const void *params[]) {
1090 	out("Sphere %g %g %g %g ",radius,zmin,zmax,thetamax);
1091 	writePL(4,4,4,1,n,tokens,params);
1092 }
1093 
1094 void		CRibOut::RiConeV(float height,float radius,float thetamax,int n,const char *tokens[],const void *params[]) {
1095 	out("Cone %g %g %g ",height,radius,thetamax);
1096 	writePL(4,4,4,1,n,tokens,params);
1097 }
1098 
1099 void		CRibOut::RiCylinderV(float radius,float zmin,float zmax,float thetamax,int n,const char *tokens[],const void *params[]) {
1100 	out("Cylinder %g %g %g %g ",radius,zmin,zmax,thetamax);
1101 	writePL(4,4,4,1,n,tokens,params);
1102 }
1103 
1104 void		CRibOut::RiHyperboloidV(float *point1,float *point2,float thetamax,int n,const char *tokens[],const void *params[]) {
1105 	out("Hyperboloid %g %g %g %g %g %g %g ",point1[0],point1[1],point1[2],point2[0],point2[1],point2[2],thetamax);
1106 	writePL(4,4,4,1,n,tokens,params);
1107 }
1108 
1109 void		CRibOut::RiParaboloidV(float rmax,float zmin,float zmax,float thetamax,int n,const char *tokens[],const void *params[]) {
1110 	out("Paraboloid %g %g %g %g ",rmax,zmin,zmax,thetamax);
1111 	writePL(4,4,4,1,n,tokens,params);
1112 }
1113 
1114 void		CRibOut::RiDiskV(float height,float radius,float thetamax,int n,const char *tokens[],const void *params[]) {
1115 	out("Disk %g %g %g ",height,radius,thetamax);
1116 	writePL(4,4,4,1,n,tokens,params);
1117 }
1118 
1119 void		CRibOut::RiTorusV(float majorrad,float minorrad,float phimin,float phimax,float thetamax,int n,const char *tokens[],const void *params[]) {
1120 	out("Torus %g %g %g %g %g",majorrad,minorrad,phimin,phimax,thetamax);
1121 	writePL(4,4,4,1,n,tokens,params);
1122 }
1123 
1124 void		CRibOut::RiProcedural(void * data,float *bound,void (*subdivfunc)(void *,float),void (*freefunc)(void *)) {
1125 	errorHandler(RIE_UNIMPLEMENT,RIE_ERROR,"Failed to output procedural geometry\n");
1126 }
1127 
1128 void		CRibOut::RiGeometryV(const char * type,int n,const char *tokens[],const void *params[]) {
1129 	errorHandler(RIE_UNIMPLEMENT,RIE_ERROR,"Failed to output optional geometry\n");
1130 }
1131 
1132 void		CRibOut::RiCurvesV(const char * degree,int ncurves,int nverts[],const char * wrap,int n,const char *tokens[],const void *params[]) {
1133 	int	i;
1134 	int	nvertices	=	0;
1135 	int	nvaryings	=	0;
1136 	int	wrapadd;
1137 
1138 	if (strcmp(wrap,RI_PERIODIC) == 0) {
1139 		wrapadd	=	0;
1140 	} else {
1141 		wrapadd	=	1;
1142 	}
1143 
1144 	out("Curves \"%s\" [",degree);
1145 
1146 	if (strcmp(degree,RI_LINEAR) == 0) {
1147 		for (i=0;i<ncurves;i++) {
1148 			nvertices	+=	nverts[i];
1149 			out("%d ",nverts[i]);
1150 		}
1151 
1152 		nvaryings		=	nvertices;
1153 	} else if (strcmp(degree,RI_CUBIC) == 0) {
1154 		for (i=0;i<ncurves;i++) {
1155 			int j		=	(nverts[i] - 4) / attributes->vStep + 1;
1156 			nvertices	+=	nverts[i];
1157 			nvaryings	+=	j + wrapadd;
1158 			out("%d ",nverts[i]);
1159 		}
1160 	}
1161 
1162 	out("] \"%s\" ",wrap);
1163 
1164 	writePL(nvertices,nvaryings,nvaryings,ncurves,n,tokens,params);
1165 }
1166 
1167 void		CRibOut::RiPointsV(int npts,int n,const char *tokens[],const void *params[]) {
1168 	out("Points ");
1169 	writePL(npts,npts,npts,1,n,tokens,params);
1170 }
1171 
1172 void		CRibOut::RiSubdivisionMeshV(const char * scheme,int nfaces,int nvertices[],int vertices[],int ntags,const char * tags[],int nargs[],int intargs[],float floatargs[],int n,const char *tokens[],const void *params[]) {
1173 	int	numVertices;
1174 	int	i,j;
1175 	int	numInt,numFloat;
1176 	int	numFacevaryings;
1177 
1178 	for (i=0,j=0;i<nfaces;j+=nvertices[i],i++);
1179 	numFacevaryings	=	j;
1180 
1181 	for (numVertices=-1,i=0;i<j;i++) {
1182 		if (vertices[i] > numVertices)	numVertices	=	vertices[i];
1183 	}
1184 	numVertices++;
1185 
1186 	out("SubdivisionMesh \"%s\" [ ",scheme);
1187 	for (i=0;i<nfaces;i++) {
1188 		out("%d ",nvertices[i]);
1189 	}
1190 
1191 	out("] [ ");
1192 	for (i=0;i<j;i++) {
1193 		out("%d ",vertices[i]);
1194 	}
1195 
1196 	out("] [");
1197 	for (i=0;i<ntags;i++) {
1198 		out(" \"%s\" ",tags[i]);
1199 	}
1200 
1201 	out("] [");
1202 	numInt		=	0;
1203 	numFloat	=	0;
1204 	for (i=0;i<ntags;i++) {
1205 		out(" %d %d ",nargs[0],nargs[1]);
1206 		numInt		+=	nargs[0];
1207 		numFloat	+=	nargs[1];
1208 		nargs		+=	2;
1209 	}
1210 
1211 	out("] [ ");
1212 	for (i=0;i<numInt;i++) {
1213 		out("%d ",intargs[i]);
1214 	}
1215 
1216 	out("] [ ");
1217 	for (i=0;i<numFloat;i++) {
1218 		out("%g ",floatargs[i]);
1219 	}
1220 	out("] ");
1221 
1222 	writePL(numVertices,numVertices,numFacevaryings,nfaces,n,tokens,params);
1223 }
1224 
1225 void		CRibOut::RiBlobbyV(int nleaf,int ncode,int code[],int nflt,float flt[],int nstr,const char *str[],int n,const char *tokens[],const void *params[]) {
1226 	errorHandler(RIE_UNIMPLEMENT,RIE_ERROR,"Blobby primitive is not implemented\n");
1227 }
1228 
1229 void		CRibOut::RiProcDelayedReadArchive(const char * data,float detail) {
1230 }
1231 
1232 void		CRibOut::RiProcRunProgram(const char * data,float detail) {
1233 }
1234 
1235 void		CRibOut::RiProcDynamicLoad(const char * data,float detail) {
1236 }
1237 
1238 void		CRibOut::RiProcFree(const char *) {
1239 }
1240 
1241 void		CRibOut::RiSolidBegin(const char * type) {
1242 	out("SolidBegin \"%s\"\n",type);
1243 }
1244 
1245 void		CRibOut::RiSolidEnd(void) {
1246 	out("SolidEnd\n");
1247 }
1248 
1249 void		*CRibOut::RiObjectBegin(void) {
1250 	out("ObjectBegin %d\n",numObjects);
1251 
1252 	return (void *) (uintptr_t) numObjects++;
1253 }
1254 
1255 void		CRibOut::RiObjectEnd(void) {
1256 	out("ObjectEnd\n");
1257 }
1258 
1259 void		CRibOut::RiObjectInstance(const void *handle) {
1260 	out("ObjectInstance %d\n",handle);
1261 }
1262 
1263 void		CRibOut::RiMotionBeginV(int N,float times[]) {
1264 	int	i;
1265 
1266 	out("MotionBegin [ ");
1267 	for (i=0;i<N;i++) {
1268 		out(" %g ",times[i]);
1269 	}
1270 	out("]\n");
1271 }
1272 
1273 void		CRibOut::RiMotionEnd(void) {
1274 	out("MotionEnd\n");
1275 }
1276 
1277 void		CRibOut::RiMakeTextureV(const char *pic,const char *tex,const char * swrap,const char * twrap,float (*filterfunc)(float,float,float,float),float swidth,float twidth,int n,const char *tokens[],const void *params[]) {
1278 	out("MakeTexture \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" %g %g ",pic,tex,swrap,twrap,getFilter(filterfunc),swidth,twidth);
1279 	writePL(n,tokens,params);
1280 }
1281 
1282 void		CRibOut::RiMakeBumpV(const char *pic,const char *tex,const char * swrap,const char * twrap,float (*filterfunc)(float,float,float,float),float swidth,float twidth,int n,const char *tokens[],const void *params[]) {
1283 	out("MakeBump \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" %g %g ",pic,tex,swrap,twrap,getFilter(filterfunc),swidth,twidth);
1284 	writePL(n,tokens,params);
1285 }
1286 
1287 void		CRibOut::RiMakeLatLongEnvironmentV(const char *pic,const char *tex,float (*filterfunc)(float,float,float,float),float swidth,float twidth,int n,const char *tokens[],const void *params[]) {
1288 	out("MakeBump \"%s\" \"%s\" \"%s\" %g %g",pic,tex,getFilter(filterfunc),swidth,twidth);
1289 	writePL(n,tokens,params);
1290 }
1291 
1292 void		CRibOut::RiMakeCubeFaceEnvironmentV(const char *px,const char *nx,const char *py,const char *ny,const char *pz,const char *nz,const char *tex,float fov,float (*filterfunc)(float,float,float,float),float swidth,float twidth,int n,const char *tokens[],const void *params[]) {
1293 	out("MakeCubeFaceEnvironment \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" %g \"%s\" %g %g ",px,nx,py,ny,pz,nz,tex,fov,getFilter(filterfunc),swidth,twidth);
1294 	writePL(n,tokens,params);
1295 }
1296 
1297 void		CRibOut::RiMakeShadowV(const char *pic,const char *tex,int n,const char *tokens[],const void *params[]) {
1298 	out("MakeShadow \"%s\" \"%s\" ",pic,tex);
1299 	writePL(n,tokens,params);
1300 }
1301 
1302 void		CRibOut::RiMakeBrickMapV(int n,const char **src,const char *dest,int numTokens,const char *tokens[],const void *params[]) {
1303 	out("MakeBrickMap [");
1304 	for(int i=0;i<n;i++) out("\"%s\" ",src[i]);
1305 	out("] \"%s\" ",dest);
1306 	writePL(numTokens,tokens,params);
1307 }
1308 
1309 void		CRibOut::RiErrorHandler(void (*handler)(int,int,const char *)) {
1310 	errorHandler	=	handler;
1311 }
1312 
1313 void		CRibOut::RiArchiveRecord(const char * type,const char *format,va_list args) {
1314 	if (strcmp(type,RI_COMMENT) == 0) {
1315 		out("#");
1316 		vout(format,args);
1317 		out("\n");
1318 	} else if (strcmp(type,RI_STRUCTURE) == 0) {
1319 		out("##");
1320 		vout(format,args);
1321 		out("\n");
1322 	} else if (strcmp(type,RI_VERBATIM) == 0) {
1323 		vout(format,args);
1324 		out("\n");
1325 	} else {
1326 		error(CODE_BADTOKEN,"Unknown record type: \"%s\"\n",type);
1327 	}
1328 }
1329 
1330 void		CRibOut::RiReadArchiveV(const char *filename,void (*callback)(const char *,...),int n,const char *tokens[],const void *params[]) {
1331 	out("ReadArchive \"%s\"\n",filename);
1332 }
1333 
1334 void		*CRibOut::RiArchiveBeginV(const char *name,int n,const char *tokens[],const void *parms[]) {
1335 	out("ArchiveBegin \"%s\" ",name);
1336 	writePL(n,tokens,parms);
1337 	return NULL;
1338 }
1339 
1340 void		CRibOut::RiArchiveEnd(void) {
1341 	out("ArchiveEnd\n");
1342 }
1343 
1344 void		CRibOut::RiResourceV(const char *handle,const char *type,int n,const char *tokens[],const void *parms[]) {
1345 	out("Resource \"%s\" \"%s\" ",handle,type);
1346 	writePL(n,tokens,parms);
1347 }
1348 
1349 void		CRibOut::RiResourceBegin(void) {
1350 	out("ResourceBegin\n");
1351 }
1352 
1353 void		CRibOut::RiResourceEnd(void) {
1354 	out("ResourceEnd\n");
1355 }
1356 
1357 void		CRibOut::RiIfBeginV(const char *expr,int n,const char *tokens[],const void *parms[]) {
1358 	out("IfBegin \"%s\" ",expr);
1359 	writePL(n,tokens,parms);
1360 }
1361 
1362 void		CRibOut::RiElseIfV(const char *expr,int n,const char *tokens[],const void *parms[]) {
1363 	out("ElseIf \"%s\" ",expr);
1364 	writePL(n,tokens,parms);
1365 }
1366 
1367 void		CRibOut::RiElse(void) {
1368 	out("Else\n");
1369 }
1370 
1371 void		CRibOut::RiIfEnd(void) {
1372 	out("IfEnd\n");
1373 }
1374 
1375 
1376 void		CRibOut::writePL(int numParameters,const char *tokens[],const void *vals[]) {
1377 	int			i,j;
1378 	const float	*f;
1379 	const int	*iv;
1380 	const char	**s;
1381 
1382 	for (i=0;i<numParameters;i++) {
1383 		CVariable	tmpVar;
1384 		CVariable	*variable;
1385 
1386 		if (declaredVariables->find(tokens[i],variable) == TRUE) {
1387 retry:;
1388 
1389 			out(" \"%s\" [",tokens[i]);
1390 
1391 			switch(variable->type) {
1392 			case TYPE_FLOAT:
1393 
1394 				f	=	(float *) vals[i];
1395 				for (j=variable->numItems;j>0;j--,f++) {
1396 					out("%g ",f[0]);
1397 				}
1398 				break;
1399 			case TYPE_COLOR:
1400 			case TYPE_VECTOR:
1401 			case TYPE_NORMAL:
1402 			case TYPE_POINT:
1403 
1404 				f	=	(float *) vals[i];
1405 				for (j=variable->numItems;j>0;j--,f+=3) {
1406 					out("%g %g %g ",f[0],f[1],f[2]);
1407 				}
1408 				break;
1409 			case TYPE_MATRIX:
1410 
1411 				f	=	(float *) vals[i];
1412 				for (j=variable->numItems;j>0;j--,f+=16) {
1413 					out("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ",f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7],f[8],f[9],f[10],f[11],f[12],f[13],f[14],f[15]);
1414 				}
1415 				break;
1416 			case TYPE_QUAD:
1417 
1418 				f	=	(float *) vals[i];
1419 				for (j=variable->numItems;j>0;j--,f+=4) {
1420 					out("%g %g %g %g ",f[0],f[1],f[2],f[3]);
1421 				}
1422 				break;
1423 			case TYPE_DOUBLE:
1424 
1425 				f	=	(float *) vals[i];
1426 				for (j=variable->numItems;j>0;j--,f+=2) {
1427 					out("%g %g ",f[0],f[1]);
1428 				}
1429 				break;
1430 			case TYPE_STRING:
1431 
1432 				s	=	(const char **) vals[i];
1433 				for (j=variable->numItems;j>0;j--,s++) {
1434 					out("\"%s\" ",s[0]);
1435 				}
1436 
1437 				break;
1438 			case TYPE_INTEGER:
1439 				iv	=	(int *) vals[i];
1440 				for (j=variable->numItems;j>0;j--,iv++) {
1441 					out("%d ",iv[0]);
1442 				}
1443 				break;
1444 			default:
1445 				break;
1446 			}
1447 
1448 			out("] ");
1449 		} else {
1450 			if (parseVariable(&tmpVar,NULL,tokens[i])) {
1451 				variable	=	&tmpVar;
1452 				goto retry;
1453 			} else {
1454 				char		tmp[512];
1455 
1456 				sprintf(tmp,"Parameter \"%s\" not found\n",tokens[i]);
1457 				errorHandler(RIE_BADTOKEN,RIE_ERROR,tmp);
1458 			}
1459 		}
1460 	}
1461 
1462 	// Print the final newline
1463 	out("\n");
1464 }
1465 
1466 void		CRibOut::writePL(int numVertex,int numVarying,int numFaceVarying,int numUniform,int numParameters,const char *tokens[],const void *vals[]) {
1467 	int			i,j;
1468 	const float	*f;
1469 	const char	**s;
1470 
1471 #define	numItems(__dest,__var)						\
1472 	switch(variable->container) {					\
1473 	case CONTAINER_UNIFORM:							\
1474 		__dest	=	__var->numItems*numUniform;		\
1475 		break;										\
1476 	case CONTAINER_VERTEX:							\
1477 		__dest	=	__var->numItems*numVertex;		\
1478 		break;										\
1479 	case CONTAINER_VARYING:							\
1480 		__dest	=	__var->numItems*numVarying;		\
1481 		break;										\
1482 	case CONTAINER_FACEVARYING:						\
1483 		__dest	=	__var->numItems*numFaceVarying;	\
1484 		break;										\
1485 	case CONTAINER_CONSTANT:						\
1486 		__dest	=	__var->numItems;				\
1487 		break;										\
1488 	default:										\
1489 		error(CODE_BUG,"Unknown container in writePL\n");	\
1490 		__dest	=	1;								\
1491 	}
1492 
1493 
1494 
1495 	for (i=0;i<numParameters;i++) {
1496 		CVariable	tmpVar;
1497 		CVariable	*variable;
1498 
1499 		if (declaredVariables->find(tokens[i],variable) == TRUE) {
1500 retry:;
1501 			out(" \"%s\" [",tokens[i]);
1502 
1503 			switch(variable->type) {
1504 			case TYPE_FLOAT:
1505 
1506 				f	=	(float *) vals[i];
1507 				numItems(j,variable);
1508 				for (;j>0;j--,f++) {
1509 					out("%g ",f[0]);
1510 				}
1511 				break;
1512 			case TYPE_COLOR:
1513 			case TYPE_VECTOR:
1514 			case TYPE_NORMAL:
1515 			case TYPE_POINT:
1516 
1517 				f	=	(float *) vals[i];
1518 				numItems(j,variable);
1519 				for (;j>0;j--,f+=3) {
1520 					out("%g %g %g ",f[0],f[1],f[2]);
1521 				}
1522 				break;
1523 			case TYPE_MATRIX:
1524 
1525 				f	=	(float *) vals[i];
1526 				numItems(j,variable);
1527 				for (;j>0;j--,f+=16) {
1528 					out("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ",f[0],f[1],f[2],f[3],f[4],f[5],f[6],f[7],f[8],f[9],f[10],f[11],f[12],f[13],f[14],f[15]);
1529 				}
1530 				break;
1531 			case TYPE_QUAD:
1532 
1533 				f	=	(float *) vals[i];
1534 				numItems(j,variable);
1535 				for (;j>0;j--,f+=4) {
1536 					out("%g %g %g %g ",f[0],f[1],f[2],f[3]);
1537 				}
1538 				break;
1539 			case TYPE_DOUBLE:
1540 
1541 				f	=	(float *) vals[i];
1542 				numItems(j,variable);
1543 				for (;j>0;j--,f+=2) {
1544 					out("%g %g ",f[0],f[1]);
1545 				}
1546 				break;
1547 			case TYPE_STRING:
1548 
1549 				s	=	(const char **) vals[i];
1550 				for (j=variable->numItems;j>0;j--,s++) {
1551 					out("\"%s\" ",s[0]);
1552 				}
1553 				break;
1554 			case TYPE_INTEGER:
1555 				break;
1556 			default:
1557 				break;
1558 			}
1559 
1560 			out("] ");
1561 		} else {
1562 			if (parseVariable(&tmpVar,NULL,tokens[i])) {
1563 				variable	=	&tmpVar;
1564 				goto retry;
1565 			} else {
1566 				char	tmp[512];
1567 
1568 				sprintf(tmp,"Parameter \"%s\" not found\n",tokens[i]);
1569 				errorHandler(RIE_BADTOKEN,RIE_ERROR,tmp);
1570 			}
1571 		}
1572 	}
1573 
1574 	// Print the final newline
1575 	out("\n");
1576 
1577 #undef numItems
1578 }
1579 
1580 void		CRibOut::declareVariable(const char *name,const char *decl) {
1581 	CVariable	cVariable,*nVariable;
1582 
1583 	assert(declaredVariables	!=	NULL);
1584 
1585 	if (parseVariable(&cVariable,name,decl) == TRUE) {
1586 		// Parse successful, insert the variable into the dictionary
1587 		CVariable	*oVariable;
1588 
1589 		if (declaredVariables->erase(cVariable.name,oVariable)) {
1590 			delete oVariable;
1591 		};
1592 
1593 		// Add the new variable into the variables list
1594 		nVariable							=	new CVariable;
1595 		nVariable[0]						=	cVariable;
1596 
1597 		// Insert the variable into the variables trie
1598 		declaredVariables->insert(nVariable->name,nVariable);
1599 	}
1600 }
1601 
1602 
1603 void		CRibOut::declareDefaultVariables() {
1604 	// Define the options
1605 	declareVariable(RI_ARCHIVE,				"string");
1606 	declareVariable(RI_PROCEDURAL,			"string");
1607 	declareVariable(RI_TEXTURE,				"string");
1608 	declareVariable(RI_SHADER,				"string");
1609 	declareVariable(RI_DISPLAY,				"string");
1610 	declareVariable(RI_RESOURCE,			"string");
1611 
1612 	declareVariable(RI_BUCKETSIZE,			"int[2]");
1613 	declareVariable(RI_METABUCKETS,			"int[2]");
1614 	declareVariable(RI_INHERITATTRIBUTES,	"int");
1615 	declareVariable(RI_GRIDSIZE,			"int");
1616 	declareVariable(RI_EYESPLITS,			"int");
1617 	declareVariable(RI_TEXTUREMEMORY,		"int");
1618 	declareVariable(RI_BRICKMEMORY,			"int");
1619 
1620 	declareVariable(RI_RADIANCECACHE,		"int");
1621 	declareVariable(RI_JITTER,				"float");
1622 	declareVariable(RI_FALSECOLOR,			"int");
1623 	declareVariable(RI_EMIT,				"int");
1624 	declareVariable(RI_DEPTHFILTER,			"string");
1625 
1626 	declareVariable(RI_MAXDEPTH,			"int");
1627 
1628 	declareVariable(RI_ENDOFFRAME,			"int");
1629 	declareVariable(RI_FILELOG,				"string");
1630 	declareVariable(RI_PROGRESS,			"int");
1631 
1632 
1633 	// Define the attributes
1634 	declareVariable(RI_NUMPROBES,			"int[2]");
1635 	declareVariable(RI_MINSUBDIVISION,		"int");
1636 	declareVariable(RI_MAXSUBDIVISION,		"int");
1637 	declareVariable(RI_MINSPLITS,			"int");
1638 	declareVariable(RI_BOUNDEXPAND,			"float");
1639 	declareVariable(RI_BINARY,				"int");
1640 	declareVariable(RI_RASTERORIENT,		"int");
1641 
1642 	declareVariable(RI_SPHERE,				"float");
1643 	declareVariable(RI_COORDINATESYSYTEM,	"string");
1644 
1645 	declareVariable(RI_DISPLACEMENTS,		"int");
1646 	declareVariable(RI_BIAS,				"float");
1647 	declareVariable(RI_MAXDIFFUSEDEPTH,		"int");
1648 	declareVariable(RI_MAXSPECULARDEPTH,	"int");
1649 	declareVariable(RI_SAMPLEMOTION,		"int");
1650 
1651 	declareVariable(RI_HANDLE,				"string");
1652 	declareVariable(RI_FILEMODE,			"string");
1653 	declareVariable(RI_MAXERROR,			"float");
1654 
1655 	declareVariable(RI_GLOBALMAP,			"string");
1656 	declareVariable(RI_CAUSTICMAP,			"string");
1657 	declareVariable(RI_SHADINGMODEL,		"string");
1658 	declareVariable(RI_ESTIMATOR,			"int");
1659 	declareVariable(RI_ILLUMINATEFRONT,		"int");
1660 
1661 	declareVariable(RI_TRANSMISSION,		"int");
1662 	declareVariable(RI_CAMERA,				"int");
1663 	declareVariable(RI_SPECULAR,			"int");
1664 	declareVariable(RI_DIFFUSE,				"int");
1665 	declareVariable(RI_PHOTON,				"int");
1666 
1667 	declareVariable(RI_DIFFUSEHITMODE,		"string");
1668 	declareVariable(RI_SPECULARHITMODE,		"string");
1669 	declareVariable(RI_TRANSMISSIONHITMODE,	"string");
1670 	declareVariable(RI_CAMERAHITMODE,		"string");
1671 
1672 	declareVariable(RI_NAME,				"string");
1673 
1674 	declareVariable(RI_HIDDEN,				"int");
1675 	declareVariable(RI_BACKFACING,			"backfacing");
1676 
1677 
1678 	// File display variables
1679 	declareVariable("quantize",				"float[4]");
1680 	declareVariable("dither",				"float");
1681 	declareVariable("gamma",				"float");
1682 	declareVariable("gain",					"float");
1683 	declareVariable("near",					"float");
1684 	declareVariable("far",					"float");
1685 	declareVariable("Software",				"string");
1686 	declareVariable("compression",			"string");
1687 	declareVariable("NP",					"float[16]");
1688 	declareVariable("Nl",					"float[16]");
1689 
1690 	// Declare the rest
1691 	declareVariable("P",	"global vertex point");
1692 	declareVariable("Ps",	"global vertex point");
1693 	declareVariable("N",	"global varying normal");
1694 	declareVariable("Ng",	"global varying normal");
1695 	declareVariable("dPdu",	"global vertex vector");
1696 	declareVariable("dPdv",	"global vertex vector");
1697 	declareVariable("L",	"global varying vector");
1698 	declareVariable("Cs",	"global varying color");
1699 	declareVariable("Os",	"global varying color");
1700 	declareVariable("Cl",	"global varying color");
1701 	declareVariable("Ol",	"global varying color");
1702 	declareVariable("Ci",	"global varying color");
1703 	declareVariable("Oi",	"global varying color");
1704 	declareVariable("s",	"global varying float");
1705 	declareVariable("t",	"global varying float");
1706 	declareVariable("st",	"varying float[2]");
1707 	declareVariable("du",	"global varying float");
1708 	declareVariable("dv",	"global varying float");
1709 	declareVariable("u",	"global varying float");
1710 	declareVariable("v",	"global varying float");
1711 	declareVariable("I",	"global varying vector");
1712 	declareVariable("E",	"global varying point");
1713 	declareVariable("alpha","global varying float");
1714 	declareVariable("time",	"global varying float");
1715 	declareVariable("Pw",	"global vertex htpoint");
1716 	declareVariable("Pz",	"vertex float");
1717 	declareVariable("width","vertex float");
1718 	declareVariable("constantwidth","constant float");
1719 
1720 	// Define uniform variables
1721 	declareVariable("ncomps","global uniform float");
1722 	declareVariable("dtime","global uniform float");
1723 	declareVariable("Np","uniform normal");
1724 
1725 	// Misc. variables
1726 	declareVariable("fov",	"float");
1727 
1728 	// Standard RI variables
1729 	declareVariable("Ka",				"float");
1730 	declareVariable("Kd",				"float");
1731 	declareVariable("Kr",				"float");
1732 	declareVariable("Ks",				"float");
1733 	declareVariable("amplitude",		"float");
1734 	declareVariable("background",		"color");
1735 	declareVariable("beamdistribution",	"float");
1736 	declareVariable("coneangle",		"float");
1737 	declareVariable("conedeltangle",	"float");
1738 	declareVariable("distance",			"float");
1739 	declareVariable("from",				"point");
1740 	declareVariable("intensity",		"float");
1741 	declareVariable("lightcolor",		"color");
1742 	declareVariable("maxdistance",		"float");
1743 	declareVariable("mindistance",		"float");
1744 	declareVariable("roughness",		"float");
1745 	declareVariable("specularcolor",	"color");
1746 	declareVariable("texturename",		"string");
1747 	declareVariable("to",				"point");
1748 }
1749 
1750