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 	@private
  8     Find the smallest number that's a power of 2 that's bigger
  9     than the given number.
 10 
 11 	@param {int} number The base number which the next power of two 
 12 	number must be found.  For example:
 13 	<pre>
 14 		var i = roundUpToNextPowerOfTwo(3);
 15 		// i is now 4
 16 
 17 		i = roundUpToNextPowerOfTwo(4);
 18 		// i is now 4
 19 
 20 		i = roundUpToNextPowerOfTwo(9);
 21 		// i is now 16
 22 	</pre>
 23 
 24 	@returns {int} A number which is greater or equal to 'number'
 25 	which is the closest power of two which exists.
 26 */
 27 c3dl.roundUpToNextPowerOfTwo = function(number)
 28 {
 29 	var i = 1;
 30 	
 31 	while( i < number)
 32 	{
 33 		i *= 2;
 34 	}
 35 
 36 	return i;
 37 }
 38 
 39 /**
 40 	Inverse of a square root.
 41 
 42 	@param {float} num
 43 
 44 	@return {float} the inverse square root of num or 0 ir num was not a 
 45 	number.
 46 */
 47 c3dl.invSqrt = function(num)
 48 {
 49 	if (!isNaN(num))
 50 	{
 51 		// We have to do this ourselves since javascript does not have it.
 52 		return 1 / Math.sqrt(num);
 53 	}
 54 	
 55 	c3dl.debug.logWarning('invSqrt() caled with a parameter that\'s not a number');
 56 	
 57 	return 0;
 58 }
 59 
 60 /**
 61 	gluLookAt Implementation
 62 
 63 	@param {Array} eye The location of the camera.
 64 	@param {Array} center Where the camera is looking at.
 65 	@param {Array} up A Vector which represents the camera's up
 66 	vector.
 67 
 68 	@returns {Array} the lookat matrix or null if one of the arguments were
 69 	not valid Vectors.
 70 */
 71 c3dl.lookAt = function(eye, center, up)
 72 {
 73 	if ( c3dl.isValidVector(eye) && c3dl.isValidVector(center) && c3dl.isValidVector(up))
 74 	{
 75 		// Figure out the Orientation
 76 		var z = c3dl.subtractVectors(eye, center, null);
 77 		var x = c3dl.vectorCrossProduct(up, z, null);
 78 		var y = c3dl.vectorCrossProduct(z, x, null);
 79 		c3dl.normalizeVector(z);
 80 		c3dl.normalizeVector(y);
 81 		c3dl.normalizeVector(x);
 82 
 83 		// makeMatrix expects values to be in column-major
 84 		return c3dl.makeMatrix( x[0], y[0], z[0], 0,
 85 								x[1], y[1], z[1], 0,
 86 								x[2], y[2], z[2], 0,
 87 								0,    0,    0,   1);			
 88 	}
 89 	
 90 	c3dl.debug.logWarning('lookAt() called with a parameters that are not vectors');
 91 	return null;
 92 }
 93 
 94 /**
 95 	@private
 96 	this function needs testing
 97 	
 98 	Create an orthographic matrix from the specified arguments.
 99 
100 	@param {float} left The coordinate of the left vertical clipping plane.
101 	@param {float} right The coordinate of the right vertical clipping plane.
102 	@param {float} bottom The coordinate of the bottom horizontal clipping 
103 	plane.
104 	@param {float} top The coordinate of the top horizontal clipping plane.
105 	@param {float} znear The distance to the near clipping plane.
106 	@param {float} zfar The distance to the far clipping plane.
107 
108 	@returns {Array} an orthographic matrix defined by the arguments.
109 */
110 c3dl.makeOrtho = function(	left, right,
111 							bottom, top,
112 							znear, zfar)
113 {
114     var tx = -(right + left) / (right - left);
115     var ty = -(top + bottom) / (top - bottom);
116     var tz = -(zfar + znear) / (zfar - znear);
117 
118 	return c3dl.makeMatrix(
119 		2 / (left - right), 0, 0,  tx,
120 		0, 2 / (top - bottom), 0,  ty,
121 		0, 0, -2 / (zfar - znear), tz,
122 		0, 0, 0, 1);
123 }
124 
125 /**
126 	Create a perspective projection matrix.
127 
128 	@param {float} fovy The field of view angle in degrees in the Y 
129 	direction.
130 	@param {float} aspect The aspect ratio
131 	@param {float} znear The distance from the viewer to the near clipping
132 	plane.
133 	@param {float} zfar The distance from the viewer to the far clipping 
134 	plane.
135 
136 	@returns {Array} A perspective projection matrix. 
137 */
138 c3dl.makePerspective = function(fovy, aspect, znear, zfar)
139 {
140 	var ymax = znear * Math.tan(fovy * Math.PI / 360.0);
141 	var ymin = -ymax;
142 	var xmin = ymin * aspect;
143 	var xmax = ymax * aspect;
144 
145 	return c3dl.makeFrustum(xmin, xmax, ymin, ymax, znear, zfar);
146 }
147 
148 /**
149 	glFrustum Implementation
150 	
151 	@param {float} left The coordinate of the left vertical clipping plane.
152 	@param {float} right The coordinate of the right vertical clipping plane.
153 	@param {float} bottom The coordinate of the bottom horizontal clipping 
154 	plane.
155 	@param {float} top The coordinate of the top horizontal clipping plane.
156 	@param {float} znear The distance to the near clipping plane.
157 	@param {float} zfar The distance to the far clipping plane.
158 
159 	@returns {Array} A perspective projection matrix.
160 */
161 c3dl.makeFrustum = function(left, right,bottom, top,znear, zfar)
162 {
163     var X = 2 * znear / (right - left);
164     var Y = 2 * znear / (top - bottom);
165     var A = (right + left) / (right - left);
166     var B = (top + bottom) / (top - bottom);
167     var C = -(zfar + znear) / (zfar - znear);
168     var D = -2 * zfar * znear / (zfar - znear);
169 	
170 	// specify values in column major order
171 	return c3dl.makeMatrix(X, 0, 0, 0, 0, Y, 0, 0, A, B, C, -1, 0, 0, D, 0);
172 }
173 
174 /**
175 	Convert 'rad' radians into degrees.
176 
177 	@param {float} rad The value in radians to convert into degrees.
178 
179 	@returns {float} The value of 'rad' radians converted to degrees.
180 */
181 c3dl.radiansToDegrees = function(rad)
182 {
183 	return rad / (Math.PI * 2) * 360.0;
184 }
185 
186 /**
187 	Convert 'deg' degrees into radians.
188 
189 	@param {float} degrees The value in degrees to convert into radians.
190 
191 	@returns {float} The value of 'deg' degrees converted to radians.
192 */
193 c3dl.degreesToRadians = function(deg)
194 {
195 	return deg / 360.0 * (Math.PI * 2);
196 }
197 
198 /**	
199 	Get a random value from min to max inclusive
200 	
201 	@param {num} min
202 	@param {num} max
203 
204 	@returns {num} a random number from min to max.
205 */
206 c3dl.getRandom = function(min, max)
207 {
208 	var norm = Math.random();
209 	return ((max-min)*norm) + min;
210 }
211