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				:	executeMisc.cpp
27 //  Classes				:	-
28 //  Description			:	This file implements the main shader execution
29 //
30 ////////////////////////////////////////////////////////////////////////
31 #include <math.h>
32 #include <float.h>
33 
34 #include "common/global.h"
35 #include "bundles.h"
36 #include "memory.h"
37 #include "attributes.h"
38 #include "renderer.h"
39 #include "stats.h"
40 #include "surface.h"
41 #include "ri_config.h"
42 
43 ///////////////////////////////////////////////////////////////////////////////////////////////////
44 //
45 //	Misc. derivative functions
46 //
47 ///////////////////////////////////////////////////////////////////////////////////////////////////
48 
49 
50 ///////////////////////////////////////////////////////////////////////
51 // Class				:	CShadingContext
52 // Method				:	duFloat
53 // Description			:	Compute the u derivative
54 // Return Value			:	-
55 // Comments				:
duFloat(float * dest,const float * src)56 void	CShadingContext::duFloat(float *dest,const float *src) {
57 	switch(currentShadingState->shadingDim) {
58 
59 
60 		// Du executing on Points or Curves (note that curves are defined along v)
61 		case SHADING_0D:
62 		{
63 			for (int j=currentShadingState->numVertices;j>0;--j) {
64 				*dest++ = 0;
65 			}
66 		}
67 		break;
68 
69 
70 		// Du executing on a 2D grid
71 		case SHADING_2D_GRID:
72 		{
73 			const int	uVertices	=	currentShadingState->numUvertices;
74 			const int	vVertices	=	currentShadingState->numVvertices;
75 			const float	*u			=	currentShadingState->varying[VARIABLE_U];
76 
77 			assert(uVertices >= 2);
78 			assert(vVertices >= 2);
79 			assert(u[1] > u[0]);
80 
81 			// These values are constant accross a grid
82 			const double	invDu1		=	1.0 / ((double)u[1] - (double)u[0]);
83 			const double	invDu2		=	1.0 / (2.0*((double)u[1] - (double)u[0]));
84 
85 			// Compute the Du
86 			for (int j=vVertices;j>0;--j) {
87 
88 				// Forward differencing
89 				*dest++	=	(float) (((double)src[1] - (double)src[0]) * invDu1);
90 				++src;
91 
92 				// Central differencing
93 				for (int i=uVertices-2;i>0;--i) {
94 					*dest++	=	(float) (((double)src[1] - (double)src[-1]) * invDu2);
95 					++src;
96 				}
97 
98 				// Backward differencing
99 				*dest++	=	(float) (((double)src[0] - (double)src[-1]) * invDu1);
100 				++src;
101 			}
102 		}
103 		break;
104 
105 
106 		// Du executing on a 2D raytraced surface
107 		case SHADING_2D:
108 		{
109 			const int	numRealVertices	=	currentShadingState->numRealVertices;
110 			const float	*dsrc			=	src + numRealVertices;
111 			float		*ddest			=	dest + numRealVertices;
112 			const float	*du				=	currentShadingState->varying[VARIABLE_DU];
113 
114 			for (int i=numRealVertices;i>0;--i) {
115 
116 				assert(*du != 0);
117 
118 				const float	val	=	(float) (((double)dsrc[0] - (double)src[0]) / ((double)*du++));
119 
120 				ddest[0]		=	val;
121 				ddest[1]		=	val;
122 				dest[0]			=	val;
123 
124 				dest++;
125 				src++;
126 				ddest			+=	2;
127 				dsrc			+=	2;
128 			}
129 		}
130 		break;
131 	}
132 }
133 
134 
135 ///////////////////////////////////////////////////////////////////////
136 // Class				:	CShadingContext
137 // Method				:	DuFloat
138 // Description			:	Compute the u differences
139 // Return Value			:	-
140 // Comments				:
DuFloat(float * dest,const float * src)141 void	CShadingContext::DuFloat(float *dest,const float *src) {
142 	switch(currentShadingState->shadingDim) {
143 
144 
145 		// Du executing on Points or Curves (note that curves are defined along v)
146 		case SHADING_0D:
147 		{
148 			for (int j=currentShadingState->numVertices;j>0;--j) {
149 				*dest++ = 0;
150 			}
151 		}
152 		break;
153 
154 
155 		// Du executing on a 2D grid
156 		case SHADING_2D_GRID:
157 		{
158 			const int	uVertices	=	currentShadingState->numUvertices;
159 			const int	vVertices	=	currentShadingState->numVvertices;
160 
161 			assert(uVertices >= 2);
162 			assert(vVertices >= 2);
163 
164 			// Compute the Du
165 			for (int j=vVertices;j>0;--j) {
166 
167 				// Forward differencing
168 				*dest++	=	(float) ((double)src[1] - (double)src[0]);
169 				src++;
170 
171 				// Central differencing
172 				for (int i=uVertices-2;i>0;--i) {
173 					*dest++	=	(float) (((double)src[1] - (double)src[-1]) * 0.5);
174 					src++;
175 				}
176 
177 				// Backward differencing
178 				*dest++	=	(float) ((double)src[0] - (double)src[-1]);
179 				src++;
180 			}
181 		}
182 		break;
183 
184 
185 		// Du executing on a 2D raytraced surface
186 		case SHADING_2D:
187 		{
188 			const int	numRealVertices	=	currentShadingState->numRealVertices;
189 			const float	*dsrc			=	src + numRealVertices;
190 			float		*ddest			=	dest + numRealVertices;
191 
192 			for (int i=numRealVertices;i>0;--i) {
193 
194 				const float	val	=	(float) ((double)dsrc[0] - (double)src[0]);
195 
196 				ddest[0]		=	val;
197 				ddest[1]		=	val;
198 				dest[0]			=	val;
199 
200 				dest++;
201 				src++;
202 				ddest			+=	2;
203 				dsrc			+=	2;
204 			}
205 		}
206 		break;
207 	}
208 }
209 
210 
211 
212 
213 ///////////////////////////////////////////////////////////////////////
214 // Class				:	CShadingContext
215 // Method				:	dvFloat
216 // Description			:	Compute the v derivatives
217 // Return Value			:	-
218 // Comments				:
dvFloat(float * dest,const float * src)219 void	CShadingContext::dvFloat(float *dest,const float *src) {
220 
221 	switch(currentShadingState->shadingDim) {
222 
223 		// Dv executing on Points
224 		case SHADING_0D:
225 		{
226 			for (int i=currentShadingState->numVertices;i>0;--i) {
227 				*dest++	=	0;
228 			}
229 		}
230 		break;
231 
232 
233 		// Dv executing on a 2D grid
234 		case SHADING_2D_GRID:
235 		{
236 			const int		uVertices	=	currentShadingState->numUvertices;
237 			const int		vVertices	=	currentShadingState->numVvertices;
238 			const float		*v			=	currentShadingState->varying[VARIABLE_V];
239 
240 			assert(uVertices >= 2);
241 			assert(vVertices >= 2);
242 			assert(v[uVertices] > v[0]);
243 
244 			const double	invDv1		=	1.0 / ((double)v[uVertices] - (double)v[0]);
245 			const double	invDv2		=	1.0 / (2.0*((double)v[uVertices] - (double)v[0]));
246 
247 			// Compute the DV
248 			for (int j=0;j<uVertices;++j) {
249 				float		*cRes	=	dest + j;
250 				const float	*cOp	=	src + j;
251 
252 				// Forward differencing
253 				cRes[0]				=	(float) ((double)(cOp[uVertices] - (double)cOp[0]) * invDv1);
254 				cRes				+=	uVertices;
255 				cOp					+=	uVertices;
256 
257 				// Central differencing
258 				for (int i=vVertices-2;i>0;--i) {
259 					cRes[0]			=	(float) (((double)cOp[uVertices] - (double)cOp[-uVertices]) * invDv2);
260 					cRes			+=	uVertices;
261 					cOp				+=	uVertices;
262 				}
263 
264 				// Backward differencing
265 				cRes[0]				=	(float) (((double)cOp[0] - (double)cOp[-uVertices]) * invDv1);
266 			}
267 		}
268 		break;
269 
270 		// Dv executing on a 2D raytraced surface
271 		case SHADING_2D:
272 		{
273 			const int	numVertices		=	currentShadingState->numVertices;
274 			const int	numRealVertices	=	currentShadingState->numRealVertices;
275 			const float	*dsrc			=	src + numRealVertices;
276 			float		*ddest			=	dest + numRealVertices;
277 			const float	*dv				=	currentShadingState->varying[VARIABLE_DV];
278 
279 			assert(numVertices == numRealVertices*3);
280 
281 			for (int i=numRealVertices;i>0;--i) {
282 
283 				assert(*dv != 0);
284 
285 				const float	val	=	(float) (((double)dsrc[1] - (double)src[0]) / ((double)*dv++));
286 
287 				ddest[0]		=	val;
288 				ddest[1]		=	val;
289 				dest[0]			=	val;
290 
291 				++dest;
292 				++src;
293 				ddest			+=	2;
294 				dsrc			+=	2;
295 			}
296 		}
297 		break;
298 	}
299 }
300 
301 
302 
303 
304 ///////////////////////////////////////////////////////////////////////
305 // Class				:	CShadingContext
306 // Method				:	DvFloat
307 // Description			:	Compute the v differences
308 // Return Value			:	-
309 // Comments				:
DvFloat(float * dest,const float * src)310 void	CShadingContext::DvFloat(float *dest,const float *src) {
311 
312 	switch(currentShadingState->shadingDim) {
313 
314 		// Dv executing on Points
315 		case SHADING_0D:
316 		{
317 			for (int i=currentShadingState->numVertices;i>0;--i) {
318 				*dest++	=	0;
319 			}
320 		}
321 		break;
322 
323 
324 		// Dv executing on a 2D grid
325 		case SHADING_2D_GRID:
326 		{
327 			const int		uVertices	=	currentShadingState->numUvertices;
328 			const int		vVertices	=	currentShadingState->numVvertices;
329 
330 			assert(uVertices >= 2);
331 			assert(vVertices >= 2);
332 
333 			// Compute the DV
334 			for (int j=0;j<uVertices;++j) {
335 				float		*cRes	=	dest + j;
336 				const float	*cOp	=	src + j;
337 
338 				// Forward differencing
339 				cRes[0]				=	(float) ((double)cOp[uVertices] - (double)cOp[0]);
340 				cRes				+=	uVertices;
341 				cOp					+=	uVertices;
342 
343 				// Central differencing
344 				for (int i=vVertices-2;i>0;--i) {
345 					cRes[0]			=	(float) (((double)cOp[uVertices] - (double)cOp[-uVertices]) * 0.5);
346 					cRes			+=	uVertices;
347 					cOp				+=	uVertices;
348 				}
349 
350 				// Backward differencing
351 				cRes[0]				=	(float) ((double)cOp[0] - (double)cOp[-uVertices]);
352 			}
353 		}
354 		break;
355 
356 		// Dv executing on a 2D raytraced surface
357 		case SHADING_2D:
358 		{
359 			const int	numVertices		=	currentShadingState->numVertices;
360 			const int	numRealVertices	=	currentShadingState->numRealVertices;
361 			const float	*dsrc			=	src + numRealVertices;
362 			float		*ddest			=	dest + numRealVertices;
363 
364 			assert(numVertices == numRealVertices*3);
365 
366 			for (int i=numRealVertices;i>0;--i) {
367 
368 				const float	val	=	(float) ((double)dsrc[1] - (double)src[0]);
369 
370 				ddest[0]		=	val;
371 				ddest[1]		=	val;
372 				dest[0]			=	val;
373 
374 				++dest;
375 				++src;
376 				ddest			+=	2;
377 				dsrc			+=	2;
378 			}
379 		}
380 		break;
381 	}
382 }
383 
384 
385 
386 
387 
388 
389 
390 
391 
392 
393 
394 
395 
396 
397 
398 
399 
400 
401 
402 
403 
404 
405 
406 
407 
408 
409 
410 
411 
412 
413 ///////////////////////////////////////////////////////////////////////
414 // Class				:	CShadingContext
415 // Method				:	duVector
416 // Description			:	Compute the u derivative
417 // Return Value			:	-
418 // Comments				:
duVector(float * dest,const float * src)419 void	CShadingContext::duVector(float *dest,const float *src) {
420 	switch(currentShadingState->shadingDim) {
421 
422 
423 		// Du executing on Points or Curves (note that curves are defined along v)
424 		case SHADING_0D:
425 		{
426 			for (int j=currentShadingState->numVertices;j>0;--j) {
427 				initv(dest,0);
428 				dest+=3;
429 			}
430 		}
431 		break;
432 
433 
434 		// Du executing on a 2D grid
435 		case SHADING_2D_GRID:
436 		{
437 			const int		uVertices	=	currentShadingState->numUvertices;
438 			const int		vVertices	=	currentShadingState->numVvertices;
439 			const float		*u			=	currentShadingState->varying[VARIABLE_U];
440 
441 			assert(uVertices >= 2);
442 			assert(vVertices >= 2);
443 			assert(u[1] > u[0]);
444 
445 			const double	invDu1		=	1.0 / ((double)u[1] - (double)u[0]);
446 			const double	invDu2		=	1.0 / (2.0*((double)u[1] - (double)u[0]));
447 
448 			for (int j=vVertices;j>0;--j) {
449 
450 				// Use forward difference
451 				*dest++	=	(float) (((double)src[3] - (double)src[0]) * invDu1);
452 				*dest++	=	(float) (((double)src[4] - (double)src[1]) * invDu1);
453 				*dest++	=	(float) (((double)src[5] - (double)src[2]) * invDu1);
454 				src		+=	3;
455 
456 				// Use central difference
457 				for (int i=uVertices-2;i>0;--i) {
458 					*dest++	=	(float) (((double)src[3] - (double)src[-3]) * invDu2);
459 					*dest++	=	(float) (((double)src[4] - (double)src[-2]) * invDu2);
460 					*dest++	=	(float) (((double)src[5] - (double)src[-1]) * invDu2);
461 					src		+=	3;
462 				}
463 
464 				// Use backward difference
465 				*dest++	=	(float) (((double)src[0] - (double)src[-3]) * invDu1);
466 				*dest++	=	(float) (((double)src[1] - (double)src[-2]) * invDu1);
467 				*dest++	=	(float) (((double)src[2] - (double)src[-1]) * invDu1);
468 				src		+=	3;
469 			}
470 		}
471 		break;
472 
473 
474 		// Du executing on a 2D raytraced surface
475 		case SHADING_2D:
476 		{
477 			const int	numRealVertices	=	currentShadingState->numRealVertices;
478 			const float	*dsrc			=	src + numRealVertices*3;
479 			float		*ddest			=	dest + numRealVertices*3;
480 			const float	*du				=	currentShadingState->varying[VARIABLE_DU];
481 
482 			for (int i=numRealVertices;i>0;--i) {
483 
484 				assert(*du != 0);
485 
486 				const double invDu	=	1 / ((double)*du++);
487 				const float	val0	=	(float) (((double)dsrc[0] - (double)src[0]) * invDu);
488 				const float	val1	=	(float) (((double)dsrc[1] - (double)src[1]) * invDu);
489 				const float	val2	=	(float) (((double)dsrc[2] - (double)src[2]) * invDu);
490 
491 				ddest[0]		=	val0;
492 				ddest[1]		=	val1;
493 				ddest[2]		=	val2;
494 				ddest[3]		=	val0;
495 				ddest[4]		=	val1;
496 				ddest[5]		=	val2;
497 				dest[0]			=	val0;
498 				dest[1]			=	val1;
499 				dest[2]			=	val2;
500 
501 				assert(dotvv(dest,dest) >= 0);
502 
503 				dest			+=	3;
504 				src				+=	3;
505 				ddest			+=	6;
506 				dsrc			+=	6;
507 			}
508 		}
509 		break;
510 	}
511 }
512 
513 
514 ///////////////////////////////////////////////////////////////////////
515 // Class				:	CShadingContext
516 // Method				:	DuVector
517 // Description			:	Compute the u differences
518 // Return Value			:	-
519 // Comments				:
DuVector(float * dest,const float * src)520 void	CShadingContext::DuVector(float *dest,const float *src) {
521 	switch(currentShadingState->shadingDim) {
522 
523 
524 		// Du executing on Points or Curves (note that curves are defined along v)
525 		case SHADING_0D:
526 		{
527 			for (int j=currentShadingState->numVertices;j>0;--j) {
528 				initv(dest,0);
529 				dest+=3;
530 			}
531 		}
532 		break;
533 
534 
535 		// Du executing on a 2D grid
536 		case SHADING_2D_GRID:
537 		{
538 			const int		uVertices	=	currentShadingState->numUvertices;
539 			const int		vVertices	=	currentShadingState->numVvertices;
540 
541 			assert(uVertices >= 2);
542 			assert(vVertices >= 2);
543 
544 			for (int j=vVertices;j>0;--j) {
545 
546 				// Use forward difference
547 				*dest++	=	(float) ((double)src[3] - (double)src[0]);
548 				*dest++	=	(float) ((double)src[4] - (double)src[1]);
549 				*dest++	=	(float) ((double)src[5] - (double)src[2]);
550 				src		+=	3;
551 
552 				// Use central difference
553 				for (int i=uVertices-2;i>0;--i) {
554 					*dest++	=	(float) (((double)src[3] - (double)src[-3]) * 0.5);
555 					*dest++	=	(float) (((double)src[4] - (double)src[-2]) * 0.5);
556 					*dest++	=	(float) (((double)src[5] - (double)src[-1]) * 0.5);
557 					src		+=	3;
558 				}
559 
560 				// Use backward difference
561 				*dest++	=	(float) ((double)src[0] - (double)src[-3]);
562 				*dest++	=	(float) ((double)src[1] - (double)src[-2]);
563 				*dest++	=	(float) ((double)src[2] - (double)src[-1]);
564 				src		+=	3;
565 			}
566 		}
567 		break;
568 
569 
570 		// Du executing on a 2D raytraced surface
571 		case SHADING_2D:
572 		{
573 			const int	numRealVertices	=	currentShadingState->numRealVertices;
574 			const float	*dsrc			=	src + numRealVertices*3;
575 			float		*ddest			=	dest + numRealVertices*3;
576 
577 			for (int i=numRealVertices;i>0;--i) {
578 
579 				const float	val0	=	(float) ((double)dsrc[0] - (double)src[0]);
580 				const float	val1	=	(float) ((double)dsrc[1] - (double)src[1]);
581 				const float	val2	=	(float) ((double)dsrc[2] - (double)src[2]);
582 
583 				ddest[0]		=	val0;
584 				ddest[1]		=	val1;
585 				ddest[2]		=	val2;
586 				ddest[3]		=	val0;
587 				ddest[4]		=	val1;
588 				ddest[5]		=	val2;
589 				dest[0]			=	val0;
590 				dest[1]			=	val1;
591 				dest[2]			=	val2;
592 
593 				assert(dotvv(dest,dest) >= 0);
594 
595 				dest			+=	3;
596 				src				+=	3;
597 				ddest			+=	6;
598 				dsrc			+=	6;
599 			}
600 		}
601 		break;
602 	}
603 }
604 
605 
606 
607 
608 
609 ///////////////////////////////////////////////////////////////////////
610 // Class				:	CShadingContext
611 // Method				:	dvVector
612 // Description			:	Compute the v derivative
613 // Return Value			:	-
614 // Comments				:
dvVector(float * dest,const float * src)615 void	CShadingContext::dvVector(float *dest,const float *src) {
616 	switch(currentShadingState->shadingDim) {
617 
618 		// Dv executing on Points
619 		case SHADING_0D:
620 		{
621 			for (int i=currentShadingState->numVertices;i>0;--i) {
622 				initv(dest,0);
623 				dest+=3;
624 			}
625 		}
626 		break;
627 
628 		// Dv executing on a 2D grid
629 		case SHADING_2D_GRID:
630 		{
631 			const int		uVertices	=	currentShadingState->numUvertices;
632 			const int		vVertices	=	currentShadingState->numVvertices;
633 			const float		*v			=	currentShadingState->varying[VARIABLE_V];
634 
635 			assert(uVertices >= 2);
636 			assert(vVertices >= 2);
637 			assert(v[uVertices] > v[0]);
638 
639 			const double	invDv1		=	1.0 / ((double)v[uVertices] - (double)v[0]);
640 			const double	invDv2		=	1.0 / (2.0*((double)v[uVertices] - (double)v[0]));
641 
642 			for (int j=0;j<uVertices;++j) {
643 				float		*cRes	=	dest + j*3;
644 				const float	*cOp	=	src + j*3;
645 
646 				// Forward differencing
647 				cRes[0]				=	(float) (((double)cOp[uVertices*3+0] - (double)cOp[0]) * invDv1);
648 				cRes[1]				=	(float) (((double)cOp[uVertices*3+1] - (double)cOp[1]) * invDv1);
649 				cRes[2]				=	(float) (((double)cOp[uVertices*3+2] - (double)cOp[2]) * invDv1);
650 				cRes				+=	uVertices*3;
651 				cOp					+=	uVertices*3;
652 
653 				// Central differencing
654 				for (int i=vVertices-2;i>0;--i) {
655 					cRes[0]			=	(float) (((double)cOp[uVertices*3+0] - (double)cOp[-uVertices*3+0]) * invDv2);
656 					cRes[1]			=	(float) (((double)cOp[uVertices*3+1] - (double)cOp[-uVertices*3+1]) * invDv2);
657 					cRes[2]			=	(float) (((double)cOp[uVertices*3+2] - (double)cOp[-uVertices*3+2]) * invDv2);
658 					cRes			+=	uVertices*3;
659 					cOp				+=	uVertices*3;
660 				}
661 
662 				// Backward differencing
663 				cRes[0]				=	(float) (((double)cOp[0] - (double)cOp[-uVertices*3+0]) * invDv1);
664 				cRes[1]				=	(float) (((double)cOp[1] - (double)cOp[-uVertices*3+1]) * invDv1);
665 				cRes[2]				=	(float) (((double)cOp[2] - (double)cOp[-uVertices*3+2]) * invDv1);
666 			}
667 		}
668 		break;
669 
670 		// Dv executing on a 2D raytraced surface
671 		case SHADING_2D:
672 		{
673 			const int	numVertices		=	currentShadingState->numVertices;
674 			const int	numRealVertices	=	currentShadingState->numRealVertices;
675 			const float	*dsrc			=	src + numRealVertices*3;
676 			float		*ddest			=	dest + numRealVertices*3;
677 			const float	*dv				=	currentShadingState->varying[VARIABLE_DV];
678 
679 			assert(numVertices == numRealVertices*3);
680 
681 			for (int i=numRealVertices;i>0;--i) {
682 
683 				assert(*dv > 0);
684 
685 				const double invDv	=	1 / ((double)*dv++);
686 				const float	val0	=	(float) (((double)dsrc[3] - (double)src[0]) * invDv);
687 				const float	val1	=	(float) (((double)dsrc[4] - (double)src[1]) * invDv);
688 				const float	val2	=	(float) (((double)dsrc[5] - (double)src[2]) * invDv);
689 
690 				ddest[0]		=	val0;
691 				ddest[1]		=	val1;
692 				ddest[2]		=	val2;
693 				ddest[3]		=	val0;
694 				ddest[4]		=	val1;
695 				ddest[5]		=	val2;
696 				dest[0]			=	val0;
697 				dest[1]			=	val1;
698 				dest[2]			=	val2;
699 
700 				dest			+=	3;
701 				src				+=	3;
702 				ddest			+=	6;
703 				dsrc			+=	6;
704 			}
705 		}
706 		break;
707 	}
708 }
709 
710 
711 ///////////////////////////////////////////////////////////////////////
712 // Class				:	CShadingContext
713 // Method				:	DvVector
714 // Description			:	Compute the v differences
715 // Return Value			:	-
716 // Comments				:
DvVector(float * dest,const float * src)717 void	CShadingContext::DvVector(float *dest,const float *src) {
718 	switch(currentShadingState->shadingDim) {
719 
720 		// Dv executing on Points
721 		case SHADING_0D:
722 		{
723 			for (int i=currentShadingState->numVertices;i>0;--i) {
724 				initv(dest,0);
725 				dest+=3;
726 			}
727 		}
728 		break;
729 
730 		// Dv executing on a 2D grid
731 		case SHADING_2D_GRID:
732 		{
733 			const int		uVertices	=	currentShadingState->numUvertices;
734 			const int		vVertices	=	currentShadingState->numVvertices;
735 
736 			assert(uVertices >= 2);
737 			assert(vVertices >= 2);
738 
739 			for (int j=0;j<uVertices;++j) {
740 				float		*cRes	=	dest + j*3;
741 				const float	*cOp	=	src + j*3;
742 
743 				// Forward differencing
744 				cRes[0]				=	(float) ((double)cOp[uVertices*3+0] - (double)cOp[0]);
745 				cRes[1]				=	(float) ((double)cOp[uVertices*3+1] - (double)cOp[1]);
746 				cRes[2]				=	(float) ((double)cOp[uVertices*3+2] - (double)cOp[2]);
747 				cRes				+=	uVertices*3;
748 				cOp					+=	uVertices*3;
749 
750 				// Central differencing
751 				for (int i=vVertices-2;i>0;--i) {
752 					cRes[0]			=	(float) (((double)cOp[uVertices*3+0] - (double)cOp[-uVertices*3+0]) * 0.5);
753 					cRes[1]			=	(float) (((double)cOp[uVertices*3+1] - (double)cOp[-uVertices*3+1]) * 0.5);
754 					cRes[2]			=	(float) (((double)cOp[uVertices*3+2] - (double)cOp[-uVertices*3+2]) * 0.5);
755 					cRes			+=	uVertices*3;
756 					cOp				+=	uVertices*3;
757 				}
758 
759 				// Backward differencing
760 				cRes[0]				=	(float) ((double)cOp[0] - (double)cOp[-uVertices*3+0]);
761 				cRes[1]				=	(float) ((double)cOp[1] - (double)cOp[-uVertices*3+1]);
762 				cRes[2]				=	(float) ((double)cOp[2] - (double)cOp[-uVertices*3+2]);
763 			}
764 		}
765 		break;
766 
767 		// Dv executing on a 2D raytraced surface
768 		case SHADING_2D:
769 		{
770 			const int	numVertices		=	currentShadingState->numVertices;
771 			const int	numRealVertices	=	currentShadingState->numRealVertices;
772 			const float	*dsrc			=	src + numRealVertices*3;
773 			float		*ddest			=	dest + numRealVertices*3;
774 
775 			assert(numVertices == numRealVertices*3);
776 
777 			for (int i=numRealVertices;i>0;--i) {
778 
779 				const float	val0	=	(float) ((double)dsrc[3] - (double)src[0]);
780 				const float	val1	=	(float) ((double)dsrc[4] - (double)src[1]);
781 				const float	val2	=	(float) ((double)dsrc[5] - (double)src[2]);
782 
783 				ddest[0]		=	val0;
784 				ddest[1]		=	val1;
785 				ddest[2]		=	val2;
786 				ddest[3]		=	val0;
787 				ddest[4]		=	val1;
788 				ddest[5]		=	val2;
789 				dest[0]			=	val0;
790 				dest[1]			=	val1;
791 				dest[2]			=	val2;
792 
793 				dest			+=	3;
794 				src				+=	3;
795 				ddest			+=	6;
796 				dsrc			+=	6;
797 			}
798 		}
799 		break;
800 	}
801 }
802 
803 
804 
805 
806 
807 
808 
809 
810 
811 // Common code for trace transmission and trace reflection
812 // Note: we are including the cone angle tangent here because
813 // there's no point finely tesselating if we have a large coneangle blur
814 #define	computeRayDifferentials																		\
815 	const float lD	=	lengthv(rays->D);															\
816 	const float	da	=	((lengthv(rays->dDdu) + lengthv(rays->dDdv))*0.5f + lD*tanConeAngle) / lD;	\
817 	const float	db	=	(lengthv(rays->dPdu) + lengthv(rays->dPdv))*0.5f;
818 
819 // Should we be using only ray-orthogonal components?
820 /*
821 	vector t1,t2,nD;																				\
822 	mulvf(t1,rays->dDdu,dotvv(rays->dDdu,rays->D)/lD);												\
823 	subvv(t1,rays->dDdu,t1);																		\
824 	mulvf(t2,rays->dDdv,dotvv(rays->dDdv,rays->D)/lD);												\
825 	subvv(t2,rays->dDdv,t2);																		\
826 	const float	da	=	((lengthv(t1) + lengthv(t2))*0.5f + lD*tanConeAngle) / lD;	\
827 	const float	db	=	(lengthv(rays->dPdu) + lengthv(rays->dPdv))*0.5f;
828 */
829 
830 #define	sampleRay(__from,__dir)				\
831 	vector	tmp0,tmp1;						\
832 	mulvf(tmp0,rays->dPdu,(urand()-0.5f)*rays->sampleBase);	\
833 	mulvf(tmp1,rays->dPdv,(urand()-0.5f)*rays->sampleBase);	\
834 	addvv(__from,tmp0,tmp1);				\
835 	addvv(__from,rays->P);					\
836 	mulvf(tmp0,rays->dDdu,urand()-0.5f);	\
837 	mulvf(tmp1,rays->dDdv,urand()-0.5f);	\
838 	addvv(__dir,tmp0,tmp1);					\
839 	addvv(__dir,rays->D);
840 
841 ///////////////////////////////////////////////////////////////////////
842 // Class				:	CShadingContext
843 // Method				:	traceTransmission
844 // Description			:	Trace transmission rays
845 // Return Value			:	-
846 // Comments				:
traceTransmission(int numRays,CTraceLocation * rays,int probeOnly)847 void	CShadingContext::traceTransmission(int numRays,CTraceLocation *rays,int probeOnly) {
848 	CTransmissionRay		*rayBase;
849 	CTransmissionRay		**raysBase;
850 	CTransmissionRay		*cRay,**cRays;
851 	const CShadingScratch	*scratch		=	&(currentShadingState->scratch);
852 	const int				shootStep		=	CRenderer::shootStep;
853 	int						numRemaining	=	shootStep;
854 	CTransmissionBundle		bundle;
855 
856 	// Set the ray label we're tracing
857 	if ((bundle.label = scratch->traceParams.label) == NULL)	bundle.label	=	rayLabelTransmission;
858 
859 	// Allocate temp memory
860 	cRay	=	rayBase		=	(CTransmissionRay *) ralloc(shootStep*sizeof(CTransmissionRay),threadMemory);
861 	cRays	=	raysBase	=	(CTransmissionRay **) ralloc(shootStep*sizeof(CTransmissionRay*),threadMemory);
862 
863 	// We can not be in shadow at this stage
864 	assert(inShadow == FALSE);
865 
866 	// We're in shadow
867 	inShadow		=	TRUE;
868 
869 	// Are we sampling the motion in the reflections?
870 	const int	sampleMotion	=	currentShadingState->currentObject->attributes->flags & ATTRIBUTES_FLAGS_SAMPLEMOTION;
871 
872 	// For each ray
873 	for (int i=numRays;i>0;--i,++rays) {
874 		const int			numSamples		=	rays->numSamples;
875 		const float			coneAngle		=	rays->coneAngle;
876 		const float			tanConeAngle	=	min(fabsf(tanf(coneAngle)),1.0f);
877 		const float			multiplier		=	1 / (float) numSamples;
878 
879 		// Compute the ray differentials
880 		computeRayDifferentials;
881 
882 		// Clear the transmission
883 		initv(rays->C,0,0,0);
884 		rays->t	=	0;
885 
886 		// Sample
887 		for (int currentSample=numSamples;currentSample>0;--currentSample) {
888 			vector	from,L,dir;
889 
890 			// Sample the ray
891 			sampleRay(from,L);
892 			subvv(L,from);
893 			const	float	d	=	lengthv(L);
894 			mulvf(dir,L,1/d);
895 
896 			// Sample a point in the cone
897 			sampleHemisphere(cRay->dir,dir,coneAngle,random4d);
898 			if (dotvv(cRay->dir,cRay->dir) > C_EPSILON) {
899 
900 				movvv(cRay->from,from);
901 				cRay->t				=	min(rays->maxDist,d) - rays->bias;
902 				cRay->tmin			=	rays->bias;
903 				if (sampleMotion)	cRay->time	=	(urand() + currentSample - 1) * multiplier;
904 				else				cRay->time	=	rays->time;
905 				cRay->flags			=	ATTRIBUTES_FLAGS_TRANSMISSION_VISIBLE;
906 				cRay->dest			=	rays->C;
907 				cRay->multiplier	=	multiplier;
908 				cRay->da			=	da;		// The ray differential
909 				cRay->db			=	db;
910 
911 				// Are we shooting this ray for real?
912 				if (probeOnly) {
913 
914 					// No, just query an intersection and record the distance
915 					trace(cRay);
916 					rays->t					+=	cRay->t*multiplier;
917 				} else {
918 					*cRays++				=	cRay++;
919 					if (--numRemaining == 0) {
920 						numTransmissionRays	+=	shootStep;
921 						bundle.numRays		=	shootStep;
922 						bundle.rays			=	(CRay **) raysBase;
923 						bundle.depth		=	0;
924 						bundle.last			=	0;
925 						bundle.postShader	=	NULL;
926 						traceEx(&bundle);
927 						cRay				=	rayBase;
928 						cRays				=	raysBase;
929 						numRemaining		=	shootStep;
930 					}
931 				}
932 			}
933 		}
934 	}
935 
936 	// Finish the bundle
937 	if (numRemaining != shootStep) {
938 		numTransmissionRays	+=	shootStep-numRemaining;
939 		bundle.numRays		=	shootStep-numRemaining;
940 		bundle.rays			=	(CRay **) raysBase;
941 		bundle.depth		=	0;
942 		bundle.last			=	0;
943 		bundle.postShader	=	NULL;
944 		traceEx(&bundle);
945 	}
946 
947 	inShadow		=	FALSE;			// We're no longer in shadow
948 }
949 
950 ///////////////////////////////////////////////////////////////////////
951 // Class				:	CShadingContext
952 // Method				:	traceReflection
953 // Description			:	Trace reflected rays
954 // Return Value			:	-
955 // Comments				:
traceReflection(int numRays,CTraceLocation * rays,int probeOnly)956 void	CShadingContext::traceReflection(int numRays,CTraceLocation *rays,int probeOnly) {
957 	CTraceRay				*interiorRayBase,*cInteriorRay;
958 	CTraceRay				*exteriorRayBase,*cExteriorRay;
959 	CTraceRay				**interiorRaysBase,**exteriorRaysBase,**cInteriorRays,**cExteriorRays;
960 	const CShadingScratch	*scratch				=	&(currentShadingState->scratch);
961 	const int				shootStep				=	CRenderer::shootStep;
962 	int						numInteriorRemaining	=	shootStep;
963 	int						numExteriorRemaining	=	shootStep;
964 	CTraceBundle			interiorBundle,exteriorBundle;
965 
966 	// Verify atmosphere shaders
967 	CAttributes *cAttr				=	currentShadingState->currentObject->attributes;
968 	CShaderInstance *interiorShader	=	cAttr->interior;
969 	CShaderInstance *exteriorShader	=	cAttr->exterior;
970 
971 	// Set the ray label
972 	if (scratch->traceParams.label == NULL)	{
973 		exteriorBundle.label	=	rayLabelTransmission;
974 		interiorBundle.label	=	rayLabelTransmission;
975 	} else {
976 		exteriorBundle.label	=	scratch->traceParams.label;
977 		interiorBundle.label	=	scratch->traceParams.label;
978 	}
979 
980 	// Allocate temp memory
981 	cExteriorRay	=	exteriorRayBase			=	(CTraceRay *) ralloc(shootStep*sizeof(CTraceRay),threadMemory);
982 	cExteriorRays	=	exteriorRaysBase		=	(CTraceRay **) ralloc(shootStep*sizeof(CTraceRay*),threadMemory);
983 
984 	if (interiorShader != exteriorShader) {
985 		cInteriorRay	=	interiorRayBase		=	(CTraceRay *) ralloc(shootStep*sizeof(CTraceRay),threadMemory);
986 		cInteriorRays	=	interiorRaysBase	=	(CTraceRay **) ralloc(shootStep*sizeof(CTraceRay*),threadMemory);
987 	}
988 
989 	// Are we sampling the motion in the reflections?
990 	const int	sampleMotion	=	cAttr->flags & ATTRIBUTES_FLAGS_SAMPLEMOTION;
991 
992 	// For each ray
993 	for (int i=numRays;i>0;--i,++rays) {
994 		const int			numSamples		=	rays->numSamples;
995 		const float			coneAngle		=	rays->coneAngle;
996 		const float			tanConeAngle	=	min(fabsf(tanf(coneAngle)),1.0f);
997 		const float			multiplier		=	1 / (float) numSamples;
998 
999 		// Compute the ray differentials
1000 		computeRayDifferentials;
1001 
1002 		// Clear the reflection
1003 		initv(rays->C,0,0,0);
1004 		rays->t	=	0;
1005 
1006 		// Sample
1007 		for (int currentSample=numSamples;currentSample>0;--currentSample) {
1008 			vector	from,D,dir;
1009 
1010 			sampleRay(from,D);
1011 
1012 			normalizev(D);
1013 
1014 			sampleHemisphere(dir,D,coneAngle,random4d);
1015 			if (dotvv(dir,dir) > C_EPSILON) {
1016 				CTraceRay *cRay;
1017 				int isExterior = (dotvv(dir,rays->N) > 0) || (interiorShader == exteriorShader);
1018 
1019 				if (isExterior) cRay = cExteriorRay;
1020 				else			cRay = cInteriorRay;
1021 
1022 				movvv(cRay->dir,dir);
1023 				movvv(cRay->from,from);
1024 				if (sampleMotion)	cRay->time		=	(urand() + currentSample - 1) * multiplier;
1025 				else				cRay->time		=	rays->time;
1026 				cRay->t				=	C_INFINITY;
1027 				cRay->tmin			=	rays->bias;
1028 				cRay->flags			=	ATTRIBUTES_FLAGS_SPECULAR_VISIBLE;
1029 				cRay->dest			=	rays->C;
1030 				cRay->multiplier	=	multiplier;
1031 				cRay->da			=	da;
1032 				cRay->db			=	db;
1033 				if (probeOnly) {
1034 
1035 					// No, just query an intersection and record the distance
1036 					trace(cRay);
1037 					rays->t					+=	cRay->t*multiplier;
1038 				} else {
1039 					if (isExterior) {
1040 						*cExteriorRays++	=	cRay;
1041 						cExteriorRay++;
1042 
1043 						if (--numExteriorRemaining == 0) {
1044 							numReflectionRays			+=	shootStep;
1045 							exteriorBundle.numRays		=	shootStep;
1046 							exteriorBundle.rays			=	(CRay **) exteriorRaysBase;
1047 							exteriorBundle.depth		=	0;
1048 							exteriorBundle.last			=	0;
1049 							exteriorBundle.postShader	=	exteriorShader;
1050 							traceEx(&exteriorBundle);
1051 							cExteriorRay				=	exteriorRayBase;
1052 							cExteriorRays				=	exteriorRaysBase;
1053 							numExteriorRemaining		=	shootStep;
1054 						}
1055 					} else {
1056 						*cInteriorRays++	=	cRay;
1057 						cInteriorRay++;
1058 
1059 						if (--numInteriorRemaining == 0) {
1060 							numReflectionRays	+=	shootStep;
1061 							interiorBundle.numRays		=	shootStep;
1062 							interiorBundle.rays			=	(CRay **) interiorRaysBase;
1063 							interiorBundle.depth		=	0;
1064 							interiorBundle.last			=	0;
1065 							interiorBundle.postShader	=	interiorShader;
1066 							traceEx(&interiorBundle);
1067 							cInteriorRay				=	interiorRayBase;
1068 							cInteriorRays				=	interiorRaysBase;
1069 							numInteriorRemaining		=	shootStep;
1070 						}
1071 					}
1072 				}
1073 			}
1074 		}
1075 	}
1076 
1077 	// Finish the bundles
1078 	if (numExteriorRemaining != shootStep) {
1079 		numReflectionRays			+=	shootStep-numExteriorRemaining;
1080 		exteriorBundle.numRays		=	shootStep-numExteriorRemaining;
1081 		exteriorBundle.rays			=	(CRay **) exteriorRaysBase;
1082 		exteriorBundle.depth		=	0;
1083 		exteriorBundle.last			=	0;
1084 		exteriorBundle.postShader	=	exteriorShader;
1085 		traceEx(&exteriorBundle);
1086 	}
1087 	if (numInteriorRemaining != shootStep) {
1088 		numReflectionRays			+=	shootStep-numInteriorRemaining;
1089 		interiorBundle.numRays		=	shootStep-numInteriorRemaining;
1090 		interiorBundle.rays			=	(CRay **) interiorRaysBase;
1091 		interiorBundle.depth		=	0;
1092 		interiorBundle.last			=	0;
1093 		interiorBundle.postShader	=	interiorShader;
1094 		traceEx(&interiorBundle);
1095 	}
1096 }
1097 
1098 
1099 
1100 
1101 
1102 
1103 
1104 
1105 
1106 
1107 ///////////////////////////////////////////////////////////////////////
1108 // Class				:	CShadingContext
1109 // Method				:	rayDiff
1110 // Description			:	Compute the ray differentials
1111 // Return Value			:	-
1112 // Comments				:
rayDiff(const float * from,const float * dir,const float * to)1113 float		*CShadingContext::rayDiff(const float *from,const float *dir,const float *to) {
1114 
1115 	// Allocate the return value
1116 	const int	numVertices	=	currentShadingState->numVertices;
1117 	float		*ab			=	(float *) ralloc(numVertices*2*sizeof(float),threadMemory);
1118 
1119 	// Compute the direction vector if not already computed
1120 	if (dir == NULL) {
1121 		int		i;
1122 
1123 		float	*D		=	(float *) ralloc(numVertices*3*sizeof(float),threadMemory);
1124 		for (i=numVertices;i>0;i--,D+=3,from+=3,to+=3)	subvv(D,to,from);
1125 
1126 		D		-=	numVertices*3;
1127 		from	-=	numVertices*3;
1128 		to		-=	numVertices*3;
1129 		dir		=	D;
1130 	}
1131 
1132 
1133 	switch(currentShadingState->shadingDim) {
1134 
1135 
1136 
1137 
1138 
1139 		// Dv executing on Points
1140 		case SHADING_0D:
1141 		{
1142 
1143 			// Set anyway
1144 			for (int i=numVertices;i>0;i--) {
1145 				*ab++	=	DEFAULT_RAY_DA;
1146 				*ab++	=	DEFAULT_RAY_DB;
1147 			}
1148 
1149 			return	ab - numVertices*2;
1150 		}
1151 		break;
1152 
1153 
1154 
1155 
1156 
1157 
1158 
1159 
1160 		// Dv executing on a 2D grid
1161 		case SHADING_2D_GRID:
1162 		{
1163 			const int	uVertices	=	currentShadingState->numUvertices;
1164 			const int	vVertices	=	currentShadingState->numVvertices;
1165 			int			i,j;
1166 
1167 			for (j=0;j<vVertices;j++) {
1168 				for (i=0;i<uVertices;i++) {
1169 
1170 					const int	ii		=	min(i,uVertices-2);
1171 					const int	jj		=	min(j,vVertices-2);
1172 
1173 					// The 4 corners of the current quad
1174 					const float	*cFrom0	=	from + jj*uVertices*3 + ii*3;
1175 					const float	*cFrom1	=	cFrom0 + 3;
1176 					const float	*cFrom2	=	cFrom0 + uVertices*3;
1177 					const float	*cFrom3	=	cFrom2 + 3;
1178 
1179 					ab[0]				=	0;
1180 					ab[1]				=	0;
1181 
1182 					vector		tmp;
1183 					subvv(tmp,cFrom1,cFrom0);
1184 					ab[1]				+=	lengthv(tmp);
1185 					subvv(tmp,cFrom2,cFrom0);
1186 					ab[1]				+=	lengthv(tmp);
1187 					subvv(tmp,cFrom1,cFrom3);
1188 					ab[1]				+=	lengthv(tmp);
1189 					subvv(tmp,cFrom2,cFrom3);
1190 					ab[1]				+=	lengthv(tmp);
1191 
1192 					// The directions at 4 corners of the quad
1193 					const float	*cDir0	=	dir + jj*uVertices*3 + ii*3;
1194 					const float	*cDir1	=	cDir0 + 3;
1195 					const float	*cDir2	=	cDir0 + uVertices*3;
1196 					const float	*cDir3	=	cDir2 + 3;
1197 
1198 					float a				=	dotvv(cDir1,cDir0);
1199 					ab[0]				+=	acosf(sqrtf(a*a / (dotvv(cDir0,cDir0)*dotvv(cDir1,cDir1) + C_EPSILON)));
1200 
1201 					a					=	dotvv(cDir2,cDir0);
1202 					ab[0]				+=	acosf(sqrtf(a*a / (dotvv(cDir0,cDir0)*dotvv(cDir2,cDir2) + C_EPSILON)));
1203 
1204 					a					=	dotvv(cDir3,cDir1);
1205 					ab[0]				+=	acosf(sqrtf(a*a / (dotvv(cDir3,cDir3)*dotvv(cDir1,cDir1) + C_EPSILON)));
1206 
1207 					a					=	dotvv(cDir2,cDir3);
1208 					ab[0]				+=	acosf(sqrtf(a*a / (dotvv(cDir2,cDir2)*dotvv(cDir3,cDir3) + C_EPSILON)));
1209 
1210 					ab[0]				*=	0.25f;
1211 					ab[1]				*=	0.25f;
1212 
1213 					ab[0]				=	tanf(min(ab[0],((float) C_PI)*0.5f - C_EPSILON));
1214 					ab[0]				=	min(ab[0],DEFAULT_RAY_DA);
1215 
1216 					// guard against bad differentials
1217 
1218 					if(ab[0] != ab[0]) ab[0]	= 	DEFAULT_RAY_DA;
1219 
1220 					assert(ab[0] >= 0);
1221 					assert(ab[1] >= 0);
1222 
1223 					ab					+=	2;
1224 				}
1225 			}
1226 
1227 			return ab - uVertices*vVertices*2;
1228 		}
1229 		break;
1230 
1231 
1232 
1233 
1234 
1235 
1236 
1237 		// Dv executing on a 2D raytraced surface
1238 		case SHADING_2D:
1239 		{
1240 			const int	numRealVertices	=	currentShadingState->numRealVertices;
1241 			const float	*dfrom			=	from + numRealVertices*3;
1242 			const float	*ddir			=	dir + numRealVertices*3;
1243 			int			i;
1244 
1245 			assert(numVertices == numRealVertices*3);
1246 
1247 			for (i=numRealVertices;i>0;i--) {
1248 				vector	tmp;
1249 
1250 				ab[0]				=	0;
1251 				ab[1]				=	0;
1252 
1253 				subvv(tmp,dfrom,from);
1254 				ab[1]				+=	lengthv(tmp);
1255 				subvv(tmp,dfrom + 3,from);
1256 				ab[1]				+=	lengthv(tmp);
1257 
1258 				float a;
1259 				a					=	dotvv(dir,ddir);
1260 				ab[0]				+=	acosf(sqrtf(a*a / (dotvv(dir,dir)*dotvv(ddir,ddir) + C_EPSILON)));
1261 				a					=	dotvv(dir,ddir+3);
1262 				ab[0]				+=	acosf(sqrtf(a*a / (dotvv(dir,dir)*dotvv(ddir+3,ddir+3) + C_EPSILON)));
1263 
1264 				ab[0]				*=	0.5f;
1265 				ab[1]				*=	0.5f;
1266 				ab[0]				=	tanf(min(ab[0],((float) C_PI)*0.5f - C_EPSILON));
1267 				ab[0]				=	min(ab[0],DEFAULT_RAY_DA);
1268 
1269 				// guard against bad differentials
1270 
1271 				if(ab[0] != ab[0]) ab[0]	= 	DEFAULT_RAY_DA;
1272 
1273 				assert(ab[0] >= 0);
1274 				assert(ab[1] >= 0);
1275 
1276 				ab					+=	2;
1277 				from				+=	3;
1278 				dir					+=	3;
1279 				dfrom				+=	6;
1280 				ddir				+=	6;
1281 			}
1282 
1283 			return ab - numRealVertices*2;
1284 		}
1285 		break;
1286 	}
1287 
1288 	assert(FALSE);
1289 	return NULL;
1290 }
1291 
1292 
1293 
1294 ///////////////////////////////////////////////////////////////////////
1295 // Class				:	CShadingContext
1296 // Method				:	rayDiff
1297 // Description			:	Compute the ray differentials
1298 // Return Value			:	-
1299 // Comments				:
rayDiff(const float * from)1300 float		*CShadingContext::rayDiff(const float *from) {
1301 
1302 	// Allocate the return value
1303 	const int	numVertices	=	currentShadingState->numVertices;
1304 	float		*b			=	(float *) ralloc(numVertices*sizeof(float),threadMemory);
1305 
1306 
1307 	switch(currentShadingState->shadingDim) {
1308 
1309 
1310 
1311 
1312 
1313 		// Dv executing on Points
1314 		case SHADING_0D:
1315 		{
1316 			// Set anyway
1317 			for (int i=numVertices;i>0;i--) {
1318 				*b++	=	DEFAULT_RAY_DB;
1319 			}
1320 
1321 			return	b - numVertices;
1322 		}
1323 		break;
1324 
1325 
1326 
1327 
1328 
1329 
1330 
1331 
1332 		// Dv executing on a 2D grid
1333 		case SHADING_2D_GRID:
1334 		{
1335 			const int	uVertices	=	currentShadingState->numUvertices;
1336 			const int	vVertices	=	currentShadingState->numVvertices;
1337 			int			i,j;
1338 
1339 			for (j=0;j<vVertices;j++) {
1340 				for (i=0;i<uVertices;i++) {
1341 
1342 					const int	ii		=	min(i,uVertices-2);
1343 					const int	jj		=	min(j,vVertices-2);
1344 
1345 					// The 4 corners of the current quad
1346 					const float	*cFrom0	=	from + jj*uVertices*3 + ii*3;
1347 					const float	*cFrom1	=	cFrom0 + 3;
1348 					const float	*cFrom2	=	cFrom0 + uVertices*3;
1349 					const float	*cFrom3	=	cFrom2 + 3;
1350 
1351 					b[0]				=	0;
1352 
1353 					vector		tmp;
1354 					subvv(tmp,cFrom1,cFrom0);
1355 					b[0]				+=	lengthv(tmp);
1356 					subvv(tmp,cFrom2,cFrom0);
1357 					b[0]				+=	lengthv(tmp);
1358 					subvv(tmp,cFrom1,cFrom3);
1359 					b[0]				+=	lengthv(tmp);
1360 					subvv(tmp,cFrom2,cFrom3);
1361 					b[0]				+=	lengthv(tmp);
1362 
1363 					b[0]				*=	0.25f;
1364 					b++;
1365 				}
1366 			}
1367 
1368 			return b - uVertices*vVertices;
1369 		}
1370 		break;
1371 
1372 
1373 
1374 
1375 
1376 
1377 
1378 		// Dv executing on a 2D raytraced surface
1379 		case SHADING_2D:
1380 		{
1381 			const int	numRealVertices	=	currentShadingState->numRealVertices;
1382 			const float	*dfrom			=	from + numRealVertices*3;
1383 			int			i;
1384 
1385 			assert(numVertices == numRealVertices*3);
1386 
1387 			for (i=numRealVertices;i>0;i--) {
1388 				vector	tmp;
1389 
1390 				b[0]				=	0;
1391 
1392 				subvv(tmp,dfrom,from);
1393 				b[0]				+=	lengthv(tmp);
1394 				subvv(tmp,dfrom + 3,from);
1395 				b[0]				+=	lengthv(tmp);
1396 				b[0]				*=	0.5f;
1397 
1398 				b++;
1399 				from				+=	3;
1400 				dfrom				+=	6;
1401 			}
1402 
1403 			return b - numRealVertices;
1404 		}
1405 		break;
1406 	}
1407 
1408 	assert(FALSE);
1409 	return NULL;
1410 }
1411