//////////////////////////////////////////////////////////////////////
//
//                             Pixie
//
// Copyright © 1999 - 2003, Okan Arikan
//
// Contact: okan@cs.berkeley.edu
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//
//  File				:	giOpcodes.h
//  Classes				:	-
//  Description			:	Shading language Global Illumination opcodes.
//
////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	gather <else>
#ifndef INIT_SHADING
#define	GATHEREXPR_PRE		const int	numRealVertices	=	currentShadingState->numRealVertices;	\
							CGatherRay	*raysBase		=	lastGather->raysBase;					\
							CGatherRay	**rays			=	(CGatherRay **) lastGather->rays;		\
							CGatherLookup	*lookup		=	lastGather->lookup;						\
							int			numRays			=	0;										\
							int			i;															\
							for (i=0;i<numRealVertices;i++) {										\
								if (tags[i]) {														\
									tags[i]++;														\
								} else {															\
									if (lookup->uniformDist) {										\
										sampleHemisphere(raysBase->dir,raysBase->gatherDir,lookup->coneAngle,gatherGenerator);	\
									} else {														\
										sampleCosineHemisphere(raysBase->dir,raysBase->gatherDir,lookup->coneAngle,gatherGenerator);	\
									}																\
									raysBase->index	=	i;											\
									raysBase->tmin	=	lookup->bias;								\
									raysBase->t		=	lookup->maxDist;							\
									raysBase->time	=	urand();									\
									raysBase->flags	=	ATTRIBUTES_FLAGS_TRACE_VISIBLE;				\
									raysBase->tags	=	&tags[i];									\
									rays[numRays++]	=	raysBase++;									\
								}																	\
							}																		\
							if (numRays > 0) {														\
								lastGather->numRays		=	numRays;								\
								lastGather->rays		=	(CRay **) rays;							\
								lastGather->last		=	0;										\
								lastGather->depth		=	0;										\
								lastGather->postShader	=	NULL;									\
								lastGather->numMisses	=	0;										\
								traceEx(lastGather);												\
								numActive				-=	lastGather->numMisses;					\
								numPassive				+=	lastGather->numMisses;					\
								if (numActive == 0) {												\
									jmp(argument(0));												\
								}																	\
							}
	
#else
#define GATHEREXPR_PRE
#endif

DEFOPCODE(Gather	,"gather"	,1,	GATHEREXPR_PRE,NULL_EXPR,NULL_EXPR,NULL_EXPR,0)

#undef GATHEREXPR_PRE

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	gatheElse <endLabel>
#ifndef INIT_SHADING
#define	GATHERELSEEXPR_PRE	int	numRealVertices = currentShadingState->numRealVertices;				\
							for (;numRealVertices>0;numRealVertices--,tags++)	{					\
								if (*tags <= 1) {													\
									if (*tags == 1) {												\
										*tags	=	0;												\
										numActive++;												\
										numPassive--;												\
									} else {														\
										*tags	=	1;												\
										numActive--;												\
										numPassive++;												\
									}																\
								}																	\
							}																		\
							if (numActive == 0) {													\
								jmp(argument(0));													\
							}

#else
#define GATHERELSEEXPR_PRE
#endif

DEFOPCODE(GatherElse	,"gatherElse"	,1,	GATHERELSEEXPR_PRE,NULL_EXPR,NULL_EXPR,NULL_EXPR,0)

#undef GATHERELSEEXPR_PRE

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	gatheEnd <gatherLabel>
#ifndef INIT_SHADING
#define	GATHERENDEXPR_PRE	int	numRealVertices = currentShadingState->numRealVertices;				\
							for (;numRealVertices>0;numRealVertices--,tags++) {						\
								if (*tags) {														\
									(*tags)--;														\
									if (*tags == 0) {												\
										numActive++;												\
										numPassive--;												\
									}																\
								}																	\
							}																		\
							lastGather->numMisses	=	0;											\
							if (lastGather->remainingSamples > 0) {									\
								lastGather->remainingSamples--;										\
								jmp(argument(0));													\
							} else {																\
								CGatherVariable	*var;												\
								CGatherLookup	*lookup		=	lastGather->lookup;					\
																									\
								delete lastGather;													\
																									\
								for (var=lookup->outputs;var!=NULL;var=var->next) {					\
									var->cDepth--;													\
									var->dest	=	var->cDepth[0];									\
									assert((var->cDepth-var->destForEachLevel) >= 0);				\
								}																	\
								for (var=lookup->nonShadeOutputs;var!=NULL;var=var->next) {			\
									var->cDepth--;													\
									var->dest	=	var->cDepth[0];									\
									assert((var->cDepth-var->destForEachLevel) >= 0);				\
								}																	\
							}

#else
#define GATHERENDEXPR_PRE
#endif

DEFOPCODE(GatherEnd	,"gatherEnd"	,1,	GATHERENDEXPR_PRE,NULL_EXPR,NULL_EXPR,NULL_EXPR,0)

#undef GATHERENDEXPR_PRE

