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				:	shading.cpp
27 //  Classes				:	CShadingContext
28 //  Description			:
29 //
30 ////////////////////////////////////////////////////////////////////////
31 #include	<stdarg.h>
32 #include	<math.h>
33 #include	<string.h>
34 
35 #include	"shading.h"
36 #include	"object.h"
37 #include	"raytracer.h"
38 #include	"brickmap.h"
39 #include	"photonMap.h"
40 #include	"pointCloud.h"
41 #include	"texture3d.h"
42 #include	"irradiance.h"
43 #include	"stats.h"
44 #include	"memory.h"
45 #include	"random.h"
46 #include	"points.h"
47 #include	"error.h"
48 #include	"remoteChannel.h"
49 #include	"renderer.h"
50 #include	"shaderPl.h"
51 #include	"ri_config.h"
52 
53 // George's extrapolated derivative extensions
54 #define		USE_EXTRAPOLATED_DERIV
55 
56 // Options that are defined and responded
57 const	char	*optionsFormat				=	"Format";
58 const	char	*optionsDeviceFrame			=	"Frame";
59 const	char	*optionsDeviceResolution	=	"DeviceResolution";
60 const	char	*optionsFrameAspectRatio	=	"FrameAspectRatio";
61 const	char	*optionsCropWindow			=	"CropWindow";
62 const	char	*optionsDepthOfField		=	"DepthOfField";
63 const	char	*optionsShutter				=	"Shutter";
64 const	char	*optionsClipping			=	"Clipping";
65 const	char	*optionsBucketSize			=	"BucketSize";
66 const	char	*optionsColorQuantizer		=	"ColorQuantizer";
67 const	char	*optionsDepthQuantizer		=	"DepthQuantizer";
68 const	char	*optionsPixelFilter			=	"PixelFilter";
69 const	char	*optionsGamma				=	"Gamma";
70 const	char	*optionsMaxRayDepth			=	"MaxRayDepth";
71 const	char	*optionsRelativeDetail		=	"RelativeDetail";
72 const	char	*optionsPixelSamples		=	"PixelSamples";
73 
74 // Attributes that are defined and responded
75 const	char	*attributesShadingRate		=	"ShadingRate";
76 const	char	*attributesSides			=	"Sides";
77 const	char	*attributesMatte			=	"matte";
78 const	char	*attributesMotionfactor		=	"GeometricApproximation:motionfactor";
79 const	char	*attributesDisplacementBnd	=	"displacementbound:sphere";
80 const	char	*attributesDisplacementSys	=	"displacementbound:coordinatesystem";
81 const	char	*attributesName				=	"identifier:name";
82 
83 const	char	*attributesTraceBias		=	"trace:bias";
84 const	char	*attributesTraceMaxDiffuse	=	"trace:maxdiffusedepth";
85 const	char	*attributesTraceMaxSpecular	=	"trace:maxspeculardepth";
86 
87 const	char	*attributesUser				=	"user:";
88 
89 // Rendererinfo requests
90 const	char	*rendererinfoRenderer		=	"renderer";
91 const	char	*rendererinfoVersion		=	"version";
92 const	char	*rendererinfoVersionStr		=	"versionstring";
93 
94 // Predefined ray labels used during raytracing
95 const	char	*rayLabelPrimary			=	"camera";
96 const	char	*rayLabelTrace				=	"trace";
97 const	char	*rayLabelTransmission		=	"transmission";
98 const	char	*rayLabelGather				=	"gather";
99 
100 
101 ///////////////////////////////////////////////////////////////////////
102 // Function				:	complete
103 // Description			:	This function fills in the missing data (not filled by the object) from attributes
104 // Return Value			:
105 // Comments				:	Thread safe
complete(int num,float ** varying,unsigned int usedParameters,const CAttributes * attributes1,const CAttributes * attributes2)106 inline void	complete(int num,float **varying,unsigned int usedParameters,const CAttributes *attributes1,const CAttributes *attributes2) {
107 	int		i;
108 
109 	if (usedParameters & PARAMETER_ALPHA) {
110 		float	*dest	=	varying[VARIABLE_ALPHA];
111 
112 		for (i=num;i>0;i--)
113 			*dest++	=	1;
114 	}
115 
116 	if (usedParameters & PARAMETER_S) {
117 		const float	*u		=	varying[VARIABLE_U];
118 		float		*s		=	varying[VARIABLE_S];
119 
120 		if (attributes1->flags & ATTRIBUTES_FLAGS_CUSTOM_ST) {
121 			const	float	*v		=	varying[VARIABLE_V];
122 			const	float	*time	=	varying[VARIABLE_TIME];
123 			const	float	*s1		=	attributes1->s;
124 			const	float	*s2		=	attributes2->s;
125 
126 			for (i=num;i>0;i--) {
127 				const	double	ctime	=	*time++;
128 				const	double	cu		=	*u++;
129 				const	double	cv		=	*v++;
130 
131 				*s++			=	(float) (((s1[0]*(1.0-ctime) + s2[0]*ctime)*(1.0-cu) +
132 											 (s1[1]*(1.0-ctime) + s2[1]*ctime)*cu)*(1.0-cv) +
133 											((s1[2]*(1.0-ctime) + s2[2]*ctime)*(1.0-cu) +
134 											 (s1[3]*(1.0-ctime) + s2[3]*ctime)*cu)*cv);
135 			}
136 		} else {
137 			memcpy(s,u,num*sizeof(float));
138 		}
139 	}
140 
141 	if (usedParameters & PARAMETER_T) {
142 		const float	*v		=	varying[VARIABLE_V];
143 		float		*t		=	varying[VARIABLE_T];
144 
145 		if (attributes1->flags & ATTRIBUTES_FLAGS_CUSTOM_ST) {
146 			const	float	*u		=	varying[VARIABLE_U];
147 			const	float	*time	=	varying[VARIABLE_TIME];
148 			const	float	*t1		=	attributes1->t;
149 			const	float	*t2		=	attributes2->t;
150 
151 			for (i=num;i>0;i--) {
152 				const	double	ctime	=	*time++;
153 				const	double	cu		=	*u++;
154 				const	double	cv		=	*v++;
155 
156 				*t++			=	(float) (((t1[0]*(1.0-ctime) + t2[0]*ctime)*(1.0-cu) +
157 										     (t1[1]*(1.0-ctime) + t2[1]*ctime)*cu)*(1.0-cv) +
158 											((t1[2]*(1.0-ctime) + t2[2]*ctime)*(1.0-cu) +
159 											 (t1[3]*(1.0-ctime) + t2[3]*ctime)*cu)*cv);
160 				u++;
161 				v++;
162 				time++;
163 			}
164 		} else {
165 			memcpy(t,v,num*sizeof(float));
166 		}
167 	}
168 
169 	if (usedParameters & PARAMETER_CS) {
170 		float			*dest	=	varying[VARIABLE_CS];
171 		const	float	*time	=	varying[VARIABLE_TIME];
172 		const	float	*c1		=	attributes1->surfaceColor;
173 		const	float	*c2		=	attributes2->surfaceColor;
174 
175 
176 		for (i=num;i>0;i--) {
177 			interpolatev(dest,c1,c2,*time++);
178 			dest	+=	3;
179 		}
180 	}
181 
182 	if (usedParameters & PARAMETER_OS) {
183 		float			*dest	=	varying[VARIABLE_OS];
184 		const	float	*time	=	varying[VARIABLE_TIME];
185 		const	float	*c1		=	attributes1->surfaceOpacity;
186 		const	float	*c2		=	attributes2->surfaceOpacity;
187 
188 		for (i=num;i>0;i--) {
189 			interpolatev(dest,c1,c2,*time++);
190 			dest	+=	3;
191 		}
192 	}
193 
194 	// If the coordinate system is right handed, flip the normal vector
195 	if (attributes1->flags & ATTRIBUTES_FLAGS_INSIDE)  {
196 		float	*src	=	varying[VARIABLE_NG];
197 		float	*src2	=	varying[VARIABLE_N];
198 
199 		for (i=num;i>0;i--) {
200 			mulvf(src,-1);
201 			mulvf(src2,-1);
202 			src		+=	3;
203 			src2	+=	3;
204 		}
205 	}
206 
207 	// Copy the normal vector
208 	if (usedParameters & PARAMETER_N) {
209 		memcpy(varying[VARIABLE_N],varying[VARIABLE_NG],3*num*sizeof(float));
210 	}
211 
212 	// ensure Oi and Ci are always filled in
213 	if (!(usedParameters & PARAMETER_CI)) {
214 		float			*dest	=	varying[VARIABLE_CI];
215 		const	float	*time	=	varying[VARIABLE_TIME];
216 		const	float	*c1		=	attributes1->surfaceColor;
217 		const	float	*c2		=	attributes2->surfaceColor;
218 
219 
220 		for (i=num;i>0;i--) {
221 			interpolatev(dest,c1,c2,*time);
222 			dest	+=	3;
223 			time	++;
224 		}
225 	}
226 
227 	if (!(usedParameters & PARAMETER_OI)) {
228 		float			*dest	=	varying[VARIABLE_OI];
229 		const	float	*time	=	varying[VARIABLE_TIME];
230 		const	float	*c1		=	attributes1->surfaceOpacity;
231 		const	float	*c2		=	attributes2->surfaceOpacity;
232 
233 		for (i=num;i>0;i--) {
234 			interpolatev(dest,c1,c2,*time);
235 			dest	+=	3;
236 			time	++;
237 		}
238 	}
239 
240 	// Finally, range-correct time
241 	// Note: It is important this is last, as before this we assume a 0-1
242 	// range for time.  After this we must never use time assuing 0-1 range
243 	if (usedParameters & (PARAMETER_TIME | PARAMETER_DTIME)) {
244 
245 		varying[VARIABLE_DTIME][0]	=	CRenderer::shutterClose - CRenderer::shutterOpen;
246 
247 		float		*time			=	varying[VARIABLE_TIME];
248 		const float idtime			= 	CRenderer::invShutterTime;
249 		const float t0				=	CRenderer::shutterOpen;
250 
251 		for (i=num;i>0;i--) {
252 			time[0] = (time[0]*idtime + t0);
253 			time++;
254 		}
255 	}
256 
257 }
258 
259 ///////////////////////////////////////////////////////////////////////
260 // Function				:	complete
261 // Description			:	This function fills in the missing data (not filled by the object) from attributes
262 // Return Value			:
263 // Comments				:	Thread safe
complete(int num,float ** varying,unsigned int usedParameters,const CAttributes * attributes)264 inline	void	complete(int num,float **varying,unsigned int usedParameters,const CAttributes *attributes) {
265 	int		i;
266 
267 	if (usedParameters & PARAMETER_ALPHA) {
268 		float	*dest	=	varying[VARIABLE_ALPHA];
269 
270 		for (i=num;i>0;i--)
271 			*dest++	=	1;
272 	}
273 
274 	if (usedParameters & PARAMETER_S) {
275 		const	float	*u		=	varying[VARIABLE_U];
276 		float			*s		=	varying[VARIABLE_S];
277 
278 		if (attributes->flags & ATTRIBUTES_FLAGS_CUSTOM_ST) {
279 			const	float	*v		=	varying[VARIABLE_V];
280 			const	float	*sCoord	=	attributes->s;
281 
282 			for (i=num;i>0;i--) {
283 				const double uu = *u;
284 				const double vv = *v;
285 				*s++		=	(float) ((sCoord[0]*(1.0-uu) + sCoord[1]*uu)*(1.0-vv) + (sCoord[2]*(1.0-uu) + sCoord[3]*uu)*vv);
286 				u++;
287 				v++;
288 			}
289 		} else {
290 			memcpy(s,u,num*sizeof(float));
291 		}
292 	}
293 
294 	if (usedParameters & PARAMETER_T) {
295 		const float	*v		=	varying[VARIABLE_V];
296 		float		*t		=	varying[VARIABLE_T];
297 
298 		if (attributes->flags & ATTRIBUTES_FLAGS_CUSTOM_ST) {
299 			const	float	*u		=	varying[VARIABLE_U];
300 			const	float	*tCoord	=	attributes->t;
301 
302 			for (i=num;i>0;i--) {
303 				const double uu = *u;
304 				const double vv = *v;
305 				*t++		=	(float) ((tCoord[0]*(1.0-uu) + tCoord[1]*uu)*(1.0-vv) + (tCoord[2]*(1.0-uu) + tCoord[3]*uu)*vv);
306 				u++;
307 				v++;
308 			}
309 		} else {
310 			memcpy(t,v,num*sizeof(float));
311 		}
312 	}
313 
314 	if (usedParameters & PARAMETER_CS) {
315 		float			*dest	=	varying[VARIABLE_CS];
316 		const	float	*src	=	attributes->surfaceColor;
317 
318 		for (i=num;i>0;i--) {
319 			movvv(dest,src);
320 			dest	+=	3;
321 		}
322 	}
323 
324 	if (usedParameters & PARAMETER_OS) {
325 		float			*dest	=	varying[VARIABLE_OS];
326 		const	float	*src	=	attributes->surfaceOpacity;
327 
328 		for (i=num;i>0;i--) {
329 			movvv(dest,src);
330 			dest	+=	3;
331 		}
332 	}
333 
334 	if (attributes->flags & ATTRIBUTES_FLAGS_INSIDE) {
335 		float	*src	=	varying[VARIABLE_NG];
336 
337 		for (i=num;i>0;i--) {
338 			mulvf(src,-1);
339 			src		+=	3;
340 		}
341 	}
342 
343 	if (usedParameters & PARAMETER_N) {
344 		memcpy(varying[VARIABLE_N],varying[VARIABLE_NG],3*num*sizeof(float));
345 	}
346 
347 	// ensure Oi and Ci are always filled in
348 	if (!(usedParameters & PARAMETER_CI)) {
349 		float			*dest	=	varying[VARIABLE_CI];
350 		const	float	*src	=	attributes->surfaceColor;
351 
352 		for (i=num;i>0;i--) {
353 			movvv(dest,src);
354 			dest	+=	3;
355 		}
356 	}
357 
358 	if (!(usedParameters & PARAMETER_OI)) {
359 		float			*dest	=	varying[VARIABLE_OI];
360 		const	float	*src	=	attributes->surfaceOpacity;
361 
362 		for (i=num;i>0;i--) {
363 			movvv(dest,src);
364 			dest	+=	3;
365 		}
366 	}
367 
368 	// Finally, range-correct time
369 	// Note: It is important this is last, as before this we assume a 0-1
370 	// range for time.  After this we must never use time assuing 0-1 range
371 	if (usedParameters & (PARAMETER_TIME | PARAMETER_DTIME)) {
372 
373 		varying[VARIABLE_DTIME][0]	=	CRenderer::shutterClose - CRenderer::shutterOpen;
374 
375 		float		*time		=	varying[VARIABLE_TIME];
376 		const float idtime		= 	CRenderer::invShutterTime;
377 		const float t0			=	CRenderer::shutterOpen;
378 
379 		for (i=num;i>0;i--) {
380 			time[0] = (time[0]*idtime + t0);
381 			time++;
382 		}
383 	}
384 }
385 
386 
387 ///////////////////////////////////////////////////////////////////////
388 // Class				:	CShadingContext
389 // Method				:	CShadingContext
390 // Description			:	Ctor
391 // Return Value			:	-
392 // Comments				:
CShadingContext(int t)393 CShadingContext::CShadingContext(int t) : thread(t) {
394 	// Initialize the shading state
395 	currentShadingState		=	NULL;
396 
397 	// Initialize the shader state memory stack
398 	memoryInit(shaderStateMemory);
399 
400 	// Initialize the thread memory stack
401 	memoryInit(threadMemory);
402 
403 	// Init the bucket we're rendering
404 	currentXBucket			=	0;
405 	currentYBucket			=	0;
406 
407 	// Init the conditionals
408 	conditionals			=	NULL;
409 	currentRayDepth			=	0;
410 	currentRayLabel			=	rayLabelPrimary;
411 	freeStates				=	NULL;
412 	inShadow				=	FALSE;
413 
414 	// (globalMemory is checkpointed)
415 	traceObjectHash			=	(TObjectHash *) ralloc(sizeof(TObjectHash)*SHADING_OBJECT_CACHE_SIZE,CRenderer::globalMemory);
416 
417 	// Fill the object pointers with impossible data
418 	for (int i=0;i<SHADING_OBJECT_CACHE_SIZE;i++)	traceObjectHash[i].object	=	(CSurface *) this;
419 
420 	// Init the PL hash
421 	for (int i=0;i<PL_HASH_SIZE;i++) plHash[i]	=	NULL;
422 
423 	// Init the random number generator
424 	randomInit(5489*(thread+1));
425 
426 	// Init the stats
427 	numIndirectDiffuseRays				=	0;
428 	numIndirectDiffuseSamples			=	0;
429 	numOcclusionRays					=	0;
430 	numOcclusionSamples					=	0;
431 	numIndirectDiffusePhotonmapLookups	=	0;
432 	numShade							=	0;
433 	numSampled							=	0;
434 	numShaded							=	0;
435 	vertexMemory						=	0;
436 	peakVertexMemory					=	0;
437 	numTracedRays						=	0;
438 	numReflectionRays					=	0;
439 	numTransmissionRays					=	0;
440 	numGatherRays						=	0;
441 }
442 
443 ///////////////////////////////////////////////////////////////////////
444 // Class				:	CShadingContext
445 // Method				:	~CShadingContext
446 // Description			:	Dtor
447 // Return Value			:	-
448 // Comments				:
~CShadingContext()449 CShadingContext::~CShadingContext() {
450 
451 	// Delete the conditionals we allocated
452 	CConditional	*cConditional;
453 	while((cConditional = conditionals) != NULL) {
454 		conditionals	=	conditionals->next;
455 		delete cConditional;
456 	}
457 
458 	// Shutdown the random number generator
459 	randomShutdown();
460 
461 	// Ditch the PL hash
462 	for (int i=0;i<PL_HASH_SIZE;i++) {
463 		CPLLookup	*cLookup;
464 		while((cLookup=plHash[i]) != NULL) {
465 			plHash[i]	=	cLookup->next;
466 			delete cLookup;
467 		}
468 	}
469 
470 	// Ditch the shading states that have been allocated
471 	assert(currentShadingState != NULL);
472 	freeState(currentShadingState);
473 	CShadingState	*cState;
474 	while ((cState=freeStates) != NULL) {
475 		freeStates	=	cState->next;
476 
477 		freeState(cState);
478 	}
479 	currentShadingState	=	NULL;
480 
481 	// Ditch the thread memory stack
482 	memoryTini(threadMemory);
483 
484 	// Ditch the shader state memory stack
485 	memoryTini(shaderStateMemory);
486 
487 	// The frame assertions
488 	assert(vertexMemory == 0);
489 
490 	// Update the global statistics
491 	stats.numIndirectDiffuseRays				+=	numIndirectDiffuseRays;
492 	stats.numIndirectDiffuseSamples				+=	numIndirectDiffuseSamples;
493 	stats.numOcclusionRays						+=	numOcclusionRays;
494 	stats.numOcclusionSamples					+=	numOcclusionSamples;
495 	stats.numIndirectDiffusePhotonmapLookups	+=	numIndirectDiffusePhotonmapLookups;
496 	stats.numShade								+=	numShade;
497 	stats.numSampled							+=	numSampled;
498 	stats.numShaded								+=	numShaded;
499 	stats.numTracedRays							+=	numTracedRays;
500 	stats.numReflectionRays						+=	numReflectionRays;
501 	stats.numTransmissionRays					+=	numTransmissionRays;
502 	stats.numGatherRays							+=	numGatherRays;
503 }
504 
505 
506 
507 
508 ///////////////////////////////////////////////////////////////////////
509 // Class				:	CShadingContext
510 // Method				:	renderPrimitive
511 // Description			:	Add an object into the scene
512 // Return Value			:
513 // Comments				:
drawObject(CObject * cObject)514 void	CShadingContext::drawObject(CObject *cObject) {
515 	// This function must be overriden
516 }
517 
518 
519 
520 
521 
522 
523 ///////////////////////////////////////////////////////////////////////
524 // Class				:	CShadingContext
525 // Method				:	shade2D
526 // Description			:	Sample/Shade bunch of points
527 // Return Value			:	-
528 // Comments				:	Thread safe
529 //
530 //
531 //
532 //	Preconditions:
533 //	!!!	->	u,v,time,I		fields of varying must be set
shade(CSurface * object,int uVertices,int vVertices,EShadingDim dim,unsigned int usedParameters,int displaceOnly)534 void	CShadingContext::shade(CSurface *object,int uVertices,int vVertices,EShadingDim dim,unsigned int usedParameters,int displaceOnly) {
535 	const CAttributes	*currentAttributes	=	object->attributes;
536 	float				**varying			=	currentShadingState->varying;
537 	float				***locals			= 	currentShadingState->locals;
538 	CShaderInstance		*displacement;
539 	CShaderInstance		*surface;
540 	CShaderInstance		*atmosphere;
541 	int					i;
542 	CSurface			*savedObject;
543 
544 	assert(uVertices > 0);
545 	assert(vVertices > 0);
546 
547 	// This is the number of vertices we will be sampling/shading
548 	int	numVertices		=	uVertices*vVertices;
549 	assert(numVertices <= CRenderer::maxGridSize);
550 	assert(numVertices > 0);
551 
552 	// Update the stats
553 	numShade++;
554 	numSampled			+=	numVertices;
555 
556 	// Are we just displacing the surface ?
557 	if (displaceOnly == FALSE) {
558 
559 		// Are we in a shadow ray ?
560 		if (inShadow == TRUE) {
561 
562 			// Yes, are we supposed to shade the objects in the shadow ?
563 			if (currentAttributes->transmissionHitMode == 'p') {
564 
565 				// No, just copy the color/opacity from the attributes field
566 				float			*opacity	=	varying[VARIABLE_OI];
567 				int				i;
568 				const	float	*so			=	currentAttributes->surfaceOpacity;
569 
570 				for (i=numVertices;i>0;i--,opacity+=3)	movvv(opacity,so);
571 
572 				// Nothing more to do here, just return
573 				return;
574 			}
575 
576 			// The transmission must be shade at this point
577 			assert(currentAttributes->transmissionHitMode == 's');
578 
579 			// We need to execute the shaders
580 			displacement	=	NULL;	//currentAttributes->displacement;	// We probably don't need to execute the displacement shader
581 			surface			=	currentAttributes->surface;
582 			atmosphere		=	NULL;
583 
584 		} else {
585 			// check the hit mode
586 
587 			// If we're raytracing, are we supposed to shade hit rays?
588 			if ((dim == SHADING_2D) && (currentAttributes->specularHitMode == 'p')) {
589 				// No, just copy the color/opacity from the attributes field
590 				float			*opacity	=	varying[VARIABLE_OI];
591 				float			*color		=	varying[VARIABLE_CI];
592 				int				i;
593 				const	float	*so			=	currentAttributes->surfaceOpacity;
594 				const	float	*sc			=	currentAttributes->surfaceColor;
595 
596 				for (i=numVertices;i>0;i--,opacity+=3,color+=3) {
597 					movvv(opacity,so);
598 					movvv(color,sc);
599 				}
600 
601 				// Nothing more to do here, just return
602 				return;
603 			}
604 
605 			// We need to execute the shaders
606 			if (currentAttributes->flags & ATTRIBUTES_FLAGS_MATTE) {
607 				displacement	=	currentAttributes->displacement;
608 				surface			=	currentAttributes->surface;				// execute the surface shader for the output opacity
609 				atmosphere		=	NULL;
610 			} else {
611 				displacement	=	currentAttributes->displacement;
612 				surface			=	currentAttributes->surface;
613 				atmosphere		=	currentAttributes->atmosphere;
614 			}
615 		}
616 
617 		// Prepare the used parameters by the shaders
618 		usedParameters			|=	currentAttributes->usedParameters | CRenderer::additionalParameters;
619 
620 		// Prepare the locals
621 		for (int a=0;a<NUM_ACCESSORS;a++) locals[a] = NULL;
622 	} else {
623 
624 		// We are only interested in the surface position, not the color
625 #ifdef IGNORE_DISPLACEMENTS_FOR_DICING
626 		if (	(currentAttributes->displacement == NULL) ||
627 			(	(usedParameters & PARAMETER_RAYTRACE) && (!(currentAttributes->flags & ATTRIBUTES_FLAGS_DISPLACEMENTS))) ||
628 				(displaceOnly & 2)
629 			) {
630 #else
631 		if (	(currentAttributes->displacement == NULL) ||
632 			(	(usedParameters & PARAMETER_RAYTRACE) && (!(currentAttributes->flags & ATTRIBUTES_FLAGS_DISPLACEMENTS)))) {
633 #endif
634 			const int	savedParameters	=	usedParameters;
635 
636 			// No, just sample the geometry
637 			// Note: we pass NULL for each of the locals here because we do not wish
638 			// to expand them (we're not running shaders) yet.  This causes the
639 			// interpolation to local shader vars from the pl not to occur
640 			for (int a=0;a<NUM_ACCESSORS;a++) locals[a] = NULL;
641 
642 			object->sample(0,numVertices,varying,locals,usedParameters);
643 			object->interpolate(numVertices,varying,locals);
644 
645 			// We're not shading just sampling
646 			if (usedParameters & PARAMETER_N) {
647 				assert(savedParameters & PARAMETER_NG);
648 
649 				// Flip the normal vector ?
650 				if (currentAttributes->flags & ATTRIBUTES_FLAGS_INSIDE) {
651 					int		i	=	numVertices;
652 					float	*N	=	varying[VARIABLE_NG];
653 
654 					for (;i>0;i--) {
655 						*N++	*=	-1;
656 						*N++	*=	-1;
657 						*N++	*=	-1;
658 					}
659 				}
660 
661 				memcpy(varying[VARIABLE_N],varying[VARIABLE_NG],numVertices*3*sizeof(float));
662 			}
663 
664 			// We're done here
665 			return;
666 		}
667 
668 		// Prepare the locals
669 		for (int a=0;a<NUM_ACCESSORS;a++) locals[a] = NULL;
670 
671 		// We need to execute the displacement shader, so get ready
672 		displacement	=	currentAttributes->displacement;
673 		surface			=	NULL;
674 		atmosphere		=	NULL;
675 
676 		// Note: we check for message passing with displacement and prepare appopriately below
677 	}
678 
679 
680 	// We're shading
681 	savedObject							=	currentShadingState->currentObject;
682 	currentShadingState->currentObject	=	object;
683 	currentShadingState->numUvertices	=	uVertices;
684 	currentShadingState->numVvertices	=	vVertices;
685 	currentShadingState->numVertices	=	numVertices;
686 
687 	// Checkpoint the shader state stack
688 	memBegin(shaderStateMemory);
689 
690 	// Allocate the caches for the shaders being executed
691 	if (surface != NULL)							locals[ACCESSOR_SURFACE]		=	surface->prepare(shaderStateMemory,varying,numVertices);
692 	if (displacement != NULL)						locals[ACCESSOR_DISPLACEMENT]	=	displacement->prepare(shaderStateMemory,varying,numVertices);
693 	if (atmosphere != NULL)							locals[ACCESSOR_ATMOSPHERE]		=	atmosphere->prepare(shaderStateMemory,varying,numVertices);
694 
695 	if (displaceOnly == TRUE) {
696 		// Verify if we have to prepare other shaders, even though displacing
697 		// due to message passing this _has_ to be after the shaderStateMemory checkPoint
698 		usedParameters	=	displacement->requiredParameters() | PARAMETER_P | PARAMETER_N;
699 
700 		if (usedParameters & PARAMETER_MESSAGEPASSING) {
701 			// displacement shader uses messsage passing, must prepare but not execute
702 			// the surface and atmosphere shaders
703 			if (currentAttributes->surface != NULL)			locals[ACCESSOR_SURFACE]		=	currentAttributes->surface->prepare(shaderStateMemory,varying,numVertices);
704 			if (currentAttributes->atmosphere != NULL)		locals[ACCESSOR_ATMOSPHERE]		=	currentAttributes->atmosphere->prepare(shaderStateMemory,varying,numVertices);
705 		}
706 	}
707 
708 
709 	// We do not prepare interior or exterior as these are limited to passing default values (no outputs, they don't recieve pl variables)
710 
711 	// If we need derivative information, treat differently
712 	if ((usedParameters & PARAMETER_DERIVATIVE) && (dim != SHADING_0D)) {	// Notice: we can not differentiate a 0 dimentional point set
713 
714 		if (dim == SHADING_2D) {											// We're raytracing, so the derivative computation is different
715 			const int numRealVertices				=	numVertices;
716 			numVertices								*=	3;					// For the extra derivative vertices
717 			currentShadingState->numVertices		=	numVertices;
718 			currentShadingState->numRealVertices	=	numRealVertices;
719 			currentShadingState->shadingDim			=	SHADING_2D;
720 			currentShadingState->numActive			=	numVertices;
721 			currentShadingState->numPassive			=	0;
722 
723 			// Sample the object at the main intersection points
724 			usedParameters							|=	PARAMETER_DPDU | PARAMETER_DPDV | PARAMETER_P;
725 			const unsigned int shadingParameters	=	usedParameters;
726 			object->sample(0,numRealVertices,varying,locals,usedParameters);
727 			usedParameters							=	shadingParameters;		// Restore the required parameters for the second round of shading
728 
729 			float	*dPdu			=	varying[VARIABLE_DPDU];
730 			float	*dPdv			=	varying[VARIABLE_DPDV];
731 			float	*du				=	varying[VARIABLE_DU];
732 			float	*dv				=	varying[VARIABLE_DV];
733 			float	*u				=	varying[VARIABLE_U];
734 			float	*v				=	varying[VARIABLE_V];
735 			float	*time			=	varying[VARIABLE_TIME];
736 			float	*I				=	varying[VARIABLE_I];
737 			int		j;
738 
739 			// Compute du/dv
740 			for (i=0,j=numRealVertices;i<numRealVertices;i++,I+=3,dPdu+=3,dPdv+=3) {
741 				const float	lengthu	=	dotvv(dPdu,dPdu);
742 				const float	lengthv	=	dotvv(dPdv,dPdv);
743 				const float	lengthi	=	dotvv(I,I);
744 
745 				float	ku			=	dotvv(I,dPdu);	ku	=	isqrtf((lengthu*lengthi - (ku*ku)) / (lengthu*lengthi + C_EPSILON));
746 				float	kv			=	dotvv(I,dPdv);	kv	=	isqrtf((lengthv*lengthi - (kv*kv)) / (lengthv*lengthi + C_EPSILON));
747 
748 				const float	dest	=	du[i];				// The ray crosssection at the intersection
749 				// Note: we are clamping the maximal du dv because otherwise the surface
750 				// sampling becomes grossly inaccurate, and in recursive raytracing, db
751 				// grows unboundedly, causing inf and nan, and messing up filtering
752 				// These are the 0-1 patch uvs, not the expanded range uvs, so this is OK.
753 				const float	dud		=	min(ku * dest * isqrtf(lengthu) + C_EPSILON,1.0f);
754 				const float	dvd		=	min(kv * dest * isqrtf(lengthv) + C_EPSILON,1.0f);
755 
756 				// Create one more shading point at (u + du,v)
757 				u[j]		=	u[i] + dud;
758 				v[j]		=	v[i];
759 				time[j]		=	time[i];
760 				movvv(varying[VARIABLE_I] + j*3,I);
761 				du[i]		=	dud;
762 				du[j]		=	dud;
763 				dv[j]		=	dvd;
764 				j++;
765 
766 				// Create one more shading point at (u,v + dv)
767 				u[j]		=	u[i];
768 				v[j]		=	v[i] + dvd;
769 				time[j]		=	time[i];
770 				movvv(varying[VARIABLE_I] + j*3,I);
771 				dv[i]		=	dvd;
772 				du[j]		=	dud;
773 				dv[j]		=	dvd;
774 				j++;
775 			}
776 
777 			// Sample the object again, this time at the extra shading points
778 			object->sample(numRealVertices,2*numRealVertices,varying,locals,usedParameters);
779 
780 			// Interpolate the various variables defined on the object
781 			object->interpolate(numVertices,varying,locals);
782 
783 		} else {
784 			// We're shading a regular grid, so take the shortcut while computing the surface derivatives
785 			int				i,j;
786 			const float		shadingRate				=	currentAttributes->shadingRate;
787 
788 			assert(dim == SHADING_2D_GRID);
789 
790 			currentShadingState->numRealVertices	=	numVertices;
791 			currentShadingState->shadingDim			=	SHADING_2D_GRID;
792 			currentShadingState->numActive			=	numVertices;
793 			currentShadingState->numPassive			=	0;
794 
795 			// First sample the object at the grid vertices
796 			usedParameters	|=	PARAMETER_P;
797 
798 			// Sample the object
799 			object->sample(0,numVertices,varying,locals,usedParameters);
800 
801 			// Interpolate the various variables defined on the object
802 			object->interpolate(numVertices,varying,locals);
803 
804 			// We're rasterizing, so the derivative information is already available
805 			memBegin(threadMemory);
806 
807 			// This array holds the projected xy pixel positions for the vertices
808 			float		*xy		=	(float *) ralloc(numVertices*2*sizeof(float),threadMemory);
809 			const float	*P		=	varying[VARIABLE_P];
810 
811 			// Project the grid vertices first
812 			// PS: The offset is not important, so do not compute it
813 			const float maxdPixeldxy = max(CRenderer::dPixeldx,CRenderer::dPixeldy);
814 			const float dPixeldx = (currentAttributes->flags & ATTRIBUTES_FLAGS_NONRASTERORIENT_DICE) ? 1.0f : CRenderer::dPixeldx;
815 			const float dPixeldy = (currentAttributes->flags & ATTRIBUTES_FLAGS_NONRASTERORIENT_DICE) ? 1.0f : CRenderer::dPixeldy;
816 			if (CRenderer::projection == OPTIONS_PROJECTION_PERSPECTIVE) {
817 				float	*cXy	=	xy;
818 
819 				for (i=numVertices;i>0;i--) {
820 					cXy[0]		=	(P[COMP_X] * CRenderer::imagePlane / P[COMP_Z])*dPixeldx;
821 					cXy[1]		=	(P[COMP_Y] * CRenderer::imagePlane / P[COMP_Z])*dPixeldy;
822 					cXy			+=	2;
823 					P			+=	3;
824 				}
825 
826 				// Compute the I
827 				memcpy(varying[VARIABLE_I],varying[VARIABLE_P],numVertices*3*sizeof(float));
828 			} else {
829 				float	*cXy	=	xy;
830 
831 				for (i=numVertices;i>0;i--) {
832 					cXy[0]		=	P[COMP_X]*dPixeldx;
833 					cXy[1]		=	P[COMP_Y]*dPixeldy;
834 					cXy			+=	2;
835 					P			+=	3;
836 				}
837 
838 				// Compute the I
839 				float		*I	=	varying[VARIABLE_I];
840 				P	=	varying[VARIABLE_P];
841 				for (i=numVertices;i>0;i--,I+=3,P+=3)	initv(I,0,0,P[COMP_Z]);
842 			}
843 
844 			float		*du			=	varying[VARIABLE_DU];
845 			float		*dv			=	varying[VARIABLE_DV];
846 			const float *u			=	varying[VARIABLE_U];
847 			const float	*v			=	varying[VARIABLE_V];
848 
849 			#ifdef USE_EXTRAPOLATED_DERIV
850 				#define extrapolateDerivU()																\
851 					if (uVertices > 3) {																\
852 						const float A =	(cDU[-3] - cDU[-2])/((cU[-3]-cU[-2])*(cU[-3]-cU[-1])) -			\
853 										(cDU[-1] - cDU[-2])/((cU[-1]-cU[-2])*(cU[-3]-cU[-1]));			\
854 						const float B =	(cDU[-1] - cDU[-2] + A*(cU[-2]*cU[-2] - cU[-1]*cU[-1])) /		\
855 										(cU[-1] - cU[-2]);												\
856 						const float C = (cDU[-1] - A*cU[-1]*cU[-1] - B*cU[-1]);							\
857 						d		= A*cU[0]*cU[0] + B*cU[0] + C;											\
858 					}
859 
860 				#define extrapolateDerivV()																														\
861 					if (vVertices > 3) {																														\
862 						const float A =	(cDV[-uVertices*3] - cDV[-uVertices*2])/((cV[-uVertices*3]-cV[-uVertices*2])*(cV[-uVertices*3]-cV[-uVertices*1])) -		\
863 										(cDV[-uVertices*1] - cDV[-uVertices*2])/((cV[-uVertices*1]-cV[-uVertices*2])*(cV[-uVertices*3]-cV[-uVertices*1]));		\
864 						const float B =	(cDV[-uVertices*1] - cDV[-uVertices*2] + A*(cV[-uVertices*2]*cV[-uVertices*2] - cV[-uVertices*1]*cV[-uVertices*1])) /	\
865 										(cV[-uVertices*1] - cV[-uVertices*2]);																					\
866 						const float C = (cDV[-uVertices*1] - A*cV[-uVertices*1]*cV[-uVertices*1] - B*cV[-uVertices*1]);											\
867 						d		= A*cV[0]*cV[0] + B*cV[0] + C;																									\
868 					}
869 
870 			#else
871 				#define extrapolateDerivU()
872 				#define extrapolateDerivV()
873 			#endif
874 
875 #define	MAX_DIFFERENTIAL_DISCREPANCY	4*shadingRate
876 
877 			if (!(currentAttributes->flags & ATTRIBUTES_FLAGS_NONRASTERORIENT_DICE)) {
878 				// Compute the du
879 				for (i=0;i<vVertices;i++) {
880 					const int	tmp		=	i*uVertices;
881 					float		*cDU	=	du	+ tmp;
882 					const float	*cU		=	u	+ tmp;
883 					float		*cXy	=	xy	+ tmp*2;
884 					float		d		=	0;
885 
886 					for (j=uVertices-1;j>0;j--) {
887 						const float	dx	=	cXy[2] - cXy[0];
888 						const float	dy	=	cXy[3] - cXy[1];
889 						float		cSr	=	shadingRate*isqrtf(dx*dx + dy*dy);
890 						if (cSr > MAX_DIFFERENTIAL_DISCREPANCY)	cSr	=	MAX_DIFFERENTIAL_DISCREPANCY;
891 						d		=	cSr*(cU[1] - cU[0]);
892 						d		=	min(d,1);
893 						d		=	max(d,C_EPSILON);
894 						assert(d > 0);
895 						assert(d <= 1);
896 						cDU[0]	=	d;
897 						cDU		+=	1;
898 						cU		+=	1;
899 						cXy		+=	2;
900 					}
901 
902 					extrapolateDerivU();
903 
904 					cDU[0]		=	d;
905 				}
906 
907 				// Compute the dv,dPdv
908 				for (i=0;i<uVertices;i++) {
909 					float		*cDV	=	dv	+	i;
910 					const float	*cV		=	v	+	i;
911 					float		*cXy	=	xy	+	i*2;
912 					float		d		=	0;
913 
914 					for (j=0;j<vVertices-1;j++) {
915 						const float	dx		=	cXy[uVertices*2]	- cXy[0];
916 						const float	dy		=	cXy[uVertices*2+1]	- cXy[1];
917 						float		cSr		=	shadingRate*isqrtf(dx*dx + dy*dy);
918 						if (cSr > MAX_DIFFERENTIAL_DISCREPANCY)	cSr	=	MAX_DIFFERENTIAL_DISCREPANCY;
919 						d		=	cSr*(cV[uVertices] - cV[0]);
920 						d		=	max(d,C_EPSILON);
921 						d		=	min(d,1);
922 						assert(d > 0);
923 						assert(d <= 1);
924 						cDV[0]	=	d;
925 						cDV		+=	uVertices;
926 						cV		+=	uVertices;
927 						cXy		+=	uVertices*2;
928 					}
929 
930 					extrapolateDerivV();
931 
932 					cDV[0]		=	d;
933 				}
934 
935 			} else {
936 				// Non raster orient
937 				vector tmp1,tmp2;
938 
939 				// Compute the du
940 				for (i=0;i<vVertices;i++) {
941 					const int	tmp		=	i*uVertices;
942 					float		*cDU	=	du	+ tmp;
943 					const float	*cU		=	u	+ tmp;
944 					float		*cXy	=	xy	+ tmp*2;
945 					float		d		=	0;
946 
947 					P				=	varying[VARIABLE_P]		+	tmp*3;
948 					for (j=uVertices-1;j>0;j--) {
949 						initv(tmp1,cXy[2]-P[3],cXy[3]-P[4],P[5]-1);
950 						initv(tmp2,cXy[0]-P[0],cXy[1]-P[1],P[2]-1);
951 						const float	dx		=	maxdPixeldxy*(cXy[2] - cXy[0]);
952 						const float	dy		=	maxdPixeldxy*(cXy[3] - cXy[1]);
953 						const float	dz		=	maxdPixeldxy*(lengthv(tmp1) - lengthv(tmp2));
954 
955 						float		cSr		=	shadingRate*isqrtf(dx*dx + dy*dy + dz*dz);
956 						if (cSr > MAX_DIFFERENTIAL_DISCREPANCY)	cSr	=	MAX_DIFFERENTIAL_DISCREPANCY;
957 						d		=	cSr*(cU[1] - cU[0]);
958 						d		=	min(d,1);
959 						d		=	max(d,C_EPSILON);
960 						assert(d > 0);
961 						assert(d <= 1);
962 						cDU[0]	=	d;
963 						cDU		+=	1;
964 						cU		+=	1;
965 						P		+=	3;
966 						cXy		+=	2;
967 					}
968 
969 					extrapolateDerivU();
970 
971 					cDU[0]		=	d;
972 				}
973 
974 				// Compute the dv,dPdv
975 				for (i=0;i<uVertices;i++) {
976 					float		*cDV	=	dv	+	i;
977 					const float	*cV		=	v	+	i;
978 					float		*cXy	=	xy	+	i*2;
979 					float		d		=	0;
980 
981 					P				=	varying[VARIABLE_P]		+	i*3;
982 					for (j=0;j<vVertices-1;j++) {
983 						initv(tmp1,cXy[uVertices*2]-P[uVertices*3+0],cXy[uVertices*2+1]-P[uVertices*3+1],P[uVertices*3+2]-1);
984 						initv(tmp2,cXy[0]-P[0],cXy[1]-P[1],P[2]-1);
985 
986 						const float	dx		=	maxdPixeldxy*(cXy[uVertices*2]		- cXy[0]);
987 						const float	dy		=	maxdPixeldxy*(cXy[uVertices*2+1]	- cXy[1]);
988 						const float	dz		=	maxdPixeldxy*(lengthv(tmp1) - lengthv(tmp2));
989 
990 						float		cSr		=	shadingRate*isqrtf(dx*dx + dy*dy + dz*dz);
991 						if (cSr > MAX_DIFFERENTIAL_DISCREPANCY)	cSr	=	MAX_DIFFERENTIAL_DISCREPANCY;
992 						d		=	cSr*(cV[uVertices] - cV[0]);
993 						d		=	max(d,C_EPSILON);
994 						d		=	min(d,1);
995 						assert(d > 0);
996 						assert(d <= 1);
997 						cDV[0]	=	d;
998 						cDV		+=	uVertices;
999 						cV		+=	uVertices;
1000 						P		+=	uVertices*3;
1001 						cXy		+=	uVertices*2;
1002 					}
1003 
1004 					extrapolateDerivV();
1005 
1006 					cDV[0]		=	d;
1007 				}
1008 			}
1009 
1010 			#undef MAX_DIFFERENTIAL_DISCREPANCY
1011 			#undef extrapolateDerivU
1012 			#undef extrapolateDerivV
1013 
1014 			// Done and done
1015 			memEnd(threadMemory);
1016 		}
1017 	} else {
1018 		// No derivative information is needed
1019 		currentShadingState->shadingDim			=	dim;
1020 		currentShadingState->numRealVertices	=	numVertices;
1021 		currentShadingState->numActive			=	numVertices;
1022 		currentShadingState->numPassive			=	0;
1023 
1024 		// Sample the object
1025 		object->sample(0,numVertices,varying,locals,usedParameters);
1026 
1027 		// Interpolate the various variables defined on the object
1028 		object->interpolate(numVertices,varying,locals);
1029 
1030 		// Compute the I
1031 		if (currentRayDepth == 0) {
1032 			if (CRenderer::projection == OPTIONS_PROJECTION_PERSPECTIVE) {
1033 				memcpy(varying[VARIABLE_I],varying[VARIABLE_P],numVertices*3*sizeof(float));
1034 			} else {
1035 				float		*I	=	varying[VARIABLE_I];
1036 				const float	*P	=	varying[VARIABLE_P];
1037 				for (i=numVertices;i>0;i--,I+=3,P+=3)	initv(I,0,0,P[COMP_Z]);
1038 			}
1039 		}
1040 	}
1041 
1042 	// Clear the tags for shader execution
1043 	memset(currentShadingState->tags,0,numVertices*sizeof(int));
1044 
1045 	// Fill in the uninitialized variables from the attributes
1046 	if (currentAttributes->next != NULL) {
1047 		complete(numVertices,varying,usedParameters,currentAttributes,currentAttributes->next);
1048 	} else {
1049 		complete(numVertices,varying,usedParameters,currentAttributes);
1050 	}
1051 
1052 	// Save the memory here
1053 	memBegin(threadMemory);
1054 
1055 	// Set up lighting here incase displacement shader uses lighting
1056 
1057 	// No lights are executed yet
1058 	currentShadingState->lightsExecuted			=	FALSE;
1059 	currentShadingState->ambientLightsExecuted	=	FALSE;
1060 	currentShadingState->lightCategory			=	0;
1061 
1062 	// Clear out previous lights etc
1063 	currentShadingState->lights					=	NULL;
1064 	currentShadingState->alights				=	NULL;
1065 	currentShadingState->currentLight			=	NULL;
1066 	currentShadingState->freeLights				=	NULL;
1067 
1068 	// Run the displacement shader here
1069 	if (displacement != NULL) {
1070 		displacement->execute(this,locals[ACCESSOR_DISPLACEMENT]);
1071 	}
1072 
1073 	// Do we need to run the surface shader?
1074 	if (displaceOnly == FALSE) {
1075 
1076 		// Is there a surface shader ?
1077 		if (surface != NULL) {
1078 			numShaded				+=	numVertices;
1079 			surface->execute(this,locals[ACCESSOR_SURFACE]);
1080 		} else {
1081 			// No surface shader eh, make up a color
1082 
1083 
1084 			// Overwrite the colors if not specified by the primitives
1085 			if (usedParameters & PARAMETER_CS)	{
1086 				const float		*Cs		=	currentAttributes->surfaceColor;
1087 				float			*C		=	varying[VARIABLE_CI];
1088 				for (i=numVertices;i>0;i--,C+=3)	movvv(C,Cs);
1089 			}
1090 
1091 			// Overwrite the opacity if not specified by the primitive
1092 			if (usedParameters & PARAMETER_OS)	{
1093 				const float		*Os		=	currentAttributes->surfaceOpacity;
1094 				float			*O		=	varying[VARIABLE_OI];
1095 				for (i=numVertices;i>0;i--,O+=3)	movvv(O,Os);
1096 			}
1097 
1098 			// Get the variables
1099 			float			*C		=	varying[VARIABLE_CI];
1100 			float			*N		=	varying[VARIABLE_N];
1101 			float			*I		=	varying[VARIABLE_I];
1102 
1103 			// Do a simple dot product shading here
1104 			for (i=numVertices;i>0;i--) {
1105 				normalizevf(N);
1106 				normalizevf(I);
1107 
1108 				mulvf(C,absf(dotvv(I,N)));
1109 				C	+=	3;
1110 				N	+=	3;
1111 				I	+=	3;
1112 			}
1113 		}
1114 
1115 		// Is there an atmosphere shader ?
1116 		if (atmosphere != NULL) {
1117 
1118 			// Do not execute atmosphere for non-camera rays
1119 			if (currentRayDepth == 0) {
1120 				atmosphere->execute(this,locals[ACCESSOR_ATMOSPHERE]);
1121 			}
1122 		}
1123 
1124 		// Is there an interior/exterior shader waiting to be executed?
1125 		if (currentShadingState->postShader != NULL) {
1126 			locals[ACCESSOR_POSTSHADER]		=	currentShadingState->postShader->prepare(shaderStateMemory,varying,numVertices);
1127 			currentShadingState->postShader->execute(this,locals[ACCESSOR_POSTSHADER]);
1128 		}
1129 	}
1130 
1131 
1132 	// Check if we should are a camera ray, and have primitive hit mode
1133 	if ((dim == SHADING_2D_GRID) && (currentAttributes->cameraHitMode == 'p')) {
1134 		// Yes, force opacity 1
1135 		float			*opacity	=	varying[VARIABLE_OI];
1136 		const	float	*so			=	currentAttributes->surfaceOpacity;
1137 		int				i;
1138 
1139 		for (i=numVertices;i>0;i--,opacity+=3) movvv(opacity,so);
1140 	}
1141 
1142 	// Restore the thread memory
1143 	memEnd(threadMemory);
1144 
1145 	// Unwind the stack of shader states
1146 	memEnd(shaderStateMemory);
1147 
1148 	// Restore the shaded object
1149 	currentShadingState->currentObject	=	savedObject;
1150 }
1151 
1152 
1153 
1154 
1155 
1156 
1157 
1158 
1159 
1160 
1161 
1162 ///////////////////////////////////////////////////////////////////////
1163 // Class				:	CShadingContext
1164 // Method				:	newState
1165 // Description			:	Allocate a new shading state
1166 // Return Value			:	-
1167 // Comments				:
1168 CShadingState	*CShadingContext::newState() {
1169 
1170 	if (freeStates == NULL) {
1171 		CShadingState	*newState			=	new CShadingState;
1172 		int				j;
1173 		float			*E;
1174 		const int		numGlobalVariables	=	CRenderer::globalVariables->numItems;
1175 		CVariable		**globalVariables	=	CRenderer::globalVariables->array;
1176 
1177 		newState->varying				=	new float*[numGlobalVariables];					vertexMemory	+=	numGlobalVariables*sizeof(float *);
1178 		newState->tags					=	new int[CRenderer::maxGridSize*3];				vertexMemory	+=	CRenderer::maxGridSize*3*sizeof(int);
1179 		newState->lightingTags			=	new int[CRenderer::maxGridSize*3];				vertexMemory	+=	CRenderer::maxGridSize*3*sizeof(int);
1180 		newState->Ns					=	new float[CRenderer::maxGridSize*9];			vertexMemory	+=	CRenderer::maxGridSize*9*sizeof(float);
1181 		newState->alights				=	NULL;
1182 		newState->freeLights			=	NULL;
1183 		newState->postShader			=	NULL;
1184 		newState->currentObject			=	NULL;
1185 
1186 		for (j=0;j<numGlobalVariables;j++) {
1187 			const	CVariable	*var	=	globalVariables[j];
1188 
1189 			assert(var != NULL);
1190 
1191 			if (	(var->container == CONTAINER_UNIFORM) || (var->container == CONTAINER_CONSTANT)	) {
1192 				if (var->type == TYPE_STRING) {
1193 					newState->varying[j]	=	(float*) new char*[var->numFloats];
1194 					vertexMemory			+=	var->numFloats*sizeof(char*);
1195 				} else {
1196 					newState->varying[j]	=	new float[var->numFloats];
1197 					vertexMemory			+=	var->numFloats*sizeof(float);
1198 				}
1199 			} else {
1200 				if (var->type == TYPE_STRING) {
1201 					newState->varying[j]	=	(float*) new char*[var->numFloats*CRenderer::maxGridSize*3];
1202 					vertexMemory			+=	var->numFloats*CRenderer::maxGridSize*3*sizeof(char*);
1203 				} else {
1204 					newState->varying[j]	=	new float[var->numFloats*CRenderer::maxGridSize*3];
1205 					vertexMemory			+=	var->numFloats*CRenderer::maxGridSize*3*sizeof(float);
1206 				}
1207 			}
1208 		}
1209 
1210 		// E is always (0,0,0)
1211 		E	=	newState->varying[VARIABLE_E];
1212 		for (j=CRenderer::maxGridSize*3;j>0;j--,E+=3)	initv(E,0,0,0);
1213 
1214 		if (vertexMemory > peakVertexMemory)	peakVertexMemory=	vertexMemory;
1215 
1216 		newState->next				=	NULL;
1217 		return	newState;
1218 	} else {
1219 		CShadingState	*newState	=	freeStates;
1220 		freeStates					=	newState->next;
1221 
1222 		return newState;
1223 	}
1224 }
1225 
1226 ///////////////////////////////////////////////////////////////////////
1227 // Class				:	CShadingContext
1228 // Method				:	newState
1229 // Description			:	Allocate a new shading state
1230 // Return Value			:	-
1231 // Comments				:
1232 void				CShadingContext::deleteState(CShadingState *cState) {
1233 	cState->next	=	freeStates;
1234 	freeStates		=	cState;
1235 }
1236 
1237 
1238 ///////////////////////////////////////////////////////////////////////
1239 // Class				:	CShadingContext
1240 // Method				:	freeState
1241 // Description			:	Ditch a shading state
1242 // Return Value			:	-
1243 // Comments				:
1244 void			CShadingContext::freeState(CShadingState *cState) {
1245 	int			j;
1246 	const int	numGlobalVariables	=	CRenderer::globalVariables->numItems;
1247 	CVariable	**globalVariables	=	CRenderer::globalVariables->array;
1248 
1249 	for (j=0;j<numGlobalVariables;j++) {
1250 		const CVariable	*var	=	globalVariables[j];
1251 
1252 		if (	(var->container == CONTAINER_UNIFORM) || (var->container == CONTAINER_CONSTANT)	) {
1253 			delete [] cState->varying[j];
1254 			vertexMemory		-=	var->numFloats*sizeof(float);
1255 		} else {
1256 			delete [] cState->varying[j];
1257 			vertexMemory		-=	var->numFloats*CRenderer::maxGridSize*3*sizeof(float);
1258 		}
1259 	}
1260 
1261 	delete [] cState->varying;					vertexMemory	-=	numGlobalVariables*sizeof(float *);
1262 	delete [] cState->tags;						vertexMemory	-=	CRenderer::maxGridSize*3*sizeof(int);
1263 	delete [] cState->lightingTags;				vertexMemory	-=	CRenderer::maxGridSize*3*sizeof(int);
1264 	delete [] cState->Ns;						vertexMemory	-=	CRenderer::maxGridSize*9*sizeof(float);
1265 
1266 	delete cState;
1267 }
1268 
1269 
1270 
1271 
1272 
1273 
1274 
1275 ///////////////////////////////////////////////////////////////////////
1276 // Class				:	CShadingContext
1277 // Method				:	variableUpdate
1278 // Description			:	This function is called to signal that there has been
1279 //							a modification on the set of active variables
1280 // Return Value			:	-
1281 // Comments				:
1282 void		CShadingContext::updateState() {
1283 	CShadingState	*cState;
1284 
1285 	// Ditch the shading states that have been allocated
1286 	while ((cState=freeStates) != NULL) {
1287 		freeStates	=	cState->next;
1288 		freeState(cState);
1289 	}
1290 
1291 	// Recreate
1292 	if (currentShadingState != NULL)	freeState(currentShadingState);
1293 
1294 	currentShadingState	=	NULL;
1295 	currentShadingState	=	newState();
1296 }
1297 
1298 ///////////////////////////////////////////////////////////////////////
1299 // Class				:	CShadingContext
1300 // Method				:	saveState
1301 // Description			:	Save the shading state so a nested tesselation
1302 //							doesn't trash our variables
1303 // Return Value			:	an opaque shading state reference
1304 // Comments				:
1305 void	*CShadingContext::saveState() {
1306 	CShadingState	*savedState		=	currentShadingState;
1307 	if (freeStates == NULL)			freeStates	=	newState();
1308 
1309 	currentShadingState				=	freeStates;
1310 	freeStates						=	currentShadingState->next;
1311 
1312 	return (void*) savedState;
1313 }
1314 
1315 ///////////////////////////////////////////////////////////////////////
1316 // Class				:	CShadingContext
1317 // Method				:	restoreState
1318 // Description			:	Restore the shading state from a previous save
1319 // Return Value			:	-
1320 // Comments				:
1321 void	CShadingContext::restoreState(void *state) {
1322 	CShadingState	*savedState		=	(CShadingState*) state;
1323 
1324 	currentShadingState->next		=	freeStates;
1325 	freeStates						=	currentShadingState;
1326 
1327 	currentShadingState				=	savedState;
1328 }
1329 
1330 
1331 ///////////////////////////////////////////////////////////////////////
1332 // Class				:	CShadingContext
1333 // Method				:	surfaceParameter
1334 // Description			:	Execute light sources
1335 // Return Value			:	-
1336 // Comments				:
1337 int		CShadingContext::surfaceParameter(void *dest,const char *name,CVariable **var,int *globalIndex) {
1338 	const CAttributes	*currentAttributes	=	currentShadingState->currentObject->attributes;
1339 
1340 	if (currentAttributes->surface != NULL)
1341 		return currentAttributes->surface->getParameter(name,dest,var,globalIndex);
1342 	return FALSE;
1343 }
1344 
1345 ///////////////////////////////////////////////////////////////////////
1346 // Class				:	CShadingContext
1347 // Method				:	displacementParameter
1348 // Description			:	Execute light sources
1349 // Return Value			:	-
1350 // Comments				:
1351 int		CShadingContext::displacementParameter(void *dest,const char *name,CVariable **var,int *globalIndex) {
1352 	const CAttributes	*currentAttributes	=	currentShadingState->currentObject->attributes;
1353 
1354 	if (currentAttributes->displacement != NULL)
1355 		return currentAttributes->displacement->getParameter(name,dest,var,globalIndex);
1356 	return FALSE;
1357 }
1358 
1359 
1360 ///////////////////////////////////////////////////////////////////////
1361 // Class				:	CShadingContext
1362 // Method				:	atmosphereParameter
1363 // Description			:	Execute light sources
1364 // Return Value			:	-
1365 // Comments				:
1366 int		CShadingContext::atmosphereParameter(void *dest,const char *name,CVariable **var,int *globalIndex) {
1367 	const CAttributes	*currentAttributes	=	currentShadingState->currentObject->attributes;
1368 
1369 	if (currentAttributes->atmosphere != NULL)
1370 		return currentAttributes->atmosphere->getParameter(name,dest,var,globalIndex);
1371 	return FALSE;
1372 }
1373 
1374 ///////////////////////////////////////////////////////////////////////
1375 // Class				:	CShadingContext
1376 // Method				:	incidentParameter
1377 // Description			:	Execute light sources
1378 // Return Value			:	-
1379 // Comments				:
1380 int		CShadingContext::incidentParameter(void *dest,const char *name,CVariable **var,int *globalIndex) {
1381 	const CAttributes	*currentAttributes	=	currentShadingState->currentObject->attributes;
1382 
1383 	if (currentAttributes->interior != NULL)
1384 		return currentAttributes->interior->getParameter(name,dest,NULL,NULL);	// skip mutable parameters
1385 	return FALSE;
1386 }
1387 
1388 ///////////////////////////////////////////////////////////////////////
1389 // Class				:	CShadingContext
1390 // Method				:	oppositeParameter
1391 // Description			:	Execute light sources
1392 // Return Value			:	-
1393 // Comments				:
1394 int		CShadingContext::oppositeParameter(void *dest,const char *name,CVariable **var,int *globalIndex) {
1395 	const CAttributes	*currentAttributes	=	currentShadingState->currentObject->attributes;
1396 
1397 	if (currentAttributes->exterior != NULL)
1398 		return currentAttributes->exterior->getParameter(name,dest,NULL,NULL);	// skip mutable parameters
1399 	return FALSE;
1400 }
1401 
1402 ///////////////////////////////////////////////////////////////////////
1403 // Class				:	CShadingContext
1404 // Method				:	options
1405 // Description			:	Execute light sources
1406 // Return Value			:	-
1407 // Comments				:
1408 int		CShadingContext::options(void *dest,const char *name,CVariable **,int *) {
1409 	if (strcmp(name,optionsFormat) == 0) {
1410 		float	*d	=	(float *) dest;
1411 		d[0]		=	(float) CRenderer::xres;
1412 		d[1]		=	(float) CRenderer::yres;
1413 		d[2]		=	(float) 1;
1414 		return TRUE;
1415 	} else if (strcmp(name,optionsDeviceFrame) == 0) {
1416 		float	*d	=	(float *) dest;
1417 		d[0]		=	(float) CRenderer::frame;
1418 		return TRUE;
1419 	} else if (strcmp(name,optionsDeviceResolution) == 0) {
1420 		float	*d	=	(float *) dest;
1421 		d[0]		=	(float) CRenderer::xres;
1422 		d[1]		=	(float) CRenderer::yres;
1423 		d[2]		=	(float) 1;
1424 		return TRUE;
1425 	} else if (strcmp(name,optionsFrameAspectRatio) == 0) {
1426 		float	*d	=	(float *) dest;
1427 		d[0]		=	(float) CRenderer::frameAR;
1428 		return TRUE;
1429 	} else if (strcmp(name,optionsCropWindow) == 0) {
1430 		float	*d	=	(float *) dest;
1431 		d[0]		=	(float) CRenderer::cropLeft;
1432 		d[1]		=	(float) CRenderer::cropTop;
1433 		d[2]		=	(float) CRenderer::cropRight;
1434 		d[3]		=	(float) CRenderer::cropBottom;
1435 		return TRUE;
1436 	} else if (strcmp(name,optionsDepthOfField) == 0) {
1437 		float	*d	=	(float *) dest;
1438 		d[0]		=	(float) CRenderer::fstop;
1439 		d[1]		=	(float) CRenderer::focallength;
1440 		d[2]		=	(float) CRenderer::focaldistance;
1441 		return TRUE;
1442 	} else if (strcmp(name,optionsShutter) == 0) {
1443 		float	*d	=	(float *) dest;
1444 		d[0]		=	(float) CRenderer::shutterOpen;
1445 		d[1]		=	(float) CRenderer::shutterClose;
1446 		return TRUE;
1447 	} else if (strcmp(name,optionsClipping) == 0) {
1448 		float	*d	=	(float *) dest;
1449 		d[0]		=	(float) CRenderer::clipMin;
1450 		d[1]		=	(float) CRenderer::clipMax;
1451 		return TRUE;
1452 	} else if (strcmp(name,optionsBucketSize) == 0) {
1453 		float	*d	=	(float *) dest;
1454 		d[0]		=	(float) CRenderer::bucketWidth;
1455 		d[1]		=	(float) CRenderer::bucketHeight;
1456 		return TRUE;
1457 	} else if (strcmp(name,optionsColorQuantizer) == 0) {
1458 		float	*d	=	(float *) dest;
1459 		d[0]		=	(float) CRenderer::colorQuantizer[0];
1460 		d[1]		=	(float) CRenderer::colorQuantizer[1];
1461 		d[2]		=	(float) CRenderer::colorQuantizer[2];
1462 		d[3]		=	(float) CRenderer::colorQuantizer[3];
1463 		return TRUE;
1464 	} else if (strcmp(name,optionsDepthQuantizer) == 0) {
1465 		float	*d	=	(float *) dest;
1466 		d[0]		=	(float) CRenderer::depthQuantizer[0];
1467 		d[1]		=	(float) CRenderer::depthQuantizer[1];
1468 		d[2]		=	(float) CRenderer::depthQuantizer[2];
1469 		d[3]		=	(float) CRenderer::depthQuantizer[3];
1470 		return TRUE;
1471 	} else if (strcmp(name,optionsPixelFilter) == 0) {
1472 		float	*d	=	(float *) dest;
1473 		d[0]		=	(float) CRenderer::pixelFilterWidth;
1474 		d[1]		=	(float) CRenderer::pixelFilterHeight;
1475 		return TRUE;
1476 	} else if (strcmp(name,optionsGamma) == 0) {
1477 		float	*d	=	(float *) dest;
1478 		d[0]		=	(float) CRenderer::gamma;
1479 		d[1]		=	(float) CRenderer::gain;
1480 		return TRUE;
1481 	} else if (strcmp(name,optionsMaxRayDepth) == 0) {
1482 		float	*d	=	(float *) dest;
1483 		d[0]		=	(float) CRenderer::maxRayDepth;
1484 		return TRUE;
1485 	} else if (strcmp(name,optionsRelativeDetail) == 0) {
1486 		float	*d	=	(float *) dest;
1487 		d[0]		=	(float) CRenderer::relativeDetail;
1488 		return TRUE;
1489 	} else if (strcmp(name,optionsPixelSamples) == 0) {
1490 		float	*d	=	(float *) dest;
1491 		d[0]		=	(float) CRenderer::pixelXsamples;
1492 		d[1]		=	(float) CRenderer::pixelYsamples;
1493 		return TRUE;
1494 	}
1495 	// User options
1496 	else if (strncmp(name,attributesUser,strlen(attributesUser)) == 0) {
1497 		CVariable *var;
1498 
1499 		if (CRenderer::userOptions->lookup(name+strlen(attributesUser),var) == TRUE) {
1500 			if (var->type == TYPE_STRING) {
1501 				char **d	=	(char **) dest;
1502 				char **s	=	(char **) var->defaultValue;
1503 				for (int i=0;i<var->numFloats;i++) {
1504 					d[i] = s[i];
1505 				}
1506 			} else {
1507 				float	*d	=	(float *) dest;
1508 				memcpy(d,var->defaultValue,sizeof(float)*var->numFloats);
1509 			}
1510 			return TRUE;
1511 		}
1512 	}
1513 
1514 	return FALSE;
1515 }
1516 
1517 ///////////////////////////////////////////////////////////////////////
1518 // Class				:	CShadingContext
1519 // Method				:	attributes
1520 // Description			:	Execute light sources
1521 // Return Value			:	-
1522 // Comments				:
1523 int		CShadingContext::attributes(void *dest,const char *name,CVariable **,int *) {
1524 	const CAttributes	*currentAttributes	=	currentShadingState->currentObject->attributes;
1525 
1526 	if (strcmp(name,attributesShadingRate) == 0) {
1527 		float	*d	=	(float *) dest;
1528 		d[0]		=	(float) currentAttributes->shadingRate;
1529 		return TRUE;
1530 	} else if (strcmp(name,attributesSides) == 0) {
1531 		float	*d	=	(float *) dest;
1532 		d[0]		=	(float) (currentAttributes->flags & ATTRIBUTES_FLAGS_DOUBLE_SIDED ? 2 : 1);
1533 		return TRUE;
1534 	} else if (strcmp(name,attributesMatte) == 0) {
1535 		float	*d	=	(float *) dest;
1536 		d[0]		=	(float) ((currentAttributes->flags & ATTRIBUTES_FLAGS_MATTE) != 0);
1537 		return TRUE;
1538 	} else if (strcmp(name,attributesMotionfactor) == 0) {
1539 		float	*d	=	(float *) dest;
1540 		d[0]		=	(float) currentAttributes->motionFactor;
1541 		return TRUE;
1542 	} else if (strcmp(name,attributesDisplacementBnd) == 0) {
1543 		float	*d	=	(float *) dest;
1544 		d[0]		=	(float) currentAttributes->maxDisplacement;
1545 		return TRUE;
1546 	} else if (strcmp(name,attributesDisplacementSys) == 0) {
1547 		char	**d	=	(char **) dest;
1548 		d[0]		=	currentAttributes->maxDisplacementSpace;
1549 		return TRUE;
1550 	} else if (strcmp(name,attributesName) == 0) {
1551 		char	**d	=	(char **) dest;
1552 		d[0]		=	currentAttributes->name;
1553 		return TRUE;
1554 	}
1555 	// Additional attributes
1556 	else if (strcmp(name,attributesTraceBias) == 0) {
1557 		float	*d	=	(float *) dest;
1558 		d[0]		=	(float) currentAttributes->bias;
1559 		return TRUE;
1560 	} else if (strcmp(name,attributesTraceMaxDiffuse) == 0) {
1561 		float	*d	=	(float *) dest;
1562 		d[0]		=	(float) currentAttributes->maxDiffuseDepth;
1563 		return TRUE;
1564 	} else if (strcmp(name,attributesTraceMaxSpecular) == 0) {
1565 		float	*d	=	(float *) dest;
1566 		d[0]		=	(float) currentAttributes->maxSpecularDepth;
1567 		return TRUE;
1568 	}
1569 	// User attributes
1570 	else if (strncmp(name,attributesUser,strlen(attributesUser)) == 0) {
1571 		CVariable *var;
1572 
1573 		if (currentAttributes->userAttributes.lookup(name+strlen(attributesUser),var) == TRUE) {
1574 			if (var->type == TYPE_STRING) {
1575 				char **d	=	(char **) dest;
1576 				char **s	=	(char **) var->defaultValue;
1577 				for (int i=0;i<var->numFloats;i++) {
1578 					d[i] = s[i];
1579 				}
1580 			} else {
1581 				float	*d	=	(float *) dest;
1582 				memcpy(d,var->defaultValue,sizeof(float)*var->numFloats);
1583 			}
1584 			return TRUE;
1585 		}
1586 	}
1587 
1588 	return FALSE;
1589 }
1590 
1591 
1592 ///////////////////////////////////////////////////////////////////////
1593 // Class				:	CShadingContext
1594 // Method				:	rendererInfo
1595 // Description			:	Execute light sources
1596 // Return Value			:	-
1597 // Comments				:
1598 int		CShadingContext::rendererInfo(void *dest,const char *name,CVariable **,int *) {
1599 
1600 	if (strcmp(name,rendererinfoRenderer) == 0) {
1601 		char	**d	=	(char **) dest;
1602 		d[0]		=	(char *) "Pixie";
1603 		return TRUE;
1604 	} else if (strcmp(name,rendererinfoVersion) == 0) {
1605 		float	*d	=	(float *) dest;
1606 		d[0]		=	(float) VERSION_RELEASE;
1607 		d[1]		=	(float) VERSION_BETA;
1608 		d[2]		=	(float) VERSION_ALPHA;
1609 		d[3]		=	(float) 0;
1610 		return TRUE;
1611 	}
1612 
1613 	return FALSE;
1614 }
1615 
1616 ///////////////////////////////////////////////////////////////////////
1617 // Class				:	CShadingContext
1618 // Method				:	shaderName
1619 // Description			:	Get the name of the shader
1620 // Return Value			:	-
1621 // Comments				:
1622 const char	*CShadingContext::shaderName() {
1623 	assert(currentShadingState->currentShaderInstance != NULL);
1624 
1625 	return currentShadingState->currentShaderInstance->getName();
1626 }
1627 
1628 ///////////////////////////////////////////////////////////////////////
1629 // Class				:	CShadingContext
1630 // Method				:	shaderName
1631 // Description			:	Get the name of a particular shader
1632 // Return Value			:	-
1633 // Comments				:
1634 const char	*CShadingContext::shaderName(const char *type) {
1635 	CAttributes	*currentAttributes	=	currentShadingState->currentObject->attributes;
1636 
1637 	if (strcmp(type,"surface") == 0) {
1638 		if (currentAttributes->surface != NULL)
1639 			return currentAttributes->surface->getName();
1640 	} else if (strcmp(type,"displacement") == 0) {
1641 		if (currentAttributes->displacement != NULL)
1642 			return currentAttributes->displacement->getName();
1643 	} else if (strcmp(type,"atmosphere") == 0) {
1644 		if (currentAttributes->atmosphere != NULL)
1645 			return currentAttributes->atmosphere->getName();
1646 	} else if (strcmp(type,"interior") == 0) {
1647 		if (currentAttributes->interior != NULL)
1648 			return currentAttributes->interior->getName();
1649 	} else if (strcmp(type,"exterior") == 0) {
1650 		if (currentAttributes->exterior != NULL)
1651 			return currentAttributes->exterior->getName();
1652 	} else if (strcmp(type,"lightsource") == 0) {
1653 		if (currentShadingState->currentLight != NULL)
1654 			return currentShadingState->currentLight->instance->getName();
1655 	}
1656 	return "";
1657 }
1658 
1659 
1660 ///////////////////////////////////////////////////////////////////////
1661 // Class				:	CShadingContext
1662 // Method				:	findCoordinateSystem
1663 // Description			:	Locate a coordinate system
1664 // Return Value			:	-
1665 // Comments				:	Sometimes we just don't care about what system it is
1666 void		CShadingContext::findCoordinateSystem(const char *name,const float *&from,const float *&to) {
1667 	ECoordinateSystem	dummy;
1668 
1669 	findCoordinateSystem(name,from,to,dummy);
1670 }
1671 
1672 ///////////////////////////////////////////////////////////////////////
1673 // Class				:	CShadingContext
1674 // Method				:	findCoordinateSystem
1675 // Description			:	Locate a coordinate system
1676 // Return Value			:	-
1677 // Comments				:
1678 void		CShadingContext::findCoordinateSystem(const char *name,const float *&from,const float *&to,ECoordinateSystem &cSystem) {
1679 	CNamedCoordinateSystem	*currentSystem;
1680 
1681 	if(CRenderer::definedCoordinateSystems->find(name,currentSystem)) {
1682 		from		=	currentSystem->from;
1683 		to			=	currentSystem->to;
1684 		cSystem		=	currentSystem->systemType;
1685 
1686 		switch(currentSystem->systemType) {
1687 		case COORDINATE_OBJECT:
1688 			if (currentShadingState->currentObject == NULL) {
1689 				error(CODE_SYSTEM,"Object system reference without an object\n");
1690 				from		=	identityMatrix;
1691 				to			=	identityMatrix;
1692 			} else {
1693 				from		=	currentShadingState->currentObject->xform->from;
1694 				to			=	currentShadingState->currentObject->xform->to;
1695 			}
1696 			break;
1697 		case COORDINATE_CAMERA:
1698 			from		=	identityMatrix;
1699 			to			=	identityMatrix;
1700 			break;
1701 		case COORDINATE_WORLD:
1702 			from		=	CRenderer::fromWorld;
1703 			to			=	CRenderer::toWorld;
1704 			break;
1705 		case COORDINATE_SHADER:
1706 			assert(currentShadingState->currentShaderInstance != NULL);
1707 
1708 			from		=	currentShadingState->currentShaderInstance->xform->from;
1709 			to			=	currentShadingState->currentShaderInstance->xform->to;
1710 			break;
1711 		case COORDINATE_LIGHT:
1712 			assert(currentShadingState->currentLightInstance != NULL);
1713 
1714 			from		=	currentShadingState->currentLightInstance->xform->from;
1715 			to			=	currentShadingState->currentLightInstance->xform->to;
1716 			break;
1717 		case COORDINATE_NDC:
1718 			from		=	CRenderer::fromNDC;
1719 			to			=	CRenderer::toNDC;
1720 			break;
1721 		case COORDINATE_RASTER:
1722 			from		=	CRenderer::fromRaster;
1723 			to			=	CRenderer::toRaster;
1724 			break;
1725 		case COORDINATE_SCREEN:
1726 			from		=	CRenderer::fromScreen;
1727 			to			=	CRenderer::toScreen;
1728 			break;
1729 		case COORDINATE_CURRENT:
1730 			from		=	identityMatrix;
1731 			to			=	identityMatrix;
1732 			break;
1733 		case COLOR_RGB:
1734 		case COLOR_HSL:
1735 		case COLOR_HSV:
1736 		case COLOR_XYZ:
1737 		case COLOR_CIE:
1738 		case COLOR_YIQ:
1739 		case COLOR_XYY:
1740 			// Don't handle color, the custom must have been handled
1741 			break;
1742 		case COORDINATE_CUSTOM:
1743 			// Don't handle color, the custom must have been handled
1744 			from		=	currentSystem->from;
1745 			to			=	currentSystem->to;
1746 			break;
1747 		default:
1748 			warning(CODE_BUG,"Unknown coordinate system: %s\n",name);
1749 			from		=	identityMatrix;
1750 			to			=	identityMatrix;
1751 			break;
1752 		}
1753 	} else {
1754 		warning(CODE_BUG,"Unknown coordinate system: %s\n",name);
1755 		from	=	identityMatrix;
1756 		to		=	identityMatrix;
1757 	}
1758 }
1759 
1760 
1761 
1762 
1763 
1764 
1765 
1766 
1767 
1768 
1769 //Period parameters
1770 #define N 624
1771 #define M 397
1772 #define MATRIX_A 0x9908b0dfUL	//constant vector a
1773 #define UMASK 0x80000000UL		//most significant w-r bits
1774 #define LMASK 0x7fffffffUL		//least significant r bits
1775 #define MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
1776 #define TWIST(u,v) ((MIXBITS(u,v) >> 1) ^ (_uTable[v & 1UL] ))
1777 
1778 
1779 ///////////////////////////////////////////////////////////////////////
1780 // Class				:	CShadingContext
1781 // Method				:	randomInit
1782 // Description			:	Init the random number generator
1783 // Return Value			:	-
1784 // Comments				:
1785 void			CShadingContext::randomInit(uint32_t s) {
1786     int j;
1787     state[0]= s & 0xffffffffUL;
1788     for (j=1; j<N; j++) {
1789         state[j] = (1812433253UL * (state[j-1] ^ (state[j-1] >> 30)) + j);
1790         state[j] &= 0xffffffffUL;  /* for >32 bit machines */
1791     }
1792     next = state;
1793     return;
1794 }
1795 
1796 ///////////////////////////////////////////////////////////////////////
1797 // Class				:	CShadingContext
1798 // Method				:	randomShutdown
1799 // Description			:	Shutdown the random number generator
1800 // Return Value			:	-
1801 // Comments				:
1802 void			CShadingContext::randomShutdown() {
1803 }
1804 
1805 ///////////////////////////////////////////////////////////////////////
1806 // Class				:	CShadingContext
1807 // Method				:	next_state
1808 // Description			:	Get the next stage for the random number generator
1809 // Return Value			:	-
1810 // Comments				:
1811 void			CShadingContext::next_state() {
1812     static const uint32_t _uTable[2] = { 0UL, MATRIX_A };
1813     register signed int j;
1814 
1815     register uint32_t *p0;
1816     register uint32_t *p1;
1817 
1818     j = ( N-M ) >> 1;
1819     p0 = state;
1820     p1 = p0 + 1;
1821     while(j) {
1822        --j;
1823         *p0 = TWIST( *p0, *p1 );
1824 		*p0 ^= p0[M];
1825 		++p1;
1826 		++p0;
1827 
1828 		*p0 = TWIST( *p0, *p1 );
1829 		*p0 ^= p0[M];
1830 		++p1;
1831 		++p0;
1832     }
1833 
1834     *p0 = TWIST( *p0, *p1);
1835     *p0 ^= p0[M];
1836     ++p1;
1837     ++p0;
1838 
1839     j = (M-1) >> 1;
1840     while( j ) {
1841        --j;
1842        *p0 = TWIST( *p0, *p1 );
1843        *p0 ^= p0[M-N];
1844        ++p1;
1845        ++p0;
1846 
1847        *p0 = TWIST( *p0, *p1 );
1848        *p0 ^= p0[M-N];
1849        ++p1;
1850        ++p0;
1851     }
1852     *p0 = TWIST( *p0, *state );
1853     *p0 ^= p0[M-N];
1854 
1855     next = state + N;
1856     return;
1857 }
1858 
1859