/** * @fileoverview gl-matrix - High performance matrix and vector operations * @author Brandon Jones * @author Colin MacKenzie IV * @version 2.2.0 */ /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ (function(e){"use strict";var t={};typeof exports=="undefined"?typeof define=="function"&&typeof define.amd=="object"&&define.amd?(t.exports={},define(function(){return t.exports})):t.exports=typeof window!="undefined"?window:e:t.exports=exports,function(e){if(!t)var t=1e-6;if(!n)var n=typeof Float32Array!="undefined"?Float32Array:Array;if(!r)var r=Math.random;var i={};i.setMatrixArrayType=function(e){n=e},typeof e!="undefined"&&(e.glMatrix=i);var s={};s.create=function(){var e=new n(2);return e[0]=0,e[1]=0,e},s.clone=function(e){var t=new n(2);return t[0]=e[0],t[1]=e[1],t},s.fromValues=function(e,t){var r=new n(2);return r[0]=e,r[1]=t,r},s.copy=function(e,t){return e[0]=t[0],e[1]=t[1],e},s.set=function(e,t,n){return e[0]=t,e[1]=n,e},s.add=function(e,t,n){return e[0]=t[0]+n[0],e[1]=t[1]+n[1],e},s.subtract=function(e,t,n){return e[0]=t[0]-n[0],e[1]=t[1]-n[1],e},s.sub=s.subtract,s.multiply=function(e,t,n){return e[0]=t[0]*n[0],e[1]=t[1]*n[1],e},s.mul=s.multiply,s.divide=function(e,t,n){return e[0]=t[0]/n[0],e[1]=t[1]/n[1],e},s.div=s.divide,s.min=function(e,t,n){return e[0]=Math.min(t[0],n[0]),e[1]=Math.min(t[1],n[1]),e},s.max=function(e,t,n){return e[0]=Math.max(t[0],n[0]),e[1]=Math.max(t[1],n[1]),e},s.scale=function(e,t,n){return e[0]=t[0]*n,e[1]=t[1]*n,e},s.scaleAndAdd=function(e,t,n,r){return e[0]=t[0]+n[0]*r,e[1]=t[1]+n[1]*r,e},s.distance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return Math.sqrt(n*n+r*r)},s.dist=s.distance,s.squaredDistance=function(e,t){var n=t[0]-e[0],r=t[1]-e[1];return n*n+r*r},s.sqrDist=s.squaredDistance,s.length=function(e){var t=e[0],n=e[1];return Math.sqrt(t*t+n*n)},s.len=s.length,s.squaredLength=function(e){var t=e[0],n=e[1];return t*t+n*n},s.sqrLen=s.squaredLength,s.negate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e},s.normalize=function(e,t){var n=t[0],r=t[1],i=n*n+r*r;return i>0&&(i=1/Math.sqrt(i),e[0]=t[0]*i,e[1]=t[1]*i),e},s.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]},s.cross=function(e,t,n){var r=t[0]*n[1]-t[1]*n[0];return e[0]=e[1]=0,e[2]=r,e},s.lerp=function(e,t,n,r){var i=t[0],s=t[1];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e},s.random=function(e,t){t=t||1;var n=r()*2*Math.PI;return e[0]=Math.cos(n)*t,e[1]=Math.sin(n)*t,e},s.transformMat2=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i,e[1]=n[1]*r+n[3]*i,e},s.transformMat2d=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[2]*i+n[4],e[1]=n[1]*r+n[3]*i+n[5],e},s.transformMat3=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[3]*i+n[6],e[1]=n[1]*r+n[4]*i+n[7],e},s.transformMat4=function(e,t,n){var r=t[0],i=t[1];return e[0]=n[0]*r+n[4]*i+n[12],e[1]=n[1]*r+n[5]*i+n[13],e},s.forEach=function(){var e=s.create();return function(t,n,r,i,s,o){var u,a;n||(n=2),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u0&&(s=1/Math.sqrt(s),e[0]=t[0]*s,e[1]=t[1]*s,e[2]=t[2]*s),e},o.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]},o.cross=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2];return e[0]=i*a-s*u,e[1]=s*o-r*a,e[2]=r*u-i*o,e},o.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e},o.random=function(e,t){t=t||1;var n=r()*2*Math.PI,i=r()*2-1,s=Math.sqrt(1-i*i)*t;return e[0]=Math.cos(n)*s,e[1]=Math.sin(n)*s,e[2]=i*t,e},o.transformMat4=function(e,t,n){var r=t[0],i=t[1],s=t[2];return e[0]=n[0]*r+n[4]*i+n[8]*s+n[12],e[1]=n[1]*r+n[5]*i+n[9]*s+n[13],e[2]=n[2]*r+n[6]*i+n[10]*s+n[14],e},o.transformMat3=function(e,t,n){var r=t[0],i=t[1],s=t[2];return e[0]=r*n[0]+i*n[3]+s*n[6],e[1]=r*n[1]+i*n[4]+s*n[7],e[2]=r*n[2]+i*n[5]+s*n[8],e},o.transformQuat=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2],f=n[3],l=f*r+u*s-a*i,c=f*i+a*r-o*s,h=f*s+o*i-u*r,p=-o*r-u*i-a*s;return e[0]=l*f+p*-o+c*-a-h*-u,e[1]=c*f+p*-u+h*-o-l*-a,e[2]=h*f+p*-a+l*-u-c*-o,e},o.forEach=function(){var e=o.create();return function(t,n,r,i,s,o){var u,a;n||(n=3),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u0&&(o=1/Math.sqrt(o),e[0]=t[0]*o,e[1]=t[1]*o,e[2]=t[2]*o,e[3]=t[3]*o),e},u.dot=function(e,t){return e[0]*t[0]+e[1]*t[1]+e[2]*t[2]+e[3]*t[3]},u.lerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2],u=t[3];return e[0]=i+r*(n[0]-i),e[1]=s+r*(n[1]-s),e[2]=o+r*(n[2]-o),e[3]=u+r*(n[3]-u),e},u.random=function(e,t){return t=t||1,e[0]=r(),e[1]=r(),e[2]=r(),e[3]=r(),u.normalize(e,e),u.scale(e,e,t),e},u.transformMat4=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3];return e[0]=n[0]*r+n[4]*i+n[8]*s+n[12]*o,e[1]=n[1]*r+n[5]*i+n[9]*s+n[13]*o,e[2]=n[2]*r+n[6]*i+n[10]*s+n[14]*o,e[3]=n[3]*r+n[7]*i+n[11]*s+n[15]*o,e},u.transformQuat=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=n[0],u=n[1],a=n[2],f=n[3],l=f*r+u*s-a*i,c=f*i+a*r-o*s,h=f*s+o*i-u*r,p=-o*r-u*i-a*s;return e[0]=l*f+p*-o+c*-a-h*-u,e[1]=c*f+p*-u+h*-o-l*-a,e[2]=h*f+p*-a+l*-u-c*-o,e},u.forEach=function(){var e=u.create();return function(t,n,r,i,s,o){var u,a;n||(n=4),r||(r=0),i?a=Math.min(i*n+r,t.length):a=t.length;for(u=r;u.999999?(r[0]=0,r[1]=0,r[2]=0,r[3]=1,r):(o.cross(e,i,s),r[0]=e[0],r[1]=e[1],r[2]=e[2],r[3]=1+u,h.normalize(r,r))}}(),h.setAxes=function(){var e=l.create();return function(t,n,r,i){return e[0]=r[0],e[3]=r[1],e[6]=r[2],e[1]=i[0],e[4]=i[1],e[7]=i[2],e[2]=n[0],e[5]=n[1],e[8]=n[2],h.normalize(t,h.fromMat3(t,e))}}(),h.clone=u.clone,h.fromValues=u.fromValues,h.copy=u.copy,h.set=u.set,h.identity=function(e){return e[0]=0,e[1]=0,e[2]=0,e[3]=1,e},h.setAxisAngle=function(e,t,n){n*=.5;var r=Math.sin(n);return e[0]=r*t[0],e[1]=r*t[1],e[2]=r*t[2],e[3]=Math.cos(n),e},h.add=u.add,h.multiply=function(e,t,n){var r=t[0],i=t[1],s=t[2],o=t[3],u=n[0],a=n[1],f=n[2],l=n[3];return e[0]=r*l+o*u+i*f-s*a,e[1]=i*l+o*a+s*u-r*f,e[2]=s*l+o*f+r*a-i*u,e[3]=o*l-r*u-i*a-s*f,e},h.mul=h.multiply,h.scale=u.scale,h.rotateX=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+o*u,e[1]=i*a+s*u,e[2]=s*a-i*u,e[3]=o*a-r*u,e},h.rotateY=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a-s*u,e[1]=i*a+o*u,e[2]=s*a+r*u,e[3]=o*a-i*u,e},h.rotateZ=function(e,t,n){n*=.5;var r=t[0],i=t[1],s=t[2],o=t[3],u=Math.sin(n),a=Math.cos(n);return e[0]=r*a+i*u,e[1]=i*a-r*u,e[2]=s*a+o*u,e[3]=o*a-s*u,e},h.calculateW=function(e,t){var n=t[0],r=t[1],i=t[2];return e[0]=n,e[1]=r,e[2]=i,e[3]=-Math.sqrt(Math.abs(1-n*n-r*r-i*i)),e},h.dot=u.dot,h.lerp=u.lerp,h.slerp=function(e,t,n,r){var i=t[0],s=t[1],o=t[2],u=t[3],a=n[0],f=n[1],l=n[2],c=n[3],h,p,d,v,m;return p=i*a+s*f+o*l+u*c,p<0&&(p=-p,a=-a,f=-f,l=-l,c=-c),1-p>1e-6?(h=Math.acos(p),d=Math.sin(h),v=Math.sin((1-r)*h)/d,m=Math.sin(r*h)/d):(v=1-r,m=r),e[0]=v*i+m*a,e[1]=v*s+m*f,e[2]=v*o+m*l,e[3]=v*u+m*c,e},h.invert=function(e,t){var n=t[0],r=t[1],i=t[2],s=t[3],o=n*n+r*r+i*i+s*s,u=o?1/o:0;return e[0]=-n*u,e[1]=-r*u,e[2]=-i*u,e[3]=s*u,e},h.conjugate=function(e,t){return e[0]=-t[0],e[1]=-t[1],e[2]=-t[2],e[3]=t[3],e},h.length=u.length,h.len=h.length,h.squaredLength=u.squaredLength,h.sqrLen=h.squaredLength,h.normalize=u.normalize,h.fromMat3=function(){var e=typeof Int8Array!="undefined"?new Int8Array([1,2,0]):[1,2,0];return function(t,n){var r=n[0]+n[4]+n[8],i;if(r>0)i=Math.sqrt(r+1),t[3]=.5*i,i=.5/i,t[0]=(n[7]-n[5])*i,t[1]=(n[2]-n[6])*i,t[2]=(n[3]-n[1])*i;else{var s=0;n[4]>n[0]&&(s=1),n[8]>n[s*3+s]&&(s=2);var o=e[s],u=e[o];i=Math.sqrt(n[s*3+s]-n[o*3+o]-n[u*3+u]+1),t[s]=.5*i,i=.5/i,t[3]=(n[u*3+o]-n[o*3+u])*i,t[o]=(n[o*3+s]+n[s*3+o])*i,t[u]=(n[u*3+s]+n[s*3+u])*i}return t}}(),h.str=function(e){return"quat("+e[0]+", "+e[1]+", "+e[2]+", "+e[3]+")"},typeof e!="undefined"&&(e.quat=h)}(t.exports)})(this); function ListNode(newitem){ this.item = newitem; } ListNode.prototype.item = null; ListNode.prototype.link = null; /** * Creates a new instance of List. * * @class A singly linked list of nodes, each with item and link properties. Unlike other languages, a list can contain unrelated object types at the same time. * However, this may result in unexpected results when processing its contents with a loop. * @property {ListNode} head Pointer to the first node in the list. * @property {ListNode} tail Pointer to the last node in the list. * @property {number} length The number of nodes in the list. */ function List(){ } List.prototype.head = null; List.prototype.tail = null; List.prototype.length = 0; /** * Inserts the given object at the end of the list. * * @param {Object} object The object to be inserted. */ List.prototype.push = function(object){ var newNode = new ListNode(object); if(this.head === null){ this.head = newNode; }else{ this.tail.link = newNode; } this.tail = newNode; this.length++; } /** * Inserts the given object at the front of the list. * * @param {Object} object The object to be inserted. */ List.prototype.push_front = function(object){ var newNode = new ListNode(object); if(this.head === null){ this.tail = newNode; }else{ newNode.link = this.head; } this.head = newNode; this.length++; } /** * Inserts the given object at the front of the list. * * @param {Object} object The object to be inserted. */ List.prototype.push_back = function(object){ this.push(object); } /** * Removes the head of the list and returns its item. * * @return {Object} The contents of the head node. */ List.prototype.pop = function(){ var item = null; if(this.head != null){ item = this.head.item; if(this.tail == this.head){ this.tail = null; } this.head = this.head.link; this.length--; } return item; } /** * Removes the head of the list and returns its item. * * @return {Object} The contents of the head node. */ List.prototype.pop_front = function(){ return this.pop(); } /** * Removes the head of the list and returns its item. * * @return {Object} The contents of the head node. */ List.prototype.pop_back = function(){ var item = null; if(this.tail != null){ item = this.tail.item; this.remove(item); //this.head = this.head.link; //this.length--; } return item; } /** * Removes the first instance found of the given object from the list. If there is more than one instance the others remain. * * @param {Object} object The object to remove. * @return {bool} True if the object was found and removed, false otherwise. */ List.prototype.remove = function(object){ if(this.head != null){ if(this.head.item === object){ this.head = this.head.link; this.length--; return true; } var prev = this.head; var curr = this.head.link; while(curr !== null){ if(curr.item === object){ prev.link = curr.link; if(this.tail.item === object){ this.tail = prev; } this.length--; return true; } prev = curr; curr = curr.link; } } return false; } /** * Searches the list for the given object. * * @param {Object} object The object to be looked for. * @return {bool} True if found, false otherwise. */ List.prototype.find = function(object){ for(var node = this.head; node !== null; node = node.link){ if(node.item == object){ return true; } } return false; } /** * Returns the object in the node at the given index. * * @param {Object} index The node index to retrieve an object from. null if the index is out of range. */ List.prototype.getAt = function(index){ var item = null; var cur = this.head; if(index >= 0 && index < this.length){ while(index > 0 && cur != null){ cur = cur.link; index--; } item = cur.item; } return item; } /** * For each item in the list the given function is called with the item and the given additional parameters as parameters. * * @param {Object} func The function to be called. * @param {Object} params Additional parameters to pass to the function. */ List.prototype.foreach = function(func, params){ for(var node = this.head; node !== null; node = node.link){ func(node.item, params); } } /** * Joins the list into a string for debugging purposes. * * @return {string} The list as a string. */ List.prototype.toString = function(){ var count = 0; var curr = this.head; var dbgstring = ""; while(curr !== null){ dbgstring += "["+count+": "; dbgstring += curr.item+"]"; //dbgstring += "--Link: "+curr.link+"\n"; curr = curr.link; count++; } return dbgstring; } /** * Creates a new instance of Vector. * * @class A simple mathematical vector that can be used for position, color, or anything else that can take advantage of a 4 float vector. Although it has 4 floats it can be used as a 2 or 3 float vector. * @param {number} x The initial x value. * @param {number} y The initial y value. * @param {number} z Optional: The initial z value. * @property {number} x The x value. * @property {number} y The y value. * @property {number} z The z value. * @property {number} w The w value. * @property {number} r An alias for x. * @property {number} g An alias for y. * @property {number} b An alias for z. * @property {number} a An alias for w. * @property {number} length The length of the vector. */ function Vector(x, y, z){ this.x = x; this.y = y; this.z = z ? z : 0; this.w = 0; } Vector.prototype.x = 0; Vector.prototype.y = 0; Vector.prototype.z = 0; Vector.prototype.w = 0; Vector.prototype.r = 0; Vector.prototype.g = 0; Vector.prototype.b = 0; Vector.prototype.a = 0; Vector.prototype.length = 0; Vector.prototype = { get r(){ return this.x; }, set r(val){ this.x = val; }, get g(){ return this.y; }, set g(val){ this.y = val; }, get b(){ return this.z; }, set b(val){ this.z = val; }, get a(){ return this.w; }, set a(val){ this.w = val; }, get length(){ return Math.sqrt((this.x*this.x)+(this.y*this.y)+(this.z*this.z)+(this.w*this.w)); }, get vec2(){ return [this.x,this.y]; }, get vec3(){ return [this.x,this.y,this.z]; }, get vec4(){ return [this.x,this.y,this.z,this.w]; }, } /** * Adds the given vector to the calling vector and returns a new vector. * * @param {Vector} val The vector to add to the caller. * @return {Vector} The result. */ Vector.prototype.add = function(val){ var temp = new Vector(0,0,0); temp.x = this.x+val.x; temp.y = this.y+val.y; temp.z = this.z+val.z; temp.w = this.w+val.w; return temp; } /** * Subtracts the given vector from the calling vector and returns a new vector. * * @param {Vector} val The vector to subtract from the caller. * @return {Vector} The result. */ Vector.prototype.sub = function(val){ var temp = new Vector(0,0,0); temp.x = this.x-val.x; temp.y = this.y-val.y; temp.z = this.z-val.z; temp.w = this.w-val.w; return temp; } /** * Multiplies the components of given vector with those of the calling vector and returns a new vector. * OR * Scales the calling vector by the given scalar. * * @param {Vector or number} val The vector or scalar to multiply the caller by. * @return {Vector} The result. */ Vector.prototype.mult = function(val){ var temp = new Vector(0,0,0); if(val instanceof Vector){ temp.x = this.x*val.x; temp.y = this.y*val.y; temp.z = this.z*val.z; temp.w = this.w*val.w; }else{ temp.x = this.x*val; temp.y = this.y*val; temp.z = this.z*val; temp.w = this.w*val; } return temp; } /** * Divides the components of given vector with those of the calling vector and returns a new vector. * OR * Divides the calling vector by the given scalar. * * @param {Vector or number} val The vector or scalar to divide the caller by. * @return {Vector} The result. */ Vector.prototype.div = function(val){ var temp = new Vector(0,0,0); if(val instanceof Vector){ temp.x = this.x/val.x; temp.y = this.y/val.y; temp.z = this.z/val.z; temp.w = this.w/val.w; }else{ temp.x = this.x/val; temp.y = this.y/val; temp.z = this.z/val; temp.w = this.w/val; } return temp; } /** * Negates the calling vector and returns a new vector. * * @return {Vector} The result. */ Vector.prototype.neg = function(){ var temp = new Vector(0,0,0); temp.x = -this.x; temp.y = -this.y; temp.z = -this.z; temp.w = -this.w; return temp; } /** * Compares the components of the caller to the given vector to determine if they are equal. * * @param {Vector} val The vector to compare the caller to. * @return {Vector} The result. */ Vector.prototype.equals = function(val){ if(this.x != val.x){ return false; } if(this.y != val.y){ return false; } if(this.z != val.z){ return false; } if(this.w != val.w){ return false; } return true; } /** * Calculates the cross product between the caller and the given vector. callerXval * * @param {Vector} val The vector to cross the caller with. * @return {Vector} The result. */ Vector.prototype.cross = function(val){ var temp = new Vector(0,0,0); temp.x = this.y*val.z-this.z*val.y; temp.y = this.z*val.x-this.x*val.z; temp.z = this.x*val.y-this.y*val.x; return temp; } /** * Calculates the dot product between the caller and the given vector. * * @param {Vector} val The vector to dot with the caller. * @return {number} The result. */ Vector.prototype.dot = function(val){ return this.x*val.x+this.y*val.y+this.z*val.z+this.w*val.w; } /** * Returns a normalized vector. * * @return {Vector} The normalized result. */ Vector.prototype.normalize = function(){ var length = this.length; var temp = new Vector(0,0,0); temp.x = this.x/length; temp.y = this.y/length; temp.z = this.z/length; temp.w = this.w/length; return temp; } /** * Joins the vector into a debug string. * * @return {string} Vector as a string. */ Vector.prototype.toString = function(){ return "["+this.x+","+this.y+","+this.z+","+this.w+"]"; } /** * Creates a Vector from a vector represented by an array. * * @param {Array} arr * @return {Vector} A new vector. */ Vector.arrayVector = function(arr){ //function arrayVector(arr){ var vec = new Vector(arr[0],arr[1], arr[2] ? arr[2] : 0); vec.w = arr[3] ? arr[3] : 0; return vec; } /** * Creates a new instance of ResourceMonitor or returns the singleton instance. * * @class Singleton that keeps track of loading resources. By default there is a global reference called Resources. * @property {ResourceMonitor} instance The singlton instance. * @property {number} totalItems The total number of items that have been requested for loading. * @property {number} leftToLoad The number of items that are still loading. */ function ResourceMonitor(){ if(ResourceMonitor.prototype.instance){ return ResourceMonitor.prototype.instance; } ResourceMonitor.prototype.instance = this; this.loadList = new List(); this.totalItems = 0; this.leftToLoad = 0; } ResourceMonitor.prototype.instance = null; ResourceMonitor.prototype.loadList = new List(); ResourceMonitor.prototype.totalItems = 0; ResourceMonitor.prototype.leftToLoad = 0; ResourceMonitor.prototype.addToLoad = function(){ this.totalItems++; this.leftToLoad++; } /** * Returns the number of items that are still loading. * * @return {number} The number of items left to load. */ ResourceMonitor.prototype.getLeftToLoad = function(){ for(var font in Fonts.fonts){ //for(var font = 0; font < Fonts.fonts.length; font++){ if(!Fonts.fonts[font].loaded){ Fonts.fonts[font].checkIfLoaded(); } } return this.leftToLoad; } /** * Returns the percentage of loaded items. * * @return {number} The percentage. */ ResourceMonitor.prototype.percentLoaded = function(){ for(var font in Fonts.fonts){ //for(var font = 0; font < Fonts.fonts.length; font++){ if(!Fonts.fonts[font].loaded){ Fonts.fonts[font].checkIfLoaded(); } } return this.leftToLoad/this.totalItems; } var Resources = new ResourceMonitor(); /** * Creates a new instance of TextureManager or returns the singleton instance. * * @class Singleton that manages image loading, texture creation, and texture reuse. By default there is a global reference called Textures. * @property {TextureManager} instance The singlton instance. * @property {Array} imgs Array of loaded images indexed by their src. */ function TextureManager(){ if(TextureManager.prototype.instance){ return TextureManager.prototype.instance; } TextureManager.prototype.instance = this; this.imgs = new Array(); this.waitingList = new List(); } TextureManager.prototype.instance = null; TextureManager.prototype.imgs = new Array(); TextureManager.prototype.waitingList = new List(); /** * Returns an image if it is already loaded, otherwise it starts loading the image source and returns a new image. * * @param {string} src The image source to be loaded. * @param {bool} crossDomain Optional: If the image is not in the same domain as the calling script this must be true. * @param {bool} logOnLoad Optional: If true a debug statement is printed when it finishes loading. * @return {Image} The image object that the requested source will be loaded into. */ TextureManager.prototype.load = function(src, crossDomain, logOnLoad){ if(this.imgs[src] == undefined){ Resources.addToLoad(); this.imgs[src] = new Image(); this.imgs[src].loaded = false; if(crossDomain){ this.imgs[src].crossOrigin = "anonymous"; } this.imgs[src].src = src; this.imgs[src].oSrc = src; this.imgs[src].onload = function(){ //if(logOnLoad == undefined || logOnLoad){ if(logOnLoad){ println(this.src+" loaded"); } Resources.leftToLoad--; if(!Textures.createTexture(this)){ Textures.waitingList.push(this); } this.loaded = true; } this.imgs[src].onabort = function(){ alert("there was an error"); } } return this.imgs[src]; } TextureManager.prototype.create = function(){ this.waitingList.foreach(this.createTexture); } /** * Creates a WebGL texture from the given image. Can also create a texure out of a canvas object allowing the use of 2D canvas drawings or text as textures. * image.texture is set to this new texture * * @param {Image} image The image to use as the texture data. * @return {bool} Returns true if the texture was created successfully. */ TextureManager.prototype.createTexture = function(image){ if(ctx != undefined){ if(ctx.createTexture){ var texture = image.texture; if(texture == undefined){ texture = ctx.createTexture(); } texture.image = image; ctx.bindTexture(ctx.TEXTURE_2D, texture); ctx.pixelStorei(ctx.UNPACK_FLIP_Y_WEBGL, true); ctx.pixelStorei(ctx.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); ctx.texImage2D(ctx.TEXTURE_2D, 0, ctx.RGBA, ctx.RGBA, ctx.UNSIGNED_BYTE, texture.image); //ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.NEAREST); //ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.NEAREST); ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_S, ctx.CLAMP_TO_EDGE); ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_WRAP_T, ctx.CLAMP_TO_EDGE); ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, ctx.LINEAR); ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, ctx.LINEAR); //ctx.generateMipmap(ctx.TEXTURE_2D); ctx.bindTexture(ctx.TEXTURE_2D, null); image.texture = texture; image.setFilters = function(min, mag){ mag = mag ? mag : min; ctx.bindTexture(ctx.TEXTURE_2D, this.texture); ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MAG_FILTER, mag); ctx.texParameteri(ctx.TEXTURE_2D, ctx.TEXTURE_MIN_FILTER, min); } return true; } } return false; } var Textures = new TextureManager(); /** * Creates a new instance of SoundManager or returns the singleton instance. * * @class Singleton that manages sound loading and playing. By default there is a global reference called Sounds. * @property {SoundManager} instance The singlton instance. * @property {Array