1 /**
  2 @preserve
  3 
  4 BenchGL - A WebGL-based javascript graphic library.
  5 Copyright (c) 2010-2011 Matteo Meli.
  6  
  7 */
  8 
  9 (function() {
 10 
 11 // benchgl.js
 12 // Contains the global variable representing the framework and some utilities.
 13 
 14 // Unique global variable repesenting the framework
 15 this.BenchGL = this.BenchGL || {};
 16 
 17 // Special function to create namespaces
 18 BenchGL.namespace = function(name) {
 19 	var parts = name.split('.'),
 20 			parent = BenchGL;
 21 			
 22 	if (parts[0] === 'BenchGL') {
 23 		parts = parts.slice(1);
 24 	}
 25 	
 26 	for (var i = 0; i < parts.length; i++) {
 27 		if (typeof parent[parts[i]] === 'undefined') {
 28 			parent[parts[i]] = {};
 29 		}
 30 		parent = parent[parts[i]];
 31 	}
 32 	
 33 	return parent;
 34 };
 35 
 36 // Special function to globalize BenchGL library
 37 BenchGL.globalize = function() {
 38 	for (var module in BenchGL) {
 39 		for (var object in BenchGL[module]) {
 40 			window[object] = BenchGL[module][object];
 41 		}
 42 	}
 43 };
 44 
 45 // utils.js
 46 // General utility functions.
 47 
 48 // Gets a DOM element from its ID.
 49 function $(id) {
 50   return document.getElementById(id);
 51 }
 52 
 53 // This function provides a way to implement "class" inheritance.
 54 $.inherit = (function() {
 55 	var F = function() {};
 56 	return function(C, P) {
 57 		F.prototype = P.prototype;
 58 		C.prototype = new F();
 59 		C.uber = P.prototype;
 60 		C.prototype.constructor = C;
 61 	}
 62 }());
 63 
 64 // Merges two or more objects into one.
 65 $.mix = function() {
 66   var i, object, key, mix = {};
 67   for (i = 0, l = arguments.length; i < l; i++) {
 68     object = arguments[i];
 69     for (key in object) {
 70       if (object.hasOwnProperty(key)) {
 71         mix[key] = object[key];
 72       }
 73     }
 74   }
 75   return mix;
 76 };
 77 
 78 // Capitalizes a string.
 79 $.capitalize = function(text) {
 80   if (text && text.length > 0) {
 81     text = text.charAt(0).toUpperCase() + text.slice(1);
 82   }
 83   return text;
 84 };
 85 
 86 // Represents an empty function.
 87 $.empty = function() {};
 88 
 89 /**
 90  * Provides requestAnimationFrame in a cross browser way.
 91  * Copyright 2010, Google Inc.
 92  * All rights reserved.
 93  * @ignore
 94  */
 95 window.requestAnimFrame = (function() {
 96   return window.requestAnimationFrame ||
 97   window.webkitRequestAnimationFrame ||
 98   window.mozRequestAnimationFrame ||
 99   window.oRequestAnimationFrame ||
100   window.msRequestAnimationFrame ||
101   function(callback, element) {
102     window.setTimeout(callback, 1000 / 60);
103   };
104 }());
105 
106 // math.js
107 // Provides a math library to handle 3D vectors, matrices and quaternions.
108 
109 BenchGL.namespace('BenchGL.math.Vector3');
110 
111 BenchGL.math.Vector3 = (function() {
112 	
113 	// Dependencies
114   var acos = Math.acos,
115   		sqrt = Math.sqrt,
116 			
117 			// Private properties and methods
118       Vector3;
119   
120   /**
121    * Creates a new Vector3.
122    * @class Represents a vector in homogeneous 3D space.
123    * @param {Number} [x=0] The x coordinate.
124    * @param {Number} [y=0] The y coordinate.
125    * @param {Number} [z=0] The z coordinate.  
126    */
127   Vector3 = function(x, y, z) {
128     this.x = x || 0;
129     this.y = y || 0;
130     this.z = z || 0;
131   };
132   
133   /**
134    * Copies this Vector3 in a new one.
135    * @returns {Vector3} A copy of this Vector3. 
136    */
137   Vector3.prototype.copy = function() {
138     return new Vector3(this.x, this.y, this.z);
139   };
140   
141   /**
142    * Sets this Vector3 coordinates.
143    * @param {Number} x The x coordinate to set.
144    * @param {Number} y The y coordinate to set.
145    * @param {Number} z The z coordinate to set.
146    */
147   Vector3.prototype.set = function(x, y, z) {
148     this.x = x;
149     this.y = y;
150     this.z = z;
151   };
152   
153   /**
154    * Gets the norm of this Vector3.
155    * @returns {Number} The norm of this Vector3.
156    */
157   Vector3.prototype.norm = function() {
158     var x = this.x, y = this.y, z = this.z;
159     return sqrt(x * x + y * y + z * z);
160   };
161   
162   /**
163    * Gets the squared norm of this Vector3.
164    * @returns {Number} The squared norm of this Vector3. 
165    */
166   Vector3.prototype.normSqr = function() {
167     var x = this.x, y = this.y, z = this.z;
168     return (x * x + y * y + z * z);
169   };
170   
171   /**
172    * Negates this Vector3. Does not affect this Vector3.
173    * @returns {Vector3} A new vector representing the negation of this Vector3.
174    */
175   Vector3.prototype.negate = function() {
176     return new Vector3(-this.x, -this.y, -this.z);
177   };
178  	
179  	/**
180  	 * Negates this Vector3. Affects this Vector3.
181  	 * @returns {Vector3} The negated version of this Vector3.
182  	 */
183   Vector3.prototype.$negate = function() {
184     this.x = -this.x;
185     this.y = -this.y;
186     this.z = -this.z;
187     return this;
188   };
189   
190   /**
191    * Normalizes this Vector3. Does not affect this Vector3.
192    * @returns {Vector3} A new vector representing the normalized version of this Vector3.
193    */
194   Vector3.prototype.unit = function() {
195     var x = this.x, y = this.y, z = this.z, d = sqrt(x * x + y * y + z * z);
196     if (d > 0) {
197       return new Vector3(x / d, y / d, z / d);
198     }
199     return this.copy();
200   };
201 
202   /**
203    * Normalizes this Vector3. Affects this Vector3.
204    * @returns {Vector3} The normalized version of this Vector3.
205    */  
206   Vector3.prototype.$unit = function(){
207     var x = this.x, y = this.y, z = this.z, d = sqrt(x * x + y * y + z * z);
208     if (d > 0) {
209       this.$scale(1 / d);
210     }
211     return this;
212   };
213   
214   /**
215    * Adds another Vector3 to this Vector3. Does not affect this Vector3.
216    * @param {Vector3} vector The Vector3 to add.
217    * @returns {Vector3} A new vector representing the addition.
218    */
219   Vector3.prototype.add = function(vector) {
220     var x = this.x + vector.x, 
221     		y = this.y + vector.y, 
222     		z = this.z + vector.z;
223     return new Vector3(x, y, z);
224   };
225 
226   /**
227    * Adds another Vector3 to this Vector3. Affects this Vector3.
228    * @param {Vector3} vector The Vector3 to add.
229    * @returns {Vector3} This Vector3 now stores the sum.
230    */  
231   Vector3.prototype.$add = function(vector) {
232     this.x += vector.x;
233     this.y += vector.y;
234     this.z += vector.z;
235     return this;
236   };
237 
238   /**
239    * Subtracts another Vector3 to this Vector3. Does not affect this Vector3.
240    * @param {Vector3} vector The Vector3 to add.
241    * @returns {Vector3} A new vector representing the subtraction.
242    */    
243   Vector3.prototype.sub = function(vector) {
244     var x = this.x - vector.x, y = this.y - vector.y, z = this.z - vector.z;
245     return new Vector3(x, y, z);
246   };
247 
248   /**
249    * Subtracts another Vector3 to this Vector3. Affects this Vector3.
250    * @param {Vector3} vector The Vector3 to add.
251    * @returns {Vector3} This Vector3 now stores the subtraction.
252    */    
253   Vector3.prototype.$sub = function(vector) {
254     this.x -= vector.x;
255     this.y -= vector.y;
256     this.z -= vector.z;
257     return this;
258   };
259   
260   /**
261    * Scales this Vector3 by a factor. Does not affect this Vector3.
262    * @param {Number} f The factor to scale this Vector3 with.
263    * @returns {Vector3} A new vector representing the scaled version of this Vector3.
264    */
265   Vector3.prototype.scale = function(f) {
266     var x = this.x * f, y = this.y * f, z = this.z * f;
267     return new Vector3(x, y, z);
268   };
269 
270   /**
271    * Scales this Vector3 by a factor. Affects this Vector3
272    * @param {Number} f The factor to scale this Vector3 with.
273    * @returns {Vector3} This Vector3 now is scaled.
274    */  
275   Vector3.prototype.$scale = function(f) {
276     this.x *= f;
277     this.y *= f;
278     this.z *= f;
279     return this;
280   };
281   
282   /**
283    * Calculates the angle between this and another Vector3.
284    * @param {Vector3} vector The other Vector3 to calculate the angle with.
285    * @returns {Number} The angle between the two Vector3.
286    */
287   Vector3.prototype.angleWith = function(vector) {
288     var dot = this.dot(vector), normThis = this.norm(), normThat = vector.norm();
289     return acos(dot / (normThis * normThat));
290   };
291   
292   /**
293    * Calculates the distance between this and another Vector3.
294    * @param {Vector3} vector The other Vector3 to calculate the distance with.
295    * @returns {Number} The distance between the two Vector3.
296    */
297   Vector3.prototype.distTo = function(vector) {
298     var x = this.x - vector.x, y = this.y - vector.y, z = this.z - vector.z;
299     return sqrt(x * x + y * y + z * z);
300   };
301 
302   /**
303    * Calculates the squared distance between this and another Vector3.
304    * @param {Vector3} vector The other Vector3 to calculate the distance with.
305    * @returns {Number} The squared distance between the two Vector3.
306    */  
307   Vector3.prototype.distToSqr = function(vector) {
308     var x = this.x - vector.x, y = this.y - vector.y, z = this.z - vector.z;
309     return (x * x + y * y + z * z);
310   };
311   
312   /**
313    * Computes the dot product between this and another Vector3.
314    * @param {Vector3} vector The other Vector3 to compute the dot product with.
315    * @returns {Number} The dot product.
316    */
317   Vector3.prototype.dot = function(vector) {
318     return (this.x * vector.x + this.y * vector.y + this.z * vector.z);
319   };
320 
321   /**
322    * Computes the cross product between this and another Vector3. 
323    * Does not affect this Vector3.
324    * @param {Vector3} vector The other Vector3 to compute the dot product with.
325    * @returns {Vector3} A new vector representing the croos product.
326    */  
327   Vector3.prototype.cross = function(vector) {
328     var x = this.x, y = this.y, z = this.z, vx = vector.x, vy = vector.y, vz = vector.z;
329     return new Vector3(y * vz - z * vy, x * vz - z * vx, x * vy - y * vx);
330   };
331   
332   /**
333    * Gets the array version of this Vector3.
334    * @returns {Array} An array representation of this Vector3.
335    */
336   Vector3.prototype.toArray = function() {
337     return [this.x, this.y, this.z];
338   };
339   
340   return Vector3;
341   
342 }());
343 
344 BenchGL.namespace('BenchGL.math.Matrix4');
345 
346 BenchGL.math.Matrix4 = (function() {
347 
348 	// Dependencies
349 	var sin = Math.sin, 
350       cos = Math.cos, 
351       sqrt = Math.sqrt,
352       tan = Math.tan, 
353       pi = Math.PI,
354       Vec3 = BenchGL.math.Vector3,
355       
356       // Private properties and methods
357 			Matrix4;
358   
359   /**
360    * Creates a new Matrix4. If no argumnets are supplied returns the identity matrix.
361    * @class Represents a four by four matrix.
362    * @param {Number} [m11=1] The element at row 1 column 1.
363    * @param {Number} [m12=0] The element at row 1 column 2.
364    * @param {Number} [m13=0] The element at row 1 column 3.
365    * @param {Number} [m14=0] The element at row 1 column 4.
366    * @param {Number} [m21=0] The element at row 2 column 1.
367    * @param {Number} [m22=1] The element at row 2 column 2. 
368    * @param {Number} [m23=0] The element at row 2 column 3. 
369    * @param {Number} [m24=0] The element at row 2 column 4. 
370    * @param {Number} [m31=0] The element at row 3 column 1. 
371    * @param {Number} [m32=0] The element at row 3 column 2. 
372    * @param {Number} [m33=1] The element at row 3 column 3. 
373    * @param {Number} [m34=0] The element at row 3 column 4. 
374    * @param {Number} [m41=0] The element at row 4 column 1.
375    * @param {Number} [m42=0] The element at row 4 column 2. 
376    * @param {Number} [m43=0] The element at row 4 column 3. 
377    * @param {Number} [m44=1] The element at row 4 column 4.    
378    */
379   Matrix4 = function(m11, m12, m13, m14, 
380                      m21, m22, m23, m24, 
381                      m31, m32, m33, m34, 
382                      m41, m42, m43, m44) {
383     if (typeof m11 !== "undefined") {
384       this.set(m11, m12, m13, m14, 
385                m21, m22, m23, m24, 
386                m31, m32, m33, m34, 
387                m41, m42, m43, m44);
388     }
389     else {
390 	    this.m11 = this.m22 = this.m33 = this.m44 = 1; 
391 	    this.m12 = this.m13 = this.m14 = 0;
392 	    this.m21 = this.m23 = this.m24 = 0; 
393 	    this.m31 = this.m32 = this.m34 = 0; 
394 	    this.m41 = this.m42 = this.m43 = 0;
395     }
396   };
397 
398   /**
399    * Sets the elements of this Matrix4.
400    * @param {Number} m11 The element at row 1 column 1.
401    * @param {Number} m12 The element at row 1 column 2.
402    * @param {Number} m13 The element at row 1 column 3.
403    * @param {Number} m14 The element at row 1 column 4.
404    * @param {Number} m21 The element at row 2 column 1.
405    * @param {Number} m22 The element at row 2 column 2. 
406    * @param {Number} m23 The element at row 2 column 3. 
407    * @param {Number} m24 The element at row 2 column 4. 
408    * @param {Number} m31 The element at row 3 column 1. 
409    * @param {Number} m32 The element at row 3 column 2. 
410    * @param {Number} m33 The element at row 3 column 3. 
411    * @param {Number} m34 The element at row 3 column 4. 
412    * @param {Number} m41 The element at row 4 column 1.
413    * @param {Number} m42 The element at row 4 column 2. 
414    * @param {Number} m43 The element at row 4 column 3. 
415    * @param {Number} m44 The element at row 4 column 4.    
416    */  
417   Matrix4.prototype.set = function(m11, m12, m13, m14, 
418                                    m21, m22, m23, m24, 
419                                    m31, m32, m33, m34, 
420                                    m41, m42, m43, m44){
421     this.m11 = m11;
422     this.m12 = m12;
423     this.m13 = m13;
424     this.m14 = m14;
425     this.m21 = m21;
426     this.m22 = m22;
427     this.m23 = m23;
428     this.m24 = m24;
429     this.m31 = m31;
430     this.m32 = m32;
431     this.m33 = m33;
432     this.m34 = m34;
433     this.m41 = m41;
434     this.m42 = m42;
435     this.m43 = m43;
436     this.m44 = m44;
437     return this;
438   };
439   
440   /**
441    * Sets this Matrix4 to the identity matrix. Affects this Matrix4.
442    * @returns {Matrix4} This Matrix4 is now an identity matrix.
443    */
444   Matrix4.prototype.$identity = function() {
445     this.m11 = this.m22 = this.m33 = this.m44 = 1; 
446     this.m12 = this.m13 = this.m14 = 0;
447     this.m21 = this.m23 = this.m24 = 0; 
448     this.m31 = this.m32 = this.m34 = 0; 
449     this.m41 = this.m42 = this.m43 = 0;
450 	  return this;    
451   };
452   
453   /**
454    * Copies this Matrix4 in another one.
455    * @returns {Matrix4} A copy of this Matrix4.
456    */
457   Matrix4.prototype.copy = function() {
458     var m11 = this.m11, m12 = this.m12, m13 = this.m13, m14 = this.m14, 
459         m21 = this.m21, m22 = this.m22, m23 = this.m23, m24 = this.m24, 
460         m31 = this.m31, m32 = this.m32, m33 = this.m33, m34 = this.m34, 
461         m41 = this.m41, m42 = this.m42, m43 = this.m43, m44 = this.m44;
462     
463     return new Matrix4(m11, m12, m13, m14, 
464                        m21, m22, m23, m24, 
465                        m31, m32, m33, m34, 
466                        m41, m42, m43, m44);
467   };
468   
469   /**
470    * Adds this Matrix4 to another one. Does not affect this Matrix4.
471    * @param {Matrix4} m The Matrix4 to add.
472    * @returns {Matrix4} A new matrix containing the addition.
473    */
474   Matrix4.prototype.add = function(m) {
475     var r = new Matrix4();
476     
477     r.m11 = this.m11 + m.m11;
478     r.m12 = this.m12 + m.m12;
479     r.m13 = this.m13 + m.m13;
480     r.m14 = this.m14 + m.m14;
481     r.m21 = this.m21 + m.m21;
482     r.m22 = this.m22 + m.m22;
483     r.m23 = this.m23 + m.m23;
484     r.m24 = this.m24 + m.m24;
485     r.m31 = this.m31 + m.m31;
486     r.m32 = this.m32 + m.m32;
487     r.m33 = this.m33 + m.m33;
488     r.m34 = this.m34 + m.m34;
489     r.m41 = this.m41 + m.m41;
490     r.m42 = this.m42 + m.m42;
491     r.m43 = this.m43 + m.m43;
492     r.m44 = this.m44 + m.m44;
493     
494     return r;
495   };
496 
497   /**
498    * Adds this Matrix4 to another one. Affects this Matrix4.
499    * @param {Matrix4} m The Matrix4 to add.
500    * @returns {Matrix4} This Matrix4 now contains the addition.
501    */  
502   Matrix4.prototype.$add = function(m){
503     this.m11 += m.m11;
504     this.m12 += m.m12;
505     this.m13 += m.m13;
506     this.m14 += m.m14;
507     this.m21 += m.m21;
508     this.m22 += m.m22;
509     this.m23 += m.m23;
510     this.m24 += m.m24;
511     this.m31 += m.m31;
512     this.m32 += m.m32;
513     this.m33 += m.m33;
514     this.m34 += m.m34;
515     this.m41 += m.m41;
516     this.m42 += m.m42;
517     this.m43 += m.m43;
518     this.m44 += m.m44;
519     return this;
520   };
521 
522   /**
523    * Subtracts this Matrix4 to another one. Does not affect this Matrix4.
524    * @param {Matrix4} m The Matrix4 to add.
525    * @returns {Matrix4} A new matrix containing the subtraction.
526    */  
527   Matrix4.prototype.sub = function(m){
528     var r = new Matrix4();
529     
530     r.m11 = this.m11 - m.m11;
531     r.m12 = this.m12 - m.m12;
532     r.m13 = this.m13 - m.m13;
533     r.m14 = this.m14 - m.m14;
534     r.m21 = this.m21 - m.m21;
535     r.m22 = this.m22 - m.m22;
536     r.m23 = this.m23 - m.m23;
537     r.m24 = this.m24 - m.m24;
538     r.m31 = this.m31 - m.m31;
539     r.m32 = this.m32 - m.m32;
540     r.m33 = this.m33 - m.m33;
541     r.m34 = this.m34 - m.m34;
542     r.m41 = this.m41 - m.m41;
543     r.m42 = this.m42 - m.m42;
544     r.m43 = this.m43 - m.m43;
545     r.m44 = this.m44 - m.m44;
546     
547     return r;
548   };
549 
550   /**
551    * Subtracts this Matrix4 to another one. Affects this Matrix4.
552    * @param {Matrix4} m The Matrix4 to add.
553    * @returns {Matrix4} This Matrix4 now contains the subtraction.
554    */   
555   Matrix4.prototype.$sub = function(m){
556     this.m11 -= m.m11;
557     this.m12 -= m.m12;
558     this.m13 -= m.m13;
559     this.m14 -= m.m14;
560     this.m21 -= m.m21;
561     this.m22 -= m.m22;
562     this.m23 -= m.m23;
563     this.m24 -= m.m24;
564     this.m31 -= m.m31;
565     this.m32 -= m.m32;
566     this.m33 -= m.m33;
567     this.m34 -= m.m34;
568     this.m41 -= m.m41;
569     this.m42 -= m.m42;
570     this.m43 -= m.m43;
571     this.m44 -= m.m44;
572     return this;
573   };
574 
575 	/**
576 	 * Multiplies a Vector3 by this Matrix4. (r = M*v)
577 	 * @returns {Vector3} A new vector with the result of the multiplication.
578 	 */
579   Matrix4.prototype.multiplyVec3 = function(vector) {
580     var vx = vector.x, 
581     		vy = vector.y, 
582     		vz = vector.z;
583     
584     return new Vec3(this.m11 * vx + this.m12 * vy + this.m13 * vz + this.m14, 
585     									 this.m21 * vx + this.m22 * vy + this.m23 * vz + this.m24, 
586     									 this.m31 * vx + this.m32 * vy + this.m33 * vz + this.m34);
587   };
588   
589 	/**
590 	 * Multiplies this Matrix4 by another one. Does not affect this Matrix4.
591 	 * @returns {Matrix4} A new matrix with the result of the multiplication.
592 	 */  
593   Matrix4.prototype.multiplyMat4 = function(m) {
594     var a11 = this.m11, a12 = this.m12, a13 = this.m13, a14 = this.m14, 
595         a21 = this.m21, a22 = this.m22, a23 = this.m23, a24 = this.m24, 
596         a31 = this.m31, a32 = this.m32, a33 = this.m33, a34 = this.m34, 
597         a41 = this.m41, a42 = this.m42, a43 = this.m43, a44 = this.m44, 
598         b11 = m.m11, b12 = m.m12, b13 = m.m13, b14 = m.m14, 
599         b21 = m.m21, b22 = m.m22, b23 = m.m23, b24 = m.m24, 
600         b31 = m.m31, b32 = m.m32, b33 = m.m33, b34 = m.m34, 
601         b41 = m.m41, b42 = m.m42, b43 = m.m43, b44 = m.m44, 
602         m11, m12, m13, m14, 
603         m21, m22, m23, m24, 
604         m31, m32, m33, m34, 
605         m41, m42, m43, m44;
606     
607     m11 = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
608     m12 = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
609     m13 = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
610     m14 = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
611     
612     m21 = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
613     m22 = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
614     m23 = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
615     m24 = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
616     
617     m31 = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
618     m32 = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
619     m33 = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
620     m34 = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
621     
622     m41 = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
623     m42 = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
624     m43 = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
625     m44 = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
626     
627     return new Matrix4(m11, m12, m13, m14, 
628                        m21, m22, m23, m24, 
629                        m31, m32, m33, m34, 
630                        m41, m42, m43, m44);
631   };
632 
633 	/**
634 	 * Multiplies this Matrix4 by another one. Affects this Matrix4.
635 	 * @returns {Matrix4} This Matrix4 now stores the result of the multiplication.
636 	 */   
637   Matrix4.prototype.$multiplyMat4 = function(m){
638     var a11 = this.m11, a12 = this.m12, a13 = this.m13, a14 = this.m14, 
639         a21 = this.m21, a22 = this.m22, a23 = this.m23, a24 = this.m24, 
640         a31 = this.m31, a32 = this.m32, a33 = this.m33, a34 = this.m34, 
641         a41 = this.m41, a42 = this.m42, a43 = this.m43, a44 = this.m44, 
642         b11 = m.m11, b12 = m.m12, b13 = m.m13, b14 = m.m14, 
643         b21 = m.m21, b22 = m.m22, b23 = m.m23, b24 = m.m24, 
644         b31 = m.m31, b32 = m.m32, b33 = m.m33, b34 = m.m34, 
645         b41 = m.m41, b42 = m.m42, b43 = m.m43, b44 = m.m44, 
646         m11, m12, m13, m14, 
647         m21, m22, m23, m24, 
648         m31, m32, m33, m34, 
649         m41, m42, m43, m44;
650     
651     m11 = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
652     m12 = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
653     m13 = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
654     m14 = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
655     
656     m21 = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
657     m22 = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
658     m23 = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
659     m24 = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
660     
661     m31 = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
662     m32 = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
663     m33 = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
664     m34 = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
665     
666     m41 = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
667     m42 = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
668     m43 = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
669     m44 = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
670     
671     this.set(m11, m12, m13, m14, 
672              m21, m22, m23, m24, 
673              m31, m32, m33, m34, 
674              m41, m42, m43, m44);
675     
676     return this;
677   };
678   
679   /**
680    * Transpose this Matrix4. Does not affect this Matrix4.
681    * @returns {Matrix4} A new matrix representing the transpose of this Matrix4.
682    */
683   Matrix4.prototype.transpose = function(){
684     var m11 = this.m11, m12 = this.m12, m13 = this.m13, m14 = this.m14, 
685         m21 = this.m21, m22 = this.m22, m23 = this.m23, m24 = this.m24, 
686         m31 = this.m31, m32 = this.m32, m33 = this.m33, m34 = this.m34, 
687         m41 = this.m41, m42 = this.m42, m43 = this.m43, m44 = this.m44;
688     
689     return new Matrix4(m11, m21, m31, m41, 
690                        m12, m22, m32, m42, 
691                        m13, m23, m33, m43, 
692                        m14, m24, m34, m44);
693   };
694 
695   /**
696    * Transpose this Matrix4. Affects this Matrix4.
697    * @returns {Matrix4} This Matrix4 is now transposed.
698    */  
699   Matrix4.prototype.$transpose = function(){
700     var m11 = this.m11, m12 = this.m12, m13 = this.m13, m14 = this.m14, 
701         m21 = this.m21, m22 = this.m22, m23 = this.m23, m24 = this.m24, 
702         m31 = this.m31, m32 = this.m32, m33 = this.m33, m34 = this.m34, 
703         m41 = this.m41, m42 = this.m42, m43 = this.m43, m44 = this.m44;
704     
705     this.set(m11, m21, m31, m41, 
706              m12, m22, m32, m42, 
707              m13, m23, m33, m43, 
708              m14, m24, m34, m44);
709     
710     return this;
711   };
712 
713   /**
714    * Inverts this Matrix4. Does not affect this Matrix4.
715    * @returns {Matrix4} A new matrix representing the inverted of this MAtrix4.
716    */  
717   Matrix4.prototype.invert = function() {
718     var m11 = this.m11, m12 = this.m12, m13 = this.m13, m14 = this.m14, 
719         m21 = this.m21, m22 = this.m22, m23 = this.m23, m24 = this.m24, 
720         m31 = this.m31, m32 = this.m32, m33 = this.m33, m34 = this.m34, 
721         m41 = this.m41, m42 = this.m42, m43 = this.m43, m44 = this.m44,
722     
723         s0 = m11 * m22 - m12 * m21, 
724         s1 = m11 * m23 - m13 * m21, 
725         s2 = m11 * m24 - m14 * m21, 
726         s3 = m12 * m23 - m13 * m22, 
727         s4 = m12 * m24 - m14 * m22, 
728         s5 = m13 * m24 - m14 * m23, 
729         c0 = m31 * m42 - m32 * m41, 
730         c1 = m31 * m43 - m33 * m41, 
731         c2 = m31 * m44 - m34 * m41, 
732         c3 = m32 * m43 - m33 * m42, 
733         c4 = m32 * m44 - m34 * m42, 
734         c5 = m33 * m44 - m34 * m43,
735     
736         det = s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0,
737     
738         a11 = m22 * c5 - m23 * c4 + m24 * c3, 
739         a12 = -m12 * c5 + m13 * c4 - m14 * c3, 
740         a13 = m42 * s5 - m43 * s4 + m44 * s3, 
741         a14 = -m32 * s5 + m33 * s4 - m34 * s3, 
742         a21 = -m21 * c5 + m23 * c2 - m24 * c1, 
743         a22 = m11 * c5 - m13 * c2 + m14 * c1, 
744         a23 = -m41 * s5 + m43 * s2 - m44 * s1, 
745         a24 = m31 * s5 - m33 * s2 + m34 * s1, 
746         a31 = m21 * c4 - m22 * c2 + m24 * c0, 
747         a32 = -m11 * c4 + m12 * c2 - m14 * c0, 
748         a33 = m41 * s4 - m42 * s2 + m44 * s0, 
749         a34 = -m31 * s4 + m32 * s2 - m34 * s0, 
750         a41 = -m21 * c3 + m22 * c1 - m23 * c0, 
751         a42 = m11 * c3 - m12 * c1 + m13 * c0, 
752         a43 = -m41 * s3 + m42 * s1 - m43 * s0, 
753         a44 = m31 * s3 - m32 * s1 + m33 * s0;
754     
755     return new Matrix4(a11 / det, a12 / det, a13 / det, a14 / det, 
756                        a21 / det, a22 / det, a23 / det, a24 / det, 
757                        a31 / det, a32 / det, a33 / det, a34 / det, 
758                        a41 / det, a42 / det, a43 / det, a44 / det);
759   };
760 
761   /**
762    * Inverts this Matrix4. Affects this Matrix4.
763    * @returns {Matrix4} This Matrix4 is now inverted.
764    */    
765   Matrix4.prototype.$invert = function() {
766     var m11 = this.m11, m12 = this.m12, m13 = this.m13, m14 = this.m14, 
767         m21 = this.m21, m22 = this.m22, m23 = this.m23, m24 = this.m24, 
768         m31 = this.m31, m32 = this.m32, m33 = this.m33, m34 = this.m34, 
769         m41 = this.m41, m42 = this.m42, m43 = this.m43, m44 = this.m44,
770     
771         s0 = m11 * m22 - m12 * m21, 
772         s1 = m11 * m23 - m13 * m21, 
773         s2 = m11 * m24 - m14 * m21, 
774         s3 = m12 * m23 - m13 * m22, 
775         s4 = m12 * m24 - m14 * m22, 
776         s5 = m13 * m24 - m14 * m23, 
777         c0 = m31 * m42 - m32 * m41, 
778         c1 = m31 * m43 - m33 * m41, 
779         c2 = m31 * m44 - m34 * m41, 
780         c3 = m32 * m43 - m33 * m42, 
781         c4 = m32 * m44 - m34 * m42, 
782         c5 = m33 * m44 - m34 * m43,
783     
784         det = s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0,
785     
786         a11 = m22 * c5 - m23 * c4 + m24 * c3, 
787         a12 = -m12 * c5 + m13 * c4 - m14 * c3, 
788         a13 = m42 * s5 - m43 * s4 + m44 * s3, 
789         a14 = -m32 * s5 + m33 * s4 - m34 * s3, 
790         a21 = -m21 * c5 + m23 * c2 - m24 * c1, 
791         a22 = m11 * c5 - m13 * c2 + m14 * c1, 
792         a23 = -m41 * s5 + m43 * s2 - m44 * s1, 
793         a24 = m31 * s5 - m33 * s2 + m34 * s1, 
794         a31 = m21 * c4 - m22 * c2 + m24 * c0, 
795         a32 = -m11 * c4 + m12 * c2 - m14 * c0, 
796         a33 = m41 * s4 - m42 * s2 + m44 * s0, 
797         a34 = -m31 * s4 + m32 * s2 - m34 * s0, 
798         a41 = -m21 * c3 + m22 * c1 - m23 * c0, 
799         a42 = m11 * c3 - m12 * c1 + m13 * c0, 
800         a43 = -m41 * s3 + m42 * s1 - m43 * s0, 
801         a44 = m31 * s3 - m32 * s1 + m33 * s0;
802     
803     this.set(a11 / det, a12 / det, a13 / det, a14 / det, 
804              a21 / det, a22 / det, a23 / det, a24 / det, 
805              a31 / det, a32 / det, a33 / det, a34 / det, 
806              a41 / det, a42 / det, a43 / det, a44 / det);
807     
808     return this;
809   };
810   
811   /**
812    * Gets a Float32Array representation of this Matrix4.
813    * @returns {Float32Array} A new Float32Array containing the elements of this Matrix.
814    */
815   Matrix4.prototype.toFloat32Array = function() {
816     return new Float32Array([this.m11, this.m21, this.m31, this.m41, 
817                              this.m12, this.m22, this.m32, this.m42, 
818                              this.m13, this.m23, this.m33, this.m43, 
819                              this.m14, this.m24, this.m34, this.m44]);
820   };
821   
822   /**
823    * Creates the identity matrix.
824    * @returns {Matrix4} The identity matrix.
825    */
826   Matrix4.Identity = function() {
827   	return new Matrix4();
828   };
829   
830   /**
831    * Creates a translation matrix.
832    * @param {Number} x The translation on x coordinate.
833    * @param {Number} y The translation on y coordinate.
834    * @param {Number} z The translation on z coordinate.      
835    * @returns {Matrix4} A translation matrix.
836    */
837   Matrix4.Translate = function(x, y, z){
838     return new Matrix4(1, 0, 0, x, 
839                        0, 1, 0, y, 
840                        0, 0, 1, z, 
841                        0, 0, 0, 1);
842   };
843 
844   /**
845    * Creates a scale matrix.
846    * @param {Number} x The scale on x coordinate.
847    * @param {Number} y The scale on y coordinate.
848    * @param {Number} z The scale on z coordinate.      
849    * @returns {Matrix4} A scale matrix.
850    */  
851   Matrix4.Scale = function(x, y, z){
852     return new Matrix4(x, 0, 0, 0, 
853                        0, y, 0, 0, 
854                        0, 0, z, 0, 
855                        0, 0, 0, 1);
856   };
857 
858   /**
859    * Creates a general rotation matrix around an axis.
860    * @param {Number} angle The rotation angle in radians.
861    * @param {Number} x The axis x coordinate.
862    * @param {Number} y The axis y coordinate.
863    * @param {Number} z The axis z coordinate.      
864    * @returns {Matrix4} A general rotation matrix.
865    */   
866   Matrix4.Rotate = function(angle, x, y, z) {
867     var axis = new Vec3(x, y, z).$unit(), 
868         ax = axis.x, ay = axis.y, az = axis.z, 
869         s = sin(angle), c = cos(angle), t = 1 - c;
870     return new Matrix4(t * ax * ax + c, t * ax * ay - az * s, t * ax * az + ay * s, 0, 
871                        t * ax * ay + az * s, t * ay * ay + c, t * ay * az - ax * s, 0, 
872                        t * ax * az - ay * s, t * ay * az + ax * s, t * az * az + c, 0, 
873                        0, 0, 0, 1);
874   };
875 
876   /**
877    * Creates a rotation matrix around an x, y and z axis.
878    * @param {Number} rx The rotation angle around x axis.
879    * @param {Number} ry The rotation angle around y axis.
880    * @param {Number} rz The rotation angle around z axis.    
881    * @returns {Matrix4} A XYZ rotation matrix.
882    */  
883   Matrix4.RotateXYZ = function(rx, ry, rz) {
884     var sx = sin(rx), cx = cos(rx), 
885         sy = sin(ry), cy = cos(ry), 
886         sz = sin(rz), cz = cos(rz);
887     
888     return new Matrix4(cy * cz, -cx * sz + sx * sy * cz, sx * sz + cx * sy * cz, 0,
889                        cy * sz, cx * cz + sx * sy * sz, -sx * cz + cx * sy * sz, 0, 
890                        -sy, sx * cy, cx * cy, 0, 
891                        0, 0, 0, 1);
892   };
893 
894   /**
895    * Creates a lookAt matrix.
896    * @param {Vector3} eye The eye vector.
897    * @param {Vector3} direction The direction vector.
898    * @param {Vector3} up The up vector.    
899    * @returns {Matrix4} A lookAt Matrix4.
900    */   
901   Matrix4.LookAt = function(eye, direction, up) {
902     var x, y, z;
903     
904     z = eye.sub(direction);
905     z.$unit();
906     x = up.cross(z);
907     x.$unit();
908     y = z.cross(x);
909     y.$unit();
910     
911     return new Matrix4(x.x, x.y, x.z, -x.dot(eye), 
912                        y.x, y.y, y.z, -y.dot(eye), 
913                        z.x, z.y, z.z, -z.dot(eye), 
914                        0, 0, 0, 1);
915   };
916 
917   /**
918    * Creates a frustum matrix.
919    * @param {Number} left The left clipping plane.
920    * @param {Number} right The right clipping plane.
921    * @param {Number} bottom The bottom clipping plane.
922    * @param {Number} top The top clipping plane.
923    * @param {Number} near The near clipping plane.
924    * @param {Number} far The far clipping plane.  
925    * @returns {Matrix4} A frustum matrix.
926    */  
927   Matrix4.Frustum = function(left, right, bottom, top, near, far) {
928     var x = 2.0 * near / (right - left), 
929         y = 2.0 * near / (top - bottom),
930         a = (right + left) / (right - left),
931         b = (top + bottom) / (top - bottom),
932         c = -(far + near) / (far - near),
933         d = -2.0 * far * near / (far - near);
934     
935     return new Matrix4(x, 0,  a, 0, 
936                        0, y,  b, 0, 
937                        0, 0,  c, d, 
938                        0, 0, -1, 0);
939   };
940 
941   /**
942    * Creates a perspective matrix.
943    * @param {Number} fovy The vertical field of view angle.
944    * @param {Number} aspect The aspect ratio aka the horizontal field of view angle.
945    * @param {Number} near The near clipping plane.
946    * @param {Number} far The far clipping plane.  
947    * @returns {Matrix4} A perspective matrix.
948    */    
949   Matrix4.Perspective = function(fovy, aspect, near, far) {
950     var ymax = near * tan(fovy * pi / 360.0),
951         ymin = -ymax,
952         xmin = ymin * aspect,
953         xmax = ymax * aspect;
954     
955     return Matrix4.Frustum(xmin, xmax, ymin, ymax, near, far);
956   };
957 
958 	return Matrix4;
959   
960 }());
961 
962 BenchGL.namespace('BenchGL.math.Quaternion');
963 
964 BenchGL.math.Quaternion = (function() {
965   
966   // Dependencies
967   var sin = Math.sin,
968   		cos = Math.cos,
969   		Mat4 = BenchGL.math.Matrix4,
970   		
971   		// Private properties and methods
972   		Quaternion;
973   /**
974    * Creates a new Quaternion.
975    * @class	Represents a quaternion.
976    * @param {Number} a The scalar part.
977    * @param {Number} b The i component of the vector part.
978    * @param {Number} c The j component of the vector part.
979    * @param {Number} d The k component of the vector part.
980    */
981   Quaternion = function(a, b, c, d) {
982     if (typeof a !== "undefined") {
983       this.a = a;
984       this.b = b;
985       this.c = c;
986       this.d = d;
987     }
988     else {
989       this.a = 1;
990       this.b = 0;
991       this.c = 0;
992       this.d = 0;
993     }
994   };
995   
996   /**
997    * Sets this Quaternion as the identity quaternion.
998    * @returns {Quaternion} This Quaternion is now the identity quaternion.
999    */
1000   Quaternion.prototype.identity = function() {
1001     this.a = 1;
1002     this.b = 0;
1003     this.c = 0;
1004     this.d = 0;
1005     return this;
1006   };
1007   
1008   /**
1009    * Multiplies this Quaternion with another one. Does not affect this Quaternion.
1010    * @param {Quaternion} quat The Quaternion to multiply with.
1011    * @returns {Quaternion} A new quaternion containing the multiplication's result.
1012    */
1013   Quaternion.prototype.multiply = function(quat) {
1014     var a1 = this.m, 
1015         b1 = this.b, 
1016         c1 = this.c, 
1017         d1 = this.d, 
1018         a2 = quat.a, 
1019         b2 = quat.b, 
1020         c2 = quat.c, 
1021         d2 = quat.d, 
1022     
1023         a = a1 * a2 - b1 * b2 - c1 * c2 - d1 * d2,
1024         b = a1 * b2 + b1 * a2 + c1 * d2 - d1 * c2,
1025         c = a1 * c2 - b1 * d2 + c1 * a2 + d1 * b2,
1026         d = a1 * d2 + b1 * c2 - c1 * b2 + d1 * a2;
1027     
1028     return new Quaternion(a, b, c, d);
1029   };
1030 
1031   /**
1032    * Multiplies this Quaternion with another one. Affects this Quaternion.
1033    * @param {Quaternion} quat The Quaternion to multiply with.
1034    * @returns {Quaternion} This Quaternion now stores the result of the multiplication.
1035    */  
1036   Quaternion.prototype.$multiply = function(quat) {
1037     var a1 = this.m, 
1038         b1 = this.b, 
1039         c1 = this.c, 
1040         d1 = this.d, 
1041         a2 = quat.a, 
1042         b2 = quat.b, 
1043         c2 = quat.c, 
1044         d2 = quat.d, 
1045     
1046         a = a1 * a2 - b1 * b2 - c1 * c2 - d1 * d2,
1047         b = a1 * b2 + b1 * a2 + c1 * d2 - d1 * c2,
1048         c = a1 * c2 - b1 * d2 + c1 * a2 + d1 * b2,
1049         d = a1 * d2 + b1 * c2 - c1 * b2 + d1 * a2;
1050     
1051     this.m = a;
1052     this.b = b;
1053     this.c = c;
1054     this.d = d;
1055         
1056     return this;
1057   };
1058   
1059   /**
1060    * Gets a Matrix4 representing this Quaternion.
1061    * @returns {Matrix4} A matrix representing this Quaternion.
1062    */
1063   Quaternion.prototype.toMatrix4 = function() {
1064     var a = this.m, b = this.b, c = this.c, d = this.d, 
1065         b2 = b * b, c2 = c * c, d2 = d * d, 
1066         bc = b * c, bd = b * d, cd = c * d, ab = a * b, ac = a * c, ad = a * d;
1067     
1068     return new Mat4(1 - 2 * c2 - 2 * d2, 2 * bc - 2 * ad, 2 * ac + 2 * bd, 0, 
1069                        2 * bc + 2 * ad, 1 - 2 * b2 - 2 * d2, 2 * cd - 2 * ab, 0, 
1070                        2 * bd - 2 * ac, 2 * ab + 2 * cd, 1 - 2 * b2 - 2 * c2, 0, 
1071                        0, 0, 0, 1);
1072   };
1073   
1074   /**
1075    * Creates a new quaternion from euler angles.
1076    * @returns {Quaternion} A new quaternion from the euler angles.
1077    */
1078   Quaternion.FromEulerAngles = function(pitch, roll, yaw) {
1079     var p = pitch * 0.5, y = yaw * 0.5, r = roll * 0.5, 
1080         cp = cos(p), sp = sin(p), 
1081         cy = cos(y), sy = sin(y), 
1082         cr = cos(r), sr = sin(r),
1083     
1084         a = cp * cy * cr + sp * sy * sr,
1085         b = sp * cy * cr - cp * sy * sr,
1086         c = cp * sy * cr + sp * cy * sr,
1087         d = cp * cy * sr - sp * sy * cr;
1088     
1089     return new Quaternion(a, b, c, d);
1090   };
1091   
1092   return Quaternion;
1093   
1094 }());
1095 
1096 BenchGL.namespace('BenchGL.math.MatrixStack');
1097 
1098 BenchGL.math.MatrixStack = (function() {
1099 
1100 	// Dependencies
1101 	var Mat4 = BenchGL.math.Matrix4,
1102 			pi = Math.PI,
1103 			
1104 			// Private properties and methods
1105       MatrixStack;
1106 	
1107 	/**
1108 	 * Creates a new MatrixStack.
1109 	 * @class Representa a stack for 4x4 matrices.
1110 	 */
1111 	MatrixStack = function() {
1112 		this.stack = [];
1113 		this.current = 0;
1114 		this.stack.push(Mat4.Identity());
1115 	};
1116 	
1117 	/**
1118 	 * Gets the matrix on top of this MatrixStack.
1119 	 * @returns {Matrix4} The matrix on top of the stack.
1120 	 */
1121 	MatrixStack.prototype.top = function() {
1122 		return this.stack[this.current];
1123 	};
1124 	
1125 	/**
1126 	 * Pushes a copy of the top matrix on this MatrixStack.
1127 	 * @returns {MatrixStack} Returns this MatrixStack.
1128 	 */
1129 	MatrixStack.prototype.push = function() {
1130 		this.stack.push(this.stack[this.current].copy());
1131 		this.current++;
1132 		return this;
1133 	};
1134 
1135 	/**
1136 	 * Pops the top matrix on top of this MatrixStack.
1137 	 * @returns {MatrixStack} Returns this MatrixStack.
1138 	 */	
1139 	MatrixStack.prototype.pop = function() {
1140 		if (this.current > 0) {
1141 			this.stack.pop();
1142 			this.current--;
1143 		}
1144 		return this;
1145 	};
1146 
1147 	/**
1148 	 * Loads a matrix on top of this MatrixStack.
1149 	 * @param {Matrix4} The matrix to load. 
1150 	 * @returns {MatrixStack} Returns this MatrixStack.
1151 	 */		
1152 	MatrixStack.prototype.load = function(matrix) {
1153 		this.stack[this.current] = matrix;
1154 		return this;
1155 	};
1156 
1157 	/**
1158 	 * Loads the identity matrix on top of this MatrixStack.
1159 	 * @returns {MatrixStack} Returns this MatrixStack.
1160 	 */		
1161 	MatrixStack.prototype.loadIdentity = function() {
1162 		this.stack[this.current] = Mat4.Identity();
1163 		return this;
1164 	};
1165 
1166 	/**
1167 	 * Multiplies a matrix with the one on top of this MatrixStack.
1168 	 * @param {Matrix4} The matrix to multiply with. 
1169 	 * @returns {MatrixStack} Returns this MatrixStack.
1170 	 */		
1171 	MatrixStack.prototype.multiply = function(matrix) {
1172 		this.stack[this.current].$multiplyMat4(matrix);
1173 		return this;
1174 	};
1175 	
1176 	/**
1177 	 * Apply a rotation to the matrix on top of this MatrixStack.
1178 	 * @param {Number} angle The rotation angle.
1179    * @param {Number} x The rotation axis x coordinate.
1180    * @param {Number} y The rotation axis y coordinate.
1181    * @param {Number} z The rotation axis z coordinate.  
1182 	 * @returns {MatrixStack} Returns this MatrixStack.
1183 	 */	
1184 	MatrixStack.prototype.rotate = function(angle, x, y, z) {
1185 		this.multiply(Mat4.Rotate(angle * pi / 180, x, y, z));
1186 		return this;
1187 	};
1188 
1189 	/**
1190 	 * Apply a rotation to the matrix on top of this MatrixStack.
1191 	 * @param {Number} rx The rotation angle around X axis. 
1192 	 * @param {Number} ry The rotation angle around Y axis.
1193 	 * @param {Number} rz The rotation angle around Z axis. 
1194 	 * @returns {MatrixStack} Returns this MatrixStack.
1195 	 */		
1196 	MatrixStack.prototype.rotateXYZ = function(rx, ry, rz) {
1197 		var conversion = pi / 180;
1198 		this.multiply(Mat4.RotateXYZ(rx * conversion, ry * conversion, rz * conversion));
1199 		return this;
1200 	};
1201 
1202 	/**
1203 	 * Apply a scale transformation to the matrix on top of this MatrixStack.
1204 	 * @param {Number} x The x scale factor. 
1205 	 * @param {Number} y The y scale factor.
1206 	 * @param {Number} z The z scale factor. 
1207 	 * @returns {MatrixStack} Returns this MatrixStack.
1208 	 */	
1209 	MatrixStack.prototype.scale = function(x, y, z) {
1210 		this.multiply(Mat4.Scale(x, y, z));
1211 		return this;
1212 	};
1213 
1214 	/**
1215 	 * Apply a translation to the matrix on top of this MatrixStack.
1216 	 * @param {Number} x The x translation factor. 
1217 	 * @param {Number} y The y translation factor.
1218 	 * @param {Number} z The z translation factor. 
1219 	 * @returns {MatrixStack} Returns this MatrixStack.
1220 	 */		
1221 	MatrixStack.prototype.translate = function(x, y, z) {
1222 		this.multiply(Mat4.Translate(x, y, z));
1223 		return this;
1224 	};
1225 
1226 	/**
1227 	 * Apply a lookAt transformation to the matrix on top of this MatrixStack.
1228 	 * @param {Vector3} eye The eye vector. 
1229 	 * @param {Vector3} direction The direction vector. 
1230 	 * @param {Vector3} up The up vector.  
1231 	 * @returns {MatrixStack} Returns this MatrixStack.
1232 	 */
1233 	MatrixStack.prototype.lookAt = function(eye, direction, up) {
1234 		this.multiply(Mat4.LookAt(eye, direction, up));
1235 		return this;
1236 	};
1237 
1238   /**
1239    * Apply a perspective transformation to the matrix on top of this MatrixStack.
1240    * @param {Number} fovy The vertical field of view angle.
1241    * @param {Number} aspect The aspect ratio aka the horizontal field of view angle.
1242    * @param {Number} near The near clipping plane.
1243    * @param {Number} far The far clipping plane.  
1244    * @returns {MatrixStack} Returns this MatrixStack.
1245    */  			
1246 	MatrixStack.prototype.perspective = function(fovy, aspect, near, far) {
1247 		this.multiply(Mat4.Perspective(fovy, aspect, near, far));
1248 		return this;
1249 	};
1250 
1251   /**
1252    * Apply a frustum transformation to the matrix on top of this MatrixStack.
1253    * @param {Number} left The left clipping plane.
1254    * @param {Number} right The right clipping plane.
1255    * @param {Number} bottom The bottom clipping plane.
1256    * @param {Number} top The top clipping plane.
1257    * @param {Number} near The near clipping plane.
1258    * @param {Number} far The far clipping plane.  
1259    * @returns {MatrixStack} Returns this MatrixStack.
1260    */  	
1261 	MatrixStack.prototype.frustum = function(left, rigth, bottom, top, near, far) {
1262 		this.multiply(Mat4.Frustum(left, rigth, bottom, top, near, far));
1263 		return this;
1264 	};
1265 	
1266 	return MatrixStack;
1267 	
1268 }());
1269 
1270 BenchGL.namespace('BenchGL.math.TransformStack');
1271 
1272 BenchGL.math.TransformStack = (function() {
1273 
1274 	// Private properties and methods
1275 	var TransformStack;
1276 	
1277 	/**
1278 	 * Creates a new TransformStack.
1279 	 * @class Represents a full stack for model, view and projection matrices (OpenGL-like).
1280 	 */
1281 	TransformStack = function() {
1282 		this.modelStack = new MatrixStack();
1283 		this.viewStack = new MatrixStack();
1284 		this.projStack = new MatrixStack();
1285 		this.currentStack = null;
1286 	};
1287 	
1288 	/**
1289 	 * Gets the current model matrix.
1290 	 * @returns {Matrix4} The current model matrix.
1291 	 */
1292 	TransformStack.prototype.getModelMatrix = function() {
1293 		return this.modelStack.top();
1294 	};
1295 
1296 	/**
1297 	 * Gets the transposed version of the current model matrix.
1298 	 * @returns {Matrix4} The current model matrix transposed.
1299 	 */	
1300 	TransformStack.prototype.getModelMatrixTranspose = function() {
1301 		return this.modelStack.top().transpose();
1302 	};
1303 
1304 	/**
1305 	 * Gets the inverse of the current model matrix.
1306 	 * @returns {Matrix4} The current model matrix inverted.
1307 	 */		
1308 	TransformStack.prototype.getModelMatrixInverse = function() {
1309 		return this.modelStack.top().invert();
1310 	};
1311 
1312 	/**
1313 	 * Gets the inverse of the transposed of the current model matrix.
1314 	 * @returns {Matrix4} The current model matrix inverted transposed.
1315 	 */	
1316 	TransformStack.prototype.getModelMatrixInverseTranspose = function() {
1317 		return this.modelStack.top().invert().$transpose();
1318 	};
1319 
1320 	/**
1321 	 * Gets the current view matrix.
1322 	 * @returns {Matrix4} The current view matrix.
1323 	 */	
1324 	TransformStack.prototype.getViewMatrix = function() {
1325 		return this.viewStack.top();
1326 	};
1327 	
1328 	/**
1329 	 * Gets the transposed version of the current view matrix.
1330 	 * @returns {Matrix4} The current view matrix transposed.
1331 	 */		
1332 	TransformStack.prototype.getViewMatrixTranspose = function() {
1333 		return this.viewStack.top().transpose();
1334 	};
1335 
1336 	/**
1337 	 * Gets the inverse of the current view matrix.
1338 	 * @returns {Matrix4} The current view matrix inverted.
1339 	 */	
1340 	TransformStack.prototype.getViewMatrixInverse = function() {
1341 		return this.viewStack.top().invert();
1342 	};
1343 
1344 	/**
1345 	 * Gets the inverse of the transposed of the current view matrix.
1346 	 * @returns {Matrix4} The current view matrix inverted transposed.
1347 	 */	
1348 	TransformStack.prototype.getViewMatrixInverseTranspose = function() {
1349 		return this.viewStack.top().invert().$transpose();
1350 	};
1351 
1352 	/**
1353 	 * Gets the current projection matrix.
1354 	 * @returns {Matrix4} The current projection matrix.
1355 	 */		
1356 	TransformStack.prototype.getProjectionMatrix = function() {
1357 		return this.projStack.top();
1358 	};
1359 
1360 	/**
1361 	 * Gets the transposed version of the current projection matrix.
1362 	 * @returns {Matrix4} The current projection matrix transposed.
1363 	 */		
1364 	TransformStack.prototype.getProjectionMatrixTranspose = function() {
1365 		return this.projStack.top().transpose();
1366 	};
1367 
1368 	/**
1369 	 * Gets the inverse of the current projection matrix.
1370 	 * @returns {Matrix4} The current projection matrix inverted.
1371 	 */		
1372 	TransformStack.prototype.getProjectionMatrixInverse = function() {
1373 		return this.projStack.top().invert();
1374 	};
1375 
1376 	/**
1377 	 * Gets the inverse of the transposed of the current projection matrix.
1378 	 * @returns {Matrix4} The current projection matrix inverted transposed.
1379 	 */		
1380 	TransformStack.prototype.getProjectionMatrixInverseTranspose = function() {
1381 		return this.projStack.top().inverse().$transpose();
1382 	};
1383 
1384 	/**
1385 	 * Gets the current modelView matrix.
1386 	 * @returns {Matrix4} The current projection matrix.
1387 	 */		
1388 	TransformStack.prototype.getModelViewMatrix = function() {
1389 		return this.viewStack.top().multiplyMat4(this.modelStack.top());
1390 	};
1391 
1392 	/**
1393 	 * Gets the transposed version of the current modelView matrix.
1394 	 * @returns {Matrix4} The current modelView matrix transposed.
1395 	 */	
1396 	TransformStack.prototype.getModelViewMatrixTranspose = function() {
1397 		return this.getModelViewMatrix().transpose();
1398 	};
1399 
1400 	/**
1401 	 * Gets the inverse of the current modelView matrix.
1402 	 * @returns {Matrix4} The current modelView matrix inverted.
1403 	 */			
1404 	TransformStack.prototype.getModelViewMatrixInverse = function() {
1405 		return this.getModelViewMatrix().invert();
1406 	};
1407 
1408 	/**
1409 	 * Gets the inverse of the transposed of the current modelView matrix.
1410 	 * @returns {Matrix4} The current modelView matrix inverted transposed.
1411 	 */		
1412 	TransformStack.prototype.getModelViewMatrixInverseTranspose = function() {
1413 		return this.getModelViewMatrix().invert().$transpose();
1414 	};
1415 	
1416 	/**
1417 	 * Gets the normal matrix (aka the inverse transpose of the modelView matrix).
1418 	 * @returns {Matrix4} The current modelView matrix inverted transposed.
1419 	 */
1420 	TransformStack.prototype.getNormalMatrix = function() {
1421 		return this.getModelViewMatrixInverseTranspose();
1422 	};
1423 	
1424 	/**
1425 	 * Sets the current stack as the projection stack.
1426 	 * @returns {TransformStack} Returns this TransformStack.
1427 	 */
1428 	TransformStack.prototype.projection = function() {
1429 		this.currentStack = this.projStack;
1430 		return this;
1431 	};
1432 
1433 	/**
1434 	 * Sets the current stack as the view stack.
1435 	 * @returns {TransformStack} Returns this TransformStack.
1436 	 */	
1437 	TransformStack.prototype.view = function() {
1438 		this.currentStack = this.viewStack;
1439 		return this;
1440 	};
1441 
1442 	/**
1443 	 * Sets the current stack as the model stack.
1444 	 * @returns {TransformStack} Returns this TransformStack.
1445 	 */	
1446 	TransformStack.prototype.model = function() {
1447 		this.currentStack = this.modelStack;
1448 		return this;
1449 	};
1450 	
1451 	/**
1452 	 * Push the matrix on top of the current stack.
1453 	 * @returns {TransformStack} Returns this TransformStack.
1454 	 */
1455 	TransformStack.prototype.pushMatrix = function() {
1456 		this.currentStack.push();
1457 		return this;
1458 	};
1459 
1460 	/**
1461 	 * Pops out the matrix on top of the current stack.
1462 	 * @returns {TransformStack} Returns this TransformStack.
1463 	 */
1464 	TransformStack.prototype.popMatrix = function() {
1465 		this.currentStack.pop();
1466 		return this;
1467 	};
1468 
1469 	/**
1470 	 * Loads the identity on the current stack.
1471 	 * @returns {TransformStack} Returns this TransformStack.
1472 	 */	
1473 	TransformStack.prototype.loadIdentity = function() {
1474 		this.currentStack.loadIdentity();
1475 		return this;
1476 	};
1477 	
1478 	/**
1479 	 * Multiply a matrix with the current stack.
1480 	 * @param {Matrix4} The matrix to multiply with. 
1481 	 * @returns {TransformStack} Returns this TransformStack.
1482 	 */		
1483 	TransformStack.prototype.multiply = function(matrix) {
1484 		this.currentStack.multiply(matrix);
1485 		return this;
1486 	};
1487 
1488   /**
1489    * Apply a perspective transformation to the current stack.
1490    * @param {Number} fovy The vertical field of view angle.
1491    * @param {Number} aspect The aspect ratio aka the horizontal field of view angle.
1492    * @param {Number} near The near clipping plane.
1493    * @param {Number} far The far clipping plane.  
1494    * @returns {TransformStack} Returns this TransformStack.
1495    */  
1496 	TransformStack.prototype.perspective = function(fovy, aspect, near, far) {
1497 		this.currentStack.perspective(fovy, aspect, near, far);
1498 		return this;
1499 	};
1500 
1501 	/**
1502 	 * Apply a lookAt transformation to the current stack.
1503 	 * @param {Vector3} eye The eye vector. 
1504 	 * @param {Vector3} direction The direction vector. 
1505 	 * @param {Vector3} up The up vector.  
1506    * @returns {TransformStack} Returns this TransformStack.
1507 	 */
1508 	TransformStack.prototype.lookAt = function(eye, direction, up) {
1509 		this.currentStack.lookAt(eye, direction, up);
1510 		return this;
1511 	};
1512 
1513 	/**
1514 	 * Apply a rotation to the current stack.
1515 	 * @param {Number} angle The rotation angle.
1516    * @param {Number} x The rotation axis x coordinate.
1517    * @param {Number} y The rotation axis y coordinate.
1518    * @param {Number} z The rotation axis z coordinate.  
1519    * @returns {TransformStack} Returns this TransformStack.
1520 	 */	
1521 	TransformStack.prototype.rotate = function(angle, x, y, z) {
1522 		this.currentStack.rotate(angle, x, y, z);
1523 		return this;
1524 	};
1525 
1526 	/**
1527 	 * Apply a rotation around x, y and z axes to the current stack.
1528 	 * @param {Number} rx The rotation angle around X axis. 
1529 	 * @param {Number} ry The rotation angle around Y axis.
1530 	 * @param {Number} rz The rotation angle around Z axis. 
1531    * @returns {TransformStack} Returns this TransformStack.
1532 	 */			
1533 	TransformStack.prototype.rotateXYZ = function(rx, ry, rz) {
1534 		this.currentStack.rotateXYZ(rx, ry, rz);
1535 		return this;
1536 	};
1537 
1538 	/**
1539 	 * Apply a translation to the current stack.
1540 	 * @param {Number} x The x translation factor. 
1541 	 * @param {Number} y The y translation factor.
1542 	 * @param {Number} z The z translation factor. 
1543    * @returns {TransformStack} Returns this TransformStack.
1544 	 */		
1545 	TransformStack.prototype.translate = function(x, y, z) {
1546 		this.currentStack.translate(x, y, z);
1547 		return this;
1548 	};
1549 
1550 	/**
1551 	 * Apply a scale transformation to the current stack.
1552 	 * @param {Number} x The x scale factor. 
1553 	 * @param {Number} y The y scale factor.
1554 	 * @param {Number} z The z scale factor. 
1555    * @returns {TransformStack} Returns this TransformStack.
1556 	 */	
1557 	TransformStack.prototype.scale = function(x, y, z) {
1558 		this.currentStack.scale(x, y, z);
1559 		return this;
1560 	};
1561 	
1562 	return TransformStack;
1563 	
1564 }());
1565 
1566 // skin.js
1567 // The skin module has the tools to manipulate colors, materials, lights and textures.
1568 
1569 BenchGL.namespace('BenchGL.skin.Color');
1570 
1571 BenchGL.skin.Color = (function() {
1572 
1573 	// Dependencies
1574   var Vec3 = BenchGL.math.Vector3, 
1575   
1576   		// Private properties and methods
1577       Color;
1578   
1579   /**
1580    * Creates a new Color.
1581    * @class Represents an RGB(A) color.
1582    * @param {Number} r The red component of the color.
1583    * @param {Number} g The green component of the color.
1584    * @param {Number} b The blue component of the color.
1585    * @param {Number} [a=1] The alpha component of the color.
1586    */
1587   Color = function(r, g, b, a) {
1588     this.r = r;
1589     this.g = g;
1590     this.b = b;
1591     this.a = a || 1;
1592   };
1593   
1594   /**
1595    * Gets an array representaton of this Color in RGB format.
1596    * @returns {Number[]} An array representing an RGB color.
1597    */
1598   Color.prototype.toRGBArray = function() {
1599     return [this.r, this.g, this.b];
1600   };
1601 
1602   /**
1603    * Gets an array representaton of this Color in RGBA format.
1604    * @returns {Number[]} An array representing an RGBA color.
1605    */  
1606   Color.prototype.toRGBAArray = function(){
1607     return [this.r, this.g, this.b, this.a];
1608   };
1609   
1610   return Color;
1611   
1612 }());
1613 
1614 BenchGL.namespace('BenchGL.skin.Material');
1615 
1616 BenchGL.skin.Material = (function() {
1617 
1618 	// Dependencies
1619 	var Color = BenchGL.skin.Color,
1620 			
1621 			// Private properties and methods
1622 			Material;
1623   
1624   /**
1625    * Creates a new Material.
1626    * @class Represents a material, thus a way to express 
1627    * interaction between light and geometric models. 
1628    * @param {Object} [options] Contains parameters to create the material.
1629    * @param {Object} [options.ambient] Holds the ambient color.
1630    * @param {Object} [options.diffuse] Holds the diffuse color.
1631    * @param {Object} [options.specular] Holds the specular color.
1632    * @param {Object} [options.emissive] Holds the emissive color.
1633    * @param {Number} [options.shininess] Specifies the shininess of the material.
1634    */
1635   Material = function(options) {
1636     options = $.mix({
1637       ambient: {
1638         r: 0.0,
1639         g: 0.0,
1640         b: 0.0
1641       },
1642       diffuse: {
1643         r: 1.0,
1644         g: 1.0,
1645         b: 1.0
1646       },
1647       specular: {
1648         r: 1.0,
1649         g: 1.0,
1650         b: 1.0
1651       },
1652       emissive: {
1653         r: 1.0,
1654         g: 1.0,
1655         b: 1.0
1656       },
1657       shininess: 0.1
1658     }, options || {});
1659     
1660     var ambient = options.ambient, 
1661         diffuse = options.diffuse, 
1662         specular = options.specular, 
1663         emissive = options.emissive;
1664     
1665     this.ambient = new Color(ambient.r, ambient.g, ambient.b);
1666     this.diffuse = new Color(diffuse.r, diffuse.g, diffuse.b);
1667     this.specular = new Color(specular.r, specular.g, specular.b);
1668     this.emissive = new Color(emissive.r, emissive.g, emissive.b);
1669     this.shininess = options.shininess;
1670   };
1671   
1672   /**
1673    * Sets the ambient color of this Material.
1674    * @param {Number} r The red component of the color.
1675    * @param {Number} g The green component of the color.
1676    * @param {Number} b The blue component of the color.
1677    * @returns {Material} Returns this Material.
1678    */
1679   Material.prototype.setAmbient = function(r, g, b) {
1680     this.ambient = new Color(r, g, b);
1681     return this;
1682   };
1683 
1684   /**
1685    * Sets the diffuse color of this Material.
1686    * @param {Number} r The red component of the color.
1687    * @param {Number} g The green component of the color.
1688    * @param {Number} b The blue component of the color.
1689    * @returns {Material} Returns this Material.
1690    */  
1691   Material.prototype.setDiffuse = function(r, g, b) {
1692     this.diffuse = new Color(r, g, b);
1693     return this;
1694   };
1695 
1696   /**
1697    * Sets the specular color of this Material.
1698    * @param {Number} r The red component of the color.
1699    * @param {Number} g The green component of the color.
1700    * @param {Number} b The blue component of the color.
1701    * @returns {Material} Returns this Material.
1702    */  
1703   Material.prototype.setSpecular = function(r, g, b) {
1704     this.specular = new Color(r, g, b);
1705     return this;
1706   };
1707 
1708   /**
1709    * Sets the emissive color of this Material.
1710    * @param {Number} r The red component of the color.
1711    * @param {Number} g The green component of the color.
1712    * @param {Number} b The blue component of the color.
1713    * @returns {Material} Returns this Material.
1714    */  
1715   Material.prototype.setEmissive = function(r, g, b) {
1716     this.emissive = new Color(r, g, b);
1717     return this;
1718   };
1719 
1720   /**
1721    * Sets the shininess of this Material.
1722    * @param {Number} shininess The shininess to set.
1723    * @returns {Material} Returns this Material.
1724    */  
1725   Material.prototype.setShininess = function(shininess) {
1726     this.shininess = shininess;
1727     return this;
1728   };
1729   
1730   return Material;
1731   
1732 }());
1733 
1734 BenchGL.namespace('BenchGL.skin.Light');
1735 
1736 BenchGL.skin.Light = (function() {
1737   
1738   // Dependencies
1739   var Vec3 = BenchGL.math.Vector3,
1740   		Color = BenchGL.skin.Color,
1741   		Material = BenchGL.skin.Material,
1742   
1743   		// Private properties and methods
1744   		Light;
1745   
1746   /**
1747    * Creates a new Light.
1748    * @class Represent a light in a 3D world.
1749    * @param {Object} [options] Contains parameters to create the light.
1750    * @param {Object} [options.position] Holds the position of the light.
1751    * @param {Object} [options.diffuse] Holds the diffuse color.
1752    * @param {Object} [options.specular] Holds the specular color.
1753    * @param {Object} [options.direction] Holds the direction of the light.
1754    * @param {Number} [options.cutoff] Holds the cutoff factor.
1755    * @param {Number} [options.exponent] Holds the cutoff factor.
1756    * @param {Number} [options.constant] Holds the costant attenuation factor.
1757    * @param {Number} [options.linear] Holds the linear attenuation factor.
1758    * @param {Number} [options.quadratic] Holds the quadratic attenuation factor.
1759    * @param {Number} [options.active] Activate the light.
1760    */
1761   Light = function(options) {
1762     options = $.mix({
1763       position: {
1764         x: 0.0,
1765         y: 0.0,
1766         z: -1.0
1767       },
1768       ambient: {
1769         r: 0.0,
1770         g: 0.0,
1771         b: 0.0
1772       },
1773       diffuse: {
1774         r: 1.0,
1775         g: 1.0,
1776         b: 1.0
1777       },
1778       specular: {
1779         r: 1.0,
1780         g: 1.0,
1781         b: 1.0
1782       },
1783       direction: {
1784         x: 0.0,
1785         y: 0.0,
1786         z: -1.0
1787       },
1788       cutoff: 180.0,
1789       exponent: 0.0,
1790       constant: 1.0,
1791       linear: 0.0,
1792       quadratic: 0.0,
1793       active: true
1794     }, options || {});
1795     
1796     var position = options.position, 
1797         ambient = options.ambient, 
1798         diffuse = options.diffuse, 
1799         specular = options.specular, 
1800         direction = options.direction;
1801     
1802     this.position = new Vec3(position.x, position.y, position.z);
1803     this.ambient = new Color(ambient.r, ambient.g, ambient.b);
1804     this.diffuse = new Color(diffuse.r, diffuse.g, diffuse.b);
1805     this.specular = new Color(specular.r, specular.g, specular.b);
1806     this.direction = new Color(direction.x, direction.y, direction.z);
1807     this.cutOff = options.cutoff;
1808     this.exponent = options.exponent;
1809     this.constant = options.constant;
1810     this.linear = options.linear;
1811     this.quadratic = options.quadratic;
1812     this.active = options.active;
1813   };
1814   
1815   /**
1816    * Sets the position of this Light.
1817    * @param {Number} x The x coordinate to set.
1818    * @param {Number} y The y coordinate to set.
1819    * @param {Number} z The z coordinate to set.
1820    * @returns {Light} Returns this Light.
1821    */
1822   Light.prototype.setPosition = function(x, y, z) {
1823     this.position = new Vec3(x, y, z);
1824     return this;
1825   };
1826 
1827   /**
1828    * Sets the ambient color of this Light.
1829    * @param {Number} r The red component of the color.
1830    * @param {Number} g The green component of the color.
1831    * @param {Number} b The blue component of the color.
1832    * @returns {Light} Returns this Light.
1833    */  
1834   Light.prototype.setAmbient = function(r, g, b) {
1835     this.ambient = new Color(r, g, b);
1836     return this;
1837   };
1838 
1839   /**
1840    * Sets the diffuse color of this Light.
1841    * @param {Number} r The red component of the color.
1842    * @param {Number} g The green component of the color.
1843    * @param {Number} b The blue component of the color.
1844    * @returns {Light} Returns this Light.
1845    */    
1846   Light.prototype.setDiffuse = function(r, g, b) {
1847     this.diffuse = new Color(r, g, b);
1848     return this;
1849   };
1850 
1851   /**
1852    * Sets the specular color of this Light.
1853    * @param {Number} r The red component of the color.
1854    * @param {Number} g The green component of the color.
1855    * @param {Number} b The blue component of the color.
1856    * @returns {Light} Returns this Light.
1857    */    
1858   Light.prototype.setSpecular = function(r, g, b) {
1859     this.specular = new Color(r, g, b);
1860     return this;
1861   };
1862 
1863   /**
1864    * Sets the direction of this Light.
1865    * @param {Number} x The x coordinate to set.
1866    * @param {Number} y The y coordinate to set.
1867    * @param {Number} z The z coordinate to set.
1868    * @returns {Light} Returns this Light.
1869    */ 
1870   Light.prototype.setDirection = function(x, y, z) {
1871     this.direction = new Vec3(x, y, z).$unit();
1872     return this;
1873   };
1874 
1875   /**
1876    * Sets the exponent of this Light's intensity.
1877    * @param {Number} exponent The exponent to set.
1878    * @returns {Light} Returns this Light.
1879    */  
1880   Light.prototype.setExponent = function(exponent) {
1881     this.exponent = exponent;
1882     return this;
1883   };
1884 
1885   /**
1886    * Sets the cutoff of this Light.
1887    * @param {Number} cutoff The cutoff to set.
1888    * @returns {Light} Returns this Light.
1889    */   
1890   Light.prototype.setCutoff = function(cutoff) {
1891     this.cutoff = cutoff;
1892     return this;
1893   };
1894 
1895   /**
1896    * Sets the constant attenuation factor of this Light.
1897    * @param {Number} constant The attenuation factor to set.
1898    * @returns {Light} Returns this Light.
1899    */   
1900   Light.prototype.setConstantAttenuation = function(constant) {
1901     this.constant = constant;
1902     return this;
1903   };
1904 
1905   /**
1906    * Sets the linear attenuation factor of this Light.
1907    * @param {Number} linear The attenuation factor to set.
1908    * @returns {Light} Returns this Light.
1909    */   
1910   Light.prototype.setLinearAttenuation = function(linear) {
1911     this.linear = linear;
1912     return this;
1913   };
1914 
1915   /**
1916    * Sets the quadratic attenuation factor of this Light.
1917    * @param {Number} quadratic The attenuation factor to set.
1918    * @returns {Light} Returns this Light.
1919    */   
1920   Light.prototype.setQuadraticAttenuation = function(quadratic) {
1921     this.quadratic = quadratic;
1922     return this;
1923   };
1924   
1925   /**
1926    * Switches the light on and off.
1927    * @param {Boolean} active True to activate this Light, false otherwise.
1928    * @returns {Light} Returns this Light.
1929    */
1930   Light.prototype.setActive = function(active) {
1931     this.active = active;
1932     return this;
1933   };
1934   
1935   return Light;
1936   
1937 }());
1938 
1939 BenchGL.namespace('BenchGL.skin.Texture');
1940 
1941 BenchGL.skin.Texture = (function() {
1942   
1943   // Private properties and methods
1944   var Texture;
1945   
1946   /**
1947    * Creates a new Texture.
1948    * @class Represent a texture.
1949    * @param {Object} options Contains some info to generate the texture.
1950    * @param {Image} options.image The image to generate the texture from.
1951    * @param {Number} [options.level] The level of the texture.
1952    * @param {Number} [options.verticalFlip] Indicates to flip the y coordinate over the texture.
1953    * @param {Number} [options.internalFmt] The WebGL internal format of the texture.
1954    * @param {Number} [options.format] The format of the texture.
1955    * @param {Number} [options.type] The data type of the colors for each pixel in the image.
1956    * @param {Number} [options.magFilter] Specifies magnification filters to use in mipmapping.
1957    * @param {Number} [options.minFilter] Specifies minification filters to use in mipmapping.
1958    * @param {Number} [options.target] The WebGL target for the texture.
1959    * @param {Boolean} [options.mipmap] Indicates if mipmap of the texture have to be created.
1960    */
1961   Texture = function(options) {
1962     options = $.mix({
1963       level: 0,
1964       verticalFlip: true,
1965       internalFmt: gl.RGBA,
1966       format: gl.RGBA,
1967       type: gl.UNSIGNED_BYTE,
1968       magFilter: gl.LINEAR,
1969       minFilter: gl.LINEAR_MIPMAP_NEAREST,
1970       mipmap: true,
1971       target: gl.TEXTURE_2D
1972     }, options || {});
1973     
1974     var texture = gl.createTexture();
1975     
1976     this.options = options;
1977     this.handler = texture;
1978     
1979     gl.bindTexture(options.target, texture);
1980     gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, options.verticalFlip);
1981     gl.texImage2D(options.target, options.level, options.internalFmt, options.format, options.type, options.image);
1982     gl.texParameteri(options.target, gl.TEXTURE_MAG_FILTER, options.magFilter);
1983     gl.texParameteri(options.target, gl.TEXTURE_MIN_FILTER, options.minFilter);
1984     if (options.mipmap) {
1985       this.generateMipmap();
1986     }
1987     gl.bindTexture(options.target, null);
1988   };
1989   
1990   /**
1991    * Destroys this Texture.
1992    */
1993   Texture.prototype.destroy = function() {
1994     gl.deleteTexture(this.handler);
1995   };
1996   
1997   /**
1998    * Binds this Texture to a sampler unit in the current shader program.
1999    * @param {Number} unit The unit to bind this Texture to.
2000    * @returns {Texture} Returns this Texture.
2001    */
2002   Texture.prototype.bind = function(unit) {
2003     gl.activeTexture(gl.TEXTURE0 + unit);
2004     gl.bindTexture(this.options.target, this.handler);
2005     return this;
2006   };
2007   
2008   /**
2009    * Unbinds this Texture from a sampler unit in the current shader program.
2010    * @param {Number} unit The unit to unbind this Texture from.
2011    * @returns {Texture} Returns this Texture.
2012    */  
2013   Texture.prototype.unbind = function(unit) {
2014     gl.activeTexture(gl.TEXTURE0 + unit);
2015     gl.bindTexture(this.options.target, null);
2016     return this;
2017   };
2018   
2019   /**
2020    * Generates mipmaps for this Texture.
2021    * @returns {Texture} Returns this Texture.
2022    */
2023   Texture.prototype.generateMipmap = function() {
2024     gl.generateMipmap(this.options.target);
2025     return this;
2026   };
2027   
2028   return Texture;
2029   
2030 }());
2031 
2032 // io.js
2033 // Offers structures and functions to perform asynchronous IO operations.
2034 
2035 BenchGL.namespace('BenchGL.io.XHRequest');
2036 
2037 BenchGL.io.XHRequest = (function() {
2038   
2039   var XHRequest;
2040 	
2041 	/**
2042 	 * Creates a new XHRequest.
2043 	 * @class Wraps an XMLHttpRequest object to load resources asynchronously. 
2044 	 * @param {Object} [options] The request's options.
2045 	 * @param {String} [options.url] The url for the request.
2046 	 * @param {String} [options.method] The method for the request.
2047 	 * @param {Boolean} [options.async] Is the request asynchronous?
2048 	 * @param {Boolean} [options.binary] Is the response in binary format?
2049 	 * @param {Function} [options.onProgress] Callback to call during request processing.
2050 	 * @param {Function} [options.onLoad] Callback to call after request loading.
2051 	 * @param {Function} [options.onError] Callback to call in case of error.
2052 	 * @param {Function} [options.onAbort] Callback to call if the request is aborted.
2053 	 * @param {Function} [options.onSuccess] Callback to call in case of success.         
2054 	 */
2055   XHRequest = function(options) {
2056     options = $.mix({
2057       url: 'www.webrendering.sourceforge.net',
2058       method: 'GET',
2059       async: true,
2060       binary: false,
2061       onProgress: $.empty,
2062       onLoad: $.empty,
2063       onError: $.empty,
2064       onAbort: $.empty,
2065       onSuccess: $.empty
2066     }, options || {});
2067     
2068     var myself = this;
2069        
2070     this.options = options;
2071     this.request = new XMLHttpRequest();
2072     
2073     this.request.addEventListener('progress', function(e) { myself.onProgress(e); }, false);
2074     this.request.addEventListener('load', function(e) { myself.onLoad(e); }, false);
2075     this.request.addEventListener('error', function(e) { myself.onError(e); }, false);
2076     this.request.addEventListener('abort', function(e) { myself.onAbort(e); }, false);
2077   };
2078   
2079   /**
2080    * Executes the request wrapped in this XHRequest.
2081    */
2082   XHRequest.prototype.send = function() {
2083     var options = this.options, 
2084     		url = this.options.url, 
2085     		method = this.options.method, 
2086     		async = this.options.async, 
2087     		binary = this.options.binary, 
2088     		request = this.request;
2089     
2090     // Opens the request
2091     request.open(method, url, async);
2092     
2093     // Handle async requests
2094     if (async) {
2095       request.onreadystatechange = function(e) {
2096         if (request.readyState === 4) {
2097           if (request.status === 200) {
2098             options.onSuccess(request.responseText);
2099           }
2100           else {
2101             options.onError(request.status);
2102           }
2103         }
2104       };
2105     }
2106     
2107     // Handles binary requests
2108     if (binary) {
2109       request.sendAsBinary(null);
2110     }
2111     else {
2112       request.send(null);
2113     }
2114     
2115     // If not async wait for the response
2116     if (!async) {
2117       if (request.status === 200) {
2118         options.onSuccess(request.responseText);
2119       }
2120       else {
2121         options.onError(request.status);
2122       }
2123     }
2124   };
2125   
2126   /**
2127    * Handles the 'onprogress' event of this XHRequest.
2128    */
2129   XHRequest.prototype.onProgress = function(e) {
2130     this.options.onProgress(e);
2131   };
2132 
2133   /**
2134    * Handles the 'onerror' event of this XHRequest.
2135    */  
2136   XHRequest.prototype.onError = function(e) {
2137     this.options.onError(e);
2138   };
2139 
2140   /**
2141    * Handles the 'onabort' event of this XHRequest.
2142    */  
2143   XHRequest.prototype.onAbort = function(e) {
2144     this.options.onAbort(e);
2145   };
2146   
2147   /**
2148    * Handles the 'onload' event of this XHRequest.
2149    */  
2150   XHRequest.prototype.onLoad = function(e) {
2151     this.options.onLoad(e);
2152   };
2153   
2154 	return XHRequest;
2155 	
2156 }());
2157 
2158 BenchGL.namespace('BenchGL.io.TextureRequest');
2159 
2160 BenchGL.io.TextureRequest = (function() {
2161 
2162 	var TextureRequest;
2163   
2164   /**
2165    * Creates a new TextureRequest.
2166    * @class Represents multiple asynchronous requests for images to build up Texture objects.
2167    * @param {Object} options Information about the requested textures.
2168    */
2169   TextureRequest = function(options) {
2170     this.texturesReqs = options;
2171   };
2172   
2173   /**
2174    * Executes all the request of this TextureRequest, 
2175    * using a callback function to handle each one of them on completion.
2176    * @param {Function} callback A callback function to handle results on completion.
2177    */
2178   TextureRequest.prototype.send = function(callback) {
2179     var texturesReqs = this.texturesReqs,
2180         keys = Object.keys(texturesReqs);
2181     
2182     keys.map(function(key) {
2183       var textureOpt = texturesReqs[key];
2184       textureOpt.image = new Image();
2185       textureOpt.image.onload = function() {
2186       	if (callback) {
2187         	callback(key, textureOpt);
2188         }
2189       };
2190       textureOpt.image.src = textureOpt.src;
2191     });
2192   };
2193   
2194   return TextureRequest;
2195   
2196 }());
2197 
2198 // ui.js
2199 // The ui module handles user interaction and events.
2200 
2201 BenchGL.namespace('BenchGL.ui.Canvas');
2202 
2203 BenchGL.ui.Canvas = (function() {
2204 
2205 	var Canvas;
2206 	
2207 	/**
2208 	 * Creates a new Canvas.
2209 	 * @class Represents a wrap object for a canvas HTML5 element.
2210 	 * @param {HTMLCanvasElement} canvas The canvas element.
2211 	 * @options {Object} options Contains callbacks to handle events in the browser.
2212 	 */
2213   Canvas = function(canvas, options) {
2214     options = $.mix({
2215       onKeyDown: $.empty,
2216       onKeyUp: $.empty,
2217       onMouseDown: $.empty,
2218       onMouseUp: $.empty,
2219       onMouseMove: $.empty,
2220       onMouseWheel: $.empty,
2221       onMouseOut: $.empty
2222     }, options || {});
2223     
2224     //canvas.contentEditable = true;
2225     
2226     this.canvas = canvas;
2227     this.events = options;
2228     this.keysDown = {};
2229     this.mouseDown = {};
2230     this.mousePosition = {
2231       x: 0.0,
2232       y: 0.0
2233     };
2234     this.mouseLastPosition = {
2235       x: 0.0,
2236       y: 0.0
2237     };
2238     this.mouseDelta = {
2239       x: 0.0,
2240       y: 0.0
2241     };
2242     
2243     var myself = this;
2244     document.addEventListener('keydown', function(e) { myself.onKeyDown(e); }, false);
2245     document.addEventListener('keyup', function(e) { myself.onKeyUp(e); }, false);
2246     canvas.addEventListener('mousedown', function(e) { myself.onMouseDown(e); }, false);
2247     canvas.addEventListener('mouseup', function(e) { myself.onMouseUp(e); }, false);
2248     canvas.addEventListener('mousemove', function(e) { myself.onMouseMove(e); }, false);
2249     canvas.addEventListener('mousewheel', function(e) { myself.onMouseWheel(e); }, false);
2250     canvas.addEventListener('DOMMouseScroll', function(e) { myself.onMouseWheel(e); }, false);
2251   };
2252   
2253   /**
2254    * Handles the 'keydown' event, if supplied.
2255    * @param {Event} e Information about the event occured.
2256    */
2257   Canvas.prototype.onKeyDown = function(e){
2258     this.keysDown[e.keyCode] = true;
2259     this.events.onKeyDown(e);
2260   };
2261 
2262   /**
2263    * Handles the 'keyup' event, if supplied.
2264    * @param {Event} e Information about the event occured.
2265    */  
2266   Canvas.prototype.onKeyUp = function(e){
2267     this.keysDown[e.keyCode] = false;
2268     this.events.onKeyUp(e);
2269   };
2270 
2271   /**
2272    * Handles the 'mousedown' event, if supplied.
2273    * @param {Event} e Information about the event occured.
2274    */   
2275   Canvas.prototype.onMouseDown = function(e){
2276     var x = e.clientX, y = this.canvas.height - e.clientY - 1;
2277     
2278     this.mousePosition.x = x;
2279     this.mousePosition.y = y;
2280     this.mouseLastPosition.x = x;
2281     this.mouseLastPosition.y = y;
2282     this.mouseDelta.x = 0.0;
2283     this.mouseDelta.y = 0.0;
2284     this.mouseDown[e.button] = true;
2285     
2286     this.events.onMouseDown(e, x, y);
2287   };
2288 
2289   /**
2290    * Handles the 'mouseup' event, if supplied.
2291    * @param {Event} e Information about the event occured.
2292    */   
2293   Canvas.prototype.onMouseUp = function(e){
2294     var x = e.clientX, y = this.canvas.height - e.clientY - 1;
2295     
2296     this.mousePosition.x = x;
2297     this.mousePosition.y = y;
2298     this.mouseLastPosition.x = x;
2299     this.mouseLastPosition.y = y;
2300     this.mouseDelta.x = 0.0;
2301     this.mouseDelta.y = 0.0;
2302     this.mouseDown[e.button] = false;
2303     
2304     this.events.onMouseUp(e, x, y);
2305   };
2306 
2307   /**
2308    * Handles the 'mousemove' event, if supplied.
2309    * @param {Event} e Information about the event occured.
2310    */   
2311   Canvas.prototype.onMouseMove = function(e){
2312     var x = e.clientX, y = this.canvas.height - e.clientY - 1;
2313     
2314     this.mouseLastPosition.x = this.mousePosition.x;
2315     this.mouseLastPosition.y = this.mousePosition.y;
2316     this.mousePosition.x = x;
2317     this.mousePosition.y = y;
2318     this.mouseDelta.x = this.mousePosition.x - this.mouseLastPosition.x;
2319     this.mouseDelta.y = this.mousePosition.y - this.mouseLastPosition.y;
2320     
2321     this.events.onMouseMove(e, this.mouseDelta.x, this.mouseDelta.y);
2322   };
2323 
2324   /**
2325    * Handles the 'mousewheel' event, if supplied.
2326    * @param {Event} e Information about the event occured.
2327    */     
2328   Canvas.prototype.onMouseWheel = function(e) {
2329     var x = e.clientX, y = this.canvas.height - e.clientY - 1, delta = 0;
2330     
2331     this.mouseLastPosition.x = this.mousePosition.x;
2332     this.mouseLastPosition.y = this.mousePosition.y;
2333     this.mousePosition.x = x;
2334     this.mousePosition.y = y;
2335     this.mouseDelta.x = 0;
2336     this.mouseDelta.y = 0;
2337     
2338     if (!e) {
2339       e = window.event;
2340     }
2341     if (e.wheelDelta) {
2342       delta = e.wheelDelta / 120;
2343       if (window.opera) {
2344         delta = -delta;
2345       }
2346     }
2347     else if (e.detail){
2348       delta = -e.detail / 3;
2349     }
2350     
2351     if (delta) {
2352       this.events.onMouseWheel(e, delta);
2353     }
2354   };
2355   
2356   return Canvas;
2357   
2358 }());
2359 
2360 BenchGL.namespace('BenchGL.ui.Camera');
2361 
2362 BenchGL.ui.Camera = (function() {
2363 	
2364 	// Dependencies
2365 	var Vec3 = BenchGL.math.Vector3,
2366 			MatStack = BenchGL.math.MatrixStack,
2367 			
2368 			// Private properties and methods
2369       Camera;
2370 	
2371 	/**
2372 	 * Creates a new Camera.
2373 	 * @class Represents a camera with a point of view over a 3D scene.
2374 	 * @param {Object} options The options to set up this Camera.
2375 	 * @param {Number} options.fovy The field of view vertical angle.
2376 	 * @param {Number} options.aspect The aspect ratio.
2377 	 * @param {Number} options.near The near clipping plane.
2378 	 * @param {Number} options.far The far clipping plane.
2379 	 * @param {Number[]} [options.eye] The position vector of this Camera.
2380 	 * @param {Number[]} [options.direction] The viewing direction vector of this Camera.
2381 	 * @param {Number[]} [options.up] The up vector of this Camera. 
2382 	 */
2383 	Camera = function(options) {
2384 		var e = options.eye,
2385 				d = options.direction,
2386 				u = options.up,
2387 				fovy = options.fovy,
2388 				aspect = options.aspect,
2389 				near = options.near,
2390 				far = options.far;
2391 		
2392 		this.fovy = fovy;
2393 		this.aspect = aspect;
2394 		this.near = near;
2395 		this.far = far;
2396 		this.eye = (e && new Vec3(e.x, e.y, e.z)) || new Vec3(0, 0, 0);
2397 		this.direction = (d && new Vec3(d.x, d.y, d.z)) || new Vec3(0, 0, -1);
2398 		this.up = (u && new Vec3(u.x, u.y, u.z)) || new Vec3(0, 1, 0);
2399 			
2400     this.projStack = new MatStack();
2401     this.viewStack = new MatStack();
2402     this.modelStack = new MatStack();
2403     
2404     this.viewStack.lookAt(this.eye, this.direction, this.up);
2405 		this.projStack.perspective(fovy, aspect, near, far);
2406 	};
2407   
2408   /**
2409    * Gets this Camera's projection stack.
2410    * @returns {MatrixStack} A projection matrix stack.
2411    */
2412   Camera.prototype.proj = function() {
2413     return this.projstack;
2414   };
2415   
2416 	/**
2417 	 * Gets this Camera's view stack.
2418 	 * @returns {MatrixStack} A view matrix stack
2419 	 */
2420   Camera.prototype.view = function() {
2421     return this.viewStack;
2422   };
2423   
2424 	/**
2425 	 * Gets this Camera's model stack.
2426 	 * @returns {MatrixStack} A model matrix stack
2427 	 */  
2428   Camera.prototype.model = function() {
2429     return this.modelStack;
2430   };
2431 
2432   /**
2433    * Gets the projection matrix of this Camera.
2434    * @returns {Matrix4} A matrix representing a projective transformation.
2435    */  
2436   Camera.prototype.projMatrix = function() {
2437     return this.projStack.top();
2438   };
2439 
2440   /**
2441    * Gets the view matrix of this Camera.
2442    * @returns {Matrix4} A matrix representing a transformation from world to camera space.
2443    */  
2444   Camera.prototype.viewMatrix = function() {
2445     return this.viewStack.top();
2446   };
2447   
2448   /**
2449    * Gets the model matrix of this Camera.
2450    * @returns {Matrix4} A matrix representing a common transformation to apply to the scene.
2451    */
2452   Camera.prototype.modelMatrix = function() {
2453     return this.modelStack.top();
2454   };
2455 
2456 	/**
2457 	 * Gets the modelView matrix of this Camera.
2458 	 * @returns {Matrix4} A matrix representing the full tranformation from object to camera space.
2459 	 */
2460   Camera.prototype.modelViewMatrix = function() {
2461     return this.viewStack.top().multiplyMat4(this.modelStack.top());
2462   };
2463   
2464   /**
2465    * Resets this Camera, loading identity matrices on top of the view and model stacks.
2466    */
2467   Camera.prototype.reset = function() {
2468     this.viewStack.loadIdentity();
2469     this.modelStack.loadIdentity();
2470   };
2471 	
2472 	/**
2473 	 * Updates this Camera's local reference frame.
2474 	 */
2475 	Camera.prototype.update = function() {
2476 		this.viewStack.lookAt(this.eye, this.direction, this.up);
2477 	};
2478 	
2479 	return Camera;
2480 	
2481 }());
2482 
2483 BenchGL.namespace('BenchGL.ui.Logger');
2484 
2485 BenchGL.ui.Logger = (function() {
2486   
2487   // Private properties and methods
2488   var instance, 
2489   		Logger;
2490 
2491 	/**
2492 	 * Gets an instance of a Logger.
2493 	 * @class Helps logging stuff.
2494 	 */
2495   Logger = function Logger() {
2496     if (instance) {
2497       return instance;
2498     }
2499     instance = this;
2500   };
2501   
2502   /**
2503    * Logs a message to console.
2504    * @param {Object} message The message to log. 
2505    */
2506   Logger.prototype.log = function(message) {
2507     console.log(message);
2508   };
2509 
2510 	return Logger;
2511 	
2512 }());
2513 
2514 BenchGL.namespace('BenchGL.ui.Timer');
2515 
2516 BenchGL.ui.Timer = (function() {
2517 
2518 	// Private properties and methods
2519 	var nowTime = 0,
2520 			lastTime = 0,
2521 			elapsedTime = 0,
2522       Timer;
2523 
2524 	/**
2525 	 * Creates a new Timer.
2526 	 * @class	A class for timing purpouses, like calculating FPS for an application.
2527 	 */
2528 	Timer = function() {
2529 		this.fps = 0;
2530 		this.lastDelta = 0;
2531 		this.maxSamples = 50;
2532 		this.samples = [];
2533 	};
2534 	
2535 	/**
2536 	 * Starts this Timer.
2537 	 */
2538 	Timer.prototype.start = function() {
2539 		nowTime = new Date().getTime();
2540 		lastTime = nowTime;
2541 		elapsedTime = 0;
2542 		return this;
2543 	};
2544 	
2545 	/**
2546 	 * Stops this Timer.
2547 	 */
2548 	Timer.prototype.stop = function() {
2549 		var now = new Date().getTime(),
2550         sample, i, l, fps = 0;
2551 		
2552     lastTime = nowTime;
2553 		nowTime = now;
2554 		elapsedTime = nowTime - lastTime;
2555 		sample = 1000.0 / elapsedTime;
2556 				
2557 		if (this.samples.unshift(sample) > this.maxSamples) {
2558       this.samples.pop();     
2559     }
2560 		
2561 		for (i = 0, l = this.samples.length; i < l; i++) {
2562 			fps += this.samples[i];
2563 		}
2564 		fps /= this.samples.length;
2565 		
2566 		this.fps = Math.round(fps);
2567 		this.lastDelta = elapsedTime;
2568 		return this;
2569 	};
2570 	
2571 	/**
2572 	 * Clears this Timer.
2573 	 */
2574 	Timer.prototype.clear = function() {
2575 		nowTime = 0;
2576 		lastTime = 0;
2577 		elapsedTime = 0;
2578 		
2579 		this.fps = 0;
2580 		this.lastDelta = 0;
2581 		this.samples = [];
2582 		return this;
2583 	};
2584 	
2585 	return Timer;
2586 	
2587 }());
2588 
2589 // worker.js
2590 // Part of the extra module, provides support to Web Workers.
2591 
2592 BenchGL.namespace('BenchGL.extra.WorkerPool');
2593 
2594 BenchGL.extra.WorkerPool = (function() {
2595 	
2596 	// Private properties and methods
2597 	var WorkerPool;
2598 	
2599 	/**
2600 	 * Creates a new WorkerPool.
2601 	 * @class Coordinates a group of WebWorkers.
2602 	 * @param {String} filename The filename for the worker script.
2603 	 * @param {Number} n The number of WebWorkers to create. 
2604 	 */
2605   WorkerPool = function(filename, n){
2606     this.workers = [];
2607     this.configs = [];
2608     while (n--) {
2609       this.workers.push(new Worker(filename));
2610     }
2611   };
2612   
2613   /**
2614    * Maps configurations to the workers in this WorkerPool.
2615    * @param {Function} mapper The mapping function.
2616    */
2617   WorkerPool.prototype.map = function(mapper) {
2618     var i, l;
2619     for (i = 0, l = this.workers.length; i < l; i++) {
2620       this.configs.push(mapper(i));
2621     }
2622   };
2623   
2624   /**
2625    * Starts and merges the computation of the workers in this WorkerGroup.
2626    * @param {Function} reducer The function to merge the results.
2627    * @param {Function} callback A callback function to call when te work is done.
2628    * @param {Object} base A base result to start the computation from.  
2629    */
2630   WorkerPool.prototype.reduce = function(reducer, callback, base) {
2631     var total = base,
2632         l = this.workers.length,
2633         worker, i,
2634         /**
2635          * @ignore For documentation tool only.
2636          */
2637         message = function(e){
2638           l--;
2639           if (total === "undefined") {
2640             total = e.data;
2641           }
2642           else {
2643             reducer(total, e.data);
2644           }
2645           if (l === 0) {
2646             callback(total);
2647           }
2648         };
2649     
2650     for (i = 0, l = this.workers.length; i < l; i++) {
2651       worker = this.workers[i];
2652       worker.onmessage = message;
2653       worker.postMessage(this.configs[i]);
2654     }
2655   };
2656   
2657   /**
2658    * Shuts down all the workers in this WorkerGroup.
2659    */
2660   WorkerPool.prototype.shutDown = function() {
2661     var workers = this.workers, 
2662         worker, i, l;
2663         
2664     for (i = 0, l = workers.length; i < l; i++) {
2665       worker = workers[i];
2666       worker.terminate();
2667     }
2668   };
2669   
2670   /**
2671    * Cleans the configurations previously assigned to workers in this WorkerGroup.
2672    */
2673   WorkerPool.prototype.clean = function(){
2674     this.configs = [];
2675   };
2676   
2677   return WorkerPool;
2678   
2679 }());
2680 
2681 // shader.js
2682 // Module webgl: Offers WebGL shader encapsulation.
2683 
2684 BenchGL.namespace('BenchGL.webgl.Shader');
2685 
2686 BenchGL.webgl.Shader = (function() {
2687 
2688 	// Private properties and methods
2689 	var Shader;
2690 	
2691 	/**
2692 	 * Creates a new Shader.
2693 	 * @class Represents a WebGL shader.
2694 	 * @param {Number} type The WebGL type of this shader.
2695 	 * @param {String} source The source string for the shader. 
2696 	 */
2697 	Shader = function(type, source) {
2698 		var shader = gl.createShader(type),
2699 				valid = false,
2700 				log = '';
2701 		
2702 		gl.shaderSource(shader, source);
2703 		gl.compileShader(shader);
2704 		
2705 		valid = gl.getShaderParameter(shader, gl.COMPILE_STATUS) !== 0;		
2706 		log += gl.getShaderInfoLog(shader);
2707 		
2708 		this.source = source;
2709 		this.handler = shader;
2710 		this.type = type;
2711 		this.valid = valid;
2712 		this.log = log;
2713 	};
2714 	
2715 	/**
2716 	 * Destroys this Shader.
2717 	 */
2718 	Shader.prototype.destroy = function() {
2719 		gl.deleteShader(this.handler);
2720 	};
2721 	
2722 	/**
2723 	 * Static container for the default vertex shaders.
2724 	 * @static
2725 	 */
2726 	Shader.Vertex = {
2727 		Default : [
2728 			"#ifdef GL_ES",
2729 			"precision highp float;",
2730 			"#endif",
2731 			
2732 			"attribute vec3 a_position;",
2733 			"attribute vec3 a_normal;",
2734 			"attribute vec2 a_texcoord;",
2735 			"attribute vec4 a_color;",
2736 			
2737 			"uniform mat4 u_modelViewMatrix;",
2738 			"uniform mat4 u_projectionMatrix;",
2739 			"uniform mat4 u_normalMatrix;",
2740 			"uniform mat4 u_viewMatrix;",
2741 			
2742 			"uniform bool u_enableLighting;",
2743 			"uniform vec3 u_ambientColor;",
2744 			"uniform vec3 u_directionalColor;",
2745 			"uniform vec3 u_lightingDirection;",
2746 			
2747 			"uniform bool u_enableLight1;",
2748 			"uniform vec3 u_lightColor1;",
2749 			"uniform vec3 u_lightPosition1;",
2750 			
2751 			"uniform bool u_enableLight2;",
2752 			"uniform vec3 u_lightColor2;",
2753 			"uniform vec3 u_lightPosition2;",
2754 		
2755 			"uniform bool u_enableLight3;",
2756 			"uniform vec3 u_lightColor3;",
2757 			"uniform vec3 u_lightPosition3;",
2758 			
2759 			"uniform bool u_enableLight4;",
2760 			"uniform vec3 u_lightColor4;",
2761 			"uniform vec3 u_lightPosition4;",
2762 			
2763 			"varying vec4 v_color;",
2764 			"varying vec2 v_texcoord;",
2765 			"varying vec3 v_lightFactor;",
2766 			
2767 			"void main(void) {",
2768 			"	vec4 ecPosition = u_modelViewMatrix * vec4(a_position, 1.0);",
2769 			
2770 			" if (!u_enableLighting) {",
2771 			"		v_lightFactor = vec3(1.0, 1.0, 1.0);",
2772 			"	} else {",
2773 			"		vec3 lightDirection;",
2774 			"		vec3 lightPosition;",
2775 			"		vec3 lightFactor1 = vec3(0.0, 0.0, 0.0);",
2776 			"		vec3 lightFactor2 = vec3(0.0, 0.0, 0.0);",
2777 			"		vec3 lightFactor3 = vec3(0.0, 0.0, 0.0);",
2778 			"		vec3 lightFactor4 = vec3(0.0, 0.0, 0.0);",
2779 			
2780 			"		vec3 normal = normalize((u_normalMatrix * vec4(a_normal, 1.0)).xyz);",
2781 	
2782 			"		vec3 directionalFactor = max(0.0, dot(normal, -u_lightingDirection)) * u_directionalColor;",
2783 			
2784 			"		if (u_enableLight1) {",
2785 			"			lightPosition = (u_viewMatrix * vec4(u_lightPosition1, 1.0)).xyz;",
2786 			"			lightDirection = normalize(lightPosition - ecPosition.xyz);",
2787 			"			lightFactor1 = max(0.0, dot(normal, lightDirection)) * u_lightColor1;",
2788 			"		}",
2789 			
2790 			"		if (u_enableLight2) {",
2791 			"			lightPosition = (u_viewMatrix * vec4(u_lightPosition2, 1.0)).xyz;",
2792 			"			lightDirection = normalize(lightPosition - ecPosition.xyz);",
2793 			"			lightFactor2 = max(0.0, dot(normal, lightDirection)) * u_lightColor2;",
2794 			"		}",
2795 			
2796 			"		if (u_enableLight3) {",
2797 			"			lightPosition = (u_viewMatrix * vec4(u_lightPosition3, 1.0)).xyz;",
2798 			"			lightDirection = normalize(lightPosition - ecPosition.xyz);",
2799 			"			lightFactor3 = max(0.0, dot(normal, lightDirection)) * u_lightColor3;",
2800 			"		}",
2801 			
2802 			"		if (u_enableLight4) {",
2803 			"			lightPosition = (u_viewMatrix * vec4(u_lightPosition4, 1.0)).xyz;",
2804 			"			lightDirection = normalize(lightPosition - ecPosition.xyz);",
2805 			"			lightFactor4 = max(0.0, dot(normal, lightDirection)) * u_lightColor4;",
2806 			"		}",
2807 			
2808 			"		v_lightFactor = u_ambientColor + directionalFactor + ",
2809 			"			lightFactor1 + lightFactor2 + lightFactor3 + lightFactor4;",
2810 			"	}",
2811 			
2812 			"	v_color = a_color;",
2813 			" v_texcoord = a_texcoord;",
2814 			" gl_Position = u_projectionMatrix * ecPosition;",
2815 			"}"
2816 			
2817 		].join("\n")
2818 	};
2819 
2820 	/**
2821 	 * Static container for the default fragment shaders.
2822 	 * @static
2823 	 */	
2824 	Shader.Fragment = {
2825 		Default : [
2826 			"#ifdef GL_ES",
2827 			"precision highp float;",
2828 			"#endif",
2829 			
2830 			"uniform bool u_enableTexturing;",
2831 			"uniform bool u_useTexture0;",
2832 			"uniform sampler2D tex0;",
2833 			
2834 			"varying vec4 v_color;",
2835 			"varying vec2 v_texcoord;",
2836 			"varying vec3 v_lightFactor;",
2837 			
2838 			"void main(void) {",
2839 			"	vec4 fColor = vec4(v_color.rgb * v_lightFactor, v_color.a);",
2840 			
2841 			"	if (u_enableTexturing) {",
2842       "   if (u_useTexture0) {",
2843 			"			fColor = vec4(texture2D(tex0, vec2(v_texcoord.s, v_texcoord.t)).rgb * v_lightFactor, 1.0);",
2844       "   }",
2845       " }",
2846 			
2847 			"	gl_FragColor = fColor;",
2848 			"}"
2849 		].join("\n")
2850 	};
2851 	
2852 	return Shader;
2853 	
2854 }());
2855 
2856 // program.js
2857 // Module webgl: Gives shader program support.
2858 
2859 BenchGL.namespace('BenchGL.webgl.ProgramAttribute');
2860 
2861 BenchGL.webgl.ProgramAttribute = (function() {
2862 
2863 	// Private properties and methods
2864   var ProgramAttribute;
2865   
2866   /**
2867    * Creates a new ProgramAttribute.
2868    * @class Represents an attribute variable in a shader program.
2869    * @param {Program} program The program in wich the attribute lives.
2870    * @param {String} name The name of the attribute.
2871    * @param {Number} type The WebGL type of the attribute.
2872    * @param {Number} size The size of the attributes in bytes.
2873    * @param {Number} location The index location in the shader.   
2874    */
2875   ProgramAttribute = function(program, name, type, size, location) {
2876     this.program = program;
2877     this.name = name;
2878     this.type = type;
2879     this.size = size;
2880     this.location = location;
2881   };
2882   
2883   /**
2884    * Sets the index of this ProgramAttribute.
2885    * @param {Number} n The index to set.
2886    */
2887   ProgramAttribute.prototype.setIndex = function(n) {
2888     gl.bindAttribLocation(this.program.handler, n, this.name);
2889     this.location = n;
2890   }; 
2891   
2892   /**
2893    * Gets the index of this ProgramAttribute.
2894    * @returns {Number} The current index of this ProgramAttribute in the program
2895    */
2896   ProgramAttribute.prototype.getIndex = function() {
2897     return this.location;
2898   };
2899   
2900   return ProgramAttribute;
2901   
2902 }());
2903 
2904 BenchGL.namespace('BenchGL.webgl.ProgramUniform');
2905 
2906 BenchGL.webgl.ProgramUniform = (function() {
2907 
2908 	// Private properties and methods
2909 	var ProgramUniform;
2910 
2911   /**
2912    * Creates a new ProgramUniform.
2913    * @class Represents an uniform variable in a shader program.
2914    * @param {Program} program The program in wich the uniform lives.
2915    * @param {String} name The name of the uniform.
2916    * @param {Number} type The WebGL type of the uniform.
2917    * @param {Number} size The size of the attributes in bytes.
2918    * @param {Number} location The index location in the shader.   
2919    */  
2920   ProgramUniform = function(program, name, type, size, location) {
2921     this.program = program;
2922     this.name = name;
2923     this.type = type;
2924     this.size = size;
2925     this.location = location;
2926     this.func = null;
2927     this.value = null;
2928     
2929     switch (type) {
2930       case gl.BOOL:
2931         this.func = function(v){
2932           gl.uniform1i(this.location, v);
2933         };
2934         break;
2935       case gl.BOOL_VEC2:
2936         this.func = function(v){
2937           gl.uniform2iv(this.location, new Uint16Array(v));
2938         };
2939         break;
2940       case gl.BOOL_VEC3:
2941         this.func = function(v){
2942           gl.uniform3iv(this.location, new Uint16Array(v));
2943         };
2944         break;
2945       case gl.BOOL_VEC4:
2946         this.func = function(v){
2947           gl.uniform4iv(this.location, new Uint16Array(v));
2948         };
2949         break;
2950       case gl.INT:
2951         this.func = function(v){
2952           gl.uniform1i(this.location, v);
2953         };
2954         break;
2955       case gl.INT_VEC2:
2956         this.func = function(v){
2957           gl.uniform2iv(this.location, new Uint16Array(v));
2958         };
2959         break;
2960       case gl.INT_VEC3:
2961         this.func = function(v){
2962           gl.uniform3iv(this.location, new Uint16Array(v));
2963         };
2964         break;
2965       case gl.INT_VEC4:
2966         this.func = function(v){
2967           gl.uniform4iv(this.location, new Uint16Array(v));
2968         };
2969         break;
2970       case gl.FLOAT:
2971         this.func = function(v){
2972           gl.uniform1f(this.location, v);
2973         };
2974         break;
2975       case gl.FLOAT_VEC2:
2976         this.func = function(v){
2977           gl.uniform2fv(this.location, new Float32Array(v));
2978         };
2979         break;
2980       case gl.FLOAT_VEC3:
2981         this.func = function(v){
2982           gl.uniform3fv(this.location, new Float32Array(v));
2983         };
2984         break;
2985       case gl.FLOAT_VEC4:
2986         this.func = function(v){
2987           gl.uniform4fv(this.location, new Float32Array(v));
2988         };
2989         break;
2990       case gl.FLOAT_MAT2:
2991         this.func = function(v){
2992           gl.uniformMatrix2fv(this.location, false, v.toFloat32Array());
2993         };
2994         break;
2995       case gl.FLOAT_MAT3:
2996         this.func = function(v){
2997           gl.uniformMatrix3fv(this.location, false, v.toFloat32Array());
2998         };
2999         break;
3000       case gl.FLOAT_MAT4:
3001         this.func = function(v){
3002           gl.uniformMatrix4fv(this.location, false, v.toFloat32Array());
3003         };
3004         break;
3005       default:
3006         throw {
3007           name: "UnknownUniformType",
3008           message: "The uniform variable type is unknown."
3009         };
3010     }
3011   };
3012   
3013   /**
3014    * Sets the value of this ProgramUniform.
3015    * @param {Object} v The value to set. 
3016    */
3017   ProgramUniform.prototype.setValue = function(v) {
3018     this.value = v;
3019     this.func(v);
3020   };
3021   
3022   /**
3023    * Get the value of this ProgramUniform.
3024    */
3025   ProgramUniform.prototype.getValue = function() {
3026     return this.value;
3027   };
3028   
3029   return ProgramUniform;
3030   
3031 }());
3032 
3033 BenchGL.namespace('BenchGL.webgl.ProgramSampler');
3034 
3035 BenchGL.webgl.ProgramSampler = (function() {
3036 
3037 	// Private properties and methods
3038 	var ProgramSampler;
3039 
3040   /**
3041    * Creates a new ProgramSampler.
3042    * @class Represents an sampler variable in a shader program.
3043    * @param {Program} program The program in wich the sampler lives.
3044    * @param {String} name The name of the sampler.
3045    * @param {Number} type The WebGL type of the sampler.
3046    * @param {Number} size The size of the attributes in bytes.
3047    * @param {Number} location The index location in the shader.   
3048    */   
3049   ProgramSampler = function(program, name, type, size, location) {
3050     this.program = program;
3051     this.name = name;
3052     this.type = type;
3053     this.size = size;
3054     this.location = location;
3055     this.unit = -1;		// The sampler unit for WebGL ( 0 < unit < 31 )
3056   };
3057   
3058   /**
3059    * Gets the unit of this ProgramSampler.
3060    */
3061   ProgramSampler.prototype.getUnit = function() {
3062     return this.unit;
3063   };
3064 
3065   /**
3066    * Sets the unit of this ProgramSampler.
3067    * @param {Number} n The unit to set. 
3068    */
3069   ProgramSampler.prototype.setUnit = function(n) {
3070     gl.uniform1i(this.location, n);
3071     this.unit = n;
3072   };
3073   
3074   return ProgramSampler;
3075   
3076 }());
3077 
3078 BenchGL.namespace('BenchGL.webgl.Program');
3079 
3080 BenchGL.webgl.Program = (function() {
3081 
3082 	// Dependencies
3083 	var Shader = BenchGL.webgl.Shader, 
3084       ProgramAttribute = BenchGL.webgl.ProgramAttribute,
3085       ProgramUniform = BenchGL.webgl.ProgramUniform,
3086       ProgramSampler = BenchGL.webgl.ProgramSampler,
3087       XHR = BenchGL.io.XHRequest,
3088       
3089       // Private properties and methods
3090       Program;
3091   
3092   /**
3093    * Creates a new Program.
3094    * @class Represents a shader program in the WebGL pipeline.
3095    * @param {Shader} vertex The vertex shader.
3096    * @param {Shader} fragment The fragment shader. 
3097    */
3098   Program = function(vertex, fragment) {
3099     var program = gl.createProgram(), 
3100     		valid = false, log = '';
3101     
3102     gl.attachShader(program, vertex.handler);
3103     gl.attachShader(program, fragment.handler);
3104     gl.linkProgram(program);
3105     
3106     valid = gl.getProgramParameter(program, gl.LINK_STATUS) !== 0;
3107     if (valid) {
3108       log += "Compiled succesfully!\n";
3109     }
3110     else {
3111       log += "Compilation error: ";
3112       log += gl.getProgramInfoLog(program);
3113       log += "\n";
3114     }
3115     
3116     this.vertex = vertex;
3117     this.fragment = fragment;
3118     this.handler = program;
3119     this.valid = valid;
3120     this.log = log;
3121     
3122     this.attributes = {};
3123     this.uniforms = {};
3124     this.samplers = {};
3125     
3126     this.buffers = {};
3127     this.cachedBuffers = {};
3128     
3129     this.build();
3130   };
3131   
3132   /**
3133    * Builds up this Program, encapsulating WebGL entities in BenchGL versions.
3134    * @private
3135    * @returns {Program} Returns this Program.
3136    */
3137   Program.prototype.build = function() {
3138     var program = this.handler, 
3139         attributes = this.attributes, 
3140         uniforms = this.uniforms, 
3141         samplers = this.samplers, 
3142         attributesCount = gl.getProgramParameter(program, gl.ACTIVE_ATTRIBUTES), 
3143         uniformsCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS),
3144         a, u, location, attribute, uniform, sampler, i;
3145     
3146     for (i = 0; i < attributesCount; ++i) {
3147       a = gl.getActiveAttrib(program, i);
3148       if (a) {
3149         location = gl.getAttribLocation(program, a.name);
3150         attribute = new ProgramAttribute(this, a.name, a.type, a.size, location);
3151         attributes[a.name] = attribute;       
3152       }
3153     }
3154     
3155     for (i = 0; i < uniformsCount; ++i) {
3156       u = gl.getActiveUniform(program, i);
3157       if (u) {
3158         location = gl.getUniformLocation(program, u.name);
3159         if (u.type === gl.SAMPLER_2D || u.type === gl.SAMPLER_CUBE) {
3160           sampler = new ProgramSampler(this, u.name, u.type, u.size, location);
3161           samplers[u.name] = sampler;
3162         }
3163         else {
3164           uniform = new ProgramUniform(this, u.name, u.type, u.size, location);
3165           uniforms[u.name] = uniform;
3166         }
3167       }
3168     }
3169     
3170     return this;
3171   };
3172   
3173   /**
3174    * Sets the vertex shader for this Program.
3175    * @param {Shader} shader The vertex shader to set.
3176    * @returns {Program} Returns this Program.
3177    */
3178   Program.prototype.setVertexShader = function(shader) {
3179     var program = this.handler,
3180         valid = false, 
3181         log = '';
3182     
3183     gl.detachShader(program, this.vertex.handler);
3184     gl.attachShader(program, shader.handler);
3185     gl.linkProgram(program);
3186     
3187     valid = gl.getProgramParameter(program, gl.LINK_STATUS) !== 0;
3188     if (valid) {
3189       log += "Recompiled succesfully!\n";
3190     }
3191     else {
3192       log += "Compilation error: ";
3193       log += gl.getProgramInfoLog(program);
3194       log += "\n";
3195     }
3196     
3197     this.vertex = shader;
3198     this.valid = valid;
3199     this.log = log;
3200     this.attributes = {};
3201     this.uniforms = {};
3202     this.samplers = {};
3203     this.buffers = {};
3204         
3205     this.build();
3206     
3207     return this;
3208   };
3209 
3210   /**
3211    * Sets the fragment shader for this Program.
3212    * @param {Shader} shader The fragment shader to set.
3213    * @returns {Program} Returns this Program.
3214    */  
3215   Program.prototype.setFragmentShader = function(shader) {
3216     var program = this.handler, 
3217         valid = false, 
3218         log = '';
3219     
3220     gl.detachShader(program, this.fragment.handler);
3221     gl.attachShader(program, shader.handler);
3222     gl.linkProgram(program);
3223     
3224     valid = gl.getProgramParameter(program, gl.LINK_STATUS) !== 0;
3225     if (valid) {
3226       log += "Recompiled succesfully!\n";
3227     }
3228     else {
3229       log += "Compilation error: ";
3230       log += gl.getProgramInfoLog(program);
3231       log += "\n";
3232     }
3233     
3234     this.fragment = shader;
3235     this.valid = valid;
3236     this.log = log;
3237     this.attributes = {};
3238     this.uniforms = {};
3239     this.samplers = {};
3240     this.buffers = {};
3241         
3242     this.build();
3243     
3244     return this;
3245   };
3246 
3247   /**
3248    * Sets the shaders for this Program.
3249    * @param {Shader} vertex The vertex shader to set.
3250    * @param {Shader} fragment The fragment shader to set.
3251    * @returns {Program} Returns this Program.
3252    */  
3253   Program.prototype.setShaders = function(vertex, fragment) {
3254     var program = this.handler, 
3255         valid = false, 
3256         log = '';
3257     
3258     gl.detachShader(program, this.vertex.handler);
3259     gl.detachShader(program, this.fragment.handler);
3260     gl.attachShader(program, vertex.handler);
3261     gl.attachShader(program, fragment.handler);
3262     gl.linkProgram(program);
3263     
3264     valid = gl.getProgramParameter(program, gl.LINK_STATUS) !== 0;
3265     if (valid) {
3266       log += "Recompiled succesfully!\n";
3267     }
3268     else {
3269       log += "Compilation error: ";
3270       log += gl.getProgramInfoLog(program);
3271       log += "\n";
3272     }
3273     
3274     this.vertex = vertex;
3275     this.fragment = fragment;
3276     this.valid = valid;
3277     this.log = log;
3278     this.attributes = {};
3279     this.uniforms = {};
3280     this.samplers = {};
3281     this.buffers = {};
3282         
3283     this.build();
3284     
3285     return this;
3286   };
3287   
3288   /**
3289    * Links this Program.
3290    */
3291   Program.prototype.link = function() {
3292     gl.linkProgram(this.handler);
3293   };
3294   
3295   /**
3296    * Destroys this Program.
3297    */
3298   Program.prototype.destroy = function() {
3299   	gl.deleteProgram(this.handler);
3300     this.vertex.destroy();
3301     this.fragment.destroy();
3302   };
3303   
3304   /**
3305    * Binds this Program as the current shader program in the WebGL pipeline.
3306    */
3307   Program.prototype.bind = function() {
3308     gl.useProgram(this.handler);
3309   };
3310 
3311   /**
3312    * Unbinds this Program as the current shader program in the WebGL pipeline.
3313    */  
3314   Program.prototype.unbind = function(){
3315     gl.useProgram(null);
3316   };
3317 
3318 	/**
3319 	 * Binds an attribute buffer in this Program.
3320 	 * @param {String} name The name of the attribute.
3321 	 * @param {Object} [options] The options for the attribute to bind. 
3322 	 * @param {Number} [options.attributeType] The WebGL attribute type. 
3323 	 * @param {Number} [options.dataType] The WebGL type of an element in the attribute buffer.
3324 	 * @param {Number} [options.drawType] The WebGL drawing mode. 
3325 	 * @param {Number} [options.size] The size of the attribute elements in bytes. 
3326 	 * @param {Number} [options.stride] The stride of the attribute buffer. 
3327 	 * @param {Number} [options.offset] The offset of the attribute buffer. 
3328 	 * @param {Object} [options.data] The attribute buffer data. 
3329    * @returns {Program} Returns this Program.
3330 	 */
3331   Program.prototype.bindAttribute = function(name, options) {
3332     options = $.mix({
3333       attributeType : gl.ARRAY_BUFFER,
3334       dataType : gl.FLOAT,
3335       drawType : gl.STATIC_DRAW,
3336       size : 1,
3337       stride : 0,
3338       offset : 0
3339     }, this.cachedBuffers[name] || {}, options || {});
3340     
3341     var attributeName = options.name || name,
3342         attributeType = options.attributeType,
3343         dataType = options.dataType,
3344         drawType = options.drawType,
3345         size = options.size,
3346         stride = options.stride,
3347         offset = options.offset,
3348         data = options.data,
3349         hasBuffer = name in this.buffers,
3350         buffer = hasBuffer ? this.buffers[name] : gl.createBuffer(),
3351         hasData = 'data' in options,
3352         index = this.attributes[attributeName] && this.attributes[attributeName].getIndex(),
3353         isAttribute = index !== undefined;
3354     
3355     if (!hasBuffer) {
3356       this.buffers[name] = buffer;
3357       isAttribute && gl.enableVertexAttribArray(index);
3358     }
3359 
3360     gl.bindBuffer(attributeType, buffer);
3361     
3362     if (hasData) {
3363       gl.bufferData(attributeType, data, drawType);
3364     }
3365     
3366     isAttribute && gl.vertexAttribPointer(index, size, dataType, false, stride, offset);
3367     
3368     delete options.data;
3369     this.cachedBuffers[name] = options;
3370     
3371     return this;
3372   };
3373   
3374   /**
3375    * Binds all the attributes in this Program following a mapping.
3376    * @param {Object} mapping The mapping that specifies values for the attributes.
3377    * @returns {Program} Returns this Program.
3378    */
3379   Program.prototype.bindAttributes = function(mapping) {
3380     for (var name in mapping) {
3381       this.bindAttribute(name, mapping[name]);
3382     }
3383     return this;
3384   };
3385 
3386 	/**
3387 	 * Binds an uniform variable in this Program.
3388 	 * @param {String} name The name of the uniform.
3389 	 * @param {Object} value The value for the uniform to bind.
3390    * @returns {Program} Returns this Program.
3391 	 */
3392   Program.prototype.bindUniform = function(name, value) {
3393     if (this.uniforms[name]) {
3394       this.uniforms[name].setValue(value);
3395     }
3396     return this;
3397   }; 
3398 
3399   /**
3400    * Binds all the uniform variables in this Program following a mapping.
3401    * @param {Object} mapping The mapping that specifies values for the uniforms.
3402    * @returns {Program} Returns this Program.
3403    */  
3404   Program.prototype.bindUniforms = function(mapping) {
3405     for (var name in mapping) {
3406       this.bindUniform(name, mapping[name]);
3407     }
3408     return this;
3409   };
3410 
3411 	/**
3412 	 * Binds a sampler variable to a unit in this Program.
3413 	 * @param {String} name The name of the sampler.
3414 	 * @param {Number} value The value for the unit to bind the sampler to.
3415    * @returns {Program} Returns this Program.
3416 	 */  
3417   Program.prototype.bindSampler = function(name, value) {
3418     if (this.samplers[name]) {
3419       this.samplers[name].setUnit(value);
3420     }
3421     return this;
3422   };
3423 
3424   /**
3425    * Binds all the sampler variables in this Program following a mapping.
3426    * @param {Object} mapping The mapping that specifies units for the sampler.
3427    * @returns {Program} Returns this Program.
3428    */  
3429   Program.prototype.bindSamplers = function(mapping) {
3430     for (var name in mapping) {
3431       this.bindSampler(name, mapping[name]);
3432     }
3433     return this;
3434   };
3435   
3436   /**
3437    * Static factory method to generate a shader Program in different ways.
3438    * @static
3439    * @param {Object} options The options for creating the Program.
3440    * @returns {Program} A new Program.
3441    */
3442   Program.factory = function(options) {
3443     var type = (options && options.type) || 'defaults', 
3444         method = 'From' + $.capitalize(type);
3445     
3446     if (typeof Program[method] !== "function") {
3447       throw {
3448         name: "UnknownProgramType",
3449         message: "Type '" + method + "' does not exist."
3450       };
3451     }
3452     
3453     return Program[method](options);
3454   };
3455 
3456   /**
3457    * Static method to create a shader Program from shader's URLs.
3458    * @static
3459    * @param {Object} [options] The options for creating the Program.
3460    * @param {String} [options.vertex] The URL string for the vertex shader.
3461    * @param {String} [options.fragment] The URL string for the fragment shader.
3462    * @param {Function} [options.onSuccess] A callback to call in case of success.
3463    * @param {Function} [options.onError] A callback to call in case of failure.
3464    * @returns {Program} A new Program.
3465    */  
3466   Program.FromUrls = function(options) {
3467     options = $.mix({
3468       vertex: '',
3469       fragment: '',
3470       onSuccess: $.empty,
3471       onError: $.empty
3472     }, options || {});
3473     
3474     new XHR({
3475       url: options.vertex,
3476       onError: function(e){
3477         options.onError(e);
3478       },
3479       onSuccess: function(vs){
3480         new XHR({
3481           url: options.fragment,
3482           onError: function(e){
3483             options.onError(e);
3484           },
3485           onSuccess: function(fs){
3486             options.onSuccess(Program.FromSources({
3487               vertex: vs,
3488               fragment: fs
3489             }));
3490           }
3491         }).send();
3492       }
3493     }).send();
3494   };
3495 
3496   /**
3497    * Static method to create a shader Program from shader's scripts inside a webpage.
3498    * @static
3499    * @param {Object} [options] The options for creating the Program.
3500    * @param {String} options.vertex The HTML element containing the vertex shader.
3501    * @param {String} options.fragment The HTML elemente containing the fragment shader.
3502    * @returns {Program} A new Program.
3503    */    
3504   Program.FromScripts = function(options) {
3505     var vs = options.vertex, 
3506         fs = options.fragment, 
3507         vertex = new Shader(gl.VERTEX_SHADER, $(vs).innerHTML), 
3508         fragment = new Shader(gl.FRAGMENT_SHADER, $(fs).innerHTML);
3509     return new Program(vertex, fragment);
3510   };
3511 
3512   /**
3513    * Static method to create a shader Program from shader's sources.
3514    * @static
3515    * @param {Object} [options] The options for creating the Program.
3516    * @param {String} options.vertex The source string for the vertex shader.
3517    * @param {String} options.fragment The source string for the fragment shader.
3518    * @returns {Program} A new Program.
3519    */    
3520   Program.FromSources = function(options) {
3521     var vs = options.vertex, 
3522         fs = options.fragment, 
3523         vertex = new Shader(gl.VERTEX_SHADER, vs), 
3524         fragment = new Shader(gl.FRAGMENT_SHADER, fs);
3525     return new Program(vertex, fragment);
3526   };
3527 
3528   /**
3529    * Static method to create a shader Program from shader's default sources.
3530    * @static
3531    * @param {Object} [options] The options for creating the Program.
3532    * @param {String} [options.vertex='Deafult'] The id string for the vertex shader.
3533    * @param {String} [options.fragment='Default'] The id string for the fragment shader.
3534    * @returns {Program} A new Program.
3535    */   
3536   Program.FromDefaults = function(options){
3537     var vs = (options && $.capitalize(options.vertex)) || 'Default', 
3538         fs = (options && $.capitalize(options.fragment)) || 'Default', 
3539         vertex = new Shader(gl.VERTEX_SHADER, Shader.Vertex[vs]), 
3540         fragment = new Shader(gl.FRAGMENT_SHADER, Shader.Fragment[fs]);
3541     return new Program(vertex, fragment);
3542   };
3543   
3544   return Program;
3545   
3546 }());
3547 
3548 // model.js
3549 // Modeule drawing: Provides a Model object to create and manipulate shapes.
3550 
3551 BenchGL.namespace('BenchGL.drawing.Model');
3552 
3553 BenchGL.drawing.Model = (function() {
3554   
3555   // Dependencies
3556   var MatStack = BenchGL.math.MatrixStack,
3557       Mat = BenchGL.skin.Material,
3558       XHR = BenchGL.io.XHRequest,
3559       sin = Math.sin,
3560       cos = Math.cos,
3561       pi = Math.PI,
3562       id = 0,
3563       
3564       // Private properties and methods
3565       Model;
3566   
3567   /**
3568    * Creates a new Model.
3569    * @class	Represents a geometric model.
3570    * @param {Object} [options] Parameters to initialize the model.
3571    * @param {Number} [drawType] The WebGL primitive type.
3572    * @param {Boolean} [useColors] Use color on a per-vertex basis.
3573    * @param {Boolean} [dynamic] Avoid caching model's geometry.
3574    * @param {Number[]} [colors=[1, 1, 1, 1]] The per-vertex color.     
3575    */
3576   Model = function(options) {
3577     options = $.mix({
3578       drawType : gl.TRIANGLES,
3579       useColors : true,
3580       dynamic : true,
3581       colors : [1, 1, 1, 1]
3582     }, options || {});
3583     
3584     this.id = options.id || id++;
3585     this.drawType = options.drawType;
3586     this.useColors = options.useColors;
3587     this.dynamic = options.dynamic;
3588     this.vertices = options.vertices;
3589     this.normals = options.normals;
3590     this.texcoords = options.texcoords;
3591     this.colors = options.colors;
3592     this.indices = options.indices;
3593     
3594     this.material = new Mat();
3595     this.uniforms = {};
3596     this.textures = [];
3597     
3598     this.matrixStack = new MatStack();
3599         
3600     if (this.useColors) {
3601       this.normalizeColors();
3602     }
3603   };
3604   
3605   /**
3606    * Gets the model matrix associated to this Model.
3607    * @returns {Matrix4} A matrix representing the position of this Model in the scene.
3608    */
3609   Model.prototype.matrix = function() {
3610   	return this.matrixStack.top();
3611   };
3612   
3613   /**
3614    * Resets the matrix of this Model.
3615    */
3616   Model.prototype.reset = function() {
3617     this.matrixStack.loadIdentity();
3618   };
3619   
3620   /**
3621    * Translates this Model through its matrix.
3622    * @param {Number} x The x-axis translation component.
3623    * @param {Number} y The y-axis translation component.
3624    * @param {Number} z The z-axis translation component.
3625    */
3626   Model.prototype.translate = function(x, y, z) {
3627     this.matrixStack.translate(x, y, z);
3628   };
3629 
3630   /**
3631    * Scales this Model through its matrix.
3632    * @param {Number} x The x-axis scale factor.
3633    * @param {Number} y The y-axis scale factor.
3634    * @param {Number} z The z-axis scale factor.
3635    */  
3636   Model.prototype.scale = function(x, y, z) {
3637     this.matrixStack.scale(x, y, z);
3638   };
3639 
3640   /**
3641    * Rotates this Model through its matrix.
3642    * @param {Number} angle The rotation angle. 
3643    * @param {Number} x The x component of the rotation axis.
3644    * @param {Number} y The y component of the rotation axis.
3645    * @param {Number} z The z component of the rotation axis.
3646    */  
3647   Model.prototype.rotate = function(angle, x, y, z) {
3648     this.matrixStack.rotate(angle, x, y, z);
3649   };
3650 
3651   /**
3652    * Rotates this Model (around the X, Y and Z axis) through its matrix.
3653    * @param {Number} rx The rotation angle around X axis.
3654    * @param {Number} ry The rotation angle around Y axis.
3655    * @param {Number} rz The rotation angle around Z axis
3656    */    
3657   Model.prototype.rotateXYZ = function(rx, ry, rz) {
3658     this.matrixStack.rotateXYZ(rx, ry, rz);
3659   };  
3660 
3661   /**
3662    * Normalizes the per-vertex color to all vertices in this Model.
3663    */   
3664   Model.prototype.normalizeColors = function() {
3665     if (!this.vertices) return;
3666     
3667     var colors = this.colors,
3668         totalLength = this.vertices.length * 4 / 3,
3669         count = totalLength / colors.length,
3670         result = new Float32Array(totalLength);
3671     
3672     if (colors.length < totalLength) {
3673       while (count--) {
3674         result.set(colors, count * colors.length);
3675       }
3676       this.colors = result;
3677     }    
3678   };
3679   
3680   /**
3681     * Sets the texture for this Model.
3682     * @param {String[]} arguments The textures' names.
3683     */ 
3684   Model.prototype.setTextures = function() {
3685     var textures = this.textures;
3686     for (var i = 0, l = arguments.length; i < l; i ++) {
3687       textures.push(arguments[i]);
3688     }
3689   };
3690 
3691 	/**
3692 	 * Sets the material ambient color of this Model.
3693 	 * @param {Number} r The red component of the color.
3694 	 * @param {Number} g The red component of the color.
3695 	 * @param {Number} b The red component of the color.
3696 	 */
3697   Model.prototype.setMaterialAmbient = function(r, g, b) {
3698     this.material.setAmbient(r, g, b);
3699   };
3700 
3701 	/**
3702 	 * Sets the material diffuse color of this Model.
3703 	 * @param {Number} r The red component of the color.
3704 	 * @param {Number} g The red component of the color.
3705 	 * @param {Number} b The red component of the color.
3706 	 */    
3707   Model.prototype.setMaterialDiffuse = function(r, g, b) {
3708     this.material.setDiffuse(r, g, b);    
3709   };
3710 
3711 	/**
3712 	 * Sets the material specular color of this Model.
3713 	 * @param {Number} r The red component of the color.
3714 	 * @param {Number} g The red component of the color.
3715 	 * @param {Number} b The red component of the color.
3716 	 */  
3717   Model.prototype.setMaterialSpecular = function(r, g, b) {
3718     this.material.setSpecular(r, g, b);    
3719   };
3720 
3721 	/**
3722 	 * Sets the material emissive color of this Model.
3723 	 * @param {Number} r The red component of the color.
3724 	 * @param {Number} g The red component of the color.
3725 	 * @param {Number} b The red component of the color.
3726 	 */   
3727   Model.prototype.setMaterialEmissive = function(r, g, b) {
3728     this.material.setEmissive(r, g, b);    
3729   };
3730 
3731 	/**
3732 	 * Sets the material shininess of this Model.
3733 	 * @param {Number} r The red component of the color.
3734 	 * @param {Number} g The red component of the color.
3735 	 * @param {Number} b The red component of the color.
3736 	 */ 
3737   Model.prototype.setMaterialShininess = function(shininess) {
3738     this.material.setShininess(shininess);
3739   };   
3740   
3741   /**
3742    * Sets custom property to this Model to bind to a uniform value in a shader program.
3743    * @param {String} name The name of the uniform variable to bind the property.
3744    * @param {Object} value The value of the property to set.
3745    */
3746   Model.prototype.setUniform = function(name, value) {
3747     this.uniforms[name] = value;
3748   };
3749   
3750   /**
3751    * Binds the vertices of this Model to a shader Program.
3752    * @param {Program} program The program to bind the vertices.
3753    * @param {Boolean} [update] Avoid using cached vertices.
3754    */
3755   Model.prototype.bindVertices = function(program, update) {
3756     if (!this.vertices) return;
3757     
3758     if (update || this.dynamic) {
3759       program.bindAttribute(this.id + '-vertices', {
3760         name: 'a_position',
3761         data: new Float32Array(this.vertices),
3762         size: 3
3763       });
3764     } else {
3765       program.bindAttribute(this.id + '-vertices');
3766     }
3767   };
3768 
3769   /**
3770    * Binds the normals of this Model to a shader Program.
3771    * @param {Program} program The program to bind the normals.
3772    * @param {Boolean} [update] Avoid using cached normals.
3773    */  
3774   Model.prototype.bindNormals = function(program, update) {
3775     if (!this.normals) return;
3776     
3777     if (update || this.dynamic) {
3778       program.bindAttribute(this.id + '-normals', {
3779         name : 'a_normal',
3780         data : new Float32Array(this.normals),
3781         size : 3
3782       });          
3783     } else {
3784       program.bindAttribute(this.id + '-normals');
3785     }
3786   };
3787 
3788   /**
3789    * Binds the texture coordinates of this Model to a shader Program.
3790    * @param {Program} program The program to bind the texture coordinates.
3791    * @param {Boolean} [update] Avoid using cached texture coordinates.
3792    */    
3793   Model.prototype.bindTexcoords = function(program, update) {
3794     if (!this.texcoords) return;
3795     
3796     if (update || this.dynamic) {
3797       program.bindAttribute(this.id + '-texcoords', {
3798         name: 'a_texcoord',
3799         data: new Float32Array(this.texcoords),
3800         size: 2
3801       });
3802     } else {
3803       program.bindAttribute(this.id + '-texcoords');
3804     }
3805   };
3806 
3807   /**
3808    * Binds the colors of this Model to a shader Program.
3809    * @param {Program} program The program to bind the colors.
3810    * @param {Boolean} [update] Avoid using cached colors.
3811    */ 
3812   Model.prototype.bindColors = function(program, update) {
3813     if (!this.colors || !this.useColors) return;
3814     
3815     if (update || this.dynamic) {
3816       program.bindAttribute(this.id + '-colors', {
3817         name : 'a_color',
3818         data: new Float32Array(this.colors),
3819         size: 4
3820       });
3821     } else {
3822       program.bindAttribute(this.id + '-colors');
3823     }
3824   };
3825 
3826   /**
3827    * Binds the indices of this Model to a shader Program.
3828    * @param {Program} program The program to bind the indices.
3829    * @param {Boolean} [update] Avoid using cached indices.
3830    */    
3831   Model.prototype.bindIndices = function(program, update) {
3832     if (!this.indices) return;
3833     
3834     if (update || this.dynamic) {
3835 	    program.bindAttribute(this.id + '-indices', {
3836 	      attributeType : gl.ELEMENT_ARRAY_BUFFER,
3837 	      data : new Uint16Array(this.indices),
3838 	    });
3839     } else {
3840     	program.bindAttribute(this.id + '-indices');
3841     }
3842   };
3843   
3844   /**
3845    * Binds the custom properties of this Model to their uniforms variable.
3846    * @param {Program} program The program to bind the properties.
3847    */
3848   Model.prototype.bindUniforms = function(program) {
3849     program.bindUniforms(this.uniforms);
3850   };
3851 
3852   /**
3853    * Binds the material properties of this Model to their uniforms variable.
3854    * @param {Program} program The program to bind the properties.
3855    */  
3856   Model.prototype.bindMaterial = function(program) {
3857     var material = this.material,
3858         uniforms = {};
3859     
3860     uniforms.u_matAmbient = material.ambient.toRGBAArray();
3861     uniforms.u_matDiffuse = material.diffuse.toRGBAArray();
3862     uniforms.u_matSpecular = material.specular.toRGBAArray();
3863     uniforms.u_matEmissive = material.emissive.toRGBAArray();
3864     uniforms.u_matShininess = material.shininess;
3865     
3866     program.bindUniforms(uniforms);
3867   };
3868 
3869   /**
3870    * Binds the textures with this Model to their sampler variable.
3871    * @param {Program} program The program to bind the properties.
3872    * @param {Texture[]} texture The previously loaded textures.
3873    */  
3874   Model.prototype.bindTextures = function(program, textures) {
3875     var names = this.textures;
3876     for (i = 0, l = names.length; i < l; i++) {
3877       var texture = textures[names[i]];
3878       if (texture) {
3879         program.bindUniform('u_useTexture' + i, true);
3880         program.bindSamplers('tex' + i, i);
3881         texture.bind(i);
3882       }
3883     }
3884     this.textures = [];
3885   };
3886   
3887   /**
3888    * Draws this Model.
3889    */
3890   Model.prototype.draw = function() {
3891     if (this.indices) {
3892       // Draw the model with as an indexed vertex array
3893       gl.drawElements(this.drawType, this.indices.length, gl.UNSIGNED_SHORT, 0);
3894     } else if (this.vertices) {
3895       // Draw the model with as a simple flat vertex array
3896       gl.drawArrays(this.drawType, 0, this.vertices.length / 3);
3897     }
3898   };
3899   
3900   /**
3901    * Static factory method to generate different kinds of Models.
3902    * @static
3903    * @param {Number} type The type of Model to create.
3904    * @param {Object} options.
3905    * @returns {Model} A new instance of Model.
3906    */
3907   Model.factory = function(type, options) {
3908     type = $.capitalize(type);
3909     
3910     if (typeof Model[type] !== "function") {
3911       throw {
3912         name: "UnknownModelType",
3913         message: "Method '" + type + "' does not exist."
3914       };
3915     }
3916     
3917     return Model[type](options);
3918   };
3919 
3920   /**
3921    * Static method to generate a triangle Model.
3922    * @static
3923    * @param {Object} [options] Contains geometric model data.
3924    * @param {Number[]} [options.vertices] Contains geometric vertices data.
3925    * @param {Number[]} [options.normals] Contains geometric normals data.
3926    * @param {Number[]} [options.texcoords] Contains texture coordinates data.
3927    * @param {Number[]} [options.colors] Contains colors data.
3928    * @returns {Model} A new instance of Model.
3929    */  
3930   Model.Triangle = function(options) {
3931     return new Model($.mix({
3932       vertices: [0, 1, 0, -1, -1, 0, 1, -1, 0],
3933       normals: [0, 0, 1, 0, 0, 1, 0, 0, 1],
3934       texcoords: [1, 1, 0, 0, 1, 0],
3935       colors: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
3936     }, options || {}));
3937   };
3938 
3939   /**
3940    * Static method to generate a rectangle Model.
3941    * @static
3942    * @param {Object} [options] Contains geometric model data.
3943    * @param {Number[]} [options.vertices] Contains geometric vertices data.
3944    * @param {Number[]} [options.normals] Contains geometric normals data.
3945    * @param {Number[]} [options.texcoords] Contains texture coordinates data.
3946    * @param {Number[]} [options.colors] Contains colors data.
3947    * @param {Number[]} [options.indices] Contains indices data.
3948    * @returns {Model} A new instance of Model.
3949    */
3950   Model.Rectangle = function(options) {
3951     return new Model($.mix({
3952       vertices: [-1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0],
3953       normals: [0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1],
3954       texcoords: [0, 0, 1, 0, 0, 1, 1, 1],
3955       colors: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
3956       indices: [0, 1, 2, 3, 1, 2]
3957     }, options || {}));
3958   };
3959 
3960   /**
3961    * Static method to generate a circle Model.
3962    * @static
3963    * @param {Object} [options] Contains parameters to generate a circle.
3964    * @param {Number[]} [options.slices] The circle's approximation slices.
3965    * @param {Number[]} [options.radius] The circle's radius.
3966    * @returns {Model} A new instance of Model.
3967    */  
3968   Model.Circle = function(options) {
3969     var n = (options) ? options.slices || 16 : 16, 
3970         r = (options) ? options.radius || 1 : 1, 
3971         vertexCoords = [0, 0, 0], 
3972         normalCoords = [0, 0, 1], 
3973         textureCoords = [0.5, 0.5],
3974         i, angle, x, y, u, v;
3975     
3976     for (i = 0; i <= n; i++) {
3977       angle = pi * i / n;
3978       x = r * cos(angle);
3979       y = r * sin(angle);
3980       u = (cos(angle) + 1) * 0.5;
3981       v = (sin(angle) + 1) * 0.5;
3982       
3983       vertexCoords.push(x);
3984       vertexCoords.push(y);
3985       vertexCoords.push(0);
3986       normalCoords.push(0);
3987       normalCoords.push(0);
3988       normalCoords.push(1);
3989       textureCoords.push(u);
3990       textureCoords.push(v);
3991     }
3992     
3993     return new Model($.mix({
3994       drawType : gl.TRIANGLE_FAN,
3995       vertices: vertexCoords,
3996       normals: normalCoords,
3997       texcoords: textureCoords,
3998       colors: [1, 1, 1, 1]
3999     }, options || {}));
4000   };
4001 
4002   /**
4003    * Static method to generate a cube Model.
4004    * @static
4005    * @param {Object} [options] Contains geometric model data.
4006    * @param {Number[]} [options.vertices] Contains geometric vertices data.
4007    * @param {Number[]} [options.normals] Contains geometric normals data.
4008    * @param {Number[]} [options.texcoords] Contains texture coordinates data.
4009    * @param {Number[]} [options.colors] Contains colors data.
4010    * @param {Number[]} [options.indices] Contains indices data.
4011    * @returns {Model} A new instance of Model.
4012    */  
4013   Model.Cube = function(options) {
4014     return new Model($.mix({
4015       vertices: [
4016       -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1,
4017       -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1,
4018       -1, 1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1,
4019       -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1,
4020       1, -1, -1, 1, 1, -1, 1, 1, 1, 1, -1, 1,
4021       -1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1],
4022       normals: [
4023       0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
4024       0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,
4025       0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
4026       0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0,
4027       1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
4028       -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0],
4029       texcoords: [
4030       0, 0, 1, 0, 1, 1, 0, 1,
4031       1, 0, 1, 1, 0, 1, 0, 0,
4032       0, 1, 0, 0, 1, 0, 1, 1,
4033       1, 1, 0, 1, 0, 0, 1, 0,
4034       1, 0, 1, 1, 0, 1, 0, 0,
4035       0, 0, 1, 0, 1, 1, 0, 1 ],
4036       colors: [
4037       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4038       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4039       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4040       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4041       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4042       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
4043       indices: [0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23]
4044     }, options || {}));
4045   };
4046 
4047   /**
4048    * Static method to generate a pyramid Model.
4049    * @static
4050    * @param {Object} [options] Contains geometric model data.
4051    * @param {Number[]} [options.vertices] Contains geometric vertices data.
4052    * @param {Number[]} [options.normals] Contains geometric normals data.
4053    * @param {Number[]} [options.texcoords] Contains texture coordinates data.
4054    * @param {Number[]} [options.colors] Contains colors data.
4055    * @returns {Model} A new instance of Model.
4056    */  
4057   Model.Pyramid = function(options) {
4058     return new Model($.mix({
4059       vertices: [
4060       0, 1, 0, -1, -1, 1, 1, -1, 1,
4061       0, 1, 0, 1, -1, -1, -1, -1, -1,
4062       0, 1, 0, 1, -1, 1, 1, -1, -1,
4063       0, 1, 0, -1, -1, -1, -1, -1, 1],
4064       normals: [
4065       0, 1, 0, -1, -1, 1, 1, -1, 1,
4066       0, 1, 0, 1, -1, -1, -1, -1, -1,
4067       0, 1, 0, 1, -1, 1, 1, -1, -1,
4068       0, 1, 0, -1, -1, -1, -1, -1, 1],
4069       texcoords: [
4070       1, 1, 0, 0, 1, 0,
4071       1, 1, 0, 0, 1, 0,
4072       1, 1, 0, 0, 1, 0,
4073       1, 1, 0, 0, 1, 0],
4074       colors: [
4075       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4076       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4077       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
4078       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
4079     }, options || {}));
4080   };
4081 
4082   /**
4083    * Static method to generate a sphere Model.
4084    * @static
4085    * @param {Object} [options] Contains parameters to generate a sphere.
4086    * @param {Number[]} [options.slices] The sphere's approximation slices.
4087    * @param {Number[]} [options.slices] The sphere's approximation slices.
4088    * @param {Number[]} [options.radius] The sphere's radius.
4089    * @returns {Model} A new instance of Model.
4090    */
4091   Model.Sphere = function(options) {
4092     var n = (options) ? options.slices || 32 : 32, 
4093         m = (options) ? options.stacks || 32 : 32, 
4094         r = (options) ? options.radius || 1.0 : 1.0, 
4095         vertexCoords = [], 
4096         normalCoords = [],
4097         textureCoords = [], 
4098         indices = [],
4099         pi2 = pi * 2,
4100         i, j, theta, phi, sint, cost, sinp, cosp,
4101         x, y, z, u, v, first, second;
4102     
4103     for (i = 0; i <= n; i++) {
4104       theta = pi * i / n;
4105       sint = sin(theta);
4106       cost = cos(theta);
4107       for (j = 0; j <= m; j++) {
4108         phi = pi2 * j / m;
4109         sinp = sin(phi);
4110         cosp = cos(phi);
4111         x = r * sint * cosp;
4112         y = r * cost;
4113         z = r * sint * sinp;
4114         u = 1 - j / m;
4115         v = 1 - i / n;
4116         
4117         vertexCoords.push(x);
4118         vertexCoords.push(y);
4119         vertexCoords.push(z);
4120         normalCoords.push(x);
4121         normalCoords.push(y);
4122         normalCoords.push(z);
4123         textureCoords.push(u);
4124         textureCoords.push(v);
4125       }
4126     }
4127     
4128     for (i = 0; i < n; i++) {
4129       for (j = 0; j < m; j++) {
4130         first = i * (m + 1) + j;
4131         second = first + m + 1;
4132         
4133         indices.push(first);
4134         indices.push(second);
4135         indices.push(first + 1);
4136         indices.push(second);
4137         indices.push(second + 1);
4138         indices.push(first + 1);
4139       }
4140     }
4141     
4142     return new Model($.mix({
4143       vertices: vertexCoords,
4144       normals: normalCoords,
4145       texcoords: textureCoords,
4146       colors: [1.0, 1.0, 1.0, 1.0],
4147       indices: indices
4148     }, options || {}));
4149   };
4150   
4151   /**
4152    * Static method to load a Model from a JSON file.
4153    * @static
4154    * @param {Object} [options] Options for creating the Model.
4155    * @param {String} [options.url] The URL of the JSON file..
4156    * @param {Object} [options.model] Contains model options.
4157    * @returns {Model} A new instance of Model.
4158    */    
4159   Model.Json = function(options) {
4160     var modelOptions = options.model,
4161         model;
4162     
4163     new XHR({
4164       url: options.url,
4165       async: false,
4166       onSuccess: function(response){
4167         var json = JSON.parse(response), 
4168             options = $.mix({
4169               vertices: json.vertexPositions,
4170               normals: json.vertexNormals,
4171               texcoords: json.vertexTextureCoords,
4172               indices: json.indices
4173             }, modelOptions || {});
4174         
4175         model = new Model(options);
4176       }
4177     }).send();
4178     
4179     return model;
4180   };
4181   
4182   return Model;
4183   
4184 }());
4185 
4186 // renderer.js
4187 // Module drawing: Implements the core of the rendering engine.
4188 
4189 BenchGL.namespace('BenchGL.drawing.SinglePassRenderingStrategy');
4190 
4191 BenchGL.drawing.SinglePassRenderingStrategy = (function() {
4192 
4193 	var SinglePassRenderingStrategy;
4194 	
4195 	/**
4196 	 * Creates a new SinglePassRenderingStrategy.
4197 	 * @class Represent the first-pass rendering algorithm.
4198 	 * @param {Renderer} renderer A reference to the Renderer performing the algorithm.
4199 	 */
4200 	SinglePassRenderingStrategy = function(renderer) {
4201 		this.renderer = renderer;
4202 	};
4203 	
4204 	/**
4205 	 * Setups camera uniforms in the current shader program.
4206 	 */
4207   SinglePassRenderingStrategy.prototype.setupCamera = function() {
4208     var program = this.renderer.program,
4209         camera = this.renderer.camera;
4210     
4211     program.bindUniform('u_projectionMatrix', camera.projMatrix());
4212     program.bindUniform('u_viewMatrix', camera.viewMatrix());
4213   };
4214 
4215 	/**
4216 	 * Setups lights uniforms in the current shader program.
4217 	 */  
4218   SinglePassRenderingStrategy.prototype.setupLights = function(){
4219     var uniforms = {},
4220         index = 0, l, light;
4221     
4222     uniforms.u_enableLighting = this.renderer.useLighting;
4223     uniforms.u_ambientColor = this.renderer.ambientColor.toRGBArray();
4224     uniforms.u_directionalColor = this.renderer.directionalColor.toRGBArray();
4225     uniforms.u_lightingDirection = this.renderer.lightingDirection.toArray();
4226     
4227     for (l in this.renderer.lights) {
4228       light = this.renderer.lights[l];
4229       uniforms['u_enableLight' + (index + 1)] = light.active;
4230       uniforms['u_lightPosition' + (index + 1)] = light.position.toArray();
4231       uniforms['u_lightColor' + (index + 1)] = light.diffuse.toRGBArray();
4232       uniforms['u_lightSpecularColor' + (index + 1)] = light.specular.toRGBArray();
4233       index++;
4234     }
4235     
4236     this.renderer.program.bindUniforms(uniforms);
4237   };
4238 
4239 	/**
4240 	 * Setups texture uniforms in the current shader program.
4241 	 */  
4242   SinglePassRenderingStrategy.prototype.setupTextures = function() {
4243     this.renderer.program.bindUniform('u_enableTexturing', this.renderer.useTexturing);
4244   };
4245 
4246 	/**
4247 	 * Setups special effects uniforms in the current shader program.
4248 	 */  
4249   SinglePassRenderingStrategy.prototype.setupEffects = function() {
4250     var effects = this.renderer.effects,
4251         uniforms = {}, 
4252         e, effect, p, property, value;
4253     
4254     for (e in effects) {
4255       effect = effects[e];
4256       for (p in effect) {
4257         property = p.charAt(0).toUpperCase() + p.slice(1);
4258         value = effect[p];
4259         uniforms['u_' + e + property] = value;
4260       }
4261     }
4262     
4263     this.renderer.program.bindUniforms(uniforms);
4264   };	
4265 
4266 	/**
4267 	 * Renders a model.
4268 	 * @param {Model} model The model to render. 
4269 	 */	
4270 	SinglePassRenderingStrategy.prototype.renderModel = function(model) {
4271     var program = this.renderer.program,
4272         camera = this.renderer.camera,
4273         textures = this.renderer.textures,
4274         modelView, i, l, texture;
4275     
4276   	model.bindVertices(program);
4277   	model.bindNormals(program);
4278   	model.bindTexcoords(program);
4279   	model.bindColors(program);
4280   	model.bindIndices(program);
4281     	
4282     model.bindMaterial(program);
4283     model.bindUniforms(program);
4284     model.bindTextures(program, textures);
4285     
4286     // Set modelView and normal matrices
4287     modelView = camera.modelViewMatrix().multiplyMat4(model.matrix());
4288     program.bindUniform('u_modelViewMatrix', modelView);
4289     program.bindUniform('u_normalMatrix', modelView.invert().$transpose());    
4290     
4291     model.draw();	
4292 	};
4293 
4294 	/**
4295 	 * Renders all the models registered to the Renderer.
4296 	 */	
4297 	SinglePassRenderingStrategy.prototype.renderAll = function() {
4298     this.setupCamera();
4299     this.setupLights();
4300     this.setupTextures();
4301     this.setupEffects();
4302     
4303     for (var i = 0, l = this.renderer.models.length; i < l; i++) {
4304       this.renderModel(this.renderer.models[i]);
4305     }   	
4306 	};
4307 	
4308 	return SinglePassRenderingStrategy;
4309 
4310 }());
4311 
4312 BenchGL.namespace('BenchGL.drawing.Renderer');
4313 
4314 BenchGL.drawing.Renderer = (function() {
4315 
4316 	// Dependencies
4317   var Vec3 = BenchGL.math.Vector3,
4318       Mat4 = BenchGL.math.Matrix4,
4319       Color = BenchGL.skin.Color, 
4320       Material = BenchGL.skin.Material, 
4321       Light = BenchGL.skin.Light, 
4322       Texture = BenchGL.skin.Texture, 
4323       TextureRequest = BenchGL.io.TextureRequest,
4324       SinglePassRenderingStrategy = BenchGL.drawing.SinglePassRenderingStrategy,
4325       
4326       // Private properties and methods 
4327       Renderer;
4328   
4329   /**
4330    * Creates a new Renderer.
4331    * @class Represents the rendering engine in BenchGL.
4332    * @param {Program} program The current active shader program.
4333    * @param {Camera} camera The camera holding the point of view over the world.
4334    * @param {Object} effects Contains special effects' specifications. 
4335    */
4336   Renderer = function(program, camera, effects) {
4337     this.program = program;
4338     this.camera = camera;
4339     this.effects = effects;
4340     
4341     // Rendering strategy
4342     this.strategy = new SinglePassRenderingStrategy(this);
4343     
4344     // Background and current color
4345     this.clearColor = new Color(0, 0, 0, 1);
4346     
4347     // Textures
4348     this.useTexturing = false;
4349     this.textures = {};
4350     
4351     // Ambient Light
4352     this.ambientColor = new Color(0.2, 0.2, 0.2);
4353     
4354     // Lights
4355     this.useLighting = false;
4356     this.directionalColor = new Color(0.8, 0.8, 0.8);
4357     this.lightingDirection = new Vec3(0.0, 0.0, -1.0);
4358     this.lights = {};
4359     
4360     // Saved models
4361     this.models = [];
4362   };
4363   
4364   /**
4365    * Clear the background.
4366    */
4367   Renderer.prototype.background = function(r, g, b, a) {
4368     var color = this.clearColor;
4369     
4370    	gl.clearColor(r || color.r, g || color.g, b || color.b, a || color.a);
4371     gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
4372     gl.enable(gl.DEPTH_TEST);
4373   };
4374   
4375   /**
4376    * Switches lighting.
4377    * @param {Boolean} lighting True to enable lighting, else otherwise.
4378    */
4379   Renderer.prototype.useLights = function(lighting) {
4380     this.useLighting = lighting;
4381   };
4382 
4383   /**
4384    * Switches texturing.
4385    * @param {Boolean} texturing True to enable texturing, else otherwise.
4386    */  
4387   Renderer.prototype.useTextures = function(texturing) {
4388     this.useTexturing = texturing;
4389   };
4390   
4391   /**
4392    * Switches alpha-blending.
4393    * @param {Boolean} blending True to enable blending, else otherwise.
4394    * @param {Object} [options] Contain info over about blending functions.
4395    */    
4396   Renderer.prototype.useAlphaBlending = function(blending, options) {
4397     options = $.mix({
4398       src: gl.SRC_ALPHA,
4399       dest: gl.ONE
4400     }, options || {});
4401     
4402     if (blending) {
4403       gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
4404       gl.enable(gl.BLEND);
4405       gl.disable(gl.DEPTH_TEST);
4406     } else {
4407       gl.disable(gl.BLEND);
4408       gl.enable(gl.DEPTH_TEST);
4409     }
4410   };
4411   
4412   /**
4413    * Sets the clear color for the backgrond.
4414    * @param {Number} r The red component of the color.
4415    * @param {Number} g The green component of the color.
4416    * @param {Number} b The blue component of the color.
4417    * @param {Number} a The alpha component of the color.
4418    */
4419   Renderer.prototype.setClearColor = function(r, g, b, a) {
4420     this.clearColor = new Color(r, g, b, a);
4421   };
4422 
4423   /**
4424    * Sets the world ambient color.
4425    * @param {Number} r The red component of the color.
4426    * @param {Number} g The green component of the color.
4427    * @param {Number} b The blue component of the color.
4428    * @param {Number} a The alpha component of the color.
4429    */  
4430   Renderer.prototype.setAmbientColor = function(r, g, b, a) {
4431     this.ambientColor = new Color(r, g, b, a);
4432   };
4433 
4434   /**
4435    * Sets the world directional light color.
4436    * @param {Number} r The red component of the color.
4437    * @param {Number} g The green component of the color.
4438    * @param {Number} b The blue component of the color.
4439    * @param {Number} a The alpha component of the color.
4440    */    
4441   Renderer.prototype.setDirectionalColor = function(r, g, b, a) {
4442     this.directionalColor = new Color(r, g, b, a);
4443   };
4444 
4445   /**
4446    * Sets the world directional light vector.
4447    * @param {Number} x The x component of the vector.
4448    * @param {Number} y The y component of the vector.
4449    * @param {Number} z The z component of the vector.
4450    */   
4451   Renderer.prototype.setLightingDirection = function(x, y, z) {
4452     this.lightingDirection = new Vec3(x, y, z).$unit();
4453   };
4454 
4455   /**
4456    * Adds a light.
4457    * @param {String} name The name for the light.
4458    * @param {Object} options Contains information about the light.
4459    */   
4460   Renderer.prototype.addLight = function(name, options) {
4461     this.lights[name] = new Light(options);
4462   };
4463   
4464   /**
4465    * Adds a single texture.
4466    * @param {String} name The name for the texture.
4467    * @param {Object} options Contains information about the texture.
4468    */  
4469   Renderer.prototype.addTexture = function(name, options) {
4470     this.textures[name] = new Texture(options);
4471   };
4472 
4473   /**
4474    * Adds multiple textures.
4475    * @param {Object} options Contains information about the textures to load.
4476    */  
4477   Renderer.prototype.addTextures = function(options) {
4478   	var myself = this;
4479   	
4480     new TextureRequest(options).send(function(name, options) {
4481     	myself.addTexture(name, options);
4482     });
4483   };
4484   
4485   /**
4486    * Adds models to this Renderer.
4487    * @param {Object} arguments The models to load.
4488    */
4489   Renderer.prototype.addModels = function() {
4490     var models = this.models,
4491         i, l, model;
4492         
4493     for (i = 0, l = arguments.length; i < l; i++) {
4494       model = arguments[i];
4495       models.push(model);
4496       
4497       model.bindVertices(this.program, true);
4498       model.bindNormals(this.program, true);
4499       model.bindTexcoords(this.program, true);
4500       model.bindColors(this.program, true);
4501       model.bindIndices(this.program, true);
4502     }
4503   };
4504   
4505 	/**
4506 	 * Setups camera uniforms in the current shader program.
4507 	 */  
4508   Renderer.prototype.setupCamera = function() {
4509     this.strategy.setupCamera();
4510   };
4511 
4512 	/**
4513 	 * Setups lights uniforms in the current shader program.
4514 	 */    
4515   Renderer.prototype.setupLights = function() {
4516     this.strategy.setupLights();
4517   };
4518 
4519 	/**
4520 	 * Setups lights uniforms in the current shader program.
4521 	 */   
4522   Renderer.prototype.setupTextures = function() {
4523     this.strategy.setupTextures();
4524   };
4525   
4526 	/**
4527 	 * Setups special effects uniforms in the current shader program.
4528 	 */    
4529   Renderer.prototype.setupEffects = function() {
4530     this.strategy.setupTextures();
4531   };
4532 
4533 	/**
4534 	 * Renders a model.
4535 	 * @param {Model} model The model to render. 
4536 	 */	  
4537   Renderer.prototype.renderModel = function(model) {
4538     this.strategy.renderModel(model);
4539   };
4540 
4541 	/**
4542 	 * Renders all the models registered to the Renderer.
4543 	 */	 
4544   Renderer.prototype.renderAll = function() {
4545     this.strategy.renderAll(); 
4546   };
4547   
4548   return Renderer;
4549   
4550 }());
4551 
4552 // webgl.js
4553 
4554 BenchGL.namespace('BenchGL.webgl.WebGL');
4555 
4556 BenchGL.webgl.WebGL = (function() {
4557 	
4558 	// Private properties and methods 
4559 	var WebGL;
4560 	
4561 	/**
4562 	 * The WebGL container.
4563 	 * @class Represents a container for the static method that retrieves a WebGL context.
4564 	 */
4565 	WebGL = {};
4566 	
4567 	/**
4568 	 * Tries to retrieve a WebGL, if availale.
4569 	 * @param {String|HTMLCanvasElement} The canvas id or element to leverage.
4570 	 * @param {Object} Options for creating the context.
4571 	 * @returns {WebGLRenderingContext} A WebGL rendering context or null if not available.
4572 	 */
4573 	WebGL.getContext = function(canvas, options) {
4574 		var canvas = typeof canvas === "string" ? $(canvas) : canvas,
4575 				options = options || {},
4576 				gl = canvas.getContext('experimental-webgl', options);
4577 		
4578 		if (!gl) {
4579 			gl = canvas.getContext('webgl', options);
4580 		}
4581 		
4582 		return gl;
4583 	};
4584 	
4585 	return WebGL;
4586 
4587 }());
4588 // core.js
4589 // The core module provides the main entry point for the library.
4590 
4591 //BenchGL.namespace('BenchGL.core.Engine');
4592 
4593 BenchGL.Engine = (function() {
4594 
4595 	// Dependencies
4596 	var WebGL = BenchGL.webgl.WebGL,
4597 			Program = BenchGL.webgl.Program,
4598 			Canvas = BenchGL.ui.Canvas,
4599 			Camera = BenchGL.ui.Camera,
4600 			Renderer = BenchGL.drawing.Renderer,
4601 			instance,
4602 			
4603 			// Private properties
4604 			Engine,
4605 			
4606 			/**
4607 			 * @ignore
4608 			 */
4609 			start = function(program, canvas, camera, effects, callback, debug) {
4610 	    	// Binds the loaded program for rendering
4611 	      program.bind();
4612 	      
4613 	      // Create a renderer
4614 	      renderer = new Renderer(program, camera, effects);
4615 	      
4616 	      if (debug) {
4617 	      	gl.setTracing(true);
4618 	      }
4619 	      
4620 	      // Call the application with library handlers references 
4621 	      callback({
4622 	        gl: gl,
4623 	        canvas: canvas,
4624 	        program: program,
4625 	        camera: camera,
4626 	        renderer: renderer
4627 	      });
4628 	      
4629 	      if (debug) {
4630 	      	gl.setTracing(false);
4631 	      }    
4632     	};
4633 
4634 	/**
4635 	 * Creates an instance of BenchGL. 
4636 	 * @class Provides an entry point for BenchGL library.
4637 	 * @param {String} canvasId The id of the canvas that WebGL exploits.
4638 	 * @param {Object} [options] General options for initializing the library.
4639 	 * @param {Object} [options.context] The options for the WebGL context.
4640 	 * @param {Object} [options.program] The options for the shader program.
4641 	 * @param {String} [options.program.type='defaults'] The type of shader program.
4642 	 * @param {String} [options.program.vertex] The vertex shader source.
4643 	 * @param {String} [options.program.fragment] The fragmente shader source.
4644 	 * @param {String} [options.camera] The options for the camera.
4645 	 * @param {Number} [options.camera.fovy=45] The field of view angle for the camera.
4646 	 * @param {Number} [options.camera.near=0.1] The near clipping plane for the camera.
4647 	 * @param {Number} [options.camera.far=100] The far clipping plane for the camera.
4648 	 * @param {Object} [effects] Special effects for the rendering engine. 
4649 	 * @param {Object} [events] Functions to eventually handle user events.
4650 	 * @param {Boolean} [debug=false] Is debug active?
4651 	 * @param {Function} [onError] Callback function to call on errors.
4652 	 * @param {Function} [onLoad] Callback function to call after loading succesfully. 
4653 	 */
4654   Engine = function(canvasId, options) {
4655   	if (instance) {
4656   		return instance;
4657   	}
4658   	
4659   	instance = this;
4660   	
4661     options = $.mix({
4662       context: {},
4663       program: {
4664         type: 'defaults'	// {defaults|urls|scripts|sources}
4665       },
4666       camera: {
4667         fovy: 45,
4668         near: 0.1,
4669         far: 100
4670       },
4671       effects: {
4672       	/* 
4673       	Example:
4674       	
4675       	fog : {
4676       		active : true,
4677       		color : [0.5, 0.5, 0.5],
4678       		near : 	10,
4679       		far : 100
4680       	}
4681       	
4682       	*/      	
4683       },
4684       events: {
4685       	/* 
4686       	Example:
4687       	
4688       	onKeyDown : function() { ... },
4689       	onMouseMove : function() { ... },
4690       	
4691       	*/
4692       },
4693       debug: false,
4694       onError: $.empty,
4695       onLoad: $.empty
4696     }, options || {});
4697     
4698     var contextOptions = options.context,
4699         eventsOptions = options.events,
4700         cameraOptions = options.camera,
4701         programOptions = options.program,
4702         effectsOptions = options.effects,
4703         canvas, program, camera, renderer;
4704     
4705     // Create the WebGL context and store it in a library-shared variable.
4706     gl = WebGL.getContext(canvasId, contextOptions);
4707     
4708     if (!gl) {
4709       options.onError();
4710       return null;
4711     }
4712     
4713     // Use webgl-trace.js library to trace webgl calls
4714     if (options.debug && WebGLDebugUtils) {
4715     	gl = WebGLDebugUtils.makeDebugContext(gl);
4716     }
4717     
4718     // Create a canvas wrapper to handle user events
4719     canvas = new Canvas(gl.canvas, eventsOptions);
4720     
4721     // Create a camera
4722     camera = new Camera($.mix(cameraOptions, {
4723       aspect: gl.canvas.width / gl.canvas.height
4724     }));
4725     
4726     // Set up the shader program asynchronously
4727     program = Program.factory($.mix({
4728       onSuccess : function(program) {
4729         start(program, canvas, camera, effectsOptions, function(application) {
4730           options.onLoad(application);
4731         }, options.debug);
4732       },
4733       onError : function(e) {
4734         options.onError(e);
4735       }
4736     }, programOptions));
4737     
4738     // If the program has loaded correctly, call the onLoad callback
4739     if (program) {
4740       start(program, canvas, camera, effectsOptions, function(application) {
4741         options.onLoad(application);
4742       }, options.debug);
4743     }
4744   };
4745   
4746  	return Engine;
4747   
4748 }());
4749 
4750 // Framework version
4751 BenchGL.version = '0.1';
4752 
4753 // WebGL context container
4754 var gl;
4755 
4756 }());
4757