OpenJsCad/lightgl.js

62 lines
27 KiB
JavaScript

/*
* lightgl.js
* http://github.com/evanw/lightgl.js/
*
* Copyright 2011 Evan Wallace
* Released under the MIT license
*/
var GL=function(){function I(){d.MODELVIEW=C|1;d.PROJECTION=C|2;var b=new n,c=new n;d.modelviewMatrix=new n;d.projectionMatrix=new n;var a=[],f=[],g,j;d.matrixMode=function(h){switch(h){case d.MODELVIEW:g="modelviewMatrix";j=a;break;case d.PROJECTION:g="projectionMatrix";j=f;break;default:throw"invalid matrix mode "+h;}};d.loadIdentity=function(){n.identity(d[g])};d.loadMatrix=function(h){h=h.m;for(var i=d[g].m,m=0;m<16;m++)i[m]=h[m]};d.multMatrix=function(h){d.loadMatrix(n.multiply(d[g],h,c))};d.perspective=
function(h,i,m,k){d.multMatrix(n.perspective(h,i,m,k,b))};d.frustum=function(h,i,m,k,o,p){d.multMatrix(n.frustum(h,i,m,k,o,p,b))};d.ortho=function(h,i,m,k,o,p){d.multMatrix(n.ortho(h,i,m,k,o,p,b))};d.scale=function(h,i,m){d.multMatrix(n.scale(h,i,m,b))};d.translate=function(h,i,m){d.multMatrix(n.translate(h,i,m,b))};d.rotate=function(h,i,m,k){d.multMatrix(n.rotate(h,i,m,k,b))};d.lookAt=function(h,i,m,k,o,p,J,K,L){d.multMatrix(n.lookAt(h,i,m,k,o,p,J,K,L,b))};d.pushMatrix=function(){j.push(Array.prototype.slice.call(d[g].m))};
d.popMatrix=function(){var h=j.pop();d[g].m=D?new Float32Array(h):h};d.project=function(h,i,m,k,o,p){k=k||d.modelviewMatrix;o=o||d.projectionMatrix;p=p||d.getParameter(d.VIEWPORT);h=o.transformPoint(k.transformPoint(new l(h,i,m)));return new l(p[0]+p[2]*(h.x*0.5+0.5),p[1]+p[3]*(h.y*0.5+0.5),h.z*0.5+0.5)};d.unProject=function(h,i,m,k,o,p){k=k||d.modelviewMatrix;o=o||d.projectionMatrix;p=p||d.getParameter(d.VIEWPORT);h=new l((h-p[0])/p[2]*2-1,(i-p[1])/p[3]*2-1,m*2-1);return n.inverse(n.multiply(o,k,
b),c).transformPoint(h)};d.matrixMode(d.MODELVIEW)}function M(){var b={mesh:new q({coords:true,colors:true,triangles:false}),mode:-1,coord:[0,0,0,0],color:[1,1,1,1],pointSize:1,shader:new y("uniform float pointSize;varying vec4 color;varying vec4 coord;varying vec2 pixel;void main(){color=gl_Color;coord=gl_TexCoord;gl_Position=gl_ModelViewProjectionMatrix*gl_Vertex;pixel=gl_Position.xy/gl_Position.w*0.5+0.5;gl_PointSize=pointSize;}",
"uniform sampler2D texture;uniform float pointSize;uniform bool useTexture;uniform vec2 windowSize;varying vec4 color;varying vec4 coord;varying vec2 pixel;void main(){gl_FragColor=color;if(useTexture)gl_FragColor*=texture2D(texture,coord.xy);}")};d.pointSize=function(c){b.shader.uniforms({pointSize:c})};d.begin=function(c){if(b.mode!=-1)throw"mismatched gl.begin() and gl.end() calls";b.mode=c;b.mesh.colors=[];b.mesh.coords=
[];b.mesh.vertices=[]};d.color=function(c,a,f,g){b.color=arguments.length==1?c.toArray().concat(1):[c,a,f,g||1]};d.texCoord=function(c,a){b.coord=arguments.length==1?c.toArray(2):[c,a]};d.vertex=function(c,a,f){b.mesh.colors.push(b.color);b.mesh.coords.push(b.coord);b.mesh.vertices.push(arguments.length==1?c.toArray():[c,a,f])};d.end=function(){if(b.mode==-1)throw"mismatched gl.begin() and gl.end() calls";b.mesh.compile();b.shader.uniforms({windowSize:[d.canvas.width,d.canvas.height],useTexture:!!d.getParameter(d.TEXTURE_BINDING_2D)}).draw(b.mesh,
b.mode);b.mode=-1}}function N(){function b(){for(var k in i)if(i[k])return true;return false}function c(k){e=Object.create(k);e.original=k;e.x=e.pageX;e.y=e.pageY;for(k=d.canvas;k;k=k.offsetParent){e.x-=k.offsetLeft;e.y-=k.offsetTop}if(m){e.deltaX=e.x-j;e.deltaY=e.y-h}else{e.deltaX=0;e.deltaY=0;m=true}j=e.x;h=e.y;e.dragging=b();e.preventDefault=function(){e.original.preventDefault()};e.stopPropagation=function(){e.original.stopPropagation()};return e}function a(k){k=c(k);d.onmousemove&&d.onmousemove(k);
k.preventDefault()}function f(k){i[k.which]=false;if(!b()){document.removeEventListener("mousemove",a);document.removeEventListener("mouseup",f);d.canvas.addEventListener("mousemove",a);d.canvas.addEventListener("mouseup",f)}k=c(k);d.onmouseup&&d.onmouseup(k);k.preventDefault()}function g(){m=false}var j=0,h=0,i={},m=false;z(d.canvas,"mousedown",function(k){if(!b()){document.addEventListener("mousemove",a);document.addEventListener("mouseup",f);d.canvas.removeEventListener("mousemove",a);d.canvas.removeEventListener("mouseup",
f)}i[k.which]=true;k=c(k);d.onmousedown&&d.onmousedown(k);k.preventDefault()});d.canvas.addEventListener("mousemove",a);d.canvas.addEventListener("mouseup",f);d.canvas.addEventListener("mouseover",g);d.canvas.addEventListener("mouseout",g)}function E(b){return{8:"BACKSPACE",9:"TAB",13:"ENTER",16:"SHIFT",27:"ESCAPE",32:"SPACE",37:"LEFT",38:"UP",39:"RIGHT",40:"DOWN"}[b]||(b>=65&&b<=90?String.fromCharCode(b):null)}function z(b,c,a){b.addEventListener(c,a)}function O(){(function(b){d.makeCurrent=function(){d=
b}})(d);d.animate=function(){function b(){d=f;var g=new Date;d.onupdate&&d.onupdate((g-a)/1E3);d.ondraw&&d.ondraw();c(b);a=g}var c=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||function(g){setTimeout(g,1E3/60)},a=new Date,f=d;b()};d.fullscreen=function(b){function c(){d.canvas.width=window.innerWidth-f-g;d.canvas.height=window.innerHeight-a-j;d.viewport(0,0,d.canvas.width,d.canvas.height);if(b.camera||!("camera"in b)){d.matrixMode(d.PROJECTION);
d.loadIdentity();d.perspective(b.fov||45,d.canvas.width/d.canvas.height,b.near||0.1,b.far||1E3);d.matrixMode(d.MODELVIEW)}d.ondraw&&d.ondraw()}b=b||{};var a=b.paddingTop||0,f=b.paddingLeft||0,g=b.paddingRight||0,j=b.paddingBottom||0;if(!document.body)throw"document.body doesn't exist yet (call gl.fullscreen() from window.onload() or from inside the <body> tag)";document.body.appendChild(d.canvas);document.body.style.overflow="hidden";d.canvas.style.position="absolute";d.canvas.style.left=f+"px";d.canvas.style.top=
a+"px";window.addEventListener("resize",c);c()}}function n(){var b=Array.prototype.concat.apply([],arguments);b.length||(b=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);this.m=D?new Float32Array(b):b}function w(){this.unique=[];this.indices=[];this.map={}}function x(b,c){this.buffer=null;this.target=b;this.type=c;this.data=[]}function q(b){b=b||{};this.vertexBuffers={};this.indexBuffers={};this.addVertexBuffer("vertices","gl_Vertex");b.coords&&this.addVertexBuffer("coords","gl_TexCoord");b.normals&&this.addVertexBuffer("normals",
"gl_Normal");b.colors&&this.addVertexBuffer("colors","gl_Color");if(!("triangles"in b)||b.triangles)this.addIndexBuffer("triangles");b.lines&&this.addIndexBuffer("lines")}function F(b){return new l((b&1)*2-1,(b&2)-1,(b&4)/2-1)}function t(b,c,a){this.t=arguments.length?b:Number.MAX_VALUE;this.hit=c;this.normal=a}function u(){var b=d.getParameter(d.VIEWPORT),c=d.modelviewMatrix.m,a=new l(c[0],c[4],c[8]),f=new l(c[1],c[5],c[9]),g=new l(c[2],c[6],c[10]);c=new l(c[3],c[7],c[11]);this.eye=new l(-c.dot(a),
-c.dot(f),-c.dot(g));a=b[0];f=a+b[2];g=b[1];c=g+b[3];this.ray00=d.unProject(a,g,1).subtract(this.eye);this.ray10=d.unProject(f,g,1).subtract(this.eye);this.ray01=d.unProject(a,c,1).subtract(this.eye);this.ray11=d.unProject(f,c,1).subtract(this.eye);this.viewport=b}function y(b,c){function a(i,m,k){for(;(result=i.exec(m))!=null;)k(result)}function f(i,m){var k={},o=/^((\s*\/\/.*\n|\s*#extension.*\n)+)[^]*$/.exec(m);m=o?o[1]+i+m.substr(o[1].length):i+m;a(/\bgl_\w+\b/g,i,function(p){if(!(p in k)){m=
m.replace(RegExp("\\b"+p+"\\b","g"),"_"+p);k[p]=true}});return m}function g(i,m){var k=d.createShader(i);d.shaderSource(k,m);d.compileShader(k);if(!d.getShaderParameter(k,d.COMPILE_STATUS))throw"compile error: "+d.getShaderInfoLog(k);return k}var j=b+c;this.needsMVPM=/(gl_ModelViewProjectionMatrix|ftransform)/.test(j);this.needsNM=/gl_NormalMatrix/.test(j);b=f("uniform mat3 gl_NormalMatrix;uniform mat4 gl_ModelViewMatrix;uniform mat4 gl_ProjectionMatrix;uniform mat4 gl_ModelViewProjectionMatrix;attribute vec4 gl_Vertex;attribute vec4 gl_TexCoord;attribute vec3 gl_Normal;attribute vec4 gl_Color;vec4 ftransform(){return gl_ModelViewProjectionMatrix*gl_Vertex;}",
b);c=f("precision highp float;uniform mat3 gl_NormalMatrix;uniform mat4 gl_ModelViewMatrix;uniform mat4 gl_ProjectionMatrix;uniform mat4 gl_ModelViewProjectionMatrix;",c);this.program=d.createProgram();d.attachShader(this.program,g(d.VERTEX_SHADER,b));d.attachShader(this.program,g(d.FRAGMENT_SHADER,c));d.linkProgram(this.program);if(!d.getProgramParameter(this.program,d.LINK_STATUS))throw"link error: "+d.getProgramInfoLog(this.program);this.attributes={};var h={};a(/uniform\s+sampler(1D|2D|3D|Cube)\s+(\w+)\s*;/g,
b+c,function(i){h[i[2]]=1});this.isSampler=h}function s(b,c,a){a=a||{};this.id=d.createTexture();this.width=b;this.height=c;this.format=a.format||d.RGBA;this.type=a.type||d.UNSIGNED_BYTE;d.bindTexture(d.TEXTURE_2D,this.id);d.pixelStorei(d.UNPACK_FLIP_Y_WEBGL,1);d.texParameteri(d.TEXTURE_2D,d.TEXTURE_MAG_FILTER,a.filter||a.magFilter||d.LINEAR);d.texParameteri(d.TEXTURE_2D,d.TEXTURE_MIN_FILTER,a.filter||a.minFilter||d.LINEAR);d.texParameteri(d.TEXTURE_2D,d.TEXTURE_WRAP_S,a.wrap||a.wrapS||d.CLAMP_TO_EDGE);
d.texParameteri(d.TEXTURE_2D,d.TEXTURE_WRAP_T,a.wrap||a.wrapT||d.CLAMP_TO_EDGE);d.texImage2D(d.TEXTURE_2D,0,this.format,b,c,0,this.format,this.type,null)}function l(b,c,a){this.x=b||0;this.y=c||0;this.z=a||0}var d,v={create:function(b){b=b||{};var c=document.createElement("canvas");c.width=800;c.height=600;if(!("alpha"in b))b.alpha=false;try{d=c.getContext("webgl",b)}catch(a){}try{d=d||c.getContext("experimental-webgl",b)}catch(f){}if(!d)throw"WebGL not supported";I();M();N();O();return d},keys:{},
Matrix:n,Indexer:w,Buffer:x,Mesh:q,HitTest:t,Raytracer:u,Shader:y,Texture:s,Vector:l};z(document,"keydown",function(b){if(!b.altKey&&!b.ctrlKey&&!b.metaKey){var c=E(b.keyCode);if(c)v.keys[c]=true;v.keys[b.keyCode]=true}});z(document,"keyup",function(b){if(!b.altKey&&!b.ctrlKey&&!b.metaKey){var c=E(b.keyCode);if(c)v.keys[c]=false;v.keys[b.keyCode]=false}});var C=305397760,D=typeof Float32Array!="undefined";n.prototype={inverse:function(){return n.inverse(this,new n)},transpose:function(){return n.transpose(this,
new n)},multiply:function(b){return n.multiply(this,b,new n)},transformPoint:function(b){var c=this.m;return(new l(c[0]*b.x+c[1]*b.y+c[2]*b.z+c[3],c[4]*b.x+c[5]*b.y+c[6]*b.z+c[7],c[8]*b.x+c[9]*b.y+c[10]*b.z+c[11])).divide(c[12]*b.x+c[13]*b.y+c[14]*b.z+c[15])},transformVector:function(b){var c=this.m;return new l(c[0]*b.x+c[1]*b.y+c[2]*b.z,c[4]*b.x+c[5]*b.y+c[6]*b.z,c[8]*b.x+c[9]*b.y+c[10]*b.z)}};n.inverse=function(b,c){c=c||new n;var a=b.m,f=c.m;f[0]=a[5]*a[10]*a[15]-a[5]*a[14]*a[11]-a[6]*a[9]*a[15]+
a[6]*a[13]*a[11]+a[7]*a[9]*a[14]-a[7]*a[13]*a[10];f[1]=-a[1]*a[10]*a[15]+a[1]*a[14]*a[11]+a[2]*a[9]*a[15]-a[2]*a[13]*a[11]-a[3]*a[9]*a[14]+a[3]*a[13]*a[10];f[2]=a[1]*a[6]*a[15]-a[1]*a[14]*a[7]-a[2]*a[5]*a[15]+a[2]*a[13]*a[7]+a[3]*a[5]*a[14]-a[3]*a[13]*a[6];f[3]=-a[1]*a[6]*a[11]+a[1]*a[10]*a[7]+a[2]*a[5]*a[11]-a[2]*a[9]*a[7]-a[3]*a[5]*a[10]+a[3]*a[9]*a[6];f[4]=-a[4]*a[10]*a[15]+a[4]*a[14]*a[11]+a[6]*a[8]*a[15]-a[6]*a[12]*a[11]-a[7]*a[8]*a[14]+a[7]*a[12]*a[10];f[5]=a[0]*a[10]*a[15]-a[0]*a[14]*a[11]-
a[2]*a[8]*a[15]+a[2]*a[12]*a[11]+a[3]*a[8]*a[14]-a[3]*a[12]*a[10];f[6]=-a[0]*a[6]*a[15]+a[0]*a[14]*a[7]+a[2]*a[4]*a[15]-a[2]*a[12]*a[7]-a[3]*a[4]*a[14]+a[3]*a[12]*a[6];f[7]=a[0]*a[6]*a[11]-a[0]*a[10]*a[7]-a[2]*a[4]*a[11]+a[2]*a[8]*a[7]+a[3]*a[4]*a[10]-a[3]*a[8]*a[6];f[8]=a[4]*a[9]*a[15]-a[4]*a[13]*a[11]-a[5]*a[8]*a[15]+a[5]*a[12]*a[11]+a[7]*a[8]*a[13]-a[7]*a[12]*a[9];f[9]=-a[0]*a[9]*a[15]+a[0]*a[13]*a[11]+a[1]*a[8]*a[15]-a[1]*a[12]*a[11]-a[3]*a[8]*a[13]+a[3]*a[12]*a[9];f[10]=a[0]*a[5]*a[15]-a[0]*
a[13]*a[7]-a[1]*a[4]*a[15]+a[1]*a[12]*a[7]+a[3]*a[4]*a[13]-a[3]*a[12]*a[5];f[11]=-a[0]*a[5]*a[11]+a[0]*a[9]*a[7]+a[1]*a[4]*a[11]-a[1]*a[8]*a[7]-a[3]*a[4]*a[9]+a[3]*a[8]*a[5];f[12]=-a[4]*a[9]*a[14]+a[4]*a[13]*a[10]+a[5]*a[8]*a[14]-a[5]*a[12]*a[10]-a[6]*a[8]*a[13]+a[6]*a[12]*a[9];f[13]=a[0]*a[9]*a[14]-a[0]*a[13]*a[10]-a[1]*a[8]*a[14]+a[1]*a[12]*a[10]+a[2]*a[8]*a[13]-a[2]*a[12]*a[9];f[14]=-a[0]*a[5]*a[14]+a[0]*a[13]*a[6]+a[1]*a[4]*a[14]-a[1]*a[12]*a[6]-a[2]*a[4]*a[13]+a[2]*a[12]*a[5];f[15]=a[0]*a[5]*
a[10]-a[0]*a[9]*a[6]-a[1]*a[4]*a[10]+a[1]*a[8]*a[6]+a[2]*a[4]*a[9]-a[2]*a[8]*a[5];a=a[0]*f[0]+a[1]*f[4]+a[2]*f[8]+a[3]*f[12];for(var g=0;g<16;g++)f[g]/=a;return c};n.transpose=function(b,c){c=c||new n;var a=b.m,f=c.m;f[0]=a[0];f[1]=a[4];f[2]=a[8];f[3]=a[12];f[4]=a[1];f[5]=a[5];f[6]=a[9];f[7]=a[13];f[8]=a[2];f[9]=a[6];f[10]=a[10];f[11]=a[14];f[12]=a[3];f[13]=a[7];f[14]=a[11];f[15]=a[15];return c};n.multiply=function(b,c,a){a=a||new n;b=b.m;c=c.m;var f=a.m;f[0]=b[0]*c[0]+b[1]*c[4]+b[2]*c[8]+b[3]*c[12];
f[1]=b[0]*c[1]+b[1]*c[5]+b[2]*c[9]+b[3]*c[13];f[2]=b[0]*c[2]+b[1]*c[6]+b[2]*c[10]+b[3]*c[14];f[3]=b[0]*c[3]+b[1]*c[7]+b[2]*c[11]+b[3]*c[15];f[4]=b[4]*c[0]+b[5]*c[4]+b[6]*c[8]+b[7]*c[12];f[5]=b[4]*c[1]+b[5]*c[5]+b[6]*c[9]+b[7]*c[13];f[6]=b[4]*c[2]+b[5]*c[6]+b[6]*c[10]+b[7]*c[14];f[7]=b[4]*c[3]+b[5]*c[7]+b[6]*c[11]+b[7]*c[15];f[8]=b[8]*c[0]+b[9]*c[4]+b[10]*c[8]+b[11]*c[12];f[9]=b[8]*c[1]+b[9]*c[5]+b[10]*c[9]+b[11]*c[13];f[10]=b[8]*c[2]+b[9]*c[6]+b[10]*c[10]+b[11]*c[14];f[11]=b[8]*c[3]+b[9]*c[7]+b[10]*
c[11]+b[11]*c[15];f[12]=b[12]*c[0]+b[13]*c[4]+b[14]*c[8]+b[15]*c[12];f[13]=b[12]*c[1]+b[13]*c[5]+b[14]*c[9]+b[15]*c[13];f[14]=b[12]*c[2]+b[13]*c[6]+b[14]*c[10]+b[15]*c[14];f[15]=b[12]*c[3]+b[13]*c[7]+b[14]*c[11]+b[15]*c[15];return a};n.identity=function(b){b=b||new n;var c=b.m;c[0]=c[5]=c[10]=c[15]=1;c[1]=c[2]=c[3]=c[4]=c[6]=c[7]=c[8]=c[9]=c[11]=c[12]=c[13]=c[14]=0;return b};n.perspective=function(b,c,a,f,g){b=Math.tan(b*Math.PI/360)*a;c=b*c;return n.frustum(-c,c,-b,b,a,f,g)};n.frustum=function(b,
c,a,f,g,j,h){h=h||new n;var i=h.m;i[0]=2*g/(c-b);i[1]=0;i[2]=(c+b)/(c-b);i[3]=0;i[4]=0;i[5]=2*g/(f-a);i[6]=(f+a)/(f-a);i[7]=0;i[8]=0;i[9]=0;i[10]=-(j+g)/(j-g);i[11]=-2*j*g/(j-g);i[12]=0;i[13]=0;i[14]=-1;i[15]=0;return h};n.ortho=function(b,c,a,f,g,j,h){h=h||new n;var i=h.m;i[0]=2/(c-b);i[1]=0;i[2]=0;i[3]=-(c+b)/(c-b);i[4]=0;i[5]=2/(f-a);i[6]=0;i[7]=-(f+a)/(f-a);i[8]=0;i[9]=0;i[10]=-2/(j-g);i[11]=-(j+g)/(j-g);i[12]=0;i[13]=0;i[14]=0;i[15]=1;return h};n.scale=function(b,c,a,f){f=f||new n;var g=f.m;
g[0]=b;g[1]=0;g[2]=0;g[3]=0;g[4]=0;g[5]=c;g[6]=0;g[7]=0;g[8]=0;g[9]=0;g[10]=a;g[11]=0;g[12]=0;g[13]=0;g[14]=0;g[15]=1;return f};n.translate=function(b,c,a,f){f=f||new n;var g=f.m;g[0]=1;g[1]=0;g[2]=0;g[3]=b;g[4]=0;g[5]=1;g[6]=0;g[7]=c;g[8]=0;g[9]=0;g[10]=1;g[11]=a;g[12]=0;g[13]=0;g[14]=0;g[15]=1;return f};n.rotate=function(b,c,a,f,g){if(!b||!c&&!a&&!f)return n.identity(g);g=g||new n;var j=g.m,h=Math.sqrt(c*c+a*a+f*f);b*=Math.PI/180;c/=h;a/=h;f/=h;h=Math.cos(b);b=Math.sin(b);var i=1-h;j[0]=c*c*i+h;
j[1]=c*a*i-f*b;j[2]=c*f*i+a*b;j[3]=0;j[4]=a*c*i+f*b;j[5]=a*a*i+h;j[6]=a*f*i-c*b;j[7]=0;j[8]=f*c*i-a*b;j[9]=f*a*i+c*b;j[10]=f*f*i+h;j[11]=0;j[12]=0;j[13]=0;j[14]=0;j[15]=1;return g};n.lookAt=function(b,c,a,f,g,j,h,i,m,k){k=k||new n;var o=k.m;b=new l(b,c,a);f=new l(f,g,j);i=new l(h,i,m);h=b.subtract(f).unit();i=i.cross(h).unit();m=h.cross(i).unit();o[0]=i.x;o[1]=i.y;o[2]=i.z;o[3]=-i.dot(b);o[4]=m.x;o[5]=m.y;o[6]=m.z;o[7]=-m.dot(b);o[8]=h.x;o[9]=h.y;o[10]=h.z;o[11]=-h.dot(b);o[12]=0;o[13]=0;o[14]=0;
o[15]=1;return k};w.prototype={add:function(b){var c=JSON.stringify(b);if(!(c in this.map)){this.map[c]=this.unique.length;this.unique.push(b)}return this.map[c]}};x.prototype={compile:function(b){for(var c=[],a=0;a<this.data.length;a+=1E4)c=Array.prototype.concat.apply(c,this.data.slice(a,a+1E4));a=this.data.length?c.length/this.data.length:0;if(a!=Math.round(a))throw"buffer elements not of consistent size, average size is "+a;this.buffer=this.buffer||d.createBuffer();this.buffer.length=c.length;
this.buffer.spacing=a;d.bindBuffer(this.target,this.buffer);d.bufferData(this.target,new this.type(c),b||d.STATIC_DRAW)}};q.prototype={addVertexBuffer:function(b,c){(this.vertexBuffers[c]=new x(d.ARRAY_BUFFER,Float32Array)).name=b;this[b]=[]},addIndexBuffer:function(b){this.indexBuffers[b]=new x(d.ELEMENT_ARRAY_BUFFER,Int16Array);this[b]=[]},compile:function(){for(var b in this.vertexBuffers){var c=this.vertexBuffers[b];c.data=this[c.name];c.compile()}for(var a in this.indexBuffers){c=this.indexBuffers[a];
c.data=this[a];c.compile()}},transform:function(b){this.vertices=this.vertices.map(function(a){return b.transformPoint(l.fromArray(a)).toArray()});if(this.normals){var c=b.inverse().transpose();this.normals=this.normals.map(function(a){return c.transformVector(l.fromArray(a)).unit().toArray()})}this.compile();return this},computeNormals:function(){this.normals||this.addVertexBuffer("normals","gl_Normal");for(var b=0;b<this.vertices.length;b++)this.normals[b]=new l;for(b=0;b<this.triangles.length;b++){var c=
this.triangles[b],a=l.fromArray(this.vertices[c[0]]),f=l.fromArray(this.vertices[c[1]]),g=l.fromArray(this.vertices[c[2]]);a=f.subtract(a).cross(g.subtract(a)).unit();this.normals[c[0]]=this.normals[c[0]].add(a);this.normals[c[1]]=this.normals[c[1]].add(a);this.normals[c[2]]=this.normals[c[2]].add(a)}for(b=0;b<this.vertices.length;b++)this.normals[b]=this.normals[b].unit().toArray();this.compile();return this},computeWireframe:function(){for(var b=new w,c=0;c<this.triangles.length;c++)for(var a=this.triangles[c],
f=0;f<a.length;f++){var g=a[f],j=a[(f+1)%a.length];b.add([Math.min(g,j),Math.max(g,j)])}this.lines||this.addIndexBuffer("lines");this.lines=b.unique;this.compile();return this},getAABB:function(){var b={min:new l(Number.MAX_VALUE,Number.MAX_VALUE,Number.MAX_VALUE)};b.max=b.min.negative();for(var c=0;c<this.vertices.length;c++){var a=l.fromArray(this.vertices[c]);b.min=l.min(b.min,a);b.max=l.max(b.max,a)}return b},getBoundingSphere:function(){var b=this.getAABB();b={center:b.min.add(b.max).divide(2),
radius:0};for(var c=0;c<this.vertices.length;c++)b.radius=Math.max(b.radius,l.fromArray(this.vertices[c]).subtract(b.center).length());return b}};q.plane=function(b){b=b||{};var c=new q(b);detailX=b.detailX||b.detail||1;detailY=b.detailY||b.detail||1;for(b=0;b<=detailY;b++)for(var a=b/detailY,f=0;f<=detailX;f++){var g=f/detailX;c.vertices.push([2*g-1,2*a-1,0]);c.coords&&c.coords.push([g,a]);c.normals&&c.normals.push([0,0,1]);if(f<detailX&&b<detailY){g=f+b*(detailX+1);c.triangles.push([g,g+1,g+detailX+
1]);c.triangles.push([g+detailX+1,g+1,g+detailX+2])}}c.compile();return c};var G=[[0,4,2,6,-1,0,0],[1,3,5,7,+1,0,0],[0,1,4,5,0,-1,0],[2,6,3,7,0,+1,0],[0,2,1,3,0,0,-1],[4,5,6,7,0,0,+1]];q.cube=function(b){b=new q(b);for(var c=0;c<G.length;c++){for(var a=G[c],f=c*4,g=0;g<4;g++){b.vertices.push(F(a[g]).toArray());b.coords&&b.coords.push([g&1,(g&2)/2]);b.normals&&b.normals.push(a.slice(4,7))}b.triangles.push([f,f+1,f+2]);b.triangles.push([f+2,f+1,f+3])}b.compile();return b};q.sphere=function(b){b=b||
{};var c=new q(b),a=new w;detail=b.detail||6;for(b=0;b<8;b++)for(var f=F(b),g=f.x*f.y*f.z>0,j=[],h=0;h<=detail;h++){for(var i=0;h+i<=detail;i++){var m=h/detail,k=i/detail,o=(detail-h-i)/detail;k={vertex:(new l(m+(m-m*m)/2,k+(k-k*k)/2,o+(o-o*o)/2)).unit().multiply(f).toArray()};if(c.coords)k.coord=f.y>0?[1-m,o]:[o,1-m];j.push(a.add(k))}if(h>0)for(i=0;h+i<=detail;i++){m=(h-1)*(detail+1)+(h-1-(h-1)*(h-1))/2+i;k=h*(detail+1)+(h-h*h)/2+i;c.triangles.push(g?[j[m],j[k],j[m+1]]:[j[m],j[m+1],j[k]]);h+i<detail&&
c.triangles.push(g?[j[k],j[k+1],j[m+1]]:[j[k],j[m+1],j[k+1]])}}c.vertices=a.unique.map(function(p){return p.vertex});if(c.coords)c.coords=a.unique.map(function(p){return p.coord});if(c.normals)c.normals=c.vertices;c.compile();return c};q.load=function(b,c){c=c||{};if(!("coords"in c))c.coords=!!b.coords;if(!("normals"in c))c.normals=!!b.normals;if(!("triangles"in c))c.triangles=!!b.triangles;if(!("lines"in c))c.lines=!!b.lines;var a=new q(c);a.vertices=b.vertices;if(a.coords)a.coords=b.coords;if(a.normals)a.normals=
b.normals;if(a.triangles)a.triangles=b.triangles;if(a.lines)a.lines=b.lines;a.compile();return a};t.prototype={mergeWith:function(b){if(b.t>0&&b.t<this.t){this.t=b.t;this.hit=b.hit;this.normal=b.normal}}};u.prototype={getRayForPixel:function(b,c){b=(b-this.viewport[0])/this.viewport[2];c=1-(c-this.viewport[1])/this.viewport[3];var a=l.lerp(this.ray00,this.ray10,b),f=l.lerp(this.ray01,this.ray11,b);return l.lerp(a,f,c).unit()}};u.hitTestBox=function(b,c,a,f){var g=a.subtract(b).divide(c),j=f.subtract(b).divide(c),
h=l.min(g,j);g=l.max(g,j);h=h.max();g=g.min();if(h>0&&h<g){b=b.add(c.multiply(h));a=a.add(1.0E-6);f=f.subtract(1.0E-6);return new t(h,b,new l((b.x>f.x)-(b.x<a.x),(b.y>f.y)-(b.y<a.y),(b.z>f.z)-(b.z<a.z)))}return null};u.hitTestSphere=function(b,c,a,f){var g=b.subtract(a),j=c.dot(c),h=2*c.dot(g);g=g.dot(g)-f*f;g=h*h-4*j*g;if(g>0){j=(-h-Math.sqrt(g))/(2*j);b=b.add(c.multiply(j));return new t(j,b,b.subtract(a).divide(f))}return null};u.hitTestTriangle=function(b,c,a,f,g){var j=f.subtract(a),h=g.subtract(a);
g=j.cross(h).unit();f=g.dot(a.subtract(b)).divide(g.dot(c));if(f>0){b=b.add(c.multiply(f));var i=b.subtract(a);a=h.dot(h);c=h.dot(j);h=h.dot(i);var m=j.dot(j);j=j.dot(i);i=a*m-c*c;m=(m*h-c*j)/i;j=(a*j-c*h)/i;if(m>=0&&j>=0&&m+j<=1)return new t(f,b,g)}return null};var P=new n,H=new n;y.prototype={uniforms:function(b){d.useProgram(this.program);for(var c in b){var a=d.getUniformLocation(this.program,c);if(a){var f=b[c];if(f instanceof l)f=[f.x,f.y,f.z];else if(f instanceof n)f=f.m;var g=Object.prototype.toString.call(f);
if(g=="[object Array]"||g=="[object Float32Array]")switch(f.length){case 1:d.uniform1fv(a,new Float32Array(f));break;case 2:d.uniform2fv(a,new Float32Array(f));break;case 3:d.uniform3fv(a,new Float32Array(f));break;case 4:d.uniform4fv(a,new Float32Array(f));break;case 9:d.uniformMatrix3fv(a,false,new Float32Array([f[0],f[3],f[6],f[1],f[4],f[7],f[2],f[5],f[8]]));break;case 16:d.uniformMatrix4fv(a,false,new Float32Array([f[0],f[4],f[8],f[12],f[1],f[5],f[9],f[13],f[2],f[6],f[10],f[14],f[3],f[7],f[11],
f[15]]));break;default:throw"don't know how to load uniform \""+c+'" of length '+f.length;}else{g=Object.prototype.toString.call(f);if(g=="[object Number]"||g=="[object Boolean]")(this.isSampler[c]?d.uniform1i:d.uniform1f).call(d,a,f);else throw'attempted to set uniform "'+c+'" to invalid value '+f;}}}return this},draw:function(b,c){this.drawBuffers(b.vertexBuffers,b.indexBuffers[c==d.LINES?"lines":"triangles"],arguments.length<2?d.TRIANGLES:c)},drawBuffers:function(b,c,a){this.uniforms({_gl_ModelViewMatrix:d.modelviewMatrix,
_gl_ProjectionMatrix:d.projectionMatrix});this.needsMVPM&&this.uniforms({_gl_ModelViewProjectionMatrix:n.multiply(d.projectionMatrix,d.modelviewMatrix,H)});if(this.needsNM){var f=n.transpose(n.inverse(d.modelviewMatrix,P),H).m;this.uniforms({_gl_NormalMatrix:[f[0],f[1],f[2],f[4],f[5],f[6],f[8],f[9],f[10]]})}f=0;for(var g in b){var j=b[g],h=this.attributes[g]||d.getAttribLocation(this.program,g.replace(/^gl_/,"_gl_"));if(!(h==-1||!j.buffer)){this.attributes[g]=h;d.bindBuffer(d.ARRAY_BUFFER,j.buffer);
d.enableVertexAttribArray(h);d.vertexAttribPointer(h,j.buffer.spacing,d.FLOAT,false,0,0);f=j.buffer.length/j.buffer.spacing}}for(g in this.attributes)g in b||d.disableVertexAttribArray(this.attributes[g]);if(f&&(!c||c.buffer))if(c){d.bindBuffer(d.ELEMENT_ARRAY_BUFFER,c.buffer);d.drawElements(a,c.buffer.length,d.UNSIGNED_SHORT,0)}else d.drawArrays(a,0,f);return this}};var A,r,B;s.prototype={bind:function(b){d.activeTexture(d.TEXTURE0+(b||0));d.bindTexture(d.TEXTURE_2D,this.id)},unbind:function(b){d.activeTexture(d.TEXTURE0+
(b||0));d.bindTexture(d.TEXTURE_2D,null)},drawTo:function(b){var c=d.getParameter(d.VIEWPORT);A=A||d.createFramebuffer();r=r||d.createRenderbuffer();d.bindFramebuffer(d.FRAMEBUFFER,A);d.bindRenderbuffer(d.RENDERBUFFER,r);if(this.width!=r.width||this.height!=r.height){r.width=this.width;r.height=this.height;d.renderbufferStorage(d.RENDERBUFFER,d.DEPTH_COMPONENT16,this.width,this.height)}d.framebufferTexture2D(d.FRAMEBUFFER,d.COLOR_ATTACHMENT0,d.TEXTURE_2D,this.id,0);d.framebufferRenderbuffer(d.FRAMEBUFFER,
d.DEPTH_ATTACHMENT,d.RENDERBUFFER,r);d.viewport(0,0,this.width,this.height);b();d.bindFramebuffer(d.FRAMEBUFFER,null);d.bindRenderbuffer(d.RENDERBUFFER,null);d.viewport(c[0],c[1],c[2],c[3])},swapWith:function(b){var c;c=b.id;b.id=this.id;this.id=c;c=b.width;b.width=this.width;this.width=c;c=b.height;b.height=this.height;this.height=c}};s.fromImage=function(b,c){c=c||{};var a=new s(b.width,b.height,c);try{d.texImage2D(d.TEXTURE_2D,0,a.format,a.format,a.type,b)}catch(f){if(location.protocol=="file:")throw'image not loaded for security reasons (serve this page over "http://" instead)';
else throw"image not loaded for security reasons (image must originate from the same domain as this page or use Cross-Origin Resource Sharing)";}c.minFilter&&c.minFilter!=d.NEAREST&&c.minFilter!=d.LINEAR&&d.generateMipmap(d.TEXTURE_2D);return a};s.fromURL=function(b,c){B=B||function(){var g=document.createElement("canvas").getContext("2d");g.canvas.width=g.canvas.height=128;for(var j=0;j<g.canvas.height;j+=16)for(var h=0;h<g.canvas.width;h+=16){g.fillStyle=(h^j)&16?"#FFF":"#DDD";g.fillRect(h,j,16,
16)}return g.canvas}();var a=s.fromImage(B,c),f=new Image;f.onload=function(){s.fromImage(f,c).swapWith(a)};f.src=b;return a};l.prototype={negative:function(){return new l(-this.x,-this.y,-this.z)},add:function(b){return b instanceof l?new l(this.x+b.x,this.y+b.y,this.z+b.z):new l(this.x+b,this.y+b,this.z+b)},subtract:function(b){return b instanceof l?new l(this.x-b.x,this.y-b.y,this.z-b.z):new l(this.x-b,this.y-b,this.z-b)},multiply:function(b){return b instanceof l?new l(this.x*b.x,this.y*b.y,this.z*
b.z):new l(this.x*b,this.y*b,this.z*b)},divide:function(b){return b instanceof l?new l(this.x/b.x,this.y/b.y,this.z/b.z):new l(this.x/b,this.y/b,this.z/b)},equals:function(b){return this.x==b.x&&this.y==b.y&&this.z==b.z},dot:function(b){return this.x*b.x+this.y*b.y+this.z*b.z},cross:function(b){return new l(this.y*b.z-this.z*b.y,this.z*b.x-this.x*b.z,this.x*b.y-this.y*b.x)},length:function(){return Math.sqrt(this.dot(this))},unit:function(){return this.divide(this.length())},min:function(){return Math.min(Math.min(this.x,
this.y),this.z)},max:function(){return Math.max(Math.max(this.x,this.y),this.z)},toAngles:function(){return{theta:Math.atan2(this.z,this.x),phi:Math.asin(this.y/this.length())}},toArray:function(b){return[this.x,this.y,this.z].slice(0,b||3)},clone:function(){return new l(this.x,this.y,this.z)},init:function(b,c,a){this.x=b;this.y=c;this.z=a;return this}};l.negative=function(b,c){c.x=-b.x;c.y=-b.y;c.z=-b.z;return c};l.add=function(b,c,a){if(c instanceof l){a.x=b.x+c.x;a.y=b.y+c.y;a.z=b.z+c.z}else{a.x=
b.x+c;a.y=b.y+c;a.z=b.z+c}return a};l.subtract=function(b,c,a){if(c instanceof l){a.x=b.x-c.x;a.y=b.y-c.y;a.z=b.z-c.z}else{a.x=b.x-c;a.y=b.y-c;a.z=b.z-c}return a};l.multiply=function(b,c,a){if(c instanceof l){a.x=b.x*c.x;a.y=b.y*c.y;a.z=b.z*c.z}else{a.x=b.x*c;a.y=b.y*c;a.z=b.z*c}return a};l.divide=function(b,c,a){if(c instanceof l){a.x=b.x/c.x;a.y=b.y/c.y;a.z=b.z/c.z}else{a.x=b.x/c;a.y=b.y/c;a.z=b.z/c}return a};l.cross=function(b,c,a){a.x=b.y*c.z-b.z*c.y;a.y=b.z*c.x-b.x*c.z;a.z=b.x*c.y-b.y*c.x;return a};
l.unit=function(b,c){var a=b.length();c.x=b.x/a;c.y=b.y/a;c.z=b.z/a;return c};l.fromAngles=function(b,c){return new l(Math.cos(b)*Math.cos(c),Math.sin(c),Math.sin(b)*Math.cos(c))};l.randomDirection=function(){return l.fromAngles(Math.random()*Math.PI*2,Math.asin(Math.random()*2-1))};l.min=function(b,c){return new l(Math.min(b.x,c.x),Math.min(b.y,c.y),Math.min(b.z,c.z))};l.max=function(b,c){return new l(Math.max(b.x,c.x),Math.max(b.y,c.y),Math.max(b.z,c.z))};l.lerp=function(b,c,a){return c.subtract(b).multiply(a).add(b)};
l.fromArray=function(b){return new l(b[0],b[1],b[2])};return v}();