1 /*
  2   Copyright (c) 2008 Seneca College
  3   Licenced under the MIT License (http://www.c3dl.org/index.php/mit-license/)
  4 */
  5 
  6 /**
  7 	@class c3dl.Effect specifies exactly how a geometric object should 
  8 	be rendered. An Effect is an instantiation of an EffectTemplate, which 
  9 	is a template for creating effects with similar results.
 10 
 11 	<p>
 12 	Effects are composed of a vertex shader, fragment shader and a rendering 
 13 	callback. The shaders perform the transformation, lighting calculations
 14 	and anything else necessary. The callback typically sets the uniform and 
 15 	vertex attributes.
 16 	</p>
 17 	
 18 	<p>
 19 	When the library is told to render an object which has an effect, it will first call
 20 	the rendering callback. This allows the user to do things such as toggle depth
 21 	tests, set the uniform variables, or adjust any other rendering state variables
 22 	required to perform the required rendering. The shader programs are then executed
 23 	and the object is rendered.
 24 	</p>
 25 	
 26 	<p>
 27 	Some effect templates have already been written and using them requires minimal 
 28 	effort.
 29 	<code><pre>
 30 	// c3dl.effects is a namespace which contains premade effects.
 31 	var effect = new c3dl.Effect();
 32 	effect.init(c3dl.effects.GOOCH);
 33 	var teapot = c3dl.Collada();
 34 	teapot.init('teapot.dae');
 35 	// the effect's parameters were not set, so the default Gooch params
 36 	// will be used.
 37 	teapot.setEffect(effect);
 38 	</pre></code>
 39 	</p>
 40 
 41 	<p>
 42 	In the example above, none of the Gooch parameters were set, therefore
 43 	the default Gooch parameters are used. However, not all effects have 
 44 	default parameters and therefore some need to be set. Wheather an effect
 45 	has default parameters is noted in c3dl.effects.
 46 	</p>
 47 */
 48 c3dl.Effect = function()
 49 {
 50 	// the effect this object is instantiating.
 51 	this.effectTemplate = null;
 52 	
 53 	// these can be changed from the default ones created by the effect template.
 54 	this.instanceParams = [];
 55 	
 56 	// prevent the effect from being initialized more than once.
 57 	this.isInitialized = false;
 58 	
 59 	/**
 60 		Call this after the Effect has been created. Once the Effect has been
 61 		created and initialized, its parameters can be set.
 62 
 63 		@param {c3dl.EffectTemplate} effectTemplate
 64 	*/
 65 	this.init = function(effectTemplate)
 66 	{
 67 		//c3dl.debug.logWarning(effectTemplate);
 68 		
 69 		var check = true;
 70 		
 71 		if(check || effectTemplate instanceof c3dl.EffectTemplate)
 72 		{
 73 			// keep a reference to the template as it holds the shaders
 74 			// which will need to be compiled during rendering.
 75 			this.effectTemplate = effectTemplate;
 76 			
 77 			// copy over the parameters which comprise of
 78 			// names, types and default values.
 79 			this.instanceParams = c3dl.copyObj(effectTemplate.getParameters());
 80 			
 81 			// prevent the Effect from being initialized more than once.
 82 			this.isInitialized = true;
 83 		}
 84 		else
 85 		{
 86 			c3dl.debug.logWarning("Invalid argument passed to c3dl.Effect's init().");
 87 		}
 88 	}
 89 	
 90 	/**
 91 		Get the EffectTemplate which was used to create this Effect.
 92 		
 93 		@returns {c3dl.EffectTemplate} the effect template which was used to
 94 		create this effect.
 95 	*/
 96 	this.getEffectTemplate = function()
 97 	{
 98 		return this.effectTemplate;
 99 	}
100 
101 	/**
102 		Get the value of the parameter 'paramName'.
103 
104 		@param {String} paramName
105 		
106 		@returns the value of 'paramName' or null if parameter does not exist or 
107 		has not been set.
108 	*/
109 	this.getParameter = function(paramName)
110 	{
111 		var isFound = false;
112 		var returnVal = null;
113 		
114 		for(var i=0; i< this.instanceParams.length; i++)
115 		{
116 			if(this.instanceParams[i].name == paramName)
117 			{
118 				isFound = true;
119 				returnVal = this.instanceParams[i].value;
120 			}
121 		}
122 		
123 		if(!isFound)
124 		{
125 			c3dl.debug.logWarning("Effect getParameter(): '" + paramName + "' does not exist.");
126 		}
127 		
128 		return returnVal;
129 	}
130 
131 	/**
132 		Set the value of the parameter 'paramName' to 'paramvalue'.
133 
134 		@param {String} paramName Name of the parameter to set.
135 		@param {} paramValue The value to set the parameter.
136 
137 		If the value does not match the parameter's type, a warning will 
138 		be displayed and the parameter will not be set.
139 	*/
140 	this.setParameter = function(paramName, paramValue)
141 	{		
142 		// When the instance effect is initialized, all the default parameters from the effect
143 		// are copied to the instance effect and then they can be changed with setParameter.
144 		// Otherwise, there would be no place to store the values.
145 		if(this.isInitialized == false)
146 		{
147 			c3dl.debug.logWarning("Effect must be initialized with init() " + 
148 									"before setting its parameters.");
149 		}
150 		else
151 		{
152 			var isFound = false;
153 			
154 			for(var i=0; !isFound && i < this.instanceParams.length; i++)
155 			{
156 				if(	paramName == this.instanceParams[i].name)
157 				{
158 					isFound = true;
159 				
160 					// check if the value matches the parameter's type
161 					if(paramValue.constructor == this.instanceParams[i].type)
162 					{
163 						this.instanceParams[i].value = paramValue;
164 					}
165 					else
166 					{
167 						// The value 'true' does not match parameter 'warmColor' type.
168 						
169 						// The value 'true' cannot be assigned to parameter 'warmColor'
170 						// because it is the incorrect type. Check the Effect documentation
171 						// for the correct type.
172 						c3dl.debug.logWarning(	"The value '" + paramValue + "' cannot be assigned " +
173 												"to parameter '" + paramName + "' because it is the " +
174 												"incorrect type. Check the c3dl.effects documentation " +
175 												" for the correct type.");
176 					}
177 				}
178 			}
179 
180 			if(!isFound)
181 			{
182 				c3dl.debug.logWarning("Effect setParameter(): '" + paramName + "' does not exist.");
183 			}
184 		}
185 	}
186 }
187