From 1d706dd789b4c4ea44aa84a4bd8e6d42f0b78a74 Mon Sep 17 00:00:00 2001 From: Szymon Nowak Date: Sun, 9 Jan 2011 20:50:35 +0100 Subject: [PATCH 1/2] Basic support for RTT. --- src/materials/RenderTexture.js | 17 +++++++++++++ src/materials/Texture.js | 6 ++++- src/renderers/WebGLRenderer.js | 46 +++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 src/materials/RenderTexture.js diff --git a/src/materials/RenderTexture.js b/src/materials/RenderTexture.js new file mode 100644 index 00000000..5b63fbd2 --- /dev/null +++ b/src/materials/RenderTexture.js @@ -0,0 +1,17 @@ +THREE.RenderTexture = function ( width, height, options ) { + + this.width = width; + this.height = height; + + options = options || {}; + + this.wrap_s = options.wrap_s !== undefined ? options.wrap_s : THREE.ClampToEdgeWrapping; + this.wrap_t = options.wrap_t !== undefined ? options.wrap_t : THREE.ClampToEdgeWrapping; + + this.mag_filter = options.mag_filter !== undefined ? options.mag_filter : THREE.LinearFilter; + this.min_filter = options.min_filter !== undefined ? options.min_filter : THREE.LinearFilter; + + this.format = options.format !== undefined ? options.format : THREE.RGBFormat; + this.type = options.type !== undefined ? options.type : THREE.UnsignedByteType; + +}; diff --git a/src/materials/Texture.js b/src/materials/Texture.js index b31dc549..d6338c84 100644 --- a/src/materials/Texture.js +++ b/src/materials/Texture.js @@ -24,7 +24,7 @@ THREE.Texture.prototype = { return new THREE.Texture( this.image, this.mapping, this.wrap_s, this.wrap_t, this.mag_filter, this.min_filter ); }, - + toString: function () { return 'THREE.Texture (
' + @@ -52,3 +52,7 @@ THREE.NearestMipMapLinearFilter = 5; THREE.LinearFilter = 6; THREE.LinearMipMapNearestFilter = 7; THREE.LinearMipMapLinearFilter = 8; + +THREE.RGBFormat = 9; + +THREE.UnsignedByteType = 10; diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index 7d41cea3..ac599c1a 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -658,7 +658,7 @@ THREE.WebGLRenderer = function ( parameters ) { }; - this.render = function( scene, camera ) { + this.render = function( scene, camera, renderTarget ) { var o, ol, webGLObject, object, buffer, lights = scene.lights, @@ -666,6 +666,8 @@ THREE.WebGLRenderer = function ( parameters ) { this.initWebGLObjects( scene ); + setRenderTarget( renderTarget ); + if ( this.autoClear ) { this.clear(); @@ -1159,6 +1161,44 @@ THREE.WebGLRenderer = function ( parameters ) { }; + function setRenderTarget( renderTexture ) { + + var framebuffer; + + if ( renderTexture && !renderTexture.__webGLFramebuffer ) { + renderTexture.__webGLFramebuffer = _gl.createFramebuffer(); + renderTexture.__webGLRenderbuffer = _gl.createRenderbuffer(); + renderTexture.__webGLTexture = _gl.createTexture(); + + // Setup renderbuffer + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTexture.__webGLRenderbuffer ); + _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTexture.width, renderTexture.height ); + + // Setup texture + _gl.bindTexture( _gl.TEXTURE_2D, renderTexture.__webGLTexture ); + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, paramThreeToGL( renderTexture.wrap_s ) ); + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, paramThreeToGL( renderTexture.wrap_t ) ); + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( renderTexture.mag_filter ) ); + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( renderTexture.min_filter ) ); + _gl.generateMipmap(_gl.TEXTURE_2D); + _gl.texImage2D( _gl.TEXTURE_2D, 0, paramThreeToGL( renderTexture.format ), renderTexture.width, renderTexture.height, 0, paramThreeToGL( renderTexture.format ), paramThreeToGL( renderTexture.type ), null); + + // Setup framebuffer + _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTexture.__webGLFramebuffer ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, renderTexture.__webGLTexture, 0 ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTexture.__webGLRenderbuffer); + + // Release everything + _gl.bindTexture( _gl.TEXTURE_2D, null ); + _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); + _gl.bindFramebuffer( _gl.FRAMEBUFFER, null); + } + + framebuffer = renderTexture ? renderTexture.__webGLFramebuffer : null; + _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + + } + function cacheUniformLocations( program, identifiers ) { var i, l, id; @@ -1229,6 +1269,10 @@ THREE.WebGLRenderer = function ( parameters ) { case THREE.LinearMipMapNearestFilter: return _gl.LINEAR_MIPMAP_NEAREST; break; case THREE.LinearMipMapLinearFilter: return _gl.LINEAR_MIPMAP_LINEAR; break; + case THREE.RGBFormat: return _gl.RGB; break; + + case THREE.UnsignedByteType: return _gl.UNSIGNED_BYTE; break; + } return 0; From 868cab1e9821b4f3479506e2889dafaa2d760085 Mon Sep 17 00:00:00 2001 From: Szymon Nowak Date: Sun, 9 Jan 2011 20:53:56 +0100 Subject: [PATCH 2/2] Very basic example for RTT feature. --- build/ThreeExtras.js | 2425 +++++++++++++-- build/ThreeWebGL.js | 5046 +++++++++++++++++++++++++++++++ examples/render_to_texture.html | 149 + 3 files changed, 7381 insertions(+), 239 deletions(-) create mode 100644 build/ThreeWebGL.js create mode 100644 examples/render_to_texture.html diff --git a/build/ThreeExtras.js b/build/ThreeExtras.js index 09eb721b..7bb445f8 100644 --- a/build/ThreeExtras.js +++ b/build/ThreeExtras.js @@ -1,239 +1,2186 @@ -// ThreeExtras.js r32 - http://github.com/mrdoob/three.js -var THREE=THREE||{};THREE.Color=function(a){this.autoUpdate=true;this.setHex(a)}; -THREE.Color.prototype={setRGB:function(a,b,f){this.r=a;this.g=b;this.b=f;if(this.autoUpdate){this.updateHex();this.updateStyleString()}},setHex:function(a){this.hex=~~a&16777215;if(this.autoUpdate){this.updateRGBA();this.updateStyleString()}},updateHex:function(){this.hex=~~(this.r*255)<<16^~~(this.g*255)<<8^~~(this.b*255)},updateRGBA:function(){this.r=(this.hex>>16&255)/255;this.g=(this.hex>>8&255)/255;this.b=(this.hex&255)/255},updateStyleString:function(){this.__styleString="rgb("+~~(this.r*255)+ -","+~~(this.g*255)+","+~~(this.b*255)+")"},clone:function(){return new THREE.Color(this.hex)},toString:function(){return"THREE.Color ( r: "+this.r+", g: "+this.g+", b: "+this.b+", hex: "+this.hex+" )"}};THREE.Vector2=function(a,b){this.x=a||0;this.y=b||0}; -THREE.Vector2.prototype={set:function(a,b){this.x=a;this.y=b;return this},copy:function(a){this.x=a.x;this.y=a.y;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;return this},unit:function(){this.multiplyScalar(1/this.length());return this},length:function(){return Math.sqrt(this.x* -this.x+this.y*this.y)},lengthSq:function(){return this.x*this.x+this.y*this.y},negate:function(){this.x=-this.x;this.y=-this.y;return this},clone:function(){return new THREE.Vector2(this.x,this.y)},toString:function(){return"THREE.Vector2 ("+this.x+", "+this.y+")"}};THREE.Vector3=function(a,b,f){this.x=a||0;this.y=b||0;this.z=f||0}; -THREE.Vector3.prototype={set:function(a,b,f){this.x=a;this.y=b;this.z=f;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;this.z+=a.z;return this},addScalar:function(a){this.x+=a;this.y+=a;this.z+=a;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;this.z-=a.z;return this}, -cross:function(a,b){this.x=a.y*b.z-a.z*b.y;this.y=a.z*b.x-a.x*b.z;this.z=a.x*b.y-a.y*b.x;return this},crossSelf:function(a){var b=this.x,f=this.y,e=this.z;this.x=f*a.z-e*a.y;this.y=e*a.x-b*a.z;this.z=b*a.y-f*a.x;return this},multiply:function(a,b){this.x=a.x*b.x;this.y=a.y*b.y;this.z=a.z*b.z;return this},multiplySelf:function(a){this.x*=a.x;this.y*=a.y;this.z*=a.z;return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;return this},divideSelf:function(a){this.x/=a.x;this.y/=a.y;this.z/= -a.z;return this},divideScalar:function(a){this.x/=a;this.y/=a;this.z/=a;return this},dot:function(a){return this.x*a.x+this.y*a.y+this.z*a.z},distanceTo:function(a){var b=this.x-a.x,f=this.y-a.y;a=this.z-a.z;return Math.sqrt(b*b+f*f+a*a)},distanceToSquared:function(a){var b=this.x-a.x,f=this.y-a.y;a=this.z-a.z;return b*b+f*f+a*a},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},negate:function(){this.x= --this.x;this.y=-this.y;this.z=-this.z;return this},normalize:function(){var a=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z);a>0?this.multiplyScalar(1/a):this.set(0,0,0);return this},setLength:function(a){return this.normalize().multiplyScalar(a)},isZero:function(){return Math.abs(this.x)<1.0E-4&&Math.abs(this.y)<1.0E-4&&Math.abs(this.z)<1.0E-4},clone:function(){return new THREE.Vector3(this.x,this.y,this.z)},toString:function(){return"THREE.Vector3 ( "+this.x+", "+this.y+", "+this.z+" )"}}; -THREE.Vector4=function(a,b,f,e){this.x=a||0;this.y=b||0;this.z=f||0;this.w=e||1}; -THREE.Vector4.prototype={set:function(a,b,f,e){this.x=a;this.y=b;this.z=f;this.w=e;return this},copy:function(a){this.x=a.x;this.y=a.y;this.z=a.z;this.w=a.w||1;return this},add:function(a,b){this.x=a.x+b.x;this.y=a.y+b.y;this.z=a.z+b.z;this.w=a.w+b.w;return this},addSelf:function(a){this.x+=a.x;this.y+=a.y;this.z+=a.z;this.w+=a.w;return this},sub:function(a,b){this.x=a.x-b.x;this.y=a.y-b.y;this.z=a.z-b.z;this.w=a.w-b.w;return this},subSelf:function(a){this.x-=a.x;this.y-=a.y;this.z-=a.z;this.w-=a.w; -return this},multiplyScalar:function(a){this.x*=a;this.y*=a;this.z*=a;this.w*=a;return this},divideScalar:function(a){this.x/=a;this.y/=a;this.z/=a;this.w/=a;return this},lerpSelf:function(a,b){this.x+=(a.x-this.x)*b;this.y+=(a.y-this.y)*b;this.z+=(a.z-this.z)*b;this.w+=(a.w-this.w)*b},clone:function(){return new THREE.Vector4(this.x,this.y,this.z,this.w)},toString:function(){return"THREE.Vector4 ("+this.x+", "+this.y+", "+this.z+", "+this.w+")"}}; -THREE.Ray=function(a,b){this.origin=a||new THREE.Vector3;this.direction=b||new THREE.Vector3}; -THREE.Ray.prototype={intersectScene:function(a){var b,f,e=a.objects,g=[];a=0;for(b=e.length;a0&&K>0&&q+K<1}var f,e,g,h,j,c,i,l,r,B, -o,v=a.geometry,z=v.vertices,A=[];f=0;for(e=v.faces.length;fi?e:i;g=g>l? -g:l}a()};this.add3Points=function(i,l,r,B,o,v){if(c){c=false;b=ir?i>o?i:o:r>o?r:o;g=l>B?l>v?l:v:B>v?B:v}else{b=ir?i>o?i>e?i:e:o>e?o:e:r>o?r>e?r:e:o>e?o:e;g=l>B?l>v?l>g?l:g:v>g?v:g:B>v?B>g?B:g:v>g?v:g}a()};this.addRectangle=function(i){if(c){c=false;b=i.getLeft();f=i.getTop();e=i.getRight();g=i.getBottom()}else{b=bi.getRight()?e:i.getRight();g=g>i.getBottom()?g:i.getBottom()}a()};this.inflate=function(i){b-=i;f-=i;e+=i;g+=i;a()};this.minSelf=function(i){b=b>i.getLeft()?b:i.getLeft();f=f>i.getTop()?f:i.getTop();e=e=0&&Math.min(g,i.getBottom())-Math.max(f,i.getTop())>=0};this.empty=function(){c=true;g=e=f=b=0;a()};this.isEmpty=function(){return c};this.toString= -function(){return"THREE.Rectangle ( left: "+b+", right: "+e+", top: "+f+", bottom: "+g+", width: "+h+", height: "+j+" )"}};THREE.Matrix3=function(){this.m=[]};THREE.Matrix3.prototype={transpose:function(){var a;a=this.m[1];this.m[1]=this.m[3];this.m[3]=a;a=this.m[2];this.m[2]=this.m[6];this.m[6]=a;a=this.m[5];this.m[5]=this.m[7];this.m[7]=a;return this}}; -THREE.Matrix4=function(a,b,f,e,g,h,j,c,i,l,r,B,o,v,z,A){this.n11=a||1;this.n12=b||0;this.n13=f||0;this.n14=e||0;this.n21=g||0;this.n22=h||1;this.n23=j||0;this.n24=c||0;this.n31=i||0;this.n32=l||0;this.n33=r||1;this.n34=B||0;this.n41=o||0;this.n42=v||0;this.n43=z||0;this.n44=A||1}; -THREE.Matrix4.prototype={identity:function(){this.n11=1;this.n21=this.n14=this.n13=this.n12=0;this.n22=1;this.n32=this.n31=this.n24=this.n23=0;this.n33=1;this.n43=this.n42=this.n41=this.n34=0;this.n44=1;return this},set:function(a,b,f,e,g,h,j,c,i,l,r,B,o,v,z,A){this.n11=a;this.n12=b;this.n13=f;this.n14=e;this.n21=g;this.n22=h;this.n23=j;this.n24=c;this.n31=i;this.n32=l;this.n33=r;this.n34=B;this.n41=o;this.n42=v;this.n43=z;this.n44=A;return this},copy:function(a){this.n11=a.n11;this.n12=a.n12;this.n13= -a.n13;this.n14=a.n14;this.n21=a.n21;this.n22=a.n22;this.n23=a.n23;this.n24=a.n24;this.n31=a.n31;this.n32=a.n32;this.n33=a.n33;this.n34=a.n34;this.n41=a.n41;this.n42=a.n42;this.n43=a.n43;this.n44=a.n44;return this},lookAt:function(a,b,f){var e=new THREE.Vector3,g=new THREE.Vector3,h=new THREE.Vector3;h.sub(a,b).normalize();e.cross(f,h).normalize();g.cross(h,e).normalize();this.n11=e.x;this.n12=e.y;this.n13=e.z;this.n14=-e.dot(a);this.n21=g.x;this.n22=g.y;this.n23=g.z;this.n24=-g.dot(a);this.n31=h.x; -this.n32=h.y;this.n33=h.z;this.n34=-h.dot(a);this.n43=this.n42=this.n41=0;this.n44=1;return this},multiplyVector3:function(a){var b=a.x,f=a.y,e=a.z,g=1/(this.n41*b+this.n42*f+this.n43*e+this.n44);a.x=(this.n11*b+this.n12*f+this.n13*e+this.n14)*g;a.y=(this.n21*b+this.n22*f+this.n23*e+this.n24)*g;a.z=(this.n31*b+this.n32*f+this.n33*e+this.n34)*g;return a},multiplyVector4:function(a){var b=a.x,f=a.y,e=a.z,g=a.w;a.x=this.n11*b+this.n12*f+this.n13*e+this.n14*g;a.y=this.n21*b+this.n22*f+this.n23*e+this.n24* -g;a.z=this.n31*b+this.n32*f+this.n33*e+this.n34*g;a.w=this.n41*b+this.n42*f+this.n43*e+this.n44*g;return a},crossVector:function(a){var b=new THREE.Vector4;b.x=this.n11*a.x+this.n12*a.y+this.n13*a.z+this.n14*a.w;b.y=this.n21*a.x+this.n22*a.y+this.n23*a.z+this.n24*a.w;b.z=this.n31*a.x+this.n32*a.y+this.n33*a.z+this.n34*a.w;b.w=a.w?this.n41*a.x+this.n42*a.y+this.n43*a.z+this.n44*a.w:1;return b},multiply:function(a,b){var f=a.n11,e=a.n12,g=a.n13,h=a.n14,j=a.n21,c=a.n22,i=a.n23,l=a.n24,r=a.n31,B=a.n32, -o=a.n33,v=a.n34,z=a.n41,A=a.n42,K=a.n43,p=a.n44,E=b.n11,d=b.n12,k=b.n13,q=b.n14,s=b.n21,n=b.n22,m=b.n23,x=b.n24,t=b.n31,D=b.n32,y=b.n33,w=b.n34,C=b.n41,$=b.n42,M=b.n43,U=b.n44;this.n11=f*E+e*s+g*t+h*C;this.n12=f*d+e*n+g*D+h*$;this.n13=f*k+e*m+g*y+h*M;this.n14=f*q+e*x+g*w+h*U;this.n21=j*E+c*s+i*t+l*C;this.n22=j*d+c*n+i*D+l*$;this.n23=j*k+c*m+i*y+l*M;this.n24=j*q+c*x+i*w+l*U;this.n31=r*E+B*s+o*t+v*C;this.n32=r*d+B*n+o*D+v*$;this.n33=r*k+B*m+o*y+v*M;this.n34=r*q+B*x+o*w+v*U;this.n41=z*E+A*s+K*t+p*C; -this.n42=z*d+A*n+K*D+p*$;this.n43=z*k+A*m+K*y+p*M;this.n44=z*q+A*x+K*w+p*U;return this},multiplySelf:function(a){var b=this.n11,f=this.n12,e=this.n13,g=this.n14,h=this.n21,j=this.n22,c=this.n23,i=this.n24,l=this.n31,r=this.n32,B=this.n33,o=this.n34,v=this.n41,z=this.n42,A=this.n43,K=this.n44,p=a.n11,E=a.n21,d=a.n31,k=a.n41,q=a.n12,s=a.n22,n=a.n32,m=a.n42,x=a.n13,t=a.n23,D=a.n33,y=a.n43,w=a.n14,C=a.n24,$=a.n34;a=a.n44;this.n11=b*p+f*E+e*d+g*k;this.n12=b*q+f*s+e*n+g*m;this.n13=b*x+f*t+e*D+g*y;this.n14= -b*w+f*C+e*$+g*a;this.n21=h*p+j*E+c*d+i*k;this.n22=h*q+j*s+c*n+i*m;this.n23=h*x+j*t+c*D+i*y;this.n24=h*w+j*C+c*$+i*a;this.n31=l*p+r*E+B*d+o*k;this.n32=l*q+r*s+B*n+o*m;this.n33=l*x+r*t+B*D+o*y;this.n34=l*w+r*C+B*$+o*a;this.n41=v*p+z*E+A*d+K*k;this.n42=v*q+z*s+A*n+K*m;this.n43=v*x+z*t+A*D+K*y;this.n44=v*w+z*C+A*$+K*a;return this},multiplyScalar:function(a){this.n11*=a;this.n12*=a;this.n13*=a;this.n14*=a;this.n21*=a;this.n22*=a;this.n23*=a;this.n24*=a;this.n31*=a;this.n32*=a;this.n33*=a;this.n34*=a;this.n41*= -a;this.n42*=a;this.n43*=a;this.n44*=a;return this},determinant:function(){return this.n14*this.n23*this.n32*this.n41-this.n13*this.n24*this.n32*this.n41-this.n14*this.n22*this.n33*this.n41+this.n12*this.n24*this.n33*this.n41+this.n13*this.n22*this.n34*this.n41-this.n12*this.n23*this.n34*this.n41-this.n14*this.n23*this.n31*this.n42+this.n13*this.n24*this.n31*this.n42+this.n14*this.n21*this.n33*this.n42-this.n11*this.n24*this.n33*this.n42-this.n13*this.n21*this.n34*this.n42+this.n11*this.n23*this.n34* -this.n42+this.n14*this.n22*this.n31*this.n43-this.n12*this.n24*this.n31*this.n43-this.n14*this.n21*this.n32*this.n43+this.n11*this.n24*this.n32*this.n43+this.n12*this.n21*this.n34*this.n43-this.n11*this.n22*this.n34*this.n43-this.n13*this.n22*this.n31*this.n44+this.n12*this.n23*this.n31*this.n44+this.n13*this.n21*this.n32*this.n44-this.n11*this.n23*this.n32*this.n44-this.n12*this.n21*this.n33*this.n44+this.n11*this.n22*this.n33*this.n44},transpose:function(){function a(b,f,e){var g=b[f];b[f]=b[e]; -b[e]=g}a(this,"n21","n12");a(this,"n31","n13");a(this,"n32","n23");a(this,"n41","n14");a(this,"n42","n24");a(this,"n43","n34");return this},clone:function(){var a=new THREE.Matrix4;a.n11=this.n11;a.n12=this.n12;a.n13=this.n13;a.n14=this.n14;a.n21=this.n21;a.n22=this.n22;a.n23=this.n23;a.n24=this.n24;a.n31=this.n31;a.n32=this.n32;a.n33=this.n33;a.n34=this.n34;a.n41=this.n41;a.n42=this.n42;a.n43=this.n43;a.n44=this.n44;return a},flatten:function(){return[this.n11,this.n21,this.n31,this.n41,this.n12, -this.n22,this.n32,this.n42,this.n13,this.n23,this.n33,this.n43,this.n14,this.n24,this.n34,this.n44]},toString:function(){return"| "+this.n11+" "+this.n12+" "+this.n13+" "+this.n14+" |\n| "+this.n21+" "+this.n22+" "+this.n23+" "+this.n24+" |\n| "+this.n31+" "+this.n32+" "+this.n33+" "+this.n34+" |\n| "+this.n41+" "+this.n42+" "+this.n43+" "+this.n44+" |"}};THREE.Matrix4.translationMatrix=function(a,b,f){var e=new THREE.Matrix4;e.n14=a;e.n24=b;e.n34=f;return e}; -THREE.Matrix4.scaleMatrix=function(a,b,f){var e=new THREE.Matrix4;e.n11=a;e.n22=b;e.n33=f;return e};THREE.Matrix4.rotationXMatrix=function(a){var b=new THREE.Matrix4;b.n22=b.n33=Math.cos(a);b.n32=Math.sin(a);b.n23=-b.n32;return b};THREE.Matrix4.rotationYMatrix=function(a){var b=new THREE.Matrix4;b.n11=b.n33=Math.cos(a);b.n13=Math.sin(a);b.n31=-b.n13;return b};THREE.Matrix4.rotationZMatrix=function(a){var b=new THREE.Matrix4;b.n11=b.n22=Math.cos(a);b.n21=Math.sin(a);b.n12=-b.n21;return b}; -THREE.Matrix4.rotationAxisAngleMatrix=function(a,b){var f=new THREE.Matrix4,e=Math.cos(b),g=Math.sin(b),h=1-e,j=a.x,c=a.y,i=a.z;f.n11=h*j*j+e;f.n12=h*j*c-g*i;f.n13=h*j*i+g*c;f.n21=h*j*c+g*i;f.n22=h*c*c+e;f.n23=h*c*i-g*j;f.n31=h*j*i-g*c;f.n32=h*c*i+g*j;f.n33=h*i*i+e;return f}; -THREE.Matrix4.makeInvert=function(a){var b=new THREE.Matrix4;b.n11=a.n23*a.n34*a.n42-a.n24*a.n33*a.n42+a.n24*a.n32*a.n43-a.n22*a.n34*a.n43-a.n23*a.n32*a.n44+a.n22*a.n33*a.n44;b.n12=a.n14*a.n33*a.n42-a.n13*a.n34*a.n42-a.n14*a.n32*a.n43+a.n12*a.n34*a.n43+a.n13*a.n32*a.n44-a.n12*a.n33*a.n44;b.n13=a.n13*a.n24*a.n42-a.n14*a.n23*a.n42+a.n14*a.n22*a.n43-a.n12*a.n24*a.n43-a.n13*a.n22*a.n44+a.n12*a.n23*a.n44;b.n14=a.n14*a.n23*a.n32-a.n13*a.n24*a.n32-a.n14*a.n22*a.n33+a.n12*a.n24*a.n33+a.n13*a.n22*a.n34-a.n12* -a.n23*a.n34;b.n21=a.n24*a.n33*a.n41-a.n23*a.n34*a.n41-a.n24*a.n31*a.n43+a.n21*a.n34*a.n43+a.n23*a.n31*a.n44-a.n21*a.n33*a.n44;b.n22=a.n13*a.n34*a.n41-a.n14*a.n33*a.n41+a.n14*a.n31*a.n43-a.n11*a.n34*a.n43-a.n13*a.n31*a.n44+a.n11*a.n33*a.n44;b.n23=a.n14*a.n23*a.n41-a.n13*a.n24*a.n41-a.n14*a.n21*a.n43+a.n11*a.n24*a.n43+a.n13*a.n21*a.n44-a.n11*a.n23*a.n44;b.n24=a.n13*a.n24*a.n31-a.n14*a.n23*a.n31+a.n14*a.n21*a.n33-a.n11*a.n24*a.n33-a.n13*a.n21*a.n34+a.n11*a.n23*a.n34;b.n31=a.n22*a.n34*a.n41-a.n24*a.n32* -a.n41+a.n24*a.n31*a.n42-a.n21*a.n34*a.n42-a.n22*a.n31*a.n44+a.n21*a.n32*a.n44;b.n32=a.n14*a.n32*a.n41-a.n12*a.n34*a.n41-a.n14*a.n31*a.n42+a.n11*a.n34*a.n42+a.n12*a.n31*a.n44-a.n11*a.n32*a.n44;b.n33=a.n13*a.n24*a.n41-a.n14*a.n22*a.n41+a.n14*a.n21*a.n42-a.n11*a.n24*a.n42-a.n12*a.n21*a.n44+a.n11*a.n22*a.n44;b.n34=a.n14*a.n22*a.n31-a.n12*a.n24*a.n31-a.n14*a.n21*a.n32+a.n11*a.n24*a.n32+a.n12*a.n21*a.n34-a.n11*a.n22*a.n34;b.n41=a.n23*a.n32*a.n41-a.n22*a.n33*a.n41-a.n23*a.n31*a.n42+a.n21*a.n33*a.n42+a.n22* -a.n31*a.n43-a.n21*a.n32*a.n43;b.n42=a.n12*a.n33*a.n41-a.n13*a.n32*a.n41+a.n13*a.n31*a.n42-a.n11*a.n33*a.n42-a.n12*a.n31*a.n43+a.n11*a.n32*a.n43;b.n43=a.n13*a.n22*a.n41-a.n12*a.n23*a.n41-a.n13*a.n21*a.n42+a.n11*a.n23*a.n42+a.n12*a.n21*a.n43-a.n11*a.n22*a.n43;b.n44=a.n12*a.n23*a.n31-a.n13*a.n22*a.n31+a.n13*a.n21*a.n32-a.n11*a.n23*a.n32-a.n12*a.n21*a.n33+a.n11*a.n22*a.n33;b.multiplyScalar(1/a.determinant());return b}; -THREE.Matrix4.makeInvert3x3=function(a){var b=a.flatten();a=new THREE.Matrix3;var f=b[10]*b[5]-b[6]*b[9],e=-b[10]*b[1]+b[2]*b[9],g=b[6]*b[1]-b[2]*b[5],h=-b[10]*b[4]+b[6]*b[8],j=b[10]*b[0]-b[2]*b[8],c=-b[6]*b[0]+b[2]*b[4],i=b[9]*b[4]-b[5]*b[8],l=-b[9]*b[0]+b[1]*b[8],r=b[5]*b[0]-b[1]*b[4];b=b[0]*f+b[1]*h+b[2]*i;if(b==0)throw"matrix not invertible";b=1/b;a.m[0]=b*f;a.m[1]=b*e;a.m[2]=b*g;a.m[3]=b*h;a.m[4]=b*j;a.m[5]=b*c;a.m[6]=b*i;a.m[7]=b*l;a.m[8]=b*r;return a}; -THREE.Matrix4.makeFrustum=function(a,b,f,e,g,h){var j,c,i;j=new THREE.Matrix4;c=2*g/(b-a);i=2*g/(e-f);a=(b+a)/(b-a);f=(e+f)/(e-f);e=-(h+g)/(h-g);g=-2*h*g/(h-g);j.n11=c;j.n12=0;j.n13=a;j.n14=0;j.n21=0;j.n22=i;j.n23=f;j.n24=0;j.n31=0;j.n32=0;j.n33=e;j.n34=g;j.n41=0;j.n42=0;j.n43=-1;j.n44=0;return j};THREE.Matrix4.makePerspective=function(a,b,f,e){var g;a=f*Math.tan(a*Math.PI/360);g=-a;return THREE.Matrix4.makeFrustum(g*b,a*b,g,a,f,e)}; -THREE.Matrix4.makeOrtho=function(a,b,f,e,g,h){var j,c,i,l;j=new THREE.Matrix4;c=b-a;i=f-e;l=h-g;a=(b+a)/c;f=(f+e)/i;g=(h+g)/l;j.n11=2/c;j.n12=0;j.n13=0;j.n14=-a;j.n21=0;j.n22=2/i;j.n23=0;j.n24=-f;j.n31=0;j.n32=0;j.n33=-2/l;j.n34=-g;j.n41=0;j.n42=0;j.n43=0;j.n44=1;return j}; -THREE.Vertex=function(a,b){this.position=a||new THREE.Vector3;this.positionWorld=new THREE.Vector3;this.positionScreen=new THREE.Vector4;this.normal=b||new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.normalScreen=new THREE.Vector3;this.tangent=new THREE.Vector4;this.__visible=true};THREE.Vertex.prototype={toString:function(){return"THREE.Vertex ( position: "+this.position+", normal: "+this.normal+" )"}}; -THREE.Face3=function(a,b,f,e,g){this.a=a;this.b=b;this.c=f;this.centroid=new THREE.Vector3;this.normal=e instanceof THREE.Vector3?e:new THREE.Vector3;this.vertexNormals=e instanceof Array?e:[];this.materials=g instanceof Array?g:[g]};THREE.Face3.prototype={toString:function(){return"THREE.Face3 ( "+this.a+", "+this.b+", "+this.c+" )"}}; -THREE.Face4=function(a,b,f,e,g,h){this.a=a;this.b=b;this.c=f;this.d=e;this.centroid=new THREE.Vector3;this.normal=g instanceof THREE.Vector3?g:new THREE.Vector3;this.vertexNormals=g instanceof Array?g:[];this.materials=h instanceof Array?h:[h]};THREE.Face4.prototype={toString:function(){return"THREE.Face4 ( "+this.a+", "+this.b+", "+this.c+" "+this.d+" )"}};THREE.UV=function(a,b){this.u=a||0;this.v=b||0}; -THREE.UV.prototype={copy:function(a){this.u=a.u;this.v=a.v},toString:function(){return"THREE.UV ("+this.u+", "+this.v+")"}};THREE.Geometry=function(){this.vertices=[];this.faces=[];this.uvs=[];this.boundingSphere=this.boundingBox=null;this.geometryChunks={};this.hasTangents=false}; -THREE.Geometry.prototype={computeCentroids:function(){var a,b,f;a=0;for(b=this.faces.length;a0){this.boundingBox={x:[this.vertices[0].position.x,this.vertices[0].position.x], -y:[this.vertices[0].position.y,this.vertices[0].position.y],z:[this.vertices[0].position.z,this.vertices[0].position.z]};for(var b=1,f=this.vertices.length;bthis.boundingBox.x[1])this.boundingBox.x[1]=a.position.x;if(a.position.ythis.boundingBox.y[1])this.boundingBox.y[1]=a.position.y;if(a.position.z< -this.boundingBox.z[0])this.boundingBox.z[0]=a.position.z;else if(a.position.z>this.boundingBox.z[1])this.boundingBox.z[1]=a.position.z}}},computeBoundingSphere:function(){for(var a=this.boundingSphere===null?0:this.boundingSphere.radius,b=0,f=this.vertices.length;b65535){l[c].counter+=1;i=l[c].hash+"_"+l[c].counter;if(this.geometryChunks[i]==undefined)this.geometryChunks[i]={faces:[],materials:j,vertices:0}}this.geometryChunks[i].faces.push(e); -this.geometryChunks[i].vertices+=h}},toString:function(){return"THREE.Geometry ( vertices: "+this.vertices+", faces: "+this.faces+", uvs: "+this.uvs+" )"}}; -THREE.Camera=function(a,b,f,e){this.fov=a;this.aspect=b;this.near=f;this.far=e;this.position=new THREE.Vector3;this.target={position:new THREE.Vector3};this.autoUpdateMatrix=true;this.projectionMatrix=null;this.matrix=new THREE.Matrix4;this.up=new THREE.Vector3(0,1,0);this.translateX=function(g){g=this.target.position.clone().subSelf(this.position).normalize().multiplyScalar(g);g.cross(g.clone(),this.up);this.position.addSelf(g);this.target.position.addSelf(g)};this.translateZ=function(g){g=this.target.position.clone().subSelf(this.position).normalize().multiplyScalar(g); -this.position.subSelf(g);this.target.position.subSelf(g)};this.updateMatrix=function(){this.matrix.lookAt(this.position,this.target.position,this.up)};this.updateProjectionMatrix=function(){this.projectionMatrix=THREE.Matrix4.makePerspective(this.fov,this.aspect,this.near,this.far)};this.updateProjectionMatrix()};THREE.Camera.prototype={toString:function(){return"THREE.Camera ( "+this.position+", "+this.target.position+" )"}};THREE.Light=function(a){this.color=new THREE.Color(a)}; -THREE.AmbientLight=function(a){THREE.Light.call(this,a)};THREE.AmbientLight.prototype=new THREE.Light;THREE.AmbientLight.prototype.constructor=THREE.AmbientLight;THREE.DirectionalLight=function(a,b){THREE.Light.call(this,a);this.position=new THREE.Vector3(0,1,0);this.intensity=b||1};THREE.DirectionalLight.prototype=new THREE.Light;THREE.DirectionalLight.prototype.constructor=THREE.DirectionalLight; -THREE.PointLight=function(a,b){THREE.Light.call(this,a);this.position=new THREE.Vector3;this.intensity=b||1};THREE.DirectionalLight.prototype=new THREE.Light;THREE.DirectionalLight.prototype.constructor=THREE.PointLight; -THREE.Object3D=function(){this.id=THREE.Object3DCounter.value++;this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.scale=new THREE.Vector3(1,1,1);this.matrix=new THREE.Matrix4;this.translationMatrix=new THREE.Matrix4;this.rotationMatrix=new THREE.Matrix4;this.scaleMatrix=new THREE.Matrix4;this.screen=new THREE.Vector3;this.visible=this.autoUpdateMatrix=true}; -THREE.Object3D.prototype={updateMatrix:function(){this.matrixPosition=THREE.Matrix4.translationMatrix(this.position.x,this.position.y,this.position.z);this.rotationMatrix=THREE.Matrix4.rotationXMatrix(this.rotation.x);this.rotationMatrix.multiplySelf(THREE.Matrix4.rotationYMatrix(this.rotation.y));this.rotationMatrix.multiplySelf(THREE.Matrix4.rotationZMatrix(this.rotation.z));this.scaleMatrix=THREE.Matrix4.scaleMatrix(this.scale.x,this.scale.y,this.scale.z);this.matrix.copy(this.matrixPosition); -this.matrix.multiplySelf(this.rotationMatrix);this.matrix.multiplySelf(this.scaleMatrix)}};THREE.Object3DCounter={value:0};THREE.Particle=function(a){THREE.Object3D.call(this);this.materials=a instanceof Array?a:[a];this.autoUpdateMatrix=false};THREE.Particle.prototype=new THREE.Object3D;THREE.Particle.prototype.constructor=THREE.Particle;THREE.ParticleSystem=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.materials=b instanceof Array?b:[b];this.autoUpdateMatrix=false}; -THREE.ParticleSystem.prototype=new THREE.Object3D;THREE.ParticleSystem.prototype.constructor=THREE.ParticleSystem;THREE.Line=function(a,b,f){THREE.Object3D.call(this);this.geometry=a;this.materials=b instanceof Array?b:[b];this.type=f!==undefined?f:THREE.LineContinuous};THREE.LineStrip=0;THREE.LinePieces=1;THREE.Line.prototype=new THREE.Object3D;THREE.Line.prototype.constructor=THREE.Line; -THREE.Mesh=function(a,b){THREE.Object3D.call(this);this.geometry=a;this.materials=b instanceof Array?b:[b];this.overdraw=this.doubleSided=this.flipSided=false;this.geometry.boundingSphere||this.geometry.computeBoundingSphere()};THREE.Mesh.prototype=new THREE.Object3D;THREE.Mesh.prototype.constructor=THREE.Mesh;THREE.FlatShading=0;THREE.SmoothShading=1;THREE.NormalBlending=0;THREE.AdditiveBlending=1;THREE.SubtractiveBlending=2; -THREE.LineBasicMaterial=function(a){this.color=new THREE.Color(16777215);this.opacity=1;this.blending=THREE.NormalBlending;this.linewidth=1;this.linejoin=this.linecap="round";if(a){a.color!==undefined&&this.color.setHex(a.color);if(a.opacity!==undefined)this.opacity=a.opacity;if(a.blending!==undefined)this.blending=a.blending;if(a.linewidth!==undefined)this.linewidth=a.linewidth;if(a.linecap!==undefined)this.linecap=a.linecap;if(a.linejoin!==undefined)this.linejoin=a.linejoin}}; -THREE.LineBasicMaterial.prototype={toString:function(){return"THREE.LineBasicMaterial (
color: "+this.color+"
opacity: "+this.opacity+"
blending: "+this.blending+"
linewidth: "+this.linewidth+"
linecap: "+this.linecap+"
linejoin: "+this.linejoin+"
)"}}; -THREE.MeshBasicMaterial=function(a){this.id=THREE.MeshBasicMaterialCounter.value++;this.color=new THREE.Color(16777215);this.env_map=this.map=null;this.combine=THREE.MultiplyOperation;this.reflectivity=1;this.refraction_ratio=0.98;this.fog=true;this.opacity=1;this.shading=THREE.SmoothShading;this.blending=THREE.NormalBlending;this.wireframe=false;this.wireframe_linewidth=1;this.wireframe_linejoin=this.wireframe_linecap="round";if(a){a.color!==undefined&&this.color.setHex(a.color);if(a.map!==undefined)this.map= -a.map;if(a.env_map!==undefined)this.env_map=a.env_map;if(a.combine!==undefined)this.combine=a.combine;if(a.reflectivity!==undefined)this.reflectivity=a.reflectivity;if(a.refraction_ratio!==undefined)this.refraction_ratio=a.refraction_ratio;if(a.fog!==undefined)this.fog=a.fog;if(a.opacity!==undefined)this.opacity=a.opacity;if(a.shading!==undefined)this.shading=a.shading;if(a.blending!==undefined)this.blending=a.blending;if(a.wireframe!==undefined)this.wireframe=a.wireframe;if(a.wireframe_linewidth!== -undefined)this.wireframe_linewidth=a.wireframe_linewidth;if(a.wireframe_linecap!==undefined)this.wireframe_linecap=a.wireframe_linecap;if(a.wireframe_linejoin!==undefined)this.wireframe_linejoin=a.wireframe_linejoin}}; -THREE.MeshBasicMaterial.prototype={toString:function(){return"THREE.MeshBasicMaterial (
id: "+this.id+"
color: "+this.color+"
map: "+this.map+"
env_map: "+this.env_map+"
combine: "+this.combine+"
reflectivity: "+this.reflectivity+"
refraction_ratio: "+this.refraction_ratio+"
opacity: "+this.opacity+"
blending: "+this.blending+"
wireframe: "+this.wireframe+"
wireframe_linewidth: "+this.wireframe_linewidth+"
wireframe_linecap: "+this.wireframe_linecap+ -"
wireframe_linejoin: "+this.wireframe_linejoin+"
)"}};THREE.MeshBasicMaterialCounter={value:0}; -THREE.MeshLambertMaterial=function(a){this.id=THREE.MeshLambertMaterialCounter.value++;this.color=new THREE.Color(16777215);this.env_map=this.map=null;this.combine=THREE.MultiplyOperation;this.reflectivity=1;this.refraction_ratio=0.98;this.fog=true;this.opacity=1;this.shading=THREE.SmoothShading;this.blending=THREE.NormalBlending;this.wireframe=false;this.wireframe_linewidth=1;this.wireframe_linejoin=this.wireframe_linecap="round";if(a){a.color!==undefined&&this.color.setHex(a.color);if(a.map!==undefined)this.map= -a.map;if(a.env_map!==undefined)this.env_map=a.env_map;if(a.combine!==undefined)this.combine=a.combine;if(a.reflectivity!==undefined)this.reflectivity=a.reflectivity;if(a.refraction_ratio!==undefined)this.refraction_ratio=a.refraction_ratio;if(a.fog!==undefined)this.fog=a.fog;if(a.opacity!==undefined)this.opacity=a.opacity;if(a.shading!==undefined)this.shading=a.shading;if(a.blending!==undefined)this.blending=a.blending;if(a.wireframe!==undefined)this.wireframe=a.wireframe;if(a.wireframe_linewidth!== -undefined)this.wireframe_linewidth=a.wireframe_linewidth;if(a.wireframe_linecap!==undefined)this.wireframe_linecap=a.wireframe_linecap;if(a.wireframe_linejoin!==undefined)this.wireframe_linejoin=a.wireframe_linejoin}}; -THREE.MeshLambertMaterial.prototype={toString:function(){return"THREE.MeshLambertMaterial (
id: "+this.id+"
color: "+this.color+"
map: "+this.map+"
env_map: "+this.env_map+"
combine: "+this.combine+"
reflectivity: "+this.reflectivity+"
refraction_ratio: "+this.refraction_ratio+"
opacity: "+this.opacity+"
shading: "+this.shading+"
blending: "+this.blending+"
wireframe: "+this.wireframe+"
wireframe_linewidth: "+this.wireframe_linewidth+"
wireframe_linecap: "+ -this.wireframe_linecap+"
wireframe_linejoin: "+this.wireframe_linejoin+"
)"}};THREE.MeshLambertMaterialCounter={value:0}; -THREE.MeshPhongMaterial=function(a){this.id=THREE.MeshPhongMaterialCounter.value++;this.color=new THREE.Color(16777215);this.ambient=new THREE.Color(328965);this.specular=new THREE.Color(1118481);this.shininess=30;this.env_map=this.specular_map=this.map=null;this.combine=THREE.MultiplyOperation;this.reflectivity=1;this.refraction_ratio=0.98;this.fog=true;this.opacity=1;this.shading=THREE.SmoothShading;this.blending=THREE.NormalBlending;this.wireframe=false;this.wireframe_linewidth=1;this.wireframe_linejoin= -this.wireframe_linecap="round";if(a){if(a.color!==undefined)this.color=new THREE.Color(a.color);if(a.ambient!==undefined)this.ambient=new THREE.Color(a.ambient);if(a.specular!==undefined)this.specular=new THREE.Color(a.specular);if(a.shininess!==undefined)this.shininess=a.shininess;if(a.map!==undefined)this.map=a.map;if(a.specular_map!==undefined)this.specular_map=a.specular_map;if(a.env_map!==undefined)this.env_map=a.env_map;if(a.combine!==undefined)this.combine=a.combine;if(a.reflectivity!==undefined)this.reflectivity= -a.reflectivity;if(a.refraction_ratio!==undefined)this.refraction_ratio=a.refraction_ratio;if(a.fog!==undefined)this.fog=a.fog;if(a.opacity!==undefined)this.opacity=a.opacity;if(a.shading!==undefined)this.shading=a.shading;if(a.blending!==undefined)this.blending=a.blending;if(a.wireframe!==undefined)this.wireframe=a.wireframe;if(a.wireframe_linewidth!==undefined)this.wireframe_linewidth=a.wireframe_linewidth;if(a.wireframe_linecap!==undefined)this.wireframe_linecap=a.wireframe_linecap;if(a.wireframe_linejoin!== -undefined)this.wireframe_linejoin=a.wireframe_linejoin}}; -THREE.MeshPhongMaterial.prototype={toString:function(){return"THREE.MeshPhongMaterial (
id: "+this.id+"
color: "+this.color+"
ambient: "+this.ambient+"
specular: "+this.specular+"
shininess: "+this.shininess+"
map: "+this.map+"
specular_map: "+this.specular_map+"
env_map: "+this.env_map+"
combine: "+this.combine+"
reflectivity: "+this.reflectivity+"
refraction_ratio: "+this.refraction_ratio+"
opacity: "+this.opacity+"
shading: "+this.shading+"
wireframe: "+ -this.wireframe+"
wireframe_linewidth: "+this.wireframe_linewidth+"
wireframe_linecap: "+this.wireframe_linecap+"
wireframe_linejoin: "+this.wireframe_linejoin+"
)"}};THREE.MeshPhongMaterialCounter={value:0}; -THREE.MeshDepthMaterial=function(a){this.opacity=1;this.shading=THREE.SmoothShading;this.blending=THREE.NormalBlending;this.wireframe=false;this.wireframe_linewidth=1;this.wireframe_linejoin=this.wireframe_linecap="round";if(a){if(a.opacity!==undefined)this.opacity=a.opacity;if(a.blending!==undefined)this.blending=a.blending}};THREE.MeshDepthMaterial.prototype={toString:function(){return"THREE.MeshDepthMaterial"}}; -THREE.MeshNormalMaterial=function(a){this.opacity=1;this.shading=THREE.FlatShading;this.blending=THREE.NormalBlending;if(a){if(a.opacity!==undefined)this.opacity=a.opacity;if(a.shading!==undefined)this.shading=a.shading;if(a.blending!==undefined)this.blending=a.blending}};THREE.MeshNormalMaterial.prototype={toString:function(){return"THREE.MeshNormalMaterial"}};THREE.MeshFaceMaterial=function(){};THREE.MeshFaceMaterial.prototype={toString:function(){return"THREE.MeshFaceMaterial"}}; -THREE.MeshShaderMaterial=function(a){this.id=THREE.MeshShaderMaterialCounter.value++;this.vertex_shader=this.fragment_shader="void main() {}";this.uniforms={};this.opacity=1;this.shading=THREE.SmoothShading;this.blending=THREE.NormalBlending;this.wireframe=false;this.wireframe_linewidth=1;this.wireframe_linejoin=this.wireframe_linecap="round";if(a){if(a.fragment_shader!==undefined)this.fragment_shader=a.fragment_shader;if(a.vertex_shader!==undefined)this.vertex_shader=a.vertex_shader;if(a.uniforms!== -undefined)this.uniforms=a.uniforms;if(a.shading!==undefined)this.shading=a.shading;if(a.blending!==undefined)this.blending=a.blending;if(a.wireframe!==undefined)this.wireframe=a.wireframe;if(a.wireframe_linewidth!==undefined)this.wireframe_linewidth=a.wireframe_linewidth;if(a.wireframe_linecap!==undefined)this.wireframe_linecap=a.wireframe_linecap;if(a.wireframe_linejoin!==undefined)this.wireframe_linejoin=a.wireframe_linejoin}}; -THREE.MeshShaderMaterial.prototype={toString:function(){return"THREE.MeshShaderMaterial (
id: "+this.id+"
blending: "+this.blending+"
wireframe: "+this.wireframe+"
wireframe_linewidth: "+this.wireframe_linewidth+"
wireframe_linecap: "+this.wireframe_linecap+"
wireframe_linejoin: "+this.wireframe_linejoin+"
)"}};THREE.MeshShaderMaterialCounter={value:0}; -THREE.ParticleBasicMaterial=function(a){this.color=new THREE.Color(16777215);this.map=null;this.opacity=1;this.blending=THREE.NormalBlending;this.offset=new THREE.Vector2;if(a){a.color!==undefined&&this.color.setHex(a.color);if(a.map!==undefined)this.map=a.map;if(a.opacity!==undefined)this.opacity=a.opacity;if(a.blending!==undefined)this.blending=a.blending}}; -THREE.ParticleBasicMaterial.prototype={toString:function(){return"THREE.ParticleBasicMaterial (
color: "+this.color+"
map: "+this.map+"
opacity: "+this.opacity+"
blending: "+this.blending+"
)"}};THREE.ParticleCircleMaterial=function(a){this.color=new THREE.Color(16777215);this.opacity=1;this.blending=THREE.NormalBlending;if(a){a.color!==undefined&&this.color.setHex(a.color);if(a.opacity!==undefined)this.opacity=a.opacity;if(a.blending!==undefined)this.blending=a.blending}}; -THREE.ParticleCircleMaterial.prototype={toString:function(){return"THREE.ParticleCircleMaterial (
color: "+this.color+"
opacity: "+this.opacity+"
blending: "+this.blending+"
)"}};THREE.ParticleDOMMaterial=function(a){this.domElement=a};THREE.ParticleDOMMaterial.prototype={toString:function(){return"THREE.ParticleDOMMaterial ( domElement: "+this.domElement+" )"}}; -THREE.Texture=function(a,b,f,e,g,h){this.image=a;this.mapping=b!==undefined?b:new THREE.UVMapping;this.wrap_s=f!==undefined?f:THREE.ClampToEdgeWrapping;this.wrap_t=e!==undefined?e:THREE.ClampToEdgeWrapping;this.mag_filter=g!==undefined?g:THREE.LinearFilter;this.min_filter=h!==undefined?h:THREE.LinearMipMapLinearFilter}; -THREE.Texture.prototype={clone:function(){return new THREE.Texture(this.image,this.mapping,this.wrap_s,this.wrap_t,this.mag_filter,this.min_filter)},toString:function(){return"THREE.Texture (
image: "+this.image+"
wrap_s: "+this.wrap_s+"
wrap_t: "+this.wrap_t+"
mag_filter: "+this.mag_filter+"
min_filter: "+this.min_filter+"
)"}};THREE.MultiplyOperation=0;THREE.MixOperation=1;THREE.RepeatWrapping=0;THREE.ClampToEdgeWrapping=1;THREE.MirroredRepeatWrapping=2; -THREE.NearestFilter=3;THREE.NearestMipMapNearestFilter=4;THREE.NearestMipMapLinearFilter=5;THREE.LinearFilter=6;THREE.LinearMipMapNearestFilter=7;THREE.LinearMipMapLinearFilter=8;var Uniforms={clone:function(a){var b,f,e,g={};for(b in a){g[b]={};for(f in a[b]){e=a[b][f];g[b][f]=e instanceof THREE.Color||e instanceof THREE.Vector3||e instanceof THREE.Texture?e.clone():e}}return g},merge:function(a){var b,f,e,g={};for(b=0;b=0&&y>=0&&w>=0&&C>=0)return true;else if(D<0&&y<0||w<0&&C<0)return false;else{if(D<0)x=Math.max(x,D/(D-y));else if(y<0)t=Math.min(t,D/(D-y));if(w<0)x=Math.max(x,w/(w-C));else if(C<0)t=Math.min(t,w/(w-C));if(tD&&M.z0&&K.z<1){o=z[v]=z[v]||new THREE.RenderableParticle;o.x=K.x/K.w;o.y=K.y/K.w;o.z=K.z;o.rotation=O.rotation.z;o.scale.x=O.scale.x*Math.abs(o.x-(K.x+m.projectionMatrix.n11)/(K.w+m.projectionMatrix.n14)); -o.scale.y=O.scale.y*Math.abs(o.y-(K.y+m.projectionMatrix.n22)/(K.w+m.projectionMatrix.n24));o.materials=O.materials;t.push(o);v++}}}}x&&t.sort(a);return t};this.unprojectVector=function(n,m){var x=new THREE.Matrix4;x.multiply(THREE.Matrix4.makeInvert(m.matrix),THREE.Matrix4.makeInvert(m.projectionMatrix));x.multiplyVector3(n);return n}}; -THREE.DOMRenderer=function(){THREE.Renderer.call(this);var a=null,b=new THREE.Projector,f,e,g,h;this.domElement=document.createElement("div");this.setSize=function(j,c){f=j;e=c;g=f/2;h=e/2};this.render=function(j,c){var i,l,r,B,o,v,z,A;a=b.projectScene(j,c);i=0;for(l=a.length;i0){J.r+=fa.r*ca;J.g+=fa.g*ca;J.b+=fa.b*ca}}else if(ca instanceof THREE.PointLight){H.sub(ca.position,X);H.normalize();ca=T.dot(H)*ia;if(ca>0){J.r+=fa.r*ca;J.g+=fa.g*ca;J.b+=fa.b*ca}}}}function Na(F,X,T){if(T.opacity!=0){a(T.opacity); -b(T.blending);var J,P,ca,fa,ia,la;if(T instanceof THREE.ParticleBasicMaterial){if(T.map){fa=T.map;ia=fa.width>>1;la=fa.height>>1;P=X.scale.x*c;ca=X.scale.y*i;T=P*ia;J=ca*la;I.set(F.x-T,F.y-J,F.x+T,F.y+J);if(Z.instersects(I)){l.save();l.translate(F.x,F.y);l.rotate(-X.rotation);l.scale(P,-ca);l.translate(-ia,-la);l.drawImage(fa,0,0);l.restore()}}}else if(T instanceof THREE.ParticleCircleMaterial){if(S){Y.r=ha.r+ja.r+u.r;Y.g=ha.g+ja.g+u.g;Y.b=ha.b+ja.b+u.b;t.r=T.color.r*Y.r;t.g=T.color.g*Y.g;t.b=T.color.b* -Y.b;t.updateStyleString()}else t.__styleString=T.color.__styleString;T=X.scale.x*c;J=X.scale.y*i;I.set(F.x-T,F.y-J,F.x+T,F.y+J);if(Z.instersects(I)){P=t.__styleString;if(A!=P)l.fillStyle=A=P;l.save();l.translate(F.x,F.y);l.rotate(-X.rotation);l.scale(T,J);l.beginPath();l.arc(0,0,1,0,G,true);l.closePath();l.fill();l.restore()}}}}function Oa(F,X,T,J){if(J.opacity!=0){a(J.opacity);b(J.blending);l.beginPath();l.moveTo(F.positionScreen.x,F.positionScreen.y);l.lineTo(X.positionScreen.x,X.positionScreen.y); -l.closePath();if(J instanceof THREE.LineBasicMaterial){t.__styleString=J.color.__styleString;F=J.linewidth;if(K!=F)l.lineWidth=K=F;F=t.__styleString;if(z!=F)l.strokeStyle=z=F;l.stroke();I.inflate(J.linewidth*2)}}}function Ia(F,X,T,J,P,ca){if(P.opacity!=0){a(P.opacity);b(P.blending);k=F.positionScreen.x;q=F.positionScreen.y;s=X.positionScreen.x;n=X.positionScreen.y;m=T.positionScreen.x;x=T.positionScreen.y;l.beginPath();l.moveTo(k,q);l.lineTo(s,n);l.lineTo(m,x);l.lineTo(k,q);l.closePath();if(P instanceof -THREE.MeshBasicMaterial)if(P.map)P.map.image.loaded&&P.map.mapping instanceof THREE.UVMapping&&xa(k,q,s,n,m,x,P.map.image,J.uvs[0].u,J.uvs[0].v,J.uvs[1].u,J.uvs[1].v,J.uvs[2].u,J.uvs[2].v);else if(P.env_map){if(P.env_map.image.loaded)if(P.env_map.mapping instanceof THREE.SphericalReflectionMapping){F=sa.matrix;H.copy(J.vertexNormalsWorld[0]);V=(H.x*F.n11+H.y*F.n12+H.z*F.n13)*0.5+0.5;O=-(H.x*F.n21+H.y*F.n22+H.z*F.n23)*0.5+0.5;H.copy(J.vertexNormalsWorld[1]);ba=(H.x*F.n11+H.y*F.n12+H.z*F.n13)*0.5+0.5; -R=-(H.x*F.n21+H.y*F.n22+H.z*F.n23)*0.5+0.5;H.copy(J.vertexNormalsWorld[2]);L=(H.x*F.n11+H.y*F.n12+H.z*F.n13)*0.5+0.5;N=-(H.x*F.n21+H.y*F.n22+H.z*F.n23)*0.5+0.5;xa(k,q,s,n,m,x,P.env_map.image,V,O,ba,R,L,N)}}else P.wireframe?Ba(P.color.__styleString,P.wireframe_linewidth):Ca(P.color.__styleString);else if(P instanceof THREE.MeshLambertMaterial){if(P.map&&!P.wireframe){P.map.mapping instanceof THREE.UVMapping&&xa(k,q,s,n,m,x,P.map.image,J.uvs[0].u,J.uvs[0].v,J.uvs[1].u,J.uvs[1].v,J.uvs[2].u,J.uvs[2].v); -b(THREE.SubtractiveBlending)}if(S)if(!P.wireframe&&P.shading==THREE.SmoothShading&&J.vertexNormalsWorld.length==3){D.r=y.r=w.r=ha.r;D.g=y.g=w.g=ha.g;D.b=y.b=w.b=ha.b;Aa(ca,J.v1.positionWorld,J.vertexNormalsWorld[0],D);Aa(ca,J.v2.positionWorld,J.vertexNormalsWorld[1],y);Aa(ca,J.v3.positionWorld,J.vertexNormalsWorld[2],w);C.r=(y.r+w.r)*0.5;C.g=(y.g+w.g)*0.5;C.b=(y.b+w.b)*0.5;U=Ja(D,y,w,C);xa(k,q,s,n,m,x,U,0,0,1,0,0,1)}else{Y.r=ha.r;Y.g=ha.g;Y.b=ha.b;Aa(ca,J.centroidWorld,J.normalWorld,Y);t.r=P.color.r* -Y.r;t.g=P.color.g*Y.g;t.b=P.color.b*Y.b;t.updateStyleString();P.wireframe?Ba(t.__styleString,P.wireframe_linewidth):Ca(t.__styleString)}else P.wireframe?Ba(P.color.__styleString,P.wireframe_linewidth):Ca(P.color.__styleString)}else if(P instanceof THREE.MeshDepthMaterial){$=sa.near;M=sa.far;D.r=D.g=D.b=1-Ea(F.positionScreen.z,$,M);y.r=y.g=y.b=1-Ea(X.positionScreen.z,$,M);w.r=w.g=w.b=1-Ea(T.positionScreen.z,$,M);C.r=(y.r+w.r)*0.5;C.g=(y.g+w.g)*0.5;C.b=(y.b+w.b)*0.5;U=Ja(D,y,w,C);xa(k,q,s,n,m,x,U,0, -0,1,0,0,1)}else if(P instanceof THREE.MeshNormalMaterial){t.r=Fa(J.normalWorld.x);t.g=Fa(J.normalWorld.y);t.b=Fa(J.normalWorld.z);t.updateStyleString();P.wireframe?Ba(t.__styleString,P.wireframe_linewidth):Ca(t.__styleString)}}}function Ba(F,X){if(z!=F)l.strokeStyle=z=F;if(K!=X)l.lineWidth=K=X;l.stroke();I.inflate(X*2)}function Ca(F){if(A!=F)l.fillStyle=A=F;l.fill()}function xa(F,X,T,J,P,ca,fa,ia,la,oa,ma,pa,ya){var ua,qa;ua=fa.width-1;qa=fa.height-1;ia*=ua;la*=qa;oa*=ua;ma*=qa;pa*=ua;ya*=qa;T-=F; -J-=X;P-=F;ca-=X;oa-=ia;ma-=la;pa-=ia;ya-=la;qa=1/(oa*ya-pa*ma);ua=(ya*T-ma*P)*qa;ma=(ya*J-ma*ca)*qa;T=(oa*P-pa*T)*qa;J=(oa*ca-pa*J)*qa;F=F-ua*ia-T*la;X=X-ma*ia-J*la;l.save();l.transform(ua,ma,T,J,F,X);l.clip();l.drawImage(fa,0,0);l.restore()}function Ja(F,X,T,J){var P=~~(F.r*255),ca=~~(F.g*255);F=~~(F.b*255);var fa=~~(X.r*255),ia=~~(X.g*255);X=~~(X.b*255);var la=~~(T.r*255),oa=~~(T.g*255);T=~~(T.b*255);var ma=~~(J.r*255),pa=~~(J.g*255);J=~~(J.b*255);ea[0]=P<0?0:P>255?255:P;ea[1]=ca<0?0:ca>255?255: -ca;ea[2]=F<0?0:F>255?255:F;ea[4]=fa<0?0:fa>255?255:fa;ea[5]=ia<0?0:ia>255?255:ia;ea[6]=X<0?0:X>255?255:X;ea[8]=la<0?0:la>255?255:la;ea[9]=oa<0?0:oa>255?255:oa;ea[10]=T<0?0:T>255?255:T;ea[12]=ma<0?0:ma>255?255:ma;ea[13]=pa<0?0:pa>255?255:pa;ea[14]=J<0?0:J>255?255:J;aa.putImageData(ka,0,0);ta.drawImage(Q,0,0);return ra}function Ea(F,X,T){F=(F-X)/(T-X);return F*F*(3-2*F)}function Fa(F){F=(F+1)*0.5;return F<0?0:F>1?1:F}function Ga(F,X){var T=X.x-F.x,J=X.y-F.y,P=1/Math.sqrt(T*T+J*J);T*=P;J*=P;X.x+=T;X.y+= -J;F.x-=T;F.y-=J}var Da,Ka,da,na,wa,Ha,La,za;l.setTransform(1,0,0,-1,c,i);this.autoClear&&this.clear();f=e.projectScene(ga,sa,this.sortElements);(S=ga.lights.length>0)&&Ma(ga);Da=0;for(Ka=f.length;Da0){ba.r+=N.color.r*Z;ba.g+=N.color.g*Z;ba.b+=N.color.b*Z}}else if(N instanceof THREE.PointLight){x.sub(N.position,O.centroidWorld);x.normalize();Z=O.normalWorld.dot(x)*N.intensity;if(Z>0){ba.r+=N.color.r*Z;ba.g+=N.color.g*Z;ba.b+=N.color.b*Z}}}}function b(V,O,ba,R,L,N){w=e(C++);w.setAttribute("d","M "+ -V.positionScreen.x+" "+V.positionScreen.y+" L "+O.positionScreen.x+" "+O.positionScreen.y+" L "+ba.positionScreen.x+","+ba.positionScreen.y+"z");if(L instanceof THREE.MeshBasicMaterial)d.__styleString=L.color.__styleString;else if(L instanceof THREE.MeshLambertMaterial)if(E){k.r=q.r;k.g=q.g;k.b=q.b;a(N,R,k);d.r=L.color.r*k.r;d.g=L.color.g*k.g;d.b=L.color.b*k.b;d.updateStyleString()}else d.__styleString=L.color.__styleString;else if(L instanceof THREE.MeshDepthMaterial){m=1-L.__2near/(L.__farPlusNear- -R.z*L.__farMinusNear);d.setRGB(m,m,m)}else L instanceof THREE.MeshNormalMaterial&&d.setRGB(g(R.normalWorld.x),g(R.normalWorld.y),g(R.normalWorld.z));L.wireframe?w.setAttribute("style","fill: none; stroke: "+d.__styleString+"; stroke-width: "+L.wireframe_linewidth+"; stroke-opacity: "+L.opacity+"; stroke-linecap: "+L.wireframe_linecap+"; stroke-linejoin: "+L.wireframe_linejoin):w.setAttribute("style","fill: "+d.__styleString+"; fill-opacity: "+L.opacity);c.appendChild(w)}function f(V,O,ba,R,L,N,Z){w= -e(C++);w.setAttribute("d","M "+V.positionScreen.x+" "+V.positionScreen.y+" L "+O.positionScreen.x+" "+O.positionScreen.y+" L "+ba.positionScreen.x+","+ba.positionScreen.y+" L "+R.positionScreen.x+","+R.positionScreen.y+"z");if(N instanceof THREE.MeshBasicMaterial)d.__styleString=N.color.__styleString;else if(N instanceof THREE.MeshLambertMaterial)if(E){k.r=q.r;k.g=q.g;k.b=q.b;a(Z,L,k);d.r=N.color.r*k.r;d.g=N.color.g*k.g;d.b=N.color.b*k.b;d.updateStyleString()}else d.__styleString=N.color.__styleString; -else if(N instanceof THREE.MeshDepthMaterial){m=1-N.__2near/(N.__farPlusNear-L.z*N.__farMinusNear);d.setRGB(m,m,m)}else N instanceof THREE.MeshNormalMaterial&&d.setRGB(g(L.normalWorld.x),g(L.normalWorld.y),g(L.normalWorld.z));N.wireframe?w.setAttribute("style","fill: none; stroke: "+d.__styleString+"; stroke-width: "+N.wireframe_linewidth+"; stroke-opacity: "+N.opacity+"; stroke-linecap: "+N.wireframe_linecap+"; stroke-linejoin: "+N.wireframe_linejoin):w.setAttribute("style","fill: "+d.__styleString+ -"; fill-opacity: "+N.opacity);c.appendChild(w)}function e(V){if(t[V]==null){t[V]=document.createElementNS("http://www.w3.org/2000/svg","path");U==0&&t[V].setAttribute("shape-rendering","crispEdges");return t[V]}return t[V]}function g(V){return V<0?Math.min((1+V)*0.5,0.5):0.5+Math.min(V*0.5,0.5)}var h=null,j=new THREE.Projector,c=document.createElementNS("http://www.w3.org/2000/svg","svg"),i,l,r,B,o,v,z,A,K=new THREE.Rectangle,p=new THREE.Rectangle,E=false,d=new THREE.Color(16777215),k=new THREE.Color(16777215), -q=new THREE.Color(0),s=new THREE.Color(0),n=new THREE.Color(0),m,x=new THREE.Vector3,t=[],D=[],y=[],w,C,$,M,U=1;this.domElement=c;this.sortElements=this.sortObjects=this.autoClear=true;this.setQuality=function(V){switch(V){case "high":U=1;break;case "low":U=0}};this.setSize=function(V,O){i=V;l=O;r=i/2;B=l/2;c.setAttribute("viewBox",-r+" "+-B+" "+i+" "+l);c.setAttribute("width",i);c.setAttribute("height",l);K.set(-r,-B,r,B)};this.clear=function(){for(;c.childNodes.length>0;)c.removeChild(c.childNodes[0])}; -this.render=function(V,O){var ba,R,L,N,Z,W,I,S;this.autoClear&&this.clear();h=j.projectScene(V,O,this.sortElements);M=$=C=0;if(E=V.lights.length>0){I=V.lights;q.setRGB(0,0,0);s.setRGB(0,0,0);n.setRGB(0,0,0);ba=0;for(R=I.length;ba0){L.__webGLUVBuffer=c.createBuffer();c.bindBuffer(c.ARRAY_BUFFER,L.__webGLUVBuffer);c.bufferData(c.ARRAY_BUFFER,new Float32Array(ba),c.STATIC_DRAW)}L.__webGLFaceBuffer=c.createBuffer(); -c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,L.__webGLFaceBuffer);c.bufferData(c.ELEMENT_ARRAY_BUFFER,new Uint16Array($),c.STATIC_DRAW);L.__webGLLineBuffer=c.createBuffer();c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,L.__webGLLineBuffer);c.bufferData(c.ELEMENT_ARRAY_BUFFER,new Uint16Array(M),c.STATIC_DRAW);L.__webGLFaceCount=$.length;L.__webGLLineCount=M.length}};this.renderBuffer=function(d,k,q,s,n){var m,x,t,D;if(!s.program){if(s instanceof THREE.MeshDepthMaterial){b(s,THREE.ShaderLib.depth);s.uniforms.mNear.value= -d.near;s.uniforms.mFar.value=d.far}else if(s instanceof THREE.MeshNormalMaterial)b(s,THREE.ShaderLib.normal);else if(s instanceof THREE.MeshBasicMaterial){b(s,THREE.ShaderLib.basic);f(s,q)}else if(s instanceof THREE.MeshLambertMaterial){b(s,THREE.ShaderLib.lambert);f(s,q)}else if(s instanceof THREE.MeshPhongMaterial){b(s,THREE.ShaderLib.phong);f(s,q)}else if(s instanceof THREE.LineBasicMaterial){b(s,THREE.ShaderLib.basic);e(s,q)}var y,w,C;y=D=x=0;for(w=k.length;y0?"#define VERTEX_TEXTURES":"","#define MAX_DIR_LIGHTS "+D.maxDirLights,"#define MAX_POINT_LIGHTS "+D.maxPointLights,D.map?"#define USE_MAP":"",D.env_map?"#define USE_ENVMAP":"","uniform mat4 objectMatrix;\nuniform mat4 modelViewMatrix;\nuniform mat4 projectionMatrix;\nuniform mat4 viewMatrix;\nuniform mat3 normalMatrix;\nuniform vec3 cameraPosition;\nattribute vec3 position;\nattribute vec3 normal;\nattribute vec2 uv;\n"].join("\n"); -c.attachShader(w,g("fragment",C+x));c.attachShader(w,g("vertex",D+y));c.linkProgram(w);c.getProgramParameter(w,c.LINK_STATUS)||alert("Could not initialise shaders\nVALIDATE_STATUS: "+c.getProgramParameter(w,c.VALIDATE_STATUS)+", gl error ["+c.getError()+"]");w.uniforms={};w.attributes={};s.program=w;x=["viewMatrix","modelViewMatrix","projectionMatrix","normalMatrix","objectMatrix","cameraPosition"];for(m in s.uniforms)x.push(m);m=s.program;y=0;for(w=x.length;y=0){c.bindBuffer(c.ARRAY_BUFFER,n.__webGLNormalBuffer); -c.vertexAttribPointer(t.normal,3,c.FLOAT,false,0,0);c.enableVertexAttribArray(t.normal)}if(t.tangent>=0){c.bindBuffer(c.ARRAY_BUFFER,n.__webGLTangentBuffer);c.vertexAttribPointer(t.tangent,4,c.FLOAT,false,0,0);c.enableVertexAttribArray(t.tangent)}if(t.uv>=0)if(n.__webGLUVBuffer){c.bindBuffer(c.ARRAY_BUFFER,n.__webGLUVBuffer);c.vertexAttribPointer(t.uv,2,c.FLOAT,false,0,0);c.enableVertexAttribArray(t.uv)}else c.disableVertexAttribArray(t.uv);if(s.wireframe||s instanceof THREE.LineBasicMaterial){t= -s.wireframe_linewidth!==undefined?s.wireframe_linewidth:s.linewidth!==undefined?s.linewidth:1;s=s instanceof THREE.LineBasicMaterial&&n.type==THREE.LineStrip?c.LINE_STRIP:c.LINES;c.lineWidth(t);c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,n.__webGLLineBuffer);c.drawElements(s,n.__webGLLineCount,c.UNSIGNED_SHORT,0)}else{c.bindBuffer(c.ELEMENT_ARRAY_BUFFER,n.__webGLFaceBuffer);c.drawElements(c.TRIANGLES,n.__webGLFaceCount,c.UNSIGNED_SHORT,0)}};this.renderPass=function(d,k,q,s,n,m,x){var t,D,y,w,C;y=0;for(w= -s.materials.length;y=0;q--){s=d.__webGLObjects[q].object;k==s&&d.__webGLObjects.splice(q,1)}};this.setupMatrices=function(d,k){d.autoUpdateMatrix&&d.updateMatrix(); -l.multiply(k.matrix,d.matrix);o.set(l.flatten());r=THREE.Matrix4.makeInvert3x3(l).transpose();z.set(r.m);A.set(d.matrix.flatten())};this.loadMatrices=function(d){c.uniformMatrix4fv(d.uniforms.viewMatrix,false,B);c.uniformMatrix4fv(d.uniforms.modelViewMatrix,false,o);c.uniformMatrix4fv(d.uniforms.projectionMatrix,false,v);c.uniformMatrix3fv(d.uniforms.normalMatrix,false,z);c.uniformMatrix4fv(d.uniforms.objectMatrix,false,A)};this.loadCamera=function(d,k){c.uniform3f(d.uniforms.cameraPosition,k.position.x, -k.position.y,k.position.z)};this.setBlending=function(d){switch(d){case THREE.AdditiveBlending:c.blendEquation(c.FUNC_ADD);c.blendFunc(c.ONE,c.ONE);break;case THREE.SubtractiveBlending:c.blendFunc(c.DST_COLOR,c.ZERO);break;default:c.blendEquation(c.FUNC_ADD);c.blendFunc(c.ONE,c.ONE_MINUS_SRC_ALPHA)}};this.setFaceCulling=function(d,k){if(d){!k||k=="ccw"?c.frontFace(c.CCW):c.frontFace(c.CW);if(d=="back")c.cullFace(c.BACK);else d=="front"?c.cullFace(c.FRONT):c.cullFace(c.FRONT_AND_BACK);c.enable(c.CULL_FACE)}else c.disable(c.CULL_FACE)}; -this.supportsVertexTextures=function(){return c.getParameter(c.MAX_VERTEX_TEXTURE_IMAGE_UNITS)>0}}; -THREE.Snippets={fog_pars_fragment:"#ifdef USE_FOG\nuniform vec3 fogColor;\n#ifdef FOG_EXP2\nuniform float fogDensity;\n#else\nuniform float fogNear;\nuniform float fogFar;\n#endif\n#endif",fog_fragment:"#ifdef USE_FOG\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\n#ifdef FOG_EXP2\nconst float LOG2 = 1.442695;\nfloat fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );\nfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );\n#else\nfloat fogFactor = smoothstep( fogNear, fogFar, depth );\n#endif\ngl_FragColor = mix( gl_FragColor, vec4( fogColor, 1.0 ), fogFactor );\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\nvarying vec3 vReflect;\nuniform float reflectivity;\nuniform samplerCube env_map;\nuniform int combine;\n#endif", -envmap_fragment:"#ifdef USE_ENVMAP\ncubeColor = textureCube( env_map, vec3( -vReflect.x, vReflect.yz ) );\nif ( combine == 1 ) {\ngl_FragColor = mix( gl_FragColor, cubeColor, reflectivity );\n} else {\ngl_FragColor = gl_FragColor * cubeColor;\n}\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\nvarying vec3 vReflect;\nuniform float refraction_ratio;\nuniform bool useRefract;\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvec3 nWorld = mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal;\nif ( useRefract ) {\nvReflect = refract( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ), refraction_ratio );\n} else {\nvReflect = reflect( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ) );\n}\n#endif", -map_pars_fragment:"#ifdef USE_MAP\nvarying vec2 vUv;\nuniform sampler2D map;\n#endif",map_pars_vertex:"#ifdef USE_MAP\nvarying vec2 vUv;\n#endif",map_fragment:"#ifdef USE_MAP\nmapColor = texture2D( map, vUv );\n#endif",map_vertex:"#ifdef USE_MAP\nvUv = uv;\n#endif",lights_pars_vertex:"uniform bool enableLighting;\nuniform vec3 ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nuniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];\nuniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];\n#ifdef PHONG\nvarying vec3 vPointLightVector[ MAX_POINT_LIGHTS ];\n#endif\n#endif", -lights_vertex:"if ( !enableLighting ) {\nvLightWeighting = vec3( 1.0 );\n} else {\nvLightWeighting = ambientLightColor;\n#if MAX_DIR_LIGHTS > 0\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nfloat directionalLightWeighting = max( dot( transformedNormal, normalize( lDirection.xyz ) ), 0.0 );\nvLightWeighting += directionalLightColor[ i ] * directionalLightWeighting;\n}\n#endif\n#if MAX_POINT_LIGHTS > 0\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );\nvec3 pointLightVector = normalize( lPosition.xyz - mvPosition.xyz );\nfloat pointLightWeighting = max( dot( transformedNormal, pointLightVector ), 0.0 );\nvLightWeighting += pointLightColor[ i ] * pointLightWeighting;\n#ifdef PHONG\nvPointLightVector[ i ] = pointLightVector;\n#endif\n}\n#endif\n}", -lights_pars_fragment:"#if MAX_DIR_LIGHTS > 0\nuniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];\n#endif\n#if MAX_POINT_LIGHTS > 0\nvarying vec3 vPointLightVector[ MAX_POINT_LIGHTS ];\n#endif\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;",lights_fragment:"vec3 normal = normalize( vNormal );\nvec3 viewPosition = normalize( vViewPosition );\nvec4 mSpecular = vec4( specular, opacity );\n#if MAX_POINT_LIGHTS > 0\nvec4 pointDiffuse = vec4( 0.0 );\nvec4 pointSpecular = vec4( 0.0 );\nfor( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {\nvec3 pointVector = normalize( vPointLightVector[ i ] );\nvec3 pointHalfVector = normalize( vPointLightVector[ i ] + vViewPosition );\nfloat pointDotNormalHalf = dot( normal, pointHalfVector );\nfloat pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );\nfloat pointSpecularWeight = 0.0;\nif ( pointDotNormalHalf >= 0.0 )\npointSpecularWeight = pow( pointDotNormalHalf, shininess );\npointDiffuse += mColor * pointDiffuseWeight;\npointSpecular += mSpecular * pointSpecularWeight;\n}\n#endif\n#if MAX_DIR_LIGHTS > 0\nvec4 dirDiffuse = vec4( 0.0 );\nvec4 dirSpecular = vec4( 0.0 );\nfor( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {\nvec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nvec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );\nfloat dirDotNormalHalf = dot( normal, dirHalfVector );\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\nfloat dirSpecularWeight = 0.0;\nif ( dirDotNormalHalf >= 0.0 )\ndirSpecularWeight = pow( dirDotNormalHalf, shininess );\ndirDiffuse += mColor * dirDiffuseWeight;\ndirSpecular += mSpecular * dirSpecularWeight;\n}\n#endif\nvec4 totalLight = vec4( ambient, opacity );\n#if MAX_DIR_LIGHTS > 0\ntotalLight += dirDiffuse + dirSpecular;\n#endif\n#if MAX_POINT_LIGHTS > 0\ntotalLight += pointDiffuse + pointSpecular;\n#endif"}; -THREE.UniformsLib={common:{color:{type:"c",value:new THREE.Color(15658734)},opacity:{type:"f",value:1},map:{type:"t",value:0,texture:null},env_map:{type:"t",value:1,texture:null},useRefract:{type:"i",value:0},reflectivity:{type:"f",value:1},refraction_ratio:{type:"f",value:0.98},combine:{type:"i",value:0},fogDensity:{type:"f",value:2.5E-4},fogNear:{type:"f",value:1},fogFar:{type:"f",value:2E3},fogColor:{type:"c",value:new THREE.Color(16777215)}},lights:{enableLighting:{type:"i",value:1},ambientLightColor:{type:"fv", -value:[]},directionalLightDirection:{type:"fv",value:[]},directionalLightColor:{type:"fv",value:[]},pointLightPosition:{type:"fv",value:[]},pointLightColor:{type:"fv",value:[]}}}; -THREE.ShaderLib={depth:{uniforms:{mNear:{type:"f",value:1},mFar:{type:"f",value:2E3}},fragment_shader:"uniform float mNear;\nuniform float mFar;\nvoid main() {\nfloat depth = gl_FragCoord.z / gl_FragCoord.w;\nfloat color = 1.0 - smoothstep( mNear, mFar, depth );\ngl_FragColor = vec4( vec3( color ), 1.0 );\n}",vertex_shader:"void main() {\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"},normal:{uniforms:{},fragment_shader:"varying vec3 vNormal;\nvoid main() {\ngl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, 1.0 );\n}", -vertex_shader:"varying vec3 vNormal;\nvoid main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvNormal = normalize( normalMatrix * normal );\ngl_Position = projectionMatrix * mvPosition;\n}"},basic:{uniforms:THREE.UniformsLib.common,fragment_shader:["uniform vec3 color;\nuniform float opacity;",THREE.Snippets.map_pars_fragment,THREE.Snippets.envmap_pars_fragment,THREE.Snippets.fog_pars_fragment,"void main() {\nvec4 mColor = vec4( color, opacity );\nvec4 mapColor = vec4( 1.0 );\nvec4 cubeColor = vec4( 1.0 );", -THREE.Snippets.map_fragment,"gl_FragColor = mColor * mapColor;",THREE.Snippets.envmap_fragment,THREE.Snippets.fog_fragment,"}"].join("\n"),vertex_shader:[THREE.Snippets.map_pars_vertex,THREE.Snippets.envmap_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",THREE.Snippets.map_vertex,THREE.Snippets.envmap_vertex,"gl_Position = projectionMatrix * mvPosition;\n}"].join("\n")},lambert:{uniforms:Uniforms.merge([THREE.UniformsLib.common,THREE.UniformsLib.lights]),fragment_shader:["uniform vec3 color;\nuniform float opacity;\nvarying vec3 vLightWeighting;", -THREE.Snippets.map_pars_fragment,THREE.Snippets.envmap_pars_fragment,THREE.Snippets.fog_pars_fragment,"void main() {\nvec4 mColor = vec4( color, opacity );\nvec4 mapColor = vec4( 1.0 );\nvec4 cubeColor = vec4( 1.0 );",THREE.Snippets.map_fragment,"gl_FragColor = mColor * mapColor * vec4( vLightWeighting, 1.0 );",THREE.Snippets.envmap_fragment,THREE.Snippets.fog_fragment,"}"].join("\n"),vertex_shader:["varying vec3 vLightWeighting;",THREE.Snippets.map_pars_vertex,THREE.Snippets.envmap_pars_vertex, -THREE.Snippets.lights_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",THREE.Snippets.map_vertex,THREE.Snippets.envmap_vertex,"vec3 transformedNormal = normalize( normalMatrix * normal );",THREE.Snippets.lights_vertex,"gl_Position = projectionMatrix * mvPosition;\n}"].join("\n")},phong:{uniforms:Uniforms.merge([THREE.UniformsLib.common,THREE.UniformsLib.lights,{ambient:{type:"c",value:new THREE.Color(328965)},specular:{type:"c",value:new THREE.Color(1118481)}, -shininess:{type:"f",value:30}}]),fragment_shader:["uniform vec3 color;\nuniform float opacity;\nuniform vec3 ambient;\nuniform vec3 specular;\nuniform float shininess;\nvarying vec3 vLightWeighting;",THREE.Snippets.map_pars_fragment,THREE.Snippets.envmap_pars_fragment,THREE.Snippets.fog_pars_fragment,THREE.Snippets.lights_pars_fragment,"void main() {\nvec4 mColor = vec4( color, opacity );\nvec4 mapColor = vec4( 1.0 );\nvec4 cubeColor = vec4( 1.0 );",THREE.Snippets.map_fragment,THREE.Snippets.lights_fragment, -"gl_FragColor = mapColor * totalLight * vec4( vLightWeighting, 1.0 );",THREE.Snippets.envmap_fragment,THREE.Snippets.fog_fragment,"}"].join("\n"),vertex_shader:["#define PHONG\nvarying vec3 vLightWeighting;\nvarying vec3 vViewPosition;\nvarying vec3 vNormal;",THREE.Snippets.map_pars_vertex,THREE.Snippets.envmap_pars_vertex,THREE.Snippets.lights_pars_vertex,"void main() {\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",THREE.Snippets.map_vertex,THREE.Snippets.envmap_vertex,"#ifndef USE_ENVMAP\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\n#endif\nvViewPosition = cameraPosition - mPosition.xyz;\nvec3 transformedNormal = normalize( normalMatrix * normal );\nvNormal = transformedNormal;", -THREE.Snippets.lights_vertex,"gl_Position = projectionMatrix * mvPosition;\n}"].join("\n")}};THREE.RenderableObject=function(){this.z=this.object=null};THREE.RenderableFace3=function(){this.z=null;this.v1=new THREE.Vertex;this.v2=new THREE.Vertex;this.v3=new THREE.Vertex;this.centroidWorld=new THREE.Vector3;this.centroidScreen=new THREE.Vector3;this.normalWorld=new THREE.Vector3;this.vertexNormalsWorld=[];this.faceMaterials=this.meshMaterials=null;this.overdraw=false;this.uvs=[null,null,null]}; -THREE.RenderableParticle=function(){this.rotation=this.z=this.y=this.x=null;this.scale=new THREE.Vector2;this.materials=null};THREE.RenderableLine=function(){this.z=null;this.v1=new THREE.Vertex;this.v2=new THREE.Vertex;this.materials=null}; -var GeometryUtils={merge:function(a,b){var f=b instanceof THREE.Mesh,e=a.vertices.length,g=f?b.geometry:b,h=a.vertices,j=g.vertices,c=a.faces,i=g.faces,l=a.uvs;g=g.uvs;f&&b.updateMatrix();for(var r=0,B=j.length;r= 0.0 )\npointSpecularWeight = pow( pointDotNormalHalf, uShininess );\npointDiffuse += vec4( uDiffuseColor, 1.0 ) * pointDiffuseWeight;\npointSpecular += vec4( uSpecularColor, 1.0 ) * pointSpecularWeight;\nvec4 dirDiffuse = vec4( 0.0, 0.0, 0.0, 0.0 );\nvec4 dirSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );\nvec4 lDirection = viewMatrix * vec4( uDirLightPos, 0.0 );\nvec3 dirVector = normalize( lDirection.xyz );\nvec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );\nfloat dirDotNormalHalf = dot( normal, dirHalfVector );\nfloat dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );\nfloat dirSpecularWeight = 0.0;\nif ( dirDotNormalHalf >= 0.0 )\ndirSpecularWeight = pow( dirDotNormalHalf, uShininess );\ndirDiffuse += vec4( uDiffuseColor, 1.0 ) * dirDiffuseWeight;\ndirSpecular += vec4( uSpecularColor, 1.0 ) * dirSpecularWeight;\nvec4 totalLight = vec4( uAmbientLightColor * uAmbientColor, 1.0 );\ntotalLight += vec4( uDirLightColor, 1.0 ) * ( dirDiffuse + dirSpecular );\ntotalLight += vec4( uPointLightColor, 1.0 ) * ( pointDiffuse + pointSpecular );\ngl_FragColor = vec4( totalLight.xyz * aoTex * diffuseTex, 1.0 );\n}", -vertex_shader:"attribute vec4 tangent;\nuniform vec3 uPointLightPos;\n#ifdef VERTEX_TEXTURES\nuniform sampler2D tDisplacement;\nuniform float uDisplacementScale;\nuniform float uDisplacementBias;\n#endif\nvarying vec3 vTangent;\nvarying vec3 vBinormal;\nvarying vec3 vNormal;\nvarying vec2 vUv;\nvarying vec3 vPointLightVector;\nvarying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\nvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\nvNormal = normalize( normalMatrix * normal );\nvTangent = normalize( normalMatrix * tangent.xyz );\nvBinormal = cross( vNormal, vTangent ) * tangent.w;\nvBinormal = normalize( vBinormal );\nvUv = uv;\nvec4 lPosition = viewMatrix * vec4( uPointLightPos, 1.0 );\nvPointLightVector = normalize( lPosition.xyz - mvPosition.xyz );\n#ifdef VERTEX_TEXTURES\nvec3 dv = texture2D( tDisplacement, uv ).xyz;\nfloat df = uDisplacementScale * dv.x + uDisplacementBias;\nvec4 displacedPosition = vec4( vNormal.xyz * df, 0.0 ) + mvPosition;\ngl_Position = projectionMatrix * displacedPosition;\n#else\ngl_Position = projectionMatrix * mvPosition;\n#endif\n}"}, -basic:{uniforms:{},vertex_shader:"void main() {\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}",fragment_shader:"void main() {\ngl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);\n}"},cube:{uniforms:{tCube:{type:"t",value:1,texture:null}},vertex_shader:"varying vec3 vViewPosition;\nvoid main() {\nvec4 mPosition = objectMatrix * vec4( position, 1.0 );\nvViewPosition = cameraPosition - mPosition.xyz;\ngl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}", -fragment_shader:"uniform samplerCube tCube;\nvarying vec3 vViewPosition;\nvoid main() {\nvec3 wPos = cameraPosition - vViewPosition;\ngl_FragColor = textureCube( tCube, vec3( - wPos.x, wPos.yz ) );\n}"}}},Cube=function(a,b,f,e,g,h,j,c){function i(A,K,p,E,d,k,q,s){var n,m,x=e||1,t=g||1,D=x+1,y=t+1,w=d/2,C=k/2;d=d/x;var $=k/t,M=l.vertices.length;if(A=="x"&&K=="y"||A=="y"&&K=="x")n="z";else if(A=="x"&&K=="z"||A=="z"&&K=="x")n="y";else if(A=="z"&&K=="y"||A=="y"&&K=="z")n="x";for(m=0;m0||(r=this.vertices.push(new THREE.Vertex(new THREE.Vector3(B,c,o)))-1);l.push(r)}b.push(l)}var v,z,A;g=b.length;for(f=0;f0)for(e=0;e1){v=this.vertices[j].position.clone(); -z=this.vertices[i].position.clone();A=this.vertices[l].position.clone();v.normalize();z.normalize();A.normalize();this.faces.push(new THREE.Face3(j,i,l,[new THREE.Vector3(v.x,v.y,v.z),new THREE.Vector3(z.x,z.y,z.z),new THREE.Vector3(A.x,A.y,A.z)]));this.uvs.push([r,B,K])}}}this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals();this.sortFacesByMaterial();this.boundingSphere={radius:a}};Sphere.prototype=new THREE.Geometry;Sphere.prototype.constructor=Sphere; -THREE.Loader=function(a){this.statusDomElement=(this.showStatus=a)?this.addStatusElement():null}; -THREE.Loader.prototype={addStatusElement:function(){var a=document.createElement("div");a.style.fontSize="0.8em";a.style.textAlign="left";a.style.background="#b00";a.style.color="#fff";a.style.width="140px";a.style.padding="0.25em 0.25em 0.25em 0.5em";a.style.position="absolute";a.style.right="0px";a.style.top="0px";a.style.zIndex=1E3;a.innerHTML="Loading ...";return a},updateProgress:function(a){var b="Loaded ";b+=a.total?(100*a.loaded/a.total).toFixed(0)+"%":(a.loaded/1E3).toFixed(2)+" KB";this.statusDomElement.innerHTML= -b},loadAsciiOld:function(a,b){var f=document.createElement("script");f.type="text/javascript";f.onload=b;f.src=a;document.getElementsByTagName("head")[0].appendChild(f)},loadAscii:function(a){var b=a.model,f=a.callback,e=a.texture_path?a.texture_path:THREE.Loader.prototype.extractUrlbase(b);a=(new Date).getTime();b=new Worker(b);b.onmessage=function(g){THREE.Loader.prototype.createModel(g.data,f,e)};b.postMessage(a)},loadBinary:function(a){var b=a.model,f=a.callback,e=a.texture_path?a.texture_path: -THREE.Loader.prototype.extractUrlbase(b),g=a.bin_path?a.bin_path:THREE.Loader.prototype.extractUrlbase(b);a=(new Date).getTime();b=new Worker(b);var h=this.showProgress?THREE.Loader.prototype.updateProgress:null;b.onmessage=function(j){THREE.Loader.prototype.loadAjaxBuffers(j.data.buffers,j.data.materials,f,g,e,h)};b.onerror=function(j){alert("worker.onerror: "+j.message+"\n"+j.data);j.preventDefault()};b.postMessage(a)},loadAjaxBuffers:function(a,b,f,e,g,h){var j=new XMLHttpRequest,c=e+"/"+a,i=0; -j.onreadystatechange=function(){if(j.readyState==4)j.status==200||j.status==0?THREE.Loader.prototype.createBinModel(j.responseText,f,g,b):alert("Couldn't load ["+c+"] ["+j.status+"]");else if(j.readyState==3){if(h){if(i==0)i=j.getResponseHeader("Content-Length");h({total:i,loaded:j.responseText.length})}}else if(j.readyState==2)i=j.getResponseHeader("Content-Length")};j.open("GET",c,true);j.overrideMimeType("text/plain; charset=x-user-defined");j.setRequestHeader("Content-Type","text/plain");j.send(null)}, -createBinModel:function(a,b,f,e){var g=function(h){function j(u,G){var H=r(u,G),Q=r(u,G+1),aa=r(u,G+2),ka=r(u,G+3),ea=(ka<<1&255|aa>>7)-127;H=(aa&127)<<16|Q<<8|H;if(H==0&&ea==-127)return 0;return(1-2*(ka>>7))*(1+H*Math.pow(2,-23))*Math.pow(2,ea)}function c(u,G){var H=r(u,G),Q=r(u,G+1),aa=r(u,G+2);return(r(u,G+3)<<24)+(aa<<16)+(Q<<8)+H}function i(u,G){var H=r(u,G);return(r(u,G+1)<<8)+H}function l(u,G){var H=r(u,G);return H>127?H-256:H}function r(u,G){return u.charCodeAt(G)&255}function B(u){var G, -H,Q;G=c(a,u);H=c(a,u+s);Q=c(a,u+n);u=i(a,u+m);THREE.Loader.prototype.f3(p,G,H,Q,u)}function o(u){var G,H,Q,aa,ka,ea;G=c(a,u);H=c(a,u+s);Q=c(a,u+n);aa=i(a,u+m);ka=c(a,u+x);ea=c(a,u+t);u=c(a,u+D);THREE.Loader.prototype.f3n(p,k,G,H,Q,aa,ka,ea,u)}function v(u){var G,H,Q,aa;G=c(a,u);H=c(a,u+y);Q=c(a,u+w);aa=c(a,u+C);u=i(a,u+$);THREE.Loader.prototype.f4(p,G,H,Q,aa,u)}function z(u){var G,H,Q,aa,ka,ea,ra,ta;G=c(a,u);H=c(a,u+y);Q=c(a,u+w);aa=c(a,u+C);ka=i(a,u+$);ea=c(a,u+M);ra=c(a,u+U);ta=c(a,u+V);u=c(a,u+ -O);THREE.Loader.prototype.f4n(p,k,G,H,Q,aa,ka,ea,ra,ta,u)}function A(u){var G,H;G=c(a,u);H=c(a,u+ba);u=c(a,u+R);THREE.Loader.prototype.uv3(p,q[G*2],q[G*2+1],q[H*2],q[H*2+1],q[u*2],q[u*2+1])}function K(u){var G,H,Q;G=c(a,u);H=c(a,u+L);Q=c(a,u+N);u=c(a,u+Z);THREE.Loader.prototype.uv4(p,q[G*2],q[G*2+1],q[H*2],q[H*2+1],q[Q*2],q[Q*2+1],q[u*2],q[u*2+1])}var p=this,E=0,d,k=[],q=[],s,n,m,x,t,D,y,w,C,$,M,U,V,O,ba,R,L,N,Z,W,I,S,Y,ha,ja;THREE.Geometry.call(this);THREE.Loader.prototype.init_materials(p,e,h); -d={signature:a.substr(E,8),header_bytes:r(a,E+8),vertex_coordinate_bytes:r(a,E+9),normal_coordinate_bytes:r(a,E+10),uv_coordinate_bytes:r(a,E+11),vertex_index_bytes:r(a,E+12),normal_index_bytes:r(a,E+13),uv_index_bytes:r(a,E+14),material_index_bytes:r(a,E+15),nvertices:c(a,E+16),nnormals:c(a,E+16+4),nuvs:c(a,E+16+8),ntri_flat:c(a,E+16+12),ntri_smooth:c(a,E+16+16),ntri_flat_uv:c(a,E+16+20),ntri_smooth_uv:c(a,E+16+24),nquad_flat:c(a,E+16+28),nquad_smooth:c(a,E+16+32),nquad_flat_uv:c(a,E+16+36),nquad_smooth_uv:c(a, -E+16+40)};E+=d.header_bytes;s=d.vertex_index_bytes;n=d.vertex_index_bytes*2;m=d.vertex_index_bytes*3;x=d.vertex_index_bytes*3+d.material_index_bytes;t=d.vertex_index_bytes*3+d.material_index_bytes+d.normal_index_bytes;D=d.vertex_index_bytes*3+d.material_index_bytes+d.normal_index_bytes*2;y=d.vertex_index_bytes;w=d.vertex_index_bytes*2;C=d.vertex_index_bytes*3;$=d.vertex_index_bytes*4;M=d.vertex_index_bytes*4+d.material_index_bytes;U=d.vertex_index_bytes*4+d.material_index_bytes+d.normal_index_bytes; -V=d.vertex_index_bytes*4+d.material_index_bytes+d.normal_index_bytes*2;O=d.vertex_index_bytes*4+d.material_index_bytes+d.normal_index_bytes*3;ba=d.uv_index_bytes;R=d.uv_index_bytes*2;L=d.uv_index_bytes;N=d.uv_index_bytes*2;Z=d.uv_index_bytes*3;h=d.vertex_index_bytes*3+d.material_index_bytes;ja=d.vertex_index_bytes*4+d.material_index_bytes;W=d.ntri_flat*h;I=d.ntri_smooth*(h+d.normal_index_bytes*3);S=d.ntri_flat_uv*(h+d.uv_index_bytes*3);Y=d.ntri_smooth_uv*(h+d.normal_index_bytes*3+d.uv_index_bytes* -3);ha=d.nquad_flat*ja;h=d.nquad_smooth*(ja+d.normal_index_bytes*4);ja=d.nquad_flat_uv*(ja+d.uv_index_bytes*4);E+=function(u){var G,H,Q,aa=d.vertex_coordinate_bytes*3,ka=u+d.nvertices*aa;for(u=u;u= 0.0 )", + "pointSpecularWeight = pow( pointDotNormalHalf, uShininess );", + + "pointDiffuse += vec4( uDiffuseColor, 1.0 ) * pointDiffuseWeight;", + "pointSpecular += vec4( uSpecularColor, 1.0 ) * pointSpecularWeight;", + + // directional light + + "vec4 dirDiffuse = vec4( 0.0, 0.0, 0.0, 0.0 );", + "vec4 dirSpecular = vec4( 0.0, 0.0, 0.0, 0.0 );", + + "vec4 lDirection = viewMatrix * vec4( uDirLightPos, 0.0 );", + + "vec3 dirVector = normalize( lDirection.xyz );", + "vec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );", + + "float dirDotNormalHalf = dot( normal, dirHalfVector );", + "float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );", + + "float dirSpecularWeight = 0.0;", + "if ( dirDotNormalHalf >= 0.0 )", + "dirSpecularWeight = pow( dirDotNormalHalf, uShininess );", + + "dirDiffuse += vec4( uDiffuseColor, 1.0 ) * dirDiffuseWeight;", + "dirSpecular += vec4( uSpecularColor, 1.0 ) * dirSpecularWeight;", + + // all lights contribution summation + + "vec4 totalLight = vec4( uAmbientLightColor * uAmbientColor, 1.0 );", + "totalLight += vec4( uDirLightColor, 1.0 ) * ( dirDiffuse + dirSpecular );", + "totalLight += vec4( uPointLightColor, 1.0 ) * ( pointDiffuse + pointSpecular );", + + "gl_FragColor = vec4( totalLight.xyz * aoTex * diffuseTex, 1.0 );", + + "}" + ].join("\n"), + + vertex_shader: [ + + "attribute vec4 tangent;", + + "uniform vec3 uPointLightPos;", + + "#ifdef VERTEX_TEXTURES", + + "uniform sampler2D tDisplacement;", + "uniform float uDisplacementScale;", + "uniform float uDisplacementBias;", + + "#endif", + + "varying vec3 vTangent;", + "varying vec3 vBinormal;", + "varying vec3 vNormal;", + "varying vec2 vUv;", + + "varying vec3 vPointLightVector;", + "varying vec3 vViewPosition;", + + "void main() {", + + "vec4 mPosition = objectMatrix * vec4( position, 1.0 );", + "vViewPosition = cameraPosition - mPosition.xyz;", + + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + "vNormal = normalize( normalMatrix * normal );", + + // tangent and binormal vectors + + "vTangent = normalize( normalMatrix * tangent.xyz );", + + "vBinormal = cross( vNormal, vTangent ) * tangent.w;", + "vBinormal = normalize( vBinormal );", + + "vUv = uv;", + + // point light + + "vec4 lPosition = viewMatrix * vec4( uPointLightPos, 1.0 );", + "vPointLightVector = normalize( lPosition.xyz - mvPosition.xyz );", + + // displacement mapping + + "#ifdef VERTEX_TEXTURES", + + "vec3 dv = texture2D( tDisplacement, uv ).xyz;", + "float df = uDisplacementScale * dv.x + uDisplacementBias;", + "vec4 displacedPosition = vec4( vNormal.xyz * df, 0.0 ) + mvPosition;", + "gl_Position = projectionMatrix * displacedPosition;", + + "#else", + + "gl_Position = projectionMatrix * mvPosition;", + + "#endif", + + "}" + + ].join("\n") + + }, + /* + 'hatching' : { + + uniforms: { + + "uSampler": { type: "t", value: 2, texture: null }, + + "uDirLightPos": { type: "v3", value: new THREE.Vector3() }, + "uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) }, + + "uAmbientLightColor": { type: "c", value: new THREE.Color( 0x050505 ) } + + }, + + vertex_shader: [ + + "varying vec3 vNormal;", + + "void main() {", + + "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", + "vNormal = normalize( normalMatrix * normal );", + + "}" + + ].join("\n"), + + fragment_shader: [ + + "uniform vec3 uDirLightPos;", + "uniform vec3 uDirLightColor;", + + "uniform vec3 uAmbientLightColor;", + + "uniform sampler2D uSampler;", + + "varying vec3 vNormal;", + + "void main() {", + + "float directionalLightWeighting = max(dot(normalize(vNormal), uDirLightPos), 0.0);", + "vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;", + + "gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);", + + "if (length(lightWeighting) < 1.00) {", + + "if (mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {", + + "gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + + "}", + + "}", + + "if (length(lightWeighting) < 0.75) {", + + "if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {", + + "gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + + "}", + "}", + + "if (length(lightWeighting) < 0.50) {", + + "if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {", + + "gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + + "}", + "}", + + "if (length(lightWeighting) < 0.3465) {", + + "if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {", + + "gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);", + + "}", + "}", + + "}" + + ].join("\n") + + }, + */ + 'basic': { + + uniforms: {}, + + vertex_shader: [ + + "void main() {", + + "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", + + "}" + + ].join("\n"), + + fragment_shader: [ + + "void main() {", + + "gl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);", + + "}" + + ].join("\n") + + }, + + 'cube': { + + uniforms: { "tCube": { type: "t", value: 1, texture: null } }, + + vertex_shader: [ + + "varying vec3 vViewPosition;", + + "void main() {", + + "vec4 mPosition = objectMatrix * vec4( position, 1.0 );", + "vViewPosition = cameraPosition - mPosition.xyz;", + + "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", + + "}" + + ].join("\n"), + + fragment_shader: [ + + "uniform samplerCube tCube;", + + "varying vec3 vViewPosition;", + + "void main() {", + + "vec3 wPos = cameraPosition - vViewPosition;", + "gl_FragColor = textureCube( tCube, vec3( - wPos.x, wPos.yz ) );", + + "}" + + ].join("\n") + + } + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Cube.as + */ + +var Cube = function ( width, height, depth, segments_width, segments_height, materials, flipped, sides ) { + + THREE.Geometry.call( this ); + + var scope = this, + width_half = width / 2, + height_half = height / 2, + depth_half = depth / 2, + flip = flipped ? - 1 : 1; + + if ( materials !== undefined ) { + + if ( materials instanceof Array ) { + + this.materials = materials; + + } else { + + this.materials = []; + + for ( var i = 0; i < 6; i ++ ) { + + this.materials.push( [ materials ] ); + + } + + } + + } else { + + this.materials = []; + + } + + this.sides = { px: true, nx: true, py: true, ny: true, pz: true, nz: true }; + + if( sides != undefined ) { + + for( var s in sides ) { + + if ( this.sides[ s ] != undefined ) { + + this.sides[ s ] = sides[ s ]; + + } + + } + + } + + this.sides.px && buildPlane( 'z', 'y', 1 * flip, - 1, depth, height, - width_half, this.materials[ 0 ] ); // px + this.sides.nx && buildPlane( 'z', 'y', - 1 * flip, - 1, depth, height, width_half, this.materials[ 1 ] ); // nx + this.sides.py && buildPlane( 'x', 'z', 1 * flip, 1, width, depth, height_half, this.materials[ 2 ] ); // py + this.sides.ny && buildPlane( 'x', 'z', 1 * flip, - 1, width, depth, - height_half, this.materials[ 3 ] ); // ny + this.sides.pz && buildPlane( 'x', 'y', 1 * flip, - 1, width, height, depth_half, this.materials[ 4 ] ); // pz + this.sides.nz && buildPlane( 'x', 'y', - 1 * flip, - 1, width, height, - depth_half, this.materials[ 5 ] ); // nz + + mergeVertices(); + + function buildPlane( u, v, udir, vdir, width, height, depth, material ) { + + var w, ix, iy, + gridX = segments_width || 1, + gridY = segments_height || 1, + gridX1 = gridX + 1, + gridY1 = gridY + 1, + width_half = width / 2, + height_half = height / 2, + segment_width = width / gridX, + segment_height = height / gridY, + offset = scope.vertices.length; + + if ( ( u == 'x' && v == 'y' ) || ( u == 'y' && v == 'x' ) ) { + + w = 'z'; + + } else if ( ( u == 'x' && v == 'z' ) || ( u == 'z' && v == 'x' ) ) { + + w = 'y'; + + } else if ( ( u == 'z' && v == 'y' ) || ( u == 'y' && v == 'z' ) ) { + + w = 'x'; + + } + + + for( iy = 0; iy < gridY1; iy++ ) { + + for( ix = 0; ix < gridX1; ix++ ) { + + var vector = new THREE.Vector3(); + vector[ u ] = ( ix * segment_width - width_half ) * udir; + vector[ v ] = ( iy * segment_height - height_half ) * vdir; + vector[ w ] = depth; + + scope.vertices.push( new THREE.Vertex( vector ) ); + + } + + } + + for( iy = 0; iy < gridY; iy++ ) { + + for( ix = 0; ix < gridX; ix++ ) { + + var a = ix + gridX1 * iy; + var b = ix + gridX1 * ( iy + 1 ); + var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); + var d = ( ix + 1 ) + gridX1 * iy; + + scope.faces.push( new THREE.Face4( a + offset, b + offset, c + offset, d + offset, null, material ) ); + scope.uvs.push( [ + new THREE.UV( ix / gridX, iy / gridY ), + new THREE.UV( ix / gridX, ( iy + 1 ) / gridY ), + new THREE.UV( ( ix + 1 ) / gridX, ( iy + 1 ) / gridY ), + new THREE.UV( ( ix + 1 ) / gridX, iy / gridY ) + ] ); + + } + + } + + } + + function mergeVertices() { + + var unique = [], changes = []; + + for ( var i = 0, il = scope.vertices.length; i < il; i ++ ) { + + var v = scope.vertices[ i ], + duplicate = false; + + for ( var j = 0, jl = unique.length; j < jl; j ++ ) { + + var vu = unique[ j ]; + + if( v.position.x == vu.position.x && v.position.y == vu.position.y && v.position.z == vu.position.z ) { + + changes[ i ] = j; + duplicate = true; + break; + + } + + } + + if ( ! duplicate ) { + + changes[ i ] = unique.length; + unique.push( new THREE.Vertex( v.position.clone() ) ); + + } + + } + + for ( i = 0, il = scope.faces.length; i < il; i ++ ) { + + var face = scope.faces[ i ]; + + face.a = changes[ face.a ]; + face.b = changes[ face.b ]; + face.c = changes[ face.c ]; + face.d = changes[ face.d ]; + + } + + scope.vertices = unique; + + } + + this.computeCentroids(); + this.computeFaceNormals(); + this.sortFacesByMaterial(); + +}; + +Cube.prototype = new THREE.Geometry(); +Cube.prototype.constructor = Cube; +/** + * @author kile / http://kile.stravaganza.org/ + */ + +var Cylinder = function ( numSegs, topRad, botRad, height, topOffset, botOffset ) { + + THREE.Geometry.call( this ); + + var scope = this, + pi = Math.PI, i; + + // VERTICES + + // Top circle vertices + for ( i = 0; i < numSegs; i ++ ) { + + v( Math.sin( 2 * pi * i / numSegs ) * topRad, Math.cos( 2 * pi * i / numSegs ) * topRad, 0 ); + + } + + // Bottom circle vertices + for ( i = 0; i < numSegs; i ++ ) { + + v( Math.sin( 2 * pi * i / numSegs ) * botRad, Math.cos( 2 * pi * i / numSegs ) * botRad, height ); + + } + + + // FACES + + // Body + for ( i = 0; i < numSegs; i++ ) { + + f4( i, i + numSegs, numSegs + ( i + 1 ) % numSegs, ( i + 1 ) % numSegs, '#ff0000' ); + } + + // Bottom circle + if ( botRad != 0 ) { + + v( 0, 0, - topOffset ); + + for ( i = numSegs; i < numSegs + ( numSegs / 2 ); i++ ) { + + f4( 2 * numSegs, ( 2 * i - 2 * numSegs ) % numSegs, ( 2 * i - 2 * numSegs + 1 ) % numSegs, ( 2 * i - 2 * numSegs + 2 ) % numSegs ); + + } + + } + + // Top circle + if ( topRad != 0 ) { + + v( 0, 0, height + topOffset ); + + for ( i = numSegs + ( numSegs / 2 ); i < 2 * numSegs; i ++ ) { + + f4( ( 2 * i - 2 * numSegs + 2 ) % numSegs + numSegs, ( 2 * i - 2 * numSegs + 1 ) % numSegs + numSegs, ( 2 * i - 2 * numSegs ) % numSegs+numSegs, 2 * numSegs + 1 ); + + } + + } + + this.computeCentroids(); + this.computeFaceNormals(); + this.sortFacesByMaterial(); + + function v( x, y, z ) { + + scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ); + + } + + function f4( a, b, c, d ) { + + scope.faces.push( new THREE.Face4( a, b, c, d ) ); + + } + +}; + +Cylinder.prototype = new THREE.Geometry(); +Cylinder.prototype.constructor = Cylinder; +/** + * @author mr.doob / http://mrdoob.com/ + * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Plane.as + */ + +var Plane = function ( width, height, segments_width, segments_height ) { + + THREE.Geometry.call( this ); + + var ix, iy, + width_half = width / 2, + height_half = height / 2, + gridX = segments_width || 1, + gridY = segments_height || 1, + gridX1 = gridX + 1, + gridY1 = gridY + 1, + segment_width = width / gridX, + segment_height = height / gridY; + + + for( iy = 0; iy < gridY1; iy++ ) { + + for( ix = 0; ix < gridX1; ix++ ) { + + var x = ix * segment_width - width_half; + var y = iy * segment_height - height_half; + + this.vertices.push( new THREE.Vertex( new THREE.Vector3( x, - y, 0 ) ) ); + + } + + } + + for( iy = 0; iy < gridY; iy++ ) { + + for( ix = 0; ix < gridX; ix++ ) { + + var a = ix + gridX1 * iy; + var b = ix + gridX1 * ( iy + 1 ); + var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); + var d = ( ix + 1 ) + gridX1 * iy; + + this.faces.push( new THREE.Face4( a, b, c, d ) ); + this.uvs.push( [ + new THREE.UV( ix / gridX, iy / gridY ), + new THREE.UV( ix / gridX, ( iy + 1 ) / gridY ), + new THREE.UV( ( ix + 1 ) / gridX, ( iy + 1 ) / gridY ), + new THREE.UV( ( ix + 1 ) / gridX, iy / gridY ) + ] ); + + } + + } + + this.computeCentroids(); + this.computeFaceNormals(); + this.sortFacesByMaterial(); + +}; + +Plane.prototype = new THREE.Geometry(); +Plane.prototype.constructor = Plane; +/** + * @author mr.doob / http://mrdoob.com/ + * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Sphere.as + */ + +var Sphere = function ( radius, segments_width, segments_height ) { + + THREE.Geometry.call( this ); + + var gridX = segments_width || 8, + gridY = segments_height || 6; + + var i, j, pi = Math.PI; + var iHor = Math.max( 3, gridX ); + var iVer = Math.max( 2, gridY ); + var aVtc = []; + + for ( j = 0; j < ( iVer + 1 ) ; j++ ) { + + var fRad1 = j / iVer; + var fZ = radius * Math.cos( fRad1 * pi ); + var fRds = radius * Math.sin( fRad1 * pi ); + var aRow = []; + var oVtx = 0; + + for ( i = 0; i < iHor; i++ ) { + + var fRad2 = 2 * i / iHor; + var fX = fRds * Math.sin( fRad2 * pi ); + var fY = fRds * Math.cos( fRad2 * pi ); + + if ( !( ( j == 0 || j == iVer ) && i > 0 ) ) { + + oVtx = this.vertices.push( new THREE.Vertex( new THREE.Vector3( fY, fZ, fX ) ) ) - 1; + + } + + aRow.push( oVtx ); + + } + + aVtc.push( aRow ); + + } + + var n1, n2, n3, iVerNum = aVtc.length; + + for ( j = 0; j < iVerNum; j++ ) { + + var iHorNum = aVtc[ j ].length; + + if ( j > 0 ) { + + for ( i = 0; i < iHorNum; i++ ) { + + var bEnd = i == ( iHorNum - 1 ); + var aP1 = aVtc[ j ][ bEnd ? 0 : i + 1 ]; + var aP2 = aVtc[ j ][ ( bEnd ? iHorNum - 1 : i ) ]; + var aP3 = aVtc[ j - 1 ][ ( bEnd ? iHorNum - 1 : i ) ]; + var aP4 = aVtc[ j - 1 ][ bEnd ? 0 : i + 1 ]; + + var fJ0 = j / ( iVerNum - 1 ); + var fJ1 = ( j - 1 ) / ( iVerNum - 1 ); + var fI0 = ( i + 1 ) / iHorNum; + var fI1 = i / iHorNum; + + var aP1uv = new THREE.UV( 1 - fI0, fJ0 ); + var aP2uv = new THREE.UV( 1 - fI1, fJ0 ); + var aP3uv = new THREE.UV( 1 - fI1, fJ1 ); + var aP4uv = new THREE.UV( 1 - fI0, fJ1 ); + + if ( j < ( aVtc.length - 1 ) ) { + + n1 = this.vertices[ aP1 ].position.clone(); + n2 = this.vertices[ aP2 ].position.clone(); + n3 = this.vertices[ aP3 ].position.clone(); + n1.normalize(); + n2.normalize(); + n3.normalize(); + + this.faces.push( new THREE.Face3( aP1, aP2, aP3, [ new THREE.Vector3( n1.x, n1.y, n1.z ), new THREE.Vector3( n2.x, n2.y, n2.z ), new THREE.Vector3( n3.x, n3.y, n3.z ) ] ) ); + + this.uvs.push( [ aP1uv, aP2uv, aP3uv ] ); + + } + + if ( j > 1 ) { + + n1 = this.vertices[aP1].position.clone(); + n2 = this.vertices[aP3].position.clone(); + n3 = this.vertices[aP4].position.clone(); + n1.normalize(); + n2.normalize(); + n3.normalize(); + + this.faces.push( new THREE.Face3( aP1, aP3, aP4, [ new THREE.Vector3( n1.x, n1.y, n1.z ), new THREE.Vector3( n2.x, n2.y, n2.z ), new THREE.Vector3( n3.x, n3.y, n3.z ) ] ) ); + + this.uvs.push( [ aP1uv, aP3uv, aP4uv ] ); + + } + + } + } + } + + this.computeCentroids(); + this.computeFaceNormals(); + this.computeVertexNormals(); + this.sortFacesByMaterial(); + + this.boundingSphere = { radius: radius }; + +}; + +Sphere.prototype = new THREE.Geometry(); +Sphere.prototype.constructor = Sphere; +/** + * @author alteredq / http://alteredqualia.com/ + */ + +THREE.Loader = function( showStatus ) { + + this.showStatus = showStatus; + + this.statusDomElement = showStatus ? this.addStatusElement() : null; + +}; + +THREE.Loader.prototype = { + + addStatusElement: function ( ) { + + var e = document.createElement( "div" ); + + e.style.fontSize = "0.8em"; + e.style.textAlign = "left"; + e.style.background = "#b00"; + e.style.color = "#fff"; + e.style.width = "140px"; + e.style.padding = "0.25em 0.25em 0.25em 0.5em"; + e.style.position = "absolute"; + e.style.right = "0px"; + e.style.top = "0px"; + e.style.zIndex = 1000; + + e.innerHTML = "Loading ..."; + + return e; + + }, + + updateProgress: function ( progress ) { + + var message = "Loaded "; + + if ( progress.total ) { + + message += ( 100 * progress.loaded / progress.total ).toFixed(0) + "%"; + + + } else { + + message += ( progress.loaded / 1000 ).toFixed(2) + " KB"; + + } + + this.statusDomElement.innerHTML = message; + + }, + + // Load models generated by Blender exporter and original OBJ converter (converter_obj_three.py) + + loadAsciiOld: function( url, callback ) { + + var element = document.createElement( 'script' ); + element.type = 'text/javascript'; + element.onload = callback; + element.src = url; + document.getElementsByTagName( "head" )[ 0 ].appendChild( element ); + + }, + + // Load models generated by slim OBJ converter with ASCII option (converter_obj_three_slim.py -t ascii) + // - parameters + // - model (required) + // - callback (required) + // - texture_path (optional: if not specified, textures will be assumed to be in the same folder as JS model file) + + loadAscii: function ( parameters ) { + + var url = parameters.model, + callback = parameters.callback, + texture_path = parameters.texture_path ? parameters.texture_path : THREE.Loader.prototype.extractUrlbase( url ), + + s = (new Date).getTime(), + worker = new Worker( url ); + + worker.onmessage = function( event ) { + + THREE.Loader.prototype.createModel( event.data, callback, texture_path ); + + }; + + worker.postMessage( s ); + + }, + + // Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary) + // - binary models consist of two files: JS and BIN + // - parameters + // - model (required) + // - callback (required) + // - bin_path (optional: if not specified, binary file will be assumed to be in the same folder as JS model file) + // - texture_path (optional: if not specified, textures will be assumed to be in the same folder as JS model file) + + loadBinary: function( parameters ) { + + // #1 load JS part via web worker + + // This isn't really necessary, JS part is tiny, + // could be done by more ordinary means. + + var url = parameters.model, + callback = parameters.callback, + texture_path = parameters.texture_path ? parameters.texture_path : THREE.Loader.prototype.extractUrlbase( url ), + bin_path = parameters.bin_path ? parameters.bin_path : THREE.Loader.prototype.extractUrlbase( url ), + + s = (new Date).getTime(), + worker = new Worker( url ), + callback_progress = this.showProgress ? THREE.Loader.prototype.updateProgress : null; + + worker.onmessage = function( event ) { + + var materials = event.data.materials, + buffers = event.data.buffers; + + // #2 load BIN part via Ajax + + // For some reason it is faster doing loading from here than from within the worker. + // Maybe passing of ginormous string as message between threads is costly? + // Also, worker loading huge data by Ajax still freezes browser. Go figure, + // worker with baked ascii JSON data keeps browser more responsive. + + THREE.Loader.prototype.loadAjaxBuffers( buffers, materials, callback, bin_path, texture_path, callback_progress ); + + }; + + worker.onerror = function (event) { + + alert( "worker.onerror: " + event.message + "\n" + event.data ); + event.preventDefault(); + + }; + + worker.postMessage( s ); + + }, + + // Binary AJAX parser based on Magi binary loader + // https://github.com/kig/magi + + // Should look more into HTML5 File API + // See also other suggestions by Gregg Tavares + // https://groups.google.com/group/o3d-discuss/browse_thread/thread/a8967bc9ce1e0978 + + loadAjaxBuffers: function( buffers, materials, callback, bin_path, texture_path, callback_progress ) { + + var xhr = new XMLHttpRequest(), + url = bin_path + "/" + buffers; + + var length = 0; + + xhr.onreadystatechange = function() { + + if ( xhr.readyState == 4 ) { + + if ( xhr.status == 200 || xhr.status == 0 ) { + + THREE.Loader.prototype.createBinModel( xhr.responseText, callback, texture_path, materials ); + + } else { + + alert( "Couldn't load [" + url + "] [" + xhr.status + "]" ); + + } + + } else if ( xhr.readyState == 3 ) { + + if ( callback_progress ) { + + if ( length == 0 ) { + + length = xhr.getResponseHeader( "Content-Length" ); + + } + + callback_progress( { total: length, loaded: xhr.responseText.length } ); + + } + + } else if ( xhr.readyState == 2 ) { + + length = xhr.getResponseHeader( "Content-Length" ); + + } + + } + + xhr.open("GET", url, true); + xhr.overrideMimeType("text/plain; charset=x-user-defined"); + xhr.setRequestHeader("Content-Type", "text/plain"); + xhr.send(null); + + }, + + createBinModel: function ( data, callback, texture_path, materials ) { + + var Model = function ( texture_path ) { + + //var s = (new Date).getTime(); + + var scope = this, + currentOffset = 0, + md, + normals = [], + uvs = [], + tri_b, tri_c, tri_m, tri_na, tri_nb, tri_nc, + quad_b, quad_c, quad_d, quad_m, quad_na, quad_nb, quad_nc, quad_nd, + tri_uvb, tri_uvc, quad_uvb, quad_uvc, quad_uvd, + start_tri_flat, start_tri_smooth, start_tri_flat_uv, start_tri_smooth_uv, + start_quad_flat, start_quad_smooth, start_quad_flat_uv, start_quad_smooth_uv, + tri_size, quad_size, + len_tri_flat, len_tri_smooth, len_tri_flat_uv, len_tri_smooth_uv, + len_quad_flat, len_quad_smooth, len_quad_flat_uv, len_quad_smooth_uv; + + + THREE.Geometry.call(this); + + THREE.Loader.prototype.init_materials( scope, materials, texture_path ); + + md = parseMetaData( data, currentOffset ); + currentOffset += md.header_bytes; + + // cache offsets + + tri_b = md.vertex_index_bytes, + tri_c = md.vertex_index_bytes*2, + tri_m = md.vertex_index_bytes*3, + tri_na = md.vertex_index_bytes*3 + md.material_index_bytes, + tri_nb = md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes, + tri_nc = md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes*2, + + quad_b = md.vertex_index_bytes, + quad_c = md.vertex_index_bytes*2, + quad_d = md.vertex_index_bytes*3, + quad_m = md.vertex_index_bytes*4, + quad_na = md.vertex_index_bytes*4 + md.material_index_bytes, + quad_nb = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes, + quad_nc = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*2, + quad_nd = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*3, + + tri_uvb = md.uv_index_bytes, + tri_uvc = md.uv_index_bytes * 2, + + quad_uvb = md.uv_index_bytes, + quad_uvc = md.uv_index_bytes * 2, + quad_uvd = md.uv_index_bytes * 3; + + // buffers sizes + + tri_size = md.vertex_index_bytes * 3 + md.material_index_bytes; + quad_size = md.vertex_index_bytes * 4 + md.material_index_bytes; + + len_tri_flat = md.ntri_flat * ( tri_size ); + len_tri_smooth = md.ntri_smooth * ( tri_size + md.normal_index_bytes * 3 ); + len_tri_flat_uv = md.ntri_flat_uv * ( tri_size + md.uv_index_bytes * 3 ); + len_tri_smooth_uv = md.ntri_smooth_uv * ( tri_size + md.normal_index_bytes * 3 + md.uv_index_bytes * 3 ); + + len_quad_flat = md.nquad_flat * ( quad_size ); + len_quad_smooth = md.nquad_smooth * ( quad_size + md.normal_index_bytes * 4 ); + len_quad_flat_uv = md.nquad_flat_uv * ( quad_size + md.uv_index_bytes * 4 ); + len_quad_smooth_uv = md.nquad_smooth_uv * ( quad_size + md.normal_index_bytes * 4 + md.uv_index_bytes * 4 ); + + // read buffers + + currentOffset += init_vertices( currentOffset ); + currentOffset += init_normals( currentOffset ); + currentOffset += init_uvs( currentOffset ); + + start_tri_flat = currentOffset; + start_tri_smooth = start_tri_flat + len_tri_flat; + start_tri_flat_uv = start_tri_smooth + len_tri_smooth; + start_tri_smooth_uv = start_tri_flat_uv + len_tri_flat_uv; + + start_quad_flat = start_tri_smooth_uv + len_tri_smooth_uv; + start_quad_smooth = start_quad_flat + len_quad_flat; + start_quad_flat_uv = start_quad_smooth + len_quad_smooth; + start_quad_smooth_uv= start_quad_flat_uv +len_quad_flat_uv; + + // have to first process faces with uvs + // so that face and uv indices match + + init_triangles_flat_uv( start_tri_flat_uv ); + init_triangles_smooth_uv( start_tri_smooth_uv ); + + init_quads_flat_uv( start_quad_flat_uv ); + init_quads_smooth_uv( start_quad_smooth_uv ); + + // now we can process untextured faces + + init_triangles_flat( start_tri_flat ); + init_triangles_smooth( start_tri_smooth ); + + init_quads_flat( start_quad_flat ); + init_quads_smooth( start_quad_smooth ); + + this.computeCentroids(); + this.computeFaceNormals(); + this.sortFacesByMaterial(); + + //var e = (new Date).getTime(); + + //log( "binary data parse time: " + (e-s) + " ms" ); + + function parseMetaData( data, offset ) { + + var metaData = { + + 'signature' :parseString( data, offset, 8 ), + 'header_bytes' :parseUChar8( data, offset + 8 ), + + 'vertex_coordinate_bytes' :parseUChar8( data, offset + 9 ), + 'normal_coordinate_bytes' :parseUChar8( data, offset + 10 ), + 'uv_coordinate_bytes' :parseUChar8( data, offset + 11 ), + + 'vertex_index_bytes' :parseUChar8( data, offset + 12 ), + 'normal_index_bytes' :parseUChar8( data, offset + 13 ), + 'uv_index_bytes' :parseUChar8( data, offset + 14 ), + 'material_index_bytes' :parseUChar8( data, offset + 15 ), + + 'nvertices' :parseUInt32( data, offset + 16 ), + 'nnormals' :parseUInt32( data, offset + 16 + 4*1 ), + 'nuvs' :parseUInt32( data, offset + 16 + 4*2 ), + + 'ntri_flat' :parseUInt32( data, offset + 16 + 4*3 ), + 'ntri_smooth' :parseUInt32( data, offset + 16 + 4*4 ), + 'ntri_flat_uv' :parseUInt32( data, offset + 16 + 4*5 ), + 'ntri_smooth_uv' :parseUInt32( data, offset + 16 + 4*6 ), + + 'nquad_flat' :parseUInt32( data, offset + 16 + 4*7 ), + 'nquad_smooth' :parseUInt32( data, offset + 16 + 4*8 ), + 'nquad_flat_uv' :parseUInt32( data, offset + 16 + 4*9 ), + 'nquad_smooth_uv' :parseUInt32( data, offset + 16 + 4*10 ) + + }; + + /* + log( "signature: " + metaData.signature ); + + log( "header_bytes: " + metaData.header_bytes ); + log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes ); + log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes ); + log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes ); + + log( "vertex_index_bytes: " + metaData.vertex_index_bytes ); + log( "normal_index_bytes: " + metaData.normal_index_bytes ); + log( "uv_index_bytes: " + metaData.uv_index_bytes ); + log( "material_index_bytes: " + metaData.material_index_bytes ); + + log( "nvertices: " + metaData.nvertices ); + log( "nnormals: " + metaData.nnormals ); + log( "nuvs: " + metaData.nuvs ); + + log( "ntri_flat: " + metaData.ntri_flat ); + log( "ntri_smooth: " + metaData.ntri_smooth ); + log( "ntri_flat_uv: " + metaData.ntri_flat_uv ); + log( "ntri_smooth_uv: " + metaData.ntri_smooth_uv ); + + log( "nquad_flat: " + metaData.nquad_flat ); + log( "nquad_smooth: " + metaData.nquad_smooth ); + log( "nquad_flat_uv: " + metaData.nquad_flat_uv ); + log( "nquad_smooth_uv: " + metaData.nquad_smooth_uv ); + + var total = metaData.header_bytes + + metaData.nvertices * metaData.vertex_coordinate_bytes * 3 + + metaData.nnormals * metaData.normal_coordinate_bytes * 3 + + metaData.nuvs * metaData.uv_coordinate_bytes * 2 + + metaData.ntri_flat * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes ) + + metaData.ntri_smooth * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 ) + + metaData.ntri_flat_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.uv_index_bytes*3 ) + + metaData.ntri_smooth_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 + metaData.uv_index_bytes*3 ) + + metaData.nquad_flat * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes ) + + metaData.nquad_smooth * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 ) + + metaData.nquad_flat_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.uv_index_bytes*4 ) + + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 ); + log( "total bytes: " + total ); + */ + + return metaData; + + } + + function parseString( data, offset, length ) { + + return data.substr( offset, length ); + + } + + function parseFloat32( data, offset ) { + + var b3 = parseUChar8( data, offset ), + b2 = parseUChar8( data, offset + 1 ), + b1 = parseUChar8( data, offset + 2 ), + b0 = parseUChar8( data, offset + 3 ), + + sign = 1 - ( 2 * ( b0 >> 7 ) ), + exponent = ((( b0 << 1 ) & 0xff) | ( b1 >> 7 )) - 127, + mantissa = (( b1 & 0x7f ) << 16) | (b2 << 8) | b3; + + if (mantissa == 0 && exponent == -127) + return 0.0; + + return sign * ( 1 + mantissa * Math.pow( 2, -23 ) ) * Math.pow( 2, exponent ); + + } + + function parseUInt32( data, offset ) { + + var b0 = parseUChar8( data, offset ), + b1 = parseUChar8( data, offset + 1 ), + b2 = parseUChar8( data, offset + 2 ), + b3 = parseUChar8( data, offset + 3 ); + + return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0; + } + + function parseUInt16( data, offset ) { + + var b0 = parseUChar8( data, offset ), + b1 = parseUChar8( data, offset + 1 ); + + return (b1 << 8) + b0; + + } + + function parseSChar8( data, offset ) { + + var b = parseUChar8( data, offset ); + return b > 127 ? b - 256 : b; + + } + + function parseUChar8( data, offset ) { + + return data.charCodeAt( offset ) & 0xff; + } + + function init_vertices( start ) { + + var i, x, y, z, + stride = md.vertex_coordinate_bytes * 3, + end = start + md.nvertices * stride; + + for( i = start; i < end; i += stride ) { + + x = parseFloat32( data, i ); + y = parseFloat32( data, i + md.vertex_coordinate_bytes ); + z = parseFloat32( data, i + md.vertex_coordinate_bytes*2 ); + + THREE.Loader.prototype.v( scope, x, y, z ); + + } + + return md.nvertices * stride; + + } + + function init_normals( start ) { + + var i, x, y, z, + stride = md.normal_coordinate_bytes * 3, + end = start + md.nnormals * stride; + + for( i = start; i < end; i += stride ) { + + x = parseSChar8( data, i ); + y = parseSChar8( data, i + md.normal_coordinate_bytes ); + z = parseSChar8( data, i + md.normal_coordinate_bytes*2 ); + + normals.push( x/127, y/127, z/127 ); + + } + + return md.nnormals * stride; + + } + + function init_uvs( start ) { + + var i, u, v, + stride = md.uv_coordinate_bytes * 2, + end = start + md.nuvs * stride; + + for( i = start; i < end; i += stride ) { + + u = parseFloat32( data, i ); + v = parseFloat32( data, i + md.uv_coordinate_bytes ); + + uvs.push( u, v ); + + } + + return md.nuvs * stride; + + } + + function add_tri( i ) { + + var a, b, c, m; + + a = parseUInt32( data, i ); + b = parseUInt32( data, i + tri_b ); + c = parseUInt32( data, i + tri_c ); + + m = parseUInt16( data, i + tri_m ); + + THREE.Loader.prototype.f3( scope, a, b, c, m ); + + } + + function add_tri_n( i ) { + + var a, b, c, m, na, nb, nc; + + a = parseUInt32( data, i ); + b = parseUInt32( data, i + tri_b ); + c = parseUInt32( data, i + tri_c ); + + m = parseUInt16( data, i + tri_m ); + + na = parseUInt32( data, i + tri_na ); + nb = parseUInt32( data, i + tri_nb ); + nc = parseUInt32( data, i + tri_nc ); + + THREE.Loader.prototype.f3n( scope, normals, a, b, c, m, na, nb, nc ); + + } + + function add_quad( i ) { + + var a, b, c, d, m; + + a = parseUInt32( data, i ); + b = parseUInt32( data, i + quad_b ); + c = parseUInt32( data, i + quad_c ); + d = parseUInt32( data, i + quad_d ); + + m = parseUInt16( data, i + quad_m ); + + THREE.Loader.prototype.f4( scope, a, b, c, d, m ); + + } + + function add_quad_n( i ) { + + var a, b, c, d, m, na, nb, nc, nd; + + a = parseUInt32( data, i ); + b = parseUInt32( data, i + quad_b ); + c = parseUInt32( data, i + quad_c ); + d = parseUInt32( data, i + quad_d ); + + m = parseUInt16( data, i + quad_m ); + + na = parseUInt32( data, i + quad_na ); + nb = parseUInt32( data, i + quad_nb ); + nc = parseUInt32( data, i + quad_nc ); + nd = parseUInt32( data, i + quad_nd ); + + THREE.Loader.prototype.f4n( scope, normals, a, b, c, d, m, na, nb, nc, nd ); + + } + + function add_uv3( i ) { + + var uva, uvb, uvc, u1, u2, u3, v1, v2, v3; + + uva = parseUInt32( data, i ); + uvb = parseUInt32( data, i + tri_uvb ); + uvc = parseUInt32( data, i + tri_uvc ); + + u1 = uvs[ uva*2 ]; + v1 = uvs[ uva*2 + 1 ]; + + u2 = uvs[ uvb*2 ]; + v2 = uvs[ uvb*2 + 1 ]; + + u3 = uvs[ uvc*2 ]; + v3 = uvs[ uvc*2 + 1 ]; + + THREE.Loader.prototype.uv3( scope, u1, v1, u2, v2, u3, v3 ); + + } + + function add_uv4( i ) { + + var uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4; + + uva = parseUInt32( data, i ); + uvb = parseUInt32( data, i + quad_uvb ); + uvc = parseUInt32( data, i + quad_uvc ); + uvd = parseUInt32( data, i + quad_uvd ); + + u1 = uvs[ uva*2 ]; + v1 = uvs[ uva*2 + 1 ]; + + u2 = uvs[ uvb*2 ]; + v2 = uvs[ uvb*2 + 1 ]; + + u3 = uvs[ uvc*2 ]; + v3 = uvs[ uvc*2 + 1 ]; + + u4 = uvs[ uvd*2 ]; + v4 = uvs[ uvd*2 + 1 ]; + + THREE.Loader.prototype.uv4( scope, u1, v1, u2, v2, u3, v3, u4, v4 ); + + } + + function init_triangles_flat( start ) { + + var i, stride = md.vertex_index_bytes * 3 + md.material_index_bytes, + end = start + md.ntri_flat * stride; + + for( i = start; i < end; i += stride ) { + + add_tri( i ); + + } + + return end - start; + + } + + function init_triangles_flat_uv( start ) { + + var i, offset = md.vertex_index_bytes * 3 + md.material_index_bytes, + stride = offset + md.uv_index_bytes * 3, + end = start + md.ntri_flat_uv * stride; + + for( i = start; i < end; i += stride ) { + + add_tri( i ); + add_uv3( i + offset ); + + } + + return end - start; + + } + + function init_triangles_smooth( start ) { + + var i, stride = md.vertex_index_bytes * 3 + md.material_index_bytes + md.normal_index_bytes * 3, + end = start + md.ntri_smooth * stride; + + for( i = start; i < end; i += stride ) { + + add_tri_n( i ); + + } + + return end - start; + + } + + function init_triangles_smooth_uv( start ) { + + var i, offset = md.vertex_index_bytes * 3 + md.material_index_bytes + md.normal_index_bytes * 3, + stride = offset + md.uv_index_bytes * 3, + end = start + md.ntri_smooth_uv * stride; + + for( i = start; i < end; i += stride ) { + + add_tri_n( i ); + add_uv3( i + offset ); + + } + + return end - start; + + } + + function init_quads_flat( start ) { + + var i, stride = md.vertex_index_bytes * 4 + md.material_index_bytes, + end = start + md.nquad_flat * stride; + + for( i = start; i < end; i += stride ) { + + add_quad( i ); + + } + + return end - start; + + } + + function init_quads_flat_uv( start ) { + + var i, offset = md.vertex_index_bytes * 4 + md.material_index_bytes, + stride = offset + md.uv_index_bytes * 4, + end = start + md.nquad_flat_uv * stride; + + for( i = start; i < end; i += stride ) { + + add_quad( i ); + add_uv4( i + offset ); + + } + + return end - start; + + } + + function init_quads_smooth( start ) { + + var i, stride = md.vertex_index_bytes * 4 + md.material_index_bytes + md.normal_index_bytes * 4, + end = start + md.nquad_smooth * stride; + + for( i = start; i < end; i += stride ) { + + add_quad_n( i ); + } + + return end - start; + + } + + function init_quads_smooth_uv( start ) { + + var i, offset = md.vertex_index_bytes * 4 + md.material_index_bytes + md.normal_index_bytes * 4, + stride = offset + md.uv_index_bytes * 4, + end = start + md.nquad_smooth_uv * stride; + + for( i = start; i < end; i += stride ) { + + add_quad_n( i ); + add_uv4( i + offset ); + + } + + return end - start; + + } + + } + + Model.prototype = new THREE.Geometry(); + Model.prototype.constructor = Model; + + callback( new Model( texture_path ) ); + + }, + + createModel: function ( data, callback, texture_path ) { + + var Model = function ( texture_path ) { + + var scope = this; + + THREE.Geometry.call( this ); + + THREE.Loader.prototype.init_materials( scope, data.materials, texture_path ); + + init_vertices(); + init_faces(); + + this.computeCentroids(); + this.computeFaceNormals(); + this.sortFacesByMaterial(); + + function init_vertices() { + + var i, l, x, y, z; + + for( i = 0, l = data.vertices.length; i < l; i += 3 ) { + + x = data.vertices[ i ]; + y = data.vertices[ i + 1 ]; + z = data.vertices[ i + 2 ]; + + THREE.Loader.prototype.v( scope, x, y, z ); + + } + + } + + function init_faces() { + + function add_tri( src, i ) { + + var a, b, c, m; + + a = src[ i ]; + b = src[ i + 1 ]; + c = src[ i + 2 ]; + + m = src[ i + 3 ]; + + THREE.Loader.prototype.f3( scope, a, b, c, m ); + + } + + function add_tri_n( src, i ) { + + var a, b, c, m, na, nb, nc; + + a = src[ i ]; + b = src[ i + 1 ]; + c = src[ i + 2 ]; + + m = src[ i + 3 ]; + + na = src[ i + 4 ]; + nb = src[ i + 5 ]; + nc = src[ i + 6 ]; + + THREE.Loader.prototype.f3n( scope, data.normals, a, b, c, m, na, nb, nc ); + + } + + function add_quad( src, i ) { + + var a, b, c, d, m; + + a = src[ i ]; + b = src[ i + 1 ]; + c = src[ i + 2 ]; + d = src[ i + 3 ]; + + m = src[ i + 4 ]; + + THREE.Loader.prototype.f4( scope, a, b, c, d, m ); + + } + + function add_quad_n( src, i ) { + + var a, b, c, d, m, na, nb, nc, nd; + + a = src[ i ]; + b = src[ i + 1 ]; + c = src[ i + 2 ]; + d = src[ i + 3 ]; + + m = src[ i + 4 ]; + + na = src[ i + 5 ]; + nb = src[ i + 6 ]; + nc = src[ i + 7 ]; + nd = src[ i + 8 ]; + + THREE.Loader.prototype.f4n( scope, data.normals, a, b, c, d, m, na, nb, nc, nd ); + + } + + function add_uv3( src, i ) { + + var uva, uvb, uvc, u1, u2, u3, v1, v2, v3; + + uva = src[ i ]; + uvb = src[ i + 1 ]; + uvc = src[ i + 2 ]; + + u1 = data.uvs[ uva * 2 ]; + v1 = data.uvs[ uva * 2 + 1 ]; + + u2 = data.uvs[ uvb * 2 ]; + v2 = data.uvs[ uvb * 2 + 1 ]; + + u3 = data.uvs[ uvc * 2 ]; + v3 = data.uvs[ uvc * 2 + 1 ]; + + THREE.Loader.prototype.uv3( scope, u1, v1, u2, v2, u3, v3 ); + + } + + function add_uv4( src, i ) { + + var uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4; + + uva = src[ i ]; + uvb = src[ i + 1 ]; + uvc = src[ i + 2 ]; + uvd = src[ i + 3 ]; + + u1 = data.uvs[ uva * 2 ]; + v1 = data.uvs[ uva * 2 + 1 ]; + + u2 = data.uvs[ uvb * 2 ]; + v2 = data.uvs[ uvb * 2 + 1 ]; + + u3 = data.uvs[ uvc * 2 ]; + v3 = data.uvs[ uvc * 2 + 1 ]; + + u4 = data.uvs[ uvd * 2 ]; + v4 = data.uvs[ uvd * 2 + 1 ]; + + THREE.Loader.prototype.uv4( scope, u1, v1, u2, v2, u3, v3, u4, v4 ); + + } + + var i, l; + + // need to process first faces with uvs + // as uvs are indexed by face indices + + for ( i = 0, l = data.triangles_uv.length; i < l; i+= 7 ) { + + add_tri( data.triangles_uv, i ); + add_uv3( data.triangles_uv, i + 4 ); + + } + + for ( i = 0, l = data.triangles_n_uv.length; i < l; i += 10 ) { + + add_tri_n( data.triangles_n_uv, i ); + add_uv3( data.triangles_n_uv, i + 7 ); + + } + + for ( i = 0, l = data.quads_uv.length; i < l; i += 9 ) { + + add_quad( data.quads_uv, i ); + add_uv4( data.quads_uv, i + 5 ); + + } + + for ( i = 0, l = data.quads_n_uv.length; i < l; i += 13 ) { + + add_quad_n( data.quads_n_uv, i ); + add_uv4( data.quads_n_uv, i + 9 ); + + } + + // now can process untextured faces + + for ( i = 0, l = data.triangles.length; i < l; i += 4 ) { + + add_tri( data.triangles, i ); + + } + + for ( i = 0, l = data.triangles_n.length; i < l; i += 7 ) { + + add_tri_n( data.triangles_n, i ); + + } + + for ( i = 0, l = data.quads.length; i < l; i += 5 ) { + + add_quad( data.quads, i ); + + } + + for ( i = 0, l = data.quads_n.length; i < l; i += 9 ) { + + add_quad_n( data.quads_n, i ); + + } + + } + + } + + Model.prototype = new THREE.Geometry(); + Model.prototype.constructor = Model; + + callback( new Model( texture_path ) ); + + }, + + v: function( scope, x, y, z ) { + + scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ); + + }, + + f3: function( scope, a, b, c, mi ) { + + var material = scope.materials[ mi ]; + scope.faces.push( new THREE.Face3( a, b, c, null, material ) ); + + }, + + f4: function( scope, a, b, c, d, mi ) { + + var material = scope.materials[ mi ]; + scope.faces.push( new THREE.Face4( a, b, c, d, null, material ) ); + + }, + + f3n: function( scope, normals, a, b, c, mi, na, nb, nc ) { + + var material = scope.materials[ mi ], + nax = normals[ na*3 ], + nay = normals[ na*3 + 1 ], + naz = normals[ na*3 + 2 ], + + nbx = normals[ nb*3 ], + nby = normals[ nb*3 + 1 ], + nbz = normals[ nb*3 + 2 ], + + ncx = normals[ nc*3 ], + ncy = normals[ nc*3 + 1 ], + ncz = normals[ nc*3 + 2 ]; + + scope.faces.push( new THREE.Face3( a, b, c, + [new THREE.Vector3( nax, nay, naz ), + new THREE.Vector3( nbx, nby, nbz ), + new THREE.Vector3( ncx, ncy, ncz )], + material ) ); + + }, + + f4n: function( scope, normals, a, b, c, d, mi, na, nb, nc, nd ) { + + var material = scope.materials[ mi ], + nax = normals[ na*3 ], + nay = normals[ na*3 + 1 ], + naz = normals[ na*3 + 2 ], + + nbx = normals[ nb*3 ], + nby = normals[ nb*3 + 1 ], + nbz = normals[ nb*3 + 2 ], + + ncx = normals[ nc*3 ], + ncy = normals[ nc*3 + 1 ], + ncz = normals[ nc*3 + 2 ], + + ndx = normals[ nd*3 ], + ndy = normals[ nd*3 + 1 ], + ndz = normals[ nd*3 + 2 ]; + + scope.faces.push( new THREE.Face4( a, b, c, d, + [new THREE.Vector3( nax, nay, naz ), + new THREE.Vector3( nbx, nby, nbz ), + new THREE.Vector3( ncx, ncy, ncz ), + new THREE.Vector3( ndx, ndy, ndz )], + material ) ); + + }, + + uv3: function( scope, u1, v1, u2, v2, u3, v3 ) { + + var uv = []; + uv.push( new THREE.UV( u1, v1 ) ); + uv.push( new THREE.UV( u2, v2 ) ); + uv.push( new THREE.UV( u3, v3 ) ); + scope.uvs.push( uv ); + + }, + + uv4: function( scope, u1, v1, u2, v2, u3, v3, u4, v4 ) { + + var uv = []; + uv.push( new THREE.UV( u1, v1 ) ); + uv.push( new THREE.UV( u2, v2 ) ); + uv.push( new THREE.UV( u3, v3 ) ); + uv.push( new THREE.UV( u4, v4 ) ); + scope.uvs.push( uv ); + + }, + + init_materials: function( scope, materials, texture_path ) { + + scope.materials = []; + + for ( var i = 0; i < materials.length; ++i ) { + + scope.materials[i] = [ THREE.Loader.prototype.createMaterial( materials[i], texture_path ) ]; + + } + + }, + + createMaterial: function ( m, texture_path ) { + + function is_pow2( n ) { + + var l = Math.log(n) / Math.LN2; + return Math.floor(l) == l; + + } + + function nearest_pow2( n ) { + + var l = Math.log(n) / Math.LN2; + return Math.pow( 2, Math.round(l) ); + + } + + var material, texture, image, color; + + if ( m.map_diffuse && texture_path ) { + + texture = document.createElement( 'canvas' ); + material = new THREE.MeshLambertMaterial( { map: new THREE.Texture( texture ) } ); + + image = new Image(); + image.onload = function () { + + if ( !is_pow2( this.width ) || !is_pow2( this.height ) ) { + + var w = nearest_pow2( this.width ), + h = nearest_pow2( this.height ); + + material.map.image.width = w; + material.map.image.height = h; + material.map.image.getContext("2d").drawImage( this, 0, 0, w, h ); + + } else { + + material.map.image = this; + + } + + material.map.image.loaded = 1; + + }; + + image.src = texture_path + "/" + m.map_diffuse; + + } else if ( m.col_diffuse ) { + + color = (m.col_diffuse[0]*255 << 16) + (m.col_diffuse[1]*255 << 8) + m.col_diffuse[2]*255; + material = new THREE.MeshLambertMaterial( { color: color, opacity: m.transparency } ); + + } else if ( m.a_dbg_color ) { + + material = new THREE.MeshLambertMaterial( { color: m.a_dbg_color } ); + + } else { + + material = new THREE.MeshLambertMaterial( { color: 0xeeeeee } ); + + } + + return material; + + }, + + extractUrlbase: function( url ) { + + var chunks = url.split( "/" ); + chunks.pop(); + return chunks.join( "/" ); + + } + +}; diff --git a/build/ThreeWebGL.js b/build/ThreeWebGL.js new file mode 100644 index 00000000..02ca905f --- /dev/null +++ b/build/ThreeWebGL.js @@ -0,0 +1,5046 @@ +// ThreeWebGL.js r32 - http://github.com/mrdoob/three.js +/** + * @author mr.doob / http://mrdoob.com/ + */ + +var THREE = THREE || {}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Color = function ( hex ) { + + this.autoUpdate = true; + this.setHex( hex ); + +}; + +THREE.Color.prototype = { + + setRGB: function ( r, g, b ) { + + this.r = r; + this.g = g; + this.b = b; + + if ( this.autoUpdate ) { + + this.updateHex(); + this.updateStyleString(); + + } + + }, + + setHex: function ( hex ) { + + this.hex = ( ~~ hex ) & 0xffffff; + + if ( this.autoUpdate ) { + + this.updateRGBA(); + this.updateStyleString(); + + } + + }, + + updateHex: function () { + + this.hex = ~~( this.r * 255 ) << 16 ^ ~~( this.g * 255 ) << 8 ^ ~~( this.b * 255 ); + + }, + + updateRGBA: function () { + + this.r = ( this.hex >> 16 & 255 ) / 255; + this.g = ( this.hex >> 8 & 255 ) / 255; + this.b = ( this.hex & 255 ) / 255; + + }, + + updateStyleString: function () { + + this.__styleString = 'rgb(' + ~~( this.r * 255 ) + ',' + ~~( this.g * 255 ) + ',' + ~~( this.b * 255 ) + ')'; + + }, + + clone: function () { + + return new THREE.Color( this.hex ); + + }, + + + toString: function () { + + return 'THREE.Color ( r: ' + this.r + ', g: ' + this.g + ', b: ' + this.b + ', hex: ' + this.hex + ' )'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + * @author philogb / http://blog.thejit.org/ + */ + +THREE.Vector2 = function ( x, y ) { + + this.x = x || 0; + this.y = y || 0; + +}; + +THREE.Vector2.prototype = { + + set: function ( x, y ) { + + this.x = x; + this.y = y; + + return this; + + }, + + copy: function ( v ) { + + this.x = v.x; + this.y = v.y; + + return this; + + }, + + addSelf: function ( v ) { + + this.x += v.x; + this.y += v.y; + + return this; + + }, + + add: function ( v1, v2 ) { + + this.x = v1.x + v2.x; + this.y = v1.y + v2.y; + + return this; + + }, + + subSelf: function ( v ) { + + this.x -= v.x; + this.y -= v.y; + + return this; + + }, + + sub: function ( v1, v2 ) { + + this.x = v1.x - v2.x; + this.y = v1.y - v2.y; + + return this; + + }, + + multiplyScalar: function ( s ) { + + this.x *= s; + this.y *= s; + + return this; + + }, + + unit: function () { + + this.multiplyScalar( 1 / this.length() ); + + return this; + + }, + + length: function () { + + return Math.sqrt( this.x * this.x + this.y * this.y ); + + }, + + lengthSq: function () { + + return this.x * this.x + this.y * this.y; + + }, + + negate: function() { + + this.x = - this.x; + this.y = - this.y; + + return this; + + }, + + clone: function () { + + return new THREE.Vector2( this.x, this.y ); + + }, + + toString: function () { + + return 'THREE.Vector2 (' + this.x + ', ' + this.y + ')'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + * @author kile / http://kile.stravaganza.org/ + * @author philogb / http://blog.thejit.org/ + */ + +THREE.Vector3 = function ( x, y, z ) { + + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; + +}; + +THREE.Vector3.prototype = { + + set: function ( x, y, z ) { + + this.x = x; + this.y = y; + this.z = z; + + return this; + + }, + + copy: function ( v ) { + + this.x = v.x; + this.y = v.y; + this.z = v.z; + + return this; + + }, + + add: function ( a, b ) { + + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; + + return this; + + }, + + addSelf: function ( v ) { + + this.x += v.x; + this.y += v.y; + this.z += v.z; + + return this; + + }, + + addScalar: function ( s ) { + + this.x += s; + this.y += s; + this.z += s; + + return this; + + }, + + sub: function( a, b ) { + + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; + + return this; + + }, + + subSelf: function ( v ) { + + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + + return this; + + }, + + cross: function ( a, b ) { + + this.x = a.y * b.z - a.z * b.y; + this.y = a.z * b.x - a.x * b.z; + this.z = a.x * b.y - a.y * b.x; + + return this; + + }, + + crossSelf: function ( v ) { + + var tx = this.x, ty = this.y, tz = this.z; + + this.x = ty * v.z - tz * v.y; + this.y = tz * v.x - tx * v.z; + this.z = tx * v.y - ty * v.x; + + return this; + + }, + + multiply: function ( a, b ) { + + this.x = a.x * b.x; + this.y = a.y * b.y; + this.z = a.z * b.z; + + return this; + + }, + + multiplySelf: function ( v ) { + + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + + return this; + + }, + + multiplyScalar: function ( s ) { + + this.x *= s; + this.y *= s; + this.z *= s; + + return this; + + }, + + divideSelf: function ( v ) { + + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; + + return this; + + }, + + divideScalar: function ( s ) { + + this.x /= s; + this.y /= s; + this.z /= s; + + return this; + + }, + + dot: function ( v ) { + + return this.x * v.x + this.y * v.y + this.z * v.z; + + }, + + distanceTo: function ( v ) { + + var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; + return Math.sqrt( dx * dx + dy * dy + dz * dz ); + + }, + + distanceToSquared: function ( v ) { + + var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; + return dx * dx + dy * dy + dz * dz; + + }, + + length: function () { + + return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); + + }, + + lengthSq: function () { + + return this.x * this.x + this.y * this.y + this.z * this.z; + + }, + + negate: function () { + + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; + + return this; + + }, + + normalize: function () { + + var length = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); + + length > 0 ? this.multiplyScalar( 1 / length ) : this.set( 0, 0, 0 ); + + return this; + + }, + + setLength: function( len ) { + + return this.normalize().multiplyScalar( len ); + + }, + + isZero: function () { + + var almostZero = 0.0001; + return ( Math.abs( this.x ) < almostZero ) && ( Math.abs( this.y ) < almostZero ) && ( Math.abs( this.z ) < almostZero ); + + }, + + clone: function () { + + return new THREE.Vector3( this.x, this.y, this.z ); + + }, + + toString: function () { + + return 'THREE.Vector3 ( ' + this.x + ', ' + this.y + ', ' + this.z + ' )'; + + } + +}; +/** + * @author supereggbert / http://www.paulbrunt.co.uk/ + * @author philogb / http://blog.thejit.org/ + */ + +THREE.Vector4 = function ( x, y, z, w ) { + + this.x = x || 0; + this.y = y || 0; + this.z = z || 0; + this.w = w || 1; + +}; + +THREE.Vector4.prototype = { + + set: function ( x, y, z, w ) { + + this.x = x; + this.y = y; + this.z = z; + this.w = w; + + return this; + + }, + + copy: function ( v ) { + + this.x = v.x; + this.y = v.y; + this.z = v.z; + this.w = v.w || 1.0; + + return this; + + }, + + add: function ( v1, v2 ) { + + this.x = v1.x + v2.x; + this.y = v1.y + v2.y; + this.z = v1.z + v2.z; + this.w = v1.w + v2.w; + + return this; + + }, + + addSelf: function ( v ) { + + this.x += v.x; + this.y += v.y; + this.z += v.z; + this.w += v.w; + + return this; + + }, + + sub: function ( v1, v2 ) { + + this.x = v1.x - v2.x; + this.y = v1.y - v2.y; + this.z = v1.z - v2.z; + this.w = v1.w - v2.w; + + return this; + + }, + + subSelf: function ( v ) { + + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; + + return this; + + }, + + multiplyScalar: function ( s ) { + + this.x *= s; + this.y *= s; + this.z *= s; + this.w *= s; + + return this; + + }, + + divideScalar: function ( s ) { + + this.x /= s; + this.y /= s; + this.z /= s; + this.w /= s; + + return this; + + }, + + lerpSelf: function ( v, alpha ) { + + this.x = this.x + (v.x - this.x) * alpha; + this.y = this.y + (v.y - this.y) * alpha; + this.z = this.z + (v.z - this.z) * alpha; + this.w = this.w + (v.w - this.w) * alpha; + }, + + clone: function () { + + return new THREE.Vector4( this.x, this.y, this.z, this.w ); + + }, + + toString: function () { + + return 'THREE.Vector4 (' + this.x + ', ' + this.y + ', ' + this.z + ', ' + this.w + ')'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Ray = function ( origin, direction ) { + + this.origin = origin || new THREE.Vector3(); + this.direction = direction || new THREE.Vector3(); + +} + +THREE.Ray.prototype = { + + intersectScene: function ( scene ) { + + var i, l, object, + objects = scene.objects, + intersects = []; + + for ( i = 0, l = objects.length; i < l; i++ ) { + + object = objects[i]; + + if ( object instanceof THREE.Mesh ) { + + intersects = intersects.concat( this.intersectObject( object ) ); + + } + + } + + intersects.sort( function ( a, b ) { return a.distance - b.distance; } ); + + return intersects; + + }, + + intersectObject: function ( object ) { + + var f, fl, face, a, b, c, d, normal, + dot, scalar, + origin, direction, + geometry = object.geometry, + vertices = geometry.vertices, + intersect, intersects = [], + intersectPoint; + + for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) { + + face = geometry.faces[ f ]; + + origin = this.origin.clone(); + direction = this.direction.clone(); + + a = object.matrix.multiplyVector3( vertices[ face.a ].position.clone() ); + b = object.matrix.multiplyVector3( vertices[ face.b ].position.clone() ); + c = object.matrix.multiplyVector3( vertices[ face.c ].position.clone() ); + d = face instanceof THREE.Face4 ? object.matrix.multiplyVector3( vertices[ face.d ].position.clone() ) : null; + + normal = object.rotationMatrix.multiplyVector3( face.normal.clone() ); + dot = direction.dot( normal ); + + if ( dot < 0 ) { // Math.abs( dot ) > 0.0001 + + scalar = normal.dot( new THREE.Vector3().sub( a, origin ) ) / dot; + intersectPoint = origin.addSelf( direction.multiplyScalar( scalar ) ); + + if ( face instanceof THREE.Face3 ) { + + if ( pointInFace3( intersectPoint, a, b, c ) ) { + + intersect = { + + distance: this.origin.distanceTo( intersectPoint ), + point: intersectPoint, + face: face, + object: object + + }; + + intersects.push( intersect ); + + } + + } else if ( face instanceof THREE.Face4 ) { + + if ( pointInFace3( intersectPoint, a, b, d ) || pointInFace3( intersectPoint, b, c, d ) ) { + + intersect = { + + distance: this.origin.distanceTo( intersectPoint ), + point: intersectPoint, + face: face, + object: object + + }; + + intersects.push( intersect ); + + } + + } + + } + + } + + return intersects; + + // http://www.blackpawn.com/texts/pointinpoly/default.html + + function pointInFace3( p, a, b, c ) { + + var v0 = c.clone().subSelf( a ), v1 = b.clone().subSelf( a ), v2 = p.clone().subSelf( a ), + dot00 = v0.dot( v0 ), dot01 = v0.dot( v1 ), dot02 = v0.dot( v2 ), dot11 = v1.dot( v1 ), dot12 = v1.dot( v2 ), + + invDenom = 1 / ( dot00 * dot11 - dot01 * dot01 ), + u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom, + v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; + + return ( u > 0 ) && ( v > 0 ) && ( u + v < 1 ); + + } + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Rectangle = function () { + + var _left, _top, _right, _bottom, + _width, _height, _isEmpty = true; + + function resize() { + + _width = _right - _left; + _height = _bottom - _top; + + } + + this.getX = function () { + + return _left; + + }; + + this.getY = function () { + + return _top; + + }; + + this.getWidth = function () { + + return _width; + + }; + + this.getHeight = function () { + + return _height; + + }; + + this.getLeft = function() { + + return _left; + + }; + + this.getTop = function() { + + return _top; + + }; + + this.getRight = function() { + + return _right; + + }; + + this.getBottom = function() { + + return _bottom; + + }; + + this.set = function ( left, top, right, bottom ) { + + _isEmpty = false; + + _left = left; _top = top; + _right = right; _bottom = bottom; + + resize(); + + }; + + this.addPoint = function ( x, y ) { + + if ( _isEmpty ) { + + _isEmpty = false; + _left = x; _top = y; + _right = x; _bottom = y; + + resize(); + + } else { + + _left = _left < x ? _left : x; // Math.min( _left, x ); + _top = _top < y ? _top : y; // Math.min( _top, y ); + _right = _right > x ? _right : x; // Math.max( _right, x ); + _bottom = _bottom > y ? _bottom : y; // Math.max( _bottom, y ); + + resize(); + } + + }; + + this.add3Points = function ( x1, y1, x2, y2, x3, y3 ) { + + if (_isEmpty) { + + _isEmpty = false; + _left = x1 < x2 ? ( x1 < x3 ? x1 : x3 ) : ( x2 < x3 ? x2 : x3 ); + _top = y1 < y2 ? ( y1 < y3 ? y1 : y3 ) : ( y2 < y3 ? y2 : y3 ); + _right = x1 > x2 ? ( x1 > x3 ? x1 : x3 ) : ( x2 > x3 ? x2 : x3 ); + _bottom = y1 > y2 ? ( y1 > y3 ? y1 : y3 ) : ( y2 > y3 ? y2 : y3 ); + + resize(); + + } else { + + _left = x1 < x2 ? ( x1 < x3 ? ( x1 < _left ? x1 : _left ) : ( x3 < _left ? x3 : _left ) ) : ( x2 < x3 ? ( x2 < _left ? x2 : _left ) : ( x3 < _left ? x3 : _left ) ); + _top = y1 < y2 ? ( y1 < y3 ? ( y1 < _top ? y1 : _top ) : ( y3 < _top ? y3 : _top ) ) : ( y2 < y3 ? ( y2 < _top ? y2 : _top ) : ( y3 < _top ? y3 : _top ) ); + _right = x1 > x2 ? ( x1 > x3 ? ( x1 > _right ? x1 : _right ) : ( x3 > _right ? x3 : _right ) ) : ( x2 > x3 ? ( x2 > _right ? x2 : _right ) : ( x3 > _right ? x3 : _right ) ); + _bottom = y1 > y2 ? ( y1 > y3 ? ( y1 > _bottom ? y1 : _bottom ) : ( y3 > _bottom ? y3 : _bottom ) ) : ( y2 > y3 ? ( y2 > _bottom ? y2 : _bottom ) : ( y3 > _bottom ? y3 : _bottom ) ); + + resize(); + + }; + + }; + + this.addRectangle = function ( r ) { + + if ( _isEmpty ) { + + _isEmpty = false; + _left = r.getLeft(); _top = r.getTop(); + _right = r.getRight(); _bottom = r.getBottom(); + + resize(); + + } else { + + _left = _left < r.getLeft() ? _left : r.getLeft(); // Math.min(_left, r.getLeft() ); + _top = _top < r.getTop() ? _top : r.getTop(); // Math.min(_top, r.getTop() ); + _right = _right > r.getRight() ? _right : r.getRight(); // Math.max(_right, r.getRight() ); + _bottom = _bottom > r.getBottom() ? _bottom : r.getBottom(); // Math.max(_bottom, r.getBottom() ); + + resize(); + + } + + }; + + this.inflate = function ( v ) { + + _left -= v; _top -= v; + _right += v; _bottom += v; + + resize(); + + }; + + this.minSelf = function ( r ) { + + _left = _left > r.getLeft() ? _left : r.getLeft(); // Math.max( _left, r.getLeft() ); + _top = _top > r.getTop() ? _top : r.getTop(); // Math.max( _top, r.getTop() ); + _right = _right < r.getRight() ? _right : r.getRight(); // Math.min( _right, r.getRight() ); + _bottom = _bottom < r.getBottom() ? _bottom : r.getBottom(); // Math.min( _bottom, r.getBottom() ); + + resize(); + + }; + + /* + this.contains = function ( x, y ) { + + return x > _left && x < _right && y > _top && y < _bottom; + + }; + */ + + this.instersects = function ( r ) { + + // return this.contains( r.getLeft(), r.getTop() ) || this.contains( r.getRight(), r.getTop() ) || this.contains( r.getLeft(), r.getBottom() ) || this.contains( r.getRight(), r.getBottom() ); + + return Math.min( _right, r.getRight() ) - Math.max( _left, r.getLeft() ) >= 0 && + Math.min( _bottom, r.getBottom() ) - Math.max( _top, r.getTop() ) >= 0; + + }; + + this.empty = function () { + + _isEmpty = true; + + _left = 0; _top = 0; + _right = 0; _bottom = 0; + + resize(); + + }; + + this.isEmpty = function () { + + return _isEmpty; + + }; + + this.toString = function () { + + return "THREE.Rectangle ( left: " + _left + ", right: " + _right + ", top: " + _top + ", bottom: " + _bottom + ", width: " + _width + ", height: " + _height + " )"; + + }; + +}; +THREE.Matrix3 = function () { + + this.m = []; + +}; + +THREE.Matrix3.prototype = { + + transpose: function () { + + var tmp; + + tmp = this.m[1]; this.m[1] = this.m[3]; this.m[3] = tmp; + tmp = this.m[2]; this.m[2] = this.m[6]; this.m[6] = tmp; + tmp = this.m[5]; this.m[5] = this.m[7]; this.m[7] = tmp; + + return this; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + * @author supereggbert / http://www.paulbrunt.co.uk/ + * @author philogb / http://blog.thejit.org/ + * @author jordi_ros / http://plattsoft.com + * @author D1plo1d / http://github.com/D1plo1d + */ + +THREE.Matrix4 = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + + this.n11 = n11 || 1; this.n12 = n12 || 0; this.n13 = n13 || 0; this.n14 = n14 || 0; + this.n21 = n21 || 0; this.n22 = n22 || 1; this.n23 = n23 || 0; this.n24 = n24 || 0; + this.n31 = n31 || 0; this.n32 = n32 || 0; this.n33 = n33 || 1; this.n34 = n34 || 0; + this.n41 = n41 || 0; this.n42 = n42 || 0; this.n43 = n43 || 0; this.n44 = n44 || 1; + +}; + +THREE.Matrix4.prototype = { + + identity: function () { + + this.n11 = 1; this.n12 = 0; this.n13 = 0; this.n14 = 0; + this.n21 = 0; this.n22 = 1; this.n23 = 0; this.n24 = 0; + this.n31 = 0; this.n32 = 0; this.n33 = 1; this.n34 = 0; + this.n41 = 0; this.n42 = 0; this.n43 = 0; this.n44 = 1; + + return this; + + }, + + set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + + this.n11 = n11; this.n12 = n12; this.n13 = n13; this.n14 = n14; + this.n21 = n21; this.n22 = n22; this.n23 = n23; this.n24 = n24; + this.n31 = n31; this.n32 = n32; this.n33 = n33; this.n34 = n34; + this.n41 = n41; this.n42 = n42; this.n43 = n43; this.n44 = n44; + + return this; + + }, + + copy: function ( m ) { + + this.n11 = m.n11; this.n12 = m.n12; this.n13 = m.n13; this.n14 = m.n14; + this.n21 = m.n21; this.n22 = m.n22; this.n23 = m.n23; this.n24 = m.n24; + this.n31 = m.n31; this.n32 = m.n32; this.n33 = m.n33; this.n34 = m.n34; + this.n41 = m.n41; this.n42 = m.n42; this.n43 = m.n43; this.n44 = m.n44; + + return this; + + }, + + lookAt: function ( eye, center, up ) { + + var x = new THREE.Vector3(), y = new THREE.Vector3(), z = new THREE.Vector3(); + + z.sub( eye, center ).normalize(); + x.cross( up, z ).normalize(); + y.cross( z, x ).normalize(); + + this.n11 = x.x; this.n12 = x.y; this.n13 = x.z; this.n14 = - x.dot( eye ); + this.n21 = y.x; this.n22 = y.y; this.n23 = y.z; this.n24 = - y.dot( eye ); + this.n31 = z.x; this.n32 = z.y; this.n33 = z.z; this.n34 = - z.dot( eye ); + this.n41 = 0; this.n42 = 0; this.n43 = 0; this.n44 = 1; + + return this; + + }, + + multiplyVector3: function ( v ) { + + var vx = v.x, vy = v.y, vz = v.z, + d = 1 / ( this.n41 * vx + this.n42 * vy + this.n43 * vz + this.n44 ); + + v.x = ( this.n11 * vx + this.n12 * vy + this.n13 * vz + this.n14 ) * d; + v.y = ( this.n21 * vx + this.n22 * vy + this.n23 * vz + this.n24 ) * d; + v.z = ( this.n31 * vx + this.n32 * vy + this.n33 * vz + this.n34 ) * d; + + return v; + + }, + + multiplyVector4: function ( v ) { + + var vx = v.x, vy = v.y, vz = v.z, vw = v.w; + + v.x = this.n11 * vx + this.n12 * vy + this.n13 * vz + this.n14 * vw; + v.y = this.n21 * vx + this.n22 * vy + this.n23 * vz + this.n24 * vw; + v.z = this.n31 * vx + this.n32 * vy + this.n33 * vz + this.n34 * vw; + v.w = this.n41 * vx + this.n42 * vy + this.n43 * vz + this.n44 * vw; + + return v; + + }, + + crossVector: function ( a ) { + + var v = new THREE.Vector4(); + + v.x = this.n11 * a.x + this.n12 * a.y + this.n13 * a.z + this.n14 * a.w; + v.y = this.n21 * a.x + this.n22 * a.y + this.n23 * a.z + this.n24 * a.w; + v.z = this.n31 * a.x + this.n32 * a.y + this.n33 * a.z + this.n34 * a.w; + + v.w = ( a.w ) ? this.n41 * a.x + this.n42 * a.y + this.n43 * a.z + this.n44 * a.w : 1; + + return v; + + }, + + multiply: function ( a, b ) { + + var a11 = a.n11, a12 = a.n12, a13 = a.n13, a14 = a.n14, + a21 = a.n21, a22 = a.n22, a23 = a.n23, a24 = a.n24, + a31 = a.n31, a32 = a.n32, a33 = a.n33, a34 = a.n34, + a41 = a.n41, a42 = a.n42, a43 = a.n43, a44 = a.n44, + + b11 = b.n11, b12 = b.n12, b13 = b.n13, b14 = b.n14, + b21 = b.n21, b22 = b.n22, b23 = b.n23, b24 = b.n24, + b31 = b.n31, b32 = b.n32, b33 = b.n33, b34 = b.n34, + b41 = b.n41, b42 = b.n42, b43 = b.n43, b44 = b.n44; + + this.n11 = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; + this.n12 = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; + this.n13 = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; + this.n14 = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; + + this.n21 = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; + this.n22 = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; + this.n23 = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; + this.n24 = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; + + this.n31 = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; + this.n32 = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; + this.n33 = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; + this.n34 = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; + + this.n41 = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; + this.n42 = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; + this.n43 = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; + this.n44 = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; + + return this; + + }, + + multiplySelf: function ( m ) { + + var n11 = this.n11, n12 = this.n12, n13 = this.n13, n14 = this.n14, + n21 = this.n21, n22 = this.n22, n23 = this.n23, n24 = this.n24, + n31 = this.n31, n32 = this.n32, n33 = this.n33, n34 = this.n34, + n41 = this.n41, n42 = this.n42, n43 = this.n43, n44 = this.n44, + mn11 = m.n11, mn21 = m.n21, mn31 = m.n31, mn41 = m.n41, + mn12 = m.n12, mn22 = m.n22, mn32 = m.n32, mn42 = m.n42, + mn13 = m.n13, mn23 = m.n23, mn33 = m.n33, mn43 = m.n43, + mn14 = m.n14, mn24 = m.n24, mn34 = m.n34, mn44 = m.n44; + + this.n11 = n11 * mn11 + n12 * mn21 + n13 * mn31 + n14 * mn41; + this.n12 = n11 * mn12 + n12 * mn22 + n13 * mn32 + n14 * mn42; + this.n13 = n11 * mn13 + n12 * mn23 + n13 * mn33 + n14 * mn43; + this.n14 = n11 * mn14 + n12 * mn24 + n13 * mn34 + n14 * mn44; + + this.n21 = n21 * mn11 + n22 * mn21 + n23 * mn31 + n24 * mn41; + this.n22 = n21 * mn12 + n22 * mn22 + n23 * mn32 + n24 * mn42; + this.n23 = n21 * mn13 + n22 * mn23 + n23 * mn33 + n24 * mn43; + this.n24 = n21 * mn14 + n22 * mn24 + n23 * mn34 + n24 * mn44; + + this.n31 = n31 * mn11 + n32 * mn21 + n33 * mn31 + n34 * mn41; + this.n32 = n31 * mn12 + n32 * mn22 + n33 * mn32 + n34 * mn42; + this.n33 = n31 * mn13 + n32 * mn23 + n33 * mn33 + n34 * mn43; + this.n34 = n31 * mn14 + n32 * mn24 + n33 * mn34 + n34 * mn44; + + this.n41 = n41 * mn11 + n42 * mn21 + n43 * mn31 + n44 * mn41; + this.n42 = n41 * mn12 + n42 * mn22 + n43 * mn32 + n44 * mn42; + this.n43 = n41 * mn13 + n42 * mn23 + n43 * mn33 + n44 * mn43; + this.n44 = n41 * mn14 + n42 * mn24 + n43 * mn34 + n44 * mn44; + + return this; + + }, + + multiplyScalar: function ( s ) { + + this.n11 *= s; this.n12 *= s; this.n13 *= s; this.n14 *= s; + this.n21 *= s; this.n22 *= s; this.n23 *= s; this.n24 *= s; + this.n31 *= s; this.n32 *= s; this.n33 *= s; this.n34 *= s; + this.n41 *= s; this.n42 *= s; this.n43 *= s; this.n44 *= s; + + return this; + + }, + + determinant: function () { + + //TODO: make this more efficient + //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) + return ( + this.n14 * this.n23 * this.n32 * this.n41- + this.n13 * this.n24 * this.n32 * this.n41- + this.n14 * this.n22 * this.n33 * this.n41+ + this.n12 * this.n24 * this.n33 * this.n41+ + + this.n13 * this.n22 * this.n34 * this.n41- + this.n12 * this.n23 * this.n34 * this.n41- + this.n14 * this.n23 * this.n31 * this.n42+ + this.n13 * this.n24 * this.n31 * this.n42+ + + this.n14 * this.n21 * this.n33 * this.n42- + this.n11 * this.n24 * this.n33 * this.n42- + this.n13 * this.n21 * this.n34 * this.n42+ + this.n11 * this.n23 * this.n34 * this.n42+ + + this.n14 * this.n22 * this.n31 * this.n43- + this.n12 * this.n24 * this.n31 * this.n43- + this.n14 * this.n21 * this.n32 * this.n43+ + this.n11 * this.n24 * this.n32 * this.n43+ + + this.n12 * this.n21 * this.n34 * this.n43- + this.n11 * this.n22 * this.n34 * this.n43- + this.n13 * this.n22 * this.n31 * this.n44+ + this.n12 * this.n23 * this.n31 * this.n44+ + + this.n13 * this.n21 * this.n32 * this.n44- + this.n11 * this.n23 * this.n32 * this.n44- + this.n12 * this.n21 * this.n33 * this.n44+ + this.n11 * this.n22 * this.n33 * this.n44 ); + + }, + + transpose: function () { + + function swap( obj, p1, p2 ) { + + var aux = obj[ p1 ]; + obj[ p1 ] = obj[ p2 ]; + obj[ p2 ] = aux; + + } + + swap( this, 'n21', 'n12' ); + swap( this, 'n31', 'n13' ); + swap( this, 'n32', 'n23' ); + swap( this, 'n41', 'n14' ); + swap( this, 'n42', 'n24' ); + swap( this, 'n43', 'n34' ); + + return this; + + }, + + clone: function () { + + var m = new THREE.Matrix4(); + + m.n11 = this.n11; m.n12 = this.n12; m.n13 = this.n13; m.n14 = this.n14; + m.n21 = this.n21; m.n22 = this.n22; m.n23 = this.n23; m.n24 = this.n24; + m.n31 = this.n31; m.n32 = this.n32; m.n33 = this.n33; m.n34 = this.n34; + m.n41 = this.n41; m.n42 = this.n42; m.n43 = this.n43; m.n44 = this.n44; + + return m; + + }, + + flatten: function() { + + return [ this.n11, this.n21, this.n31, this.n41, + this.n12, this.n22, this.n32, this.n42, + this.n13, this.n23, this.n33, this.n43, + this.n14, this.n24, this.n34, this.n44 ]; + + }, + + toString: function() { + + return "| " + this.n11 + " " + this.n12 + " " + this.n13 + " " + this.n14 + " |\n" + + "| " + this.n21 + " " + this.n22 + " " + this.n23 + " " + this.n24 + " |\n" + + "| " + this.n31 + " " + this.n32 + " " + this.n33 + " " + this.n34 + " |\n" + + "| " + this.n41 + " " + this.n42 + " " + this.n43 + " " + this.n44 + " |"; + + } + +}; + +THREE.Matrix4.translationMatrix = function ( x, y, z ) { + + var m = new THREE.Matrix4(); + + m.n14 = x; + m.n24 = y; + m.n34 = z; + + return m; + +}; + +THREE.Matrix4.scaleMatrix = function ( x, y, z ) { + + var m = new THREE.Matrix4(); + + m.n11 = x; + m.n22 = y; + m.n33 = z; + + return m; + +}; + +THREE.Matrix4.rotationXMatrix = function ( theta ) { + + var rot = new THREE.Matrix4(); + + rot.n22 = rot.n33 = Math.cos( theta ); + rot.n32 = Math.sin( theta ); + rot.n23 = - rot.n32; + + return rot; + +}; + +THREE.Matrix4.rotationYMatrix = function ( theta ) { + + var rot = new THREE.Matrix4(); + + rot.n11 = rot.n33 = Math.cos( theta ); + rot.n13 = Math.sin( theta ); + rot.n31 = - rot.n13; + + return rot; + +}; + +THREE.Matrix4.rotationZMatrix = function ( theta ) { + + var rot = new THREE.Matrix4(); + + rot.n11 = rot.n22 = Math.cos( theta ); + rot.n21 = Math.sin( theta ); + rot.n12 = - rot.n21; + + return rot; + +}; + +THREE.Matrix4.rotationAxisAngleMatrix = function ( axis, angle ) { + + //Based on http://www.gamedev.net/reference/articles/article1199.asp + + var rot = new THREE.Matrix4(), + c = Math.cos( angle ), + s = Math.sin( angle ), + t = 1 - c, + x = axis.x, y = axis.y, z = axis.z; + + rot.n11 = t * x * x + c; + rot.n12 = t * x * y - s * z; + rot.n13 = t * x * z + s * y; + rot.n21 = t * x * y + s * z; + rot.n22 = t * y * y + c; + rot.n23 = t * y * z - s * x; + rot.n31 = t * x * z - s * y; + rot.n32 = t * y * z + s * x; + rot.n33 = t * z * z + c; + + return rot; + +}; + +THREE.Matrix4.makeInvert = function ( m1 ) { + + //TODO: make this more efficient + //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) + var m2 = new THREE.Matrix4(); + + m2.n11 = m1.n23*m1.n34*m1.n42 - m1.n24*m1.n33*m1.n42 + m1.n24*m1.n32*m1.n43 - m1.n22*m1.n34*m1.n43 - m1.n23*m1.n32*m1.n44 + m1.n22*m1.n33*m1.n44; + m2.n12 = m1.n14*m1.n33*m1.n42 - m1.n13*m1.n34*m1.n42 - m1.n14*m1.n32*m1.n43 + m1.n12*m1.n34*m1.n43 + m1.n13*m1.n32*m1.n44 - m1.n12*m1.n33*m1.n44; + m2.n13 = m1.n13*m1.n24*m1.n42 - m1.n14*m1.n23*m1.n42 + m1.n14*m1.n22*m1.n43 - m1.n12*m1.n24*m1.n43 - m1.n13*m1.n22*m1.n44 + m1.n12*m1.n23*m1.n44; + m2.n14 = m1.n14*m1.n23*m1.n32 - m1.n13*m1.n24*m1.n32 - m1.n14*m1.n22*m1.n33 + m1.n12*m1.n24*m1.n33 + m1.n13*m1.n22*m1.n34 - m1.n12*m1.n23*m1.n34; + m2.n21 = m1.n24*m1.n33*m1.n41 - m1.n23*m1.n34*m1.n41 - m1.n24*m1.n31*m1.n43 + m1.n21*m1.n34*m1.n43 + m1.n23*m1.n31*m1.n44 - m1.n21*m1.n33*m1.n44; + m2.n22 = m1.n13*m1.n34*m1.n41 - m1.n14*m1.n33*m1.n41 + m1.n14*m1.n31*m1.n43 - m1.n11*m1.n34*m1.n43 - m1.n13*m1.n31*m1.n44 + m1.n11*m1.n33*m1.n44; + m2.n23 = m1.n14*m1.n23*m1.n41 - m1.n13*m1.n24*m1.n41 - m1.n14*m1.n21*m1.n43 + m1.n11*m1.n24*m1.n43 + m1.n13*m1.n21*m1.n44 - m1.n11*m1.n23*m1.n44; + m2.n24 = m1.n13*m1.n24*m1.n31 - m1.n14*m1.n23*m1.n31 + m1.n14*m1.n21*m1.n33 - m1.n11*m1.n24*m1.n33 - m1.n13*m1.n21*m1.n34 + m1.n11*m1.n23*m1.n34; + m2.n31 = m1.n22*m1.n34*m1.n41 - m1.n24*m1.n32*m1.n41 + m1.n24*m1.n31*m1.n42 - m1.n21*m1.n34*m1.n42 - m1.n22*m1.n31*m1.n44 + m1.n21*m1.n32*m1.n44; + m2.n32 = m1.n14*m1.n32*m1.n41 - m1.n12*m1.n34*m1.n41 - m1.n14*m1.n31*m1.n42 + m1.n11*m1.n34*m1.n42 + m1.n12*m1.n31*m1.n44 - m1.n11*m1.n32*m1.n44; + m2.n33 = m1.n13*m1.n24*m1.n41 - m1.n14*m1.n22*m1.n41 + m1.n14*m1.n21*m1.n42 - m1.n11*m1.n24*m1.n42 - m1.n12*m1.n21*m1.n44 + m1.n11*m1.n22*m1.n44; + m2.n34 = m1.n14*m1.n22*m1.n31 - m1.n12*m1.n24*m1.n31 - m1.n14*m1.n21*m1.n32 + m1.n11*m1.n24*m1.n32 + m1.n12*m1.n21*m1.n34 - m1.n11*m1.n22*m1.n34; + m2.n41 = m1.n23*m1.n32*m1.n41 - m1.n22*m1.n33*m1.n41 - m1.n23*m1.n31*m1.n42 + m1.n21*m1.n33*m1.n42 + m1.n22*m1.n31*m1.n43 - m1.n21*m1.n32*m1.n43; + m2.n42 = m1.n12*m1.n33*m1.n41 - m1.n13*m1.n32*m1.n41 + m1.n13*m1.n31*m1.n42 - m1.n11*m1.n33*m1.n42 - m1.n12*m1.n31*m1.n43 + m1.n11*m1.n32*m1.n43; + m2.n43 = m1.n13*m1.n22*m1.n41 - m1.n12*m1.n23*m1.n41 - m1.n13*m1.n21*m1.n42 + m1.n11*m1.n23*m1.n42 + m1.n12*m1.n21*m1.n43 - m1.n11*m1.n22*m1.n43; + m2.n44 = m1.n12*m1.n23*m1.n31 - m1.n13*m1.n22*m1.n31 + m1.n13*m1.n21*m1.n32 - m1.n11*m1.n23*m1.n32 - m1.n12*m1.n21*m1.n33 + m1.n11*m1.n22*m1.n33; + m2.multiplyScalar( 1 / m1.determinant() ); + + return m2; + +}; + +THREE.Matrix4.makeInvert3x3 = function ( m1 ) { + + // input: THREE.Matrix4, output: THREE.Matrix3 + // ( based on http://code.google.com/p/webgl-mjs/ ) + + var m = m1.flatten(), + m2 = new THREE.Matrix3(), + + a11 = m[ 10 ] * m[ 5 ] - m[ 6 ] * m[ 9 ], + a21 = - m[ 10 ] * m[ 1 ] + m[ 2 ] * m[ 9 ], + a31 = m[ 6 ] * m[ 1 ] - m[ 2 ] * m[ 5 ], + a12 = - m[ 10 ] * m[ 4 ] + m[ 6 ] * m[ 8 ], + a22 = m[ 10 ] * m[ 0 ] - m[ 2 ] * m[ 8 ], + a32 = - m[ 6 ] * m[ 0 ] + m[ 2 ] * m[ 4 ], + a13 = m[ 9 ] * m[ 4 ] - m[ 5 ] * m[ 8 ], + a23 = - m[ 9 ] * m[ 0 ] + m[ 1 ] * m[ 8 ], + a33 = m[ 5 ] * m[ 0 ] - m[ 1 ] * m[ 4 ], + det = m[ 0 ] * ( a11 ) + m[ 1 ] * ( a12 ) + m[ 2 ] * ( a13 ), + idet; + + // no inverse + if (det == 0) throw "matrix not invertible"; + + idet = 1.0 / det; + + m2.m[ 0 ] = idet * a11; m2.m[ 1 ] = idet * a21; m2.m[ 2 ] = idet * a31; + m2.m[ 3 ] = idet * a12; m2.m[ 4 ] = idet * a22; m2.m[ 5 ] = idet * a32; + m2.m[ 6 ] = idet * a13; m2.m[ 7 ] = idet * a23; m2.m[ 8 ] = idet * a33; + + return m2; + +} + +THREE.Matrix4.makeFrustum = function( left, right, bottom, top, near, far ) { + + var m, x, y, a, b, c, d; + + m = new THREE.Matrix4(); + x = 2 * near / ( right - left ); + y = 2 * near / ( top - bottom ); + a = ( right + left ) / ( right - left ); + b = ( top + bottom ) / ( top - bottom ); + c = - ( far + near ) / ( far - near ); + d = - 2 * far * near / ( far - near ); + + m.n11 = x; m.n12 = 0; m.n13 = a; m.n14 = 0; + m.n21 = 0; m.n22 = y; m.n23 = b; m.n24 = 0; + m.n31 = 0; m.n32 = 0; m.n33 = c; m.n34 = d; + m.n41 = 0; m.n42 = 0; m.n43 = - 1; m.n44 = 0; + + return m; + +}; + +THREE.Matrix4.makePerspective = function( fov, aspect, near, far ) { + + var ymax, ymin, xmin, xmax; + + ymax = near * Math.tan( fov * Math.PI / 360 ); + ymin = - ymax; + xmin = ymin * aspect; + xmax = ymax * aspect; + + return THREE.Matrix4.makeFrustum( xmin, xmax, ymin, ymax, near, far ); + +}; + +THREE.Matrix4.makeOrtho = function( left, right, top, bottom, near, far ) { + + var m, x, y, z, w, h, p; + + m = new THREE.Matrix4(); + w = right - left; + h = top - bottom; + p = far - near; + x = ( right + left ) / w; + y = ( top + bottom ) / h; + z = ( far + near ) / p; + + m.n11 = 2 / w; m.n12 = 0; m.n13 = 0; m.n14 = -x; + m.n21 = 0; m.n22 = 2 / h; m.n23 = 0; m.n24 = -y; + m.n31 = 0; m.n32 = 0; m.n33 = -2 / p; m.n34 = -z; + m.n41 = 0; m.n42 = 0; m.n43 = 0; m.n44 = 1; + + return m; + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Vertex = function ( position, normal ) { + + this.position = position || new THREE.Vector3(); + this.positionWorld = new THREE.Vector3(); + this.positionScreen = new THREE.Vector4(); + + this.normal = normal || new THREE.Vector3(); + this.normalWorld = new THREE.Vector3(); + this.normalScreen = new THREE.Vector3(); + + this.tangent = new THREE.Vector4(); + + this.__visible = true; + +}; + +THREE.Vertex.prototype = { + + toString: function () { + + return 'THREE.Vertex ( position: ' + this.position + ', normal: ' + this.normal + ' )'; + } +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Face3 = function ( a, b, c, normal, materials ) { + + this.a = a; + this.b = b; + this.c = c; + + this.centroid = new THREE.Vector3(); + this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3(); + this.vertexNormals = normal instanceof Array ? normal : []; + + this.materials = materials instanceof Array ? materials : [ materials ]; + +}; + +THREE.Face3.prototype = { + + toString: function () { + + return 'THREE.Face3 ( ' + this.a + ', ' + this.b + ', ' + this.c + ' )'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Face4 = function ( a, b, c, d, normal, materials ) { + + this.a = a; + this.b = b; + this.c = c; + this.d = d; + + this.centroid = new THREE.Vector3(); + this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3(); + this.vertexNormals = normal instanceof Array ? normal : []; + + this.materials = materials instanceof Array ? materials : [ materials ]; + +}; + + +THREE.Face4.prototype = { + + toString: function () { + + return 'THREE.Face4 ( ' + this.a + ', ' + this.b + ', ' + this.c + ' ' + this.d + ' )'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.UV = function ( u, v ) { + + this.u = u || 0; + this.v = v || 0; + +}; + +THREE.UV.prototype = { + + copy: function ( uv ) { + + this.u = uv.u; + this.v = uv.v; + + }, + + toString: function () { + + return 'THREE.UV (' + this.u + ', ' + this.v + ')'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + * @author kile / http://kile.stravaganza.org/ + * @author alteredq / http://alteredqualia.com/ + */ + +THREE.Geometry = function () { + + this.vertices = []; + this.faces = []; + this.uvs = []; + + this.boundingBox = null; + this.boundingSphere = null; + + this.geometryChunks = {}; + + this.hasTangents = false; + +}; + +THREE.Geometry.prototype = { + + computeCentroids: function () { + + var f, fl, face; + + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + + face = this.faces[ f ]; + face.centroid.set( 0, 0, 0 ); + + if ( face instanceof THREE.Face3 ) { + + face.centroid.addSelf( this.vertices[ face.a ].position ); + face.centroid.addSelf( this.vertices[ face.b ].position ); + face.centroid.addSelf( this.vertices[ face.c ].position ); + face.centroid.divideScalar( 3 ); + + } else if ( face instanceof THREE.Face4 ) { + + face.centroid.addSelf( this.vertices[ face.a ].position ); + face.centroid.addSelf( this.vertices[ face.b ].position ); + face.centroid.addSelf( this.vertices[ face.c ].position ); + face.centroid.addSelf( this.vertices[ face.d ].position ); + face.centroid.divideScalar( 4 ); + + } + + } + + }, + + computeFaceNormals: function ( useVertexNormals ) { + + var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC, + cb = new THREE.Vector3(), ab = new THREE.Vector3(); + + for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { + + vertex = this.vertices[ v ]; + vertex.normal.set( 0, 0, 0 ); + + } + + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + + face = this.faces[ f ]; + + if ( useVertexNormals && face.vertexNormals.length ) { + + cb.set( 0, 0, 0 ); + + for ( n = 0, nl = face.normal.length; n < nl; n++ ) { + + cb.addSelf( face.vertexNormals[n] ); + + } + + cb.divideScalar( 3 ); + + if ( ! cb.isZero() ) { + + cb.normalize(); + + } + + face.normal.copy( cb ); + + } else { + + vA = this.vertices[ face.a ]; + vB = this.vertices[ face.b ]; + vC = this.vertices[ face.c ]; + + cb.sub( vC.position, vB.position ); + ab.sub( vA.position, vB.position ); + cb.crossSelf( ab ); + + if ( !cb.isZero() ) { + + cb.normalize(); + + } + + face.normal.copy( cb ); + + } + + } + + }, + + computeVertexNormals: function () { + + var v, vl, vertices = [], + f, fl, face; + + for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { + + vertices[ v ] = new THREE.Vector3(); + + } + + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + + face = this.faces[ f ]; + + if ( face instanceof THREE.Face3 ) { + + vertices[ face.a ].addSelf( face.normal ); + vertices[ face.b ].addSelf( face.normal ); + vertices[ face.c ].addSelf( face.normal ); + + } else if ( face instanceof THREE.Face4 ) { + + vertices[ face.a ].addSelf( face.normal ); + vertices[ face.b ].addSelf( face.normal ); + vertices[ face.c ].addSelf( face.normal ); + vertices[ face.d ].addSelf( face.normal ); + + } + + } + + for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { + + vertices[ v ].normalize(); + + } + + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + + face = this.faces[ f ]; + + if ( face instanceof THREE.Face3 ) { + + face.vertexNormals[ 0 ] = vertices[ face.a ].clone(); + face.vertexNormals[ 1 ] = vertices[ face.b ].clone(); + face.vertexNormals[ 2 ] = vertices[ face.c ].clone(); + + } else if ( face instanceof THREE.Face4 ) { + + face.vertexNormals[ 0 ] = vertices[ face.a ].clone(); + face.vertexNormals[ 1 ] = vertices[ face.b ].clone(); + face.vertexNormals[ 2 ] = vertices[ face.c ].clone(); + face.vertexNormals[ 3 ] = vertices[ face.d ].clone(); + + } + + } + + }, + + computeTangents: function() { + + // based on http://www.terathon.com/code/tangent.html + // tangents go to vertices + + var f, fl, v, vl, face, uv, vA, vB, vC, uvA, uvB, uvC, + x1, x2, y1, y2, z1, z2, + s1, s2, t1, t2, r, t, test, + tan1 = [], tan2 = [], + sdir = new THREE.Vector3(), tdir = new THREE.Vector3(), + tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(), + n = new THREE.Vector3(), w; + + for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { + + tan1[ v ] = new THREE.Vector3(); + tan2[ v ] = new THREE.Vector3(); + + } + + function handleTriangle( context, a, b, c, ua, ub, uc ) { + + vA = context.vertices[ a ].position; + vB = context.vertices[ b ].position; + vC = context.vertices[ c ].position; + + uvA = uv[ ua ]; + uvB = uv[ ub ]; + uvC = uv[ uc ]; + + x1 = vB.x - vA.x; + x2 = vC.x - vA.x; + y1 = vB.y - vA.y; + y2 = vC.y - vA.y; + z1 = vB.z - vA.z; + z2 = vC.z - vA.z; + + s1 = uvB.u - uvA.u; + s2 = uvC.u - uvA.u; + t1 = uvB.v - uvA.v; + t2 = uvC.v - uvA.v; + + r = 1.0 / ( s1 * t2 - s2 * t1 ); + sdir.set( ( t2 * x1 - t1 * x2 ) * r, + ( t2 * y1 - t1 * y2 ) * r, + ( t2 * z1 - t1 * z2 ) * r ); + tdir.set( ( s1 * x2 - s2 * x1 ) * r, + ( s1 * y2 - s2 * y1 ) * r, + ( s1 * z2 - s2 * z1 ) * r ); + + tan1[ a ].addSelf( sdir ); + tan1[ b ].addSelf( sdir ); + tan1[ c ].addSelf( sdir ); + + tan2[ a ].addSelf( tdir ); + tan2[ b ].addSelf( tdir ); + tan2[ c ].addSelf( tdir ); + + } + + for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { + + face = this.faces[ f ]; + uv = this.uvs[ f ]; + + if ( face instanceof THREE.Face3 ) { + + handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 ); + + this.vertices[ face.a ].normal.copy( face.vertexNormals[ 0 ] ); + this.vertices[ face.b ].normal.copy( face.vertexNormals[ 1 ] ); + this.vertices[ face.c ].normal.copy( face.vertexNormals[ 2 ] ); + + + } else if ( face instanceof THREE.Face4 ) { + + handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 ); + handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 ); + + this.vertices[ face.a ].normal.copy( face.vertexNormals[ 0 ] ); + this.vertices[ face.b ].normal.copy( face.vertexNormals[ 1 ] ); + this.vertices[ face.c ].normal.copy( face.vertexNormals[ 2 ] ); + this.vertices[ face.d ].normal.copy( face.vertexNormals[ 3 ] ); + + } + + } + + for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { + + n.copy( this.vertices[ v ].normal ); + t = tan1[ v ]; + + // Gram-Schmidt orthogonalize + + tmp.copy( t ); + tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize(); + + // Calculate handedness + + tmp2.cross( this.vertices[ v ].normal, t ); + test = tmp2.dot( tan2[ v ] ); + w = (test < 0.0) ? -1.0 : 1.0; + + this.vertices[ v ].tangent.set( tmp.x, tmp.y, tmp.z, w ); + + } + + this.hasTangents = true; + + }, + + computeBoundingBox: function () { + + var vertex; + + if ( this.vertices.length > 0 ) { + + this.boundingBox = { 'x': [ this.vertices[ 0 ].position.x, this.vertices[ 0 ].position.x ], + 'y': [ this.vertices[ 0 ].position.y, this.vertices[ 0 ].position.y ], + 'z': [ this.vertices[ 0 ].position.z, this.vertices[ 0 ].position.z ] }; + + for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) { + + vertex = this.vertices[ v ]; + + if ( vertex.position.x < this.boundingBox.x[ 0 ] ) { + + this.boundingBox.x[ 0 ] = vertex.position.x; + + } else if ( vertex.position.x > this.boundingBox.x[ 1 ] ) { + + this.boundingBox.x[ 1 ] = vertex.position.x; + + } + + if ( vertex.position.y < this.boundingBox.y[ 0 ] ) { + + this.boundingBox.y[ 0 ] = vertex.position.y; + + } else if ( vertex.position.y > this.boundingBox.y[ 1 ] ) { + + this.boundingBox.y[ 1 ] = vertex.position.y; + + } + + if ( vertex.position.z < this.boundingBox.z[ 0 ] ) { + + this.boundingBox.z[ 0 ] = vertex.position.z; + + } else if ( vertex.position.z > this.boundingBox.z[ 1 ] ) { + + this.boundingBox.z[ 1 ] = vertex.position.z; + + } + + } + + } + + }, + + computeBoundingSphere: function () { + + var radius = this.boundingSphere === null ? 0 : this.boundingSphere.radius; + + for ( var v = 0, vl = this.vertices.length; v < vl; v ++ ) { + + radius = Math.max( radius, this.vertices[ v ].position.length() ); + + } + + this.boundingSphere = { radius: radius }; + + }, + + sortFacesByMaterial: function () { + + // TODO + // Should optimize by grouping faces with ColorFill / ColorStroke materials + // which could then use vertex color attributes instead of each being + // in its separate VBO + + var i, l, f, fl, face, material, materials, vertices, mhash, ghash, hash_map = {}; + + function materialHash( material ) { + + var hash_array = []; + + for ( i = 0, l = material.length; i < l; i++ ) { + + if ( material[ i ] == undefined ) { + + hash_array.push( "undefined" ); + + } else { + + hash_array.push( material[ i ].toString() ); + + } + + } + + return hash_array.join( '_' ); + + } + + for ( f = 0, fl = this.faces.length; f < fl; f++ ) { + + face = this.faces[ f ]; + materials = face.materials; + + mhash = materialHash( materials ); + + if ( hash_map[ mhash ] == undefined ) { + + hash_map[ mhash ] = { 'hash': mhash, 'counter': 0 }; + + } + + ghash = hash_map[ mhash ].hash + '_' + hash_map[ mhash ].counter; + + if ( this.geometryChunks[ ghash ] == undefined ) { + + this.geometryChunks[ ghash ] = { 'faces': [], 'materials': materials, 'vertices': 0 }; + + } + + vertices = face instanceof THREE.Face3 ? 3 : 4; + + if ( this.geometryChunks[ ghash ].vertices + vertices > 65535 ) { + + hash_map[ mhash ].counter += 1; + ghash = hash_map[ mhash ].hash + '_' + hash_map[ mhash ].counter; + + if ( this.geometryChunks[ ghash ] == undefined ) { + + this.geometryChunks[ ghash ] = { 'faces': [], 'materials': materials, 'vertices': 0 }; + + } + + } + + this.geometryChunks[ ghash ].faces.push( f ); + this.geometryChunks[ ghash ].vertices += vertices; + + } + + }, + + toString: function () { + + return 'THREE.Geometry ( vertices: ' + this.vertices + ', faces: ' + this.faces + ', uvs: ' + this.uvs + ' )'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Camera = function ( fov, aspect, near, far ) { + + this.fov = fov; + this.aspect = aspect; + this.near = near; + this.far = far; + + this.position = new THREE.Vector3(); + this.target = { position: new THREE.Vector3() }; + + this.autoUpdateMatrix = true; + + this.projectionMatrix = null; + this.matrix = new THREE.Matrix4(); + + this.up = new THREE.Vector3( 0, 1, 0 ); + + this.translateX = function ( amount ) { + + var vector = this.target.position.clone().subSelf( this.position ).normalize().multiplyScalar( amount ); + vector.cross( vector.clone(), this.up ); + + this.position.addSelf( vector ); + this.target.position.addSelf( vector ); + + }; + + /* TODO + this.translateY = function ( amount ) { + + }; + */ + + this.translateZ = function ( amount ) { + + var vector = this.target.position.clone().subSelf( this.position ).normalize().multiplyScalar( amount ); + + this.position.subSelf( vector ); + this.target.position.subSelf( vector ); + + }; + + this.updateMatrix = function () { + + this.matrix.lookAt( this.position, this.target.position, this.up ); + + }; + + this.updateProjectionMatrix = function () { + + this.projectionMatrix = THREE.Matrix4.makePerspective( this.fov, this.aspect, this.near, this.far ); + + }; + + this.updateProjectionMatrix(); + +}; + +THREE.Camera.prototype = { + + toString: function () { + + return 'THREE.Camera ( ' + this.position + ', ' + this.target.position + ' )'; + + } + +}; +THREE.Light = function ( hex ) { + + this.color = new THREE.Color( hex ); + +}; +THREE.AmbientLight = function ( hex ) { + + THREE.Light.call( this, hex ); + +}; + +THREE.AmbientLight.prototype = new THREE.Light(); +THREE.AmbientLight.prototype.constructor = THREE.AmbientLight; +THREE.DirectionalLight = function ( hex, intensity ) { + + THREE.Light.call( this, hex ); + + this.position = new THREE.Vector3( 0, 1, 0 ); + this.intensity = intensity || 1; + +}; + +THREE.DirectionalLight.prototype = new THREE.Light(); +THREE.DirectionalLight.prototype.constructor = THREE.DirectionalLight; +THREE.PointLight = function ( hex, intensity ) { + + THREE.Light.call( this, hex ); + + this.position = new THREE.Vector3(); + this.intensity = intensity || 1; + +}; + +THREE.DirectionalLight.prototype = new THREE.Light(); +THREE.DirectionalLight.prototype.constructor = THREE.PointLight; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Object3D = function () { + + this.id = THREE.Object3DCounter.value ++; + + this.position = new THREE.Vector3(); + this.rotation = new THREE.Vector3(); + this.scale = new THREE.Vector3( 1, 1, 1 ); + + this.matrix = new THREE.Matrix4(); + this.translationMatrix = new THREE.Matrix4(); + this.rotationMatrix = new THREE.Matrix4(); + this.scaleMatrix = new THREE.Matrix4(); + + this.screen = new THREE.Vector3(); + + this.autoUpdateMatrix = true; + this.visible = true; + +}; + +THREE.Object3D.prototype = { + + updateMatrix: function () { + + this.matrixPosition = THREE.Matrix4.translationMatrix( this.position.x, this.position.y, this.position.z ); + + this.rotationMatrix = THREE.Matrix4.rotationXMatrix( this.rotation.x ); + this.rotationMatrix.multiplySelf( THREE.Matrix4.rotationYMatrix( this.rotation.y ) ); + this.rotationMatrix.multiplySelf( THREE.Matrix4.rotationZMatrix( this.rotation.z ) ); + + this.scaleMatrix = THREE.Matrix4.scaleMatrix( this.scale.x, this.scale.y, this.scale.z ); + + this.matrix.copy( this.matrixPosition ); + this.matrix.multiplySelf( this.rotationMatrix ); + this.matrix.multiplySelf( this.scaleMatrix ); + + } + +}; + +THREE.Object3DCounter = { value: 0 }; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Particle = function ( materials ) { + + THREE.Object3D.call( this ); + + this.materials = materials instanceof Array ? materials : [ materials ]; + + this.autoUpdateMatrix = false; + +}; + +THREE.Particle.prototype = new THREE.Object3D(); +THREE.Particle.prototype.constructor = THREE.Particle; +/** + * @author alteredq / http://alteredqualia.com/ + */ + +THREE.ParticleSystem = function ( geometry, materials ) { + + THREE.Object3D.call( this ); + + this.geometry = geometry; + this.materials = materials instanceof Array ? materials : [ materials ]; + + this.autoUpdateMatrix = false; + +}; + +THREE.ParticleSystem.prototype = new THREE.Object3D(); +THREE.ParticleSystem.prototype.constructor = THREE.ParticleSystem; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Line = function ( geometry, materials, type ) { + + THREE.Object3D.call( this ); + + this.geometry = geometry; + this.materials = materials instanceof Array ? materials : [ materials ]; + + this.type = type !== undefined ? type : THREE.LineContinuous; + +}; + +THREE.LineStrip = 0; +THREE.LinePieces = 1; + +THREE.Line.prototype = new THREE.Object3D(); +THREE.Line.prototype.constructor = THREE.Line; +/** + * @author mr.doob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + */ + +THREE.Mesh = function ( geometry, materials ) { + + THREE.Object3D.call( this ); + + this.geometry = geometry; + this.materials = materials instanceof Array ? materials : [ materials ]; + + this.flipSided = false; + this.doubleSided = false; + + this.overdraw = false; // TODO: Move to material? + + this.geometry.boundingSphere || this.geometry.computeBoundingSphere(); + +}; + +THREE.Mesh.prototype = new THREE.Object3D(); +THREE.Mesh.prototype.constructor = THREE.Mesh; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.FlatShading = 0; +THREE.SmoothShading = 1; + +THREE.NormalBlending = 0; +THREE.AdditiveBlending = 1; +THREE.SubtractiveBlending = 2; +/** + * @author mr.doob / http://mrdoob.com/ + * + * parameters = { + * color: , + * opacity: , + * blending: THREE.NormalBlending, + * linewidth: + * } + */ + +THREE.LineBasicMaterial = function ( parameters ) { + + this.color = new THREE.Color( 0xffffff ); + this.opacity = 1; + this.blending = THREE.NormalBlending; + this.linewidth = 1; + this.linecap = 'round'; + this.linejoin = 'round'; + + if ( parameters ) { + + if ( parameters.color !== undefined ) this.color.setHex( parameters.color ); + if ( parameters.opacity !== undefined ) this.opacity = parameters.opacity; + if ( parameters.blending !== undefined ) this.blending = parameters.blending; + if ( parameters.linewidth !== undefined ) this.linewidth = parameters.linewidth; + if ( parameters.linecap !== undefined ) this.linecap = parameters.linecap; + if ( parameters.linejoin !== undefined ) this.linejoin = parameters.linejoin; + } + +}; + +THREE.LineBasicMaterial.prototype = { + + toString: function () { + + return 'THREE.LineBasicMaterial (
' + + 'color: ' + this.color + '
' + + 'opacity: ' + this.opacity + '
' + + 'blending: ' + this.blending + '
' + + 'linewidth: ' + this.linewidth +'
' + + 'linecap: ' + this.linecap +'
' + + 'linejoin: ' + this.linejoin +'
' + + ')'; + + } + +} +/** + * @author mr.doob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + * + * parameters = { + * color: , + * map: new THREE.Texture( ), + + * env_map: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), + * combine: THREE.Multiply, + * reflectivity: , + * refraction_ratio: , + + * opacity: , + * shading: THREE.SmoothShading, + * blending: THREE.NormalBlending, + * wireframe: , + * wireframe_linewidth: + * } + */ + +THREE.MeshBasicMaterial = function ( parameters ) { + + this.id = THREE.MeshBasicMaterialCounter.value ++; + + this.color = new THREE.Color( 0xffffff ); + this.map = null; + + this.env_map = null; + this.combine = THREE.MultiplyOperation; + this.reflectivity = 1; + this.refraction_ratio = 0.98; + + this.fog = true; + + this.opacity = 1; + this.shading = THREE.SmoothShading; + this.blending = THREE.NormalBlending; + + this.wireframe = false; + this.wireframe_linewidth = 1; + this.wireframe_linecap = 'round'; + this.wireframe_linejoin = 'round'; + + if ( parameters ) { + + if ( parameters.color !== undefined ) this.color.setHex( parameters.color ); + if ( parameters.map !== undefined ) this.map = parameters.map; + + if ( parameters.env_map !== undefined ) this.env_map = parameters.env_map; + if ( parameters.combine !== undefined ) this.combine = parameters.combine; + if ( parameters.reflectivity !== undefined ) this.reflectivity = parameters.reflectivity; + if ( parameters.refraction_ratio !== undefined ) this.refraction_ratio = parameters.refraction_ratio; + + if ( parameters.fog !== undefined ) this.fog = parameters.fog; + + if ( parameters.opacity !== undefined ) this.opacity = parameters.opacity; + if ( parameters.shading !== undefined ) this.shading = parameters.shading; + if ( parameters.blending !== undefined ) this.blending = parameters.blending; + + if ( parameters.wireframe !== undefined ) this.wireframe = parameters.wireframe; + if ( parameters.wireframe_linewidth !== undefined ) this.wireframe_linewidth = parameters.wireframe_linewidth; + if ( parameters.wireframe_linecap !== undefined ) this.wireframe_linecap = parameters.wireframe_linecap; + if ( parameters.wireframe_linejoin !== undefined ) this.wireframe_linejoin = parameters.wireframe_linejoin; + + } + +}; + +THREE.MeshBasicMaterial.prototype = { + + toString: function () { + + return 'THREE.MeshBasicMaterial (
' + + 'id: ' + this.id + '
' + + 'color: ' + this.color + '
' + + 'map: ' + this.map + '
' + + + 'env_map: ' + this.env_map + '
' + + 'combine: ' + this.combine + '
' + + 'reflectivity: ' + this.reflectivity + '
' + + 'refraction_ratio: ' + this.refraction_ratio + '
' + + + 'opacity: ' + this.opacity + '
' + + 'blending: ' + this.blending + '
' + + + 'wireframe: ' + this.wireframe + '
' + + 'wireframe_linewidth: ' + this.wireframe_linewidth +'
' + + 'wireframe_linecap: ' + this.wireframe_linecap +'
' + + 'wireframe_linejoin: ' + this.wireframe_linejoin +'
' + + ')'; + + } + +}; + +THREE.MeshBasicMaterialCounter = { value: 0 }; +/** + * @author mr.doob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + * + * parameters = { + * color: , + * map: new THREE.Texture( ), + + * env_map: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), + * combine: THREE.Multiply, + * reflectivity: , + * refraction_ratio: , + + * opacity: , + * shading: THREE.SmoothShading, + * blending: THREE.NormalBlending, + * wireframe: , + * wireframe_linewidth: + * } + */ + +THREE.MeshLambertMaterial = function ( parameters ) { + + this.id = THREE.MeshLambertMaterialCounter.value ++; + + this.color = new THREE.Color( 0xffffff ); + this.map = null; + + this.env_map = null; + this.combine = THREE.MultiplyOperation; + this.reflectivity = 1; + this.refraction_ratio = 0.98; + + this.fog = true; + + this.opacity = 1; + this.shading = THREE.SmoothShading; + this.blending = THREE.NormalBlending; + + this.wireframe = false; + this.wireframe_linewidth = 1; + this.wireframe_linecap = 'round'; + this.wireframe_linejoin = 'round'; + + if ( parameters ) { + + if ( parameters.color !== undefined ) this.color.setHex( parameters.color ); + if ( parameters.map !== undefined ) this.map = parameters.map; + + if ( parameters.env_map !== undefined ) this.env_map = parameters.env_map; + if ( parameters.combine !== undefined ) this.combine = parameters.combine; + if ( parameters.reflectivity !== undefined ) this.reflectivity = parameters.reflectivity; + if ( parameters.refraction_ratio !== undefined ) this.refraction_ratio = parameters.refraction_ratio; + + if ( parameters.fog !== undefined ) this.fog = parameters.fog; + + if ( parameters.opacity !== undefined ) this.opacity = parameters.opacity; + if ( parameters.shading !== undefined ) this.shading = parameters.shading; + if ( parameters.blending !== undefined ) this.blending = parameters.blending; + + if ( parameters.wireframe !== undefined ) this.wireframe = parameters.wireframe; + if ( parameters.wireframe_linewidth !== undefined ) this.wireframe_linewidth = parameters.wireframe_linewidth; + if ( parameters.wireframe_linecap !== undefined ) this.wireframe_linecap = parameters.wireframe_linecap; + if ( parameters.wireframe_linejoin !== undefined ) this.wireframe_linejoin = parameters.wireframe_linejoin; + + } + +}; + +THREE.MeshLambertMaterial.prototype = { + + toString: function () { + + return 'THREE.MeshLambertMaterial (
' + + 'id: ' + this.id + '
' + + 'color: ' + this.color + '
' + + 'map: ' + this.map + '
' + + + 'env_map: ' + this.env_map + '
' + + 'combine: ' + this.combine + '
' + + 'reflectivity: ' + this.reflectivity + '
' + + 'refraction_ratio: ' + this.refraction_ratio + '
' + + + 'opacity: ' + this.opacity + '
' + + 'shading: ' + this.shading + '
' + + 'blending: ' + this.blending + '
' + + + 'wireframe: ' + this.wireframe + '
' + + 'wireframe_linewidth: ' + this.wireframe_linewidth +'
' + + 'wireframe_linecap: ' + this.wireframe_linecap +'
' + + 'wireframe_linejoin: ' + this.wireframe_linejoin +'
' + + ' )'; + + } + +}; + +THREE.MeshLambertMaterialCounter = { value: 0 }; +/** + * @author mr.doob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + * + * parameters = { + * color: , + * ambient: , + * specular: , + * shininess: , + + * map: new THREE.Texture( ), + * specular_map: new THREE.Texture( ), + + * env_map: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ), + * combine: THREE.Multiply, + * reflectivity: , + * refraction_ratio: , + + * opacity: , + * shading: THREE.SmoothShading, + * blending: THREE.NormalBlending, + * wireframe: , + * wireframe_linewidth: + * } + */ + +THREE.MeshPhongMaterial = function ( parameters ) { + + this.id = THREE.MeshPhongMaterialCounter.value ++; + + this.color = new THREE.Color( 0xffffff ); + this.ambient = new THREE.Color( 0x050505 ); + this.specular = new THREE.Color( 0x111111 ); + this.shininess = 30; + + this.map = null; + this.specular_map = null; + + this.env_map = null; + this.combine = THREE.MultiplyOperation; + this.reflectivity = 1; + this.refraction_ratio = 0.98; + + this.fog = true; + + this.opacity = 1; + this.shading = THREE.SmoothShading; + this.blending = THREE.NormalBlending; + + this.wireframe = false; + this.wireframe_linewidth = 1; + this.wireframe_linecap = 'round'; + this.wireframe_linejoin = 'round'; + + if ( parameters ) { + + if ( parameters.color !== undefined ) this.color = new THREE.Color( parameters.color ); + if ( parameters.ambient !== undefined ) this.ambient = new THREE.Color( parameters.ambient ); + if ( parameters.specular !== undefined ) this.specular = new THREE.Color( parameters.specular ); + if ( parameters.shininess !== undefined ) this.shininess = parameters.shininess; + + if ( parameters.map !== undefined ) this.map = parameters.map; + if ( parameters.specular_map !== undefined ) this.specular_map = parameters.specular_map; + + if ( parameters.env_map !== undefined ) this.env_map = parameters.env_map; + if ( parameters.combine !== undefined ) this.combine = parameters.combine; + if ( parameters.reflectivity !== undefined ) this.reflectivity = parameters.reflectivity; + if ( parameters.refraction_ratio !== undefined ) this.refraction_ratio = parameters.refraction_ratio; + + if ( parameters.fog !== undefined ) this.fog = parameters.fog; + + if ( parameters.opacity !== undefined ) this.opacity = parameters.opacity; + if ( parameters.shading !== undefined ) this.shading = parameters.shading; + if ( parameters.blending !== undefined ) this.blending = parameters.blending; + + if ( parameters.wireframe !== undefined ) this.wireframe = parameters.wireframe; + if ( parameters.wireframe_linewidth !== undefined ) this.wireframe_linewidth = parameters.wireframe_linewidth; + if ( parameters.wireframe_linecap !== undefined ) this.wireframe_linecap = parameters.wireframe_linecap; + if ( parameters.wireframe_linejoin !== undefined ) this.wireframe_linejoin = parameters.wireframe_linejoin; + + } + +}; + +THREE.MeshPhongMaterial.prototype = { + + toString: function () { + + return 'THREE.MeshPhongMaterial (
' + + 'id: ' + this.id + '
' + + 'color: ' + this.color + '
' + + 'ambient: ' + this.ambient + '
' + + 'specular: ' + this.specular + '
' + + 'shininess: ' + this.shininess + '
' + + + 'map: ' + this.map + '
' + + 'specular_map: ' + this.specular_map + '
' + + + 'env_map: ' + this.env_map + '
' + + 'combine: ' + this.combine + '
' + + 'reflectivity: ' + this.reflectivity + '
' + + 'refraction_ratio: ' + this.refraction_ratio + '
' + + + 'opacity: ' + this.opacity + '
' + + 'shading: ' + this.shading + '
' + + + 'wireframe: ' + this.wireframe + '
' + + 'wireframe_linewidth: ' + this.wireframe_linewidth + '
' + + 'wireframe_linecap: ' + this.wireframe_linecap +'
' + + 'wireframe_linejoin: ' + this.wireframe_linejoin +'
' + + ')'; + + } + +}; + +THREE.MeshPhongMaterialCounter = { value: 0 }; +/** + * @author mr.doob / http://mrdoob.com/ + * + * parameters = { + * opacity: , + * blending: THREE.NormalBlending + * } + */ + +THREE.MeshDepthMaterial = function ( parameters ) { + + this.opacity = 1; + this.shading = THREE.SmoothShading; + this.blending = THREE.NormalBlending; + + this.wireframe = false; + this.wireframe_linewidth = 1; + this.wireframe_linecap = 'round'; + this.wireframe_linejoin = 'round'; + + if ( parameters ) { + + if ( parameters.opacity !== undefined ) this.opacity = parameters.opacity; + if ( parameters.blending !== undefined ) this.blending = parameters.blending; + + } + +}; + +THREE.MeshDepthMaterial.prototype = { + + toString: function () { + + return 'THREE.MeshDepthMaterial'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + * + * parameters = { + * opacity: , + * shading: THREE.FlatShading, + * blending: THREE.NormalBlending + * } + */ + +THREE.MeshNormalMaterial = function ( parameters ) { + + this.opacity = 1; + this.shading = THREE.FlatShading; + this.blending = THREE.NormalBlending; + + if ( parameters ) { + + if ( parameters.opacity !== undefined ) this.opacity = parameters.opacity; + if ( parameters.shading !== undefined ) this.shading = parameters.shading; + if ( parameters.blending !== undefined ) this.blending = parameters.blending; + + } + +}; + +THREE.MeshNormalMaterial.prototype = { + + toString: function () { + + return 'THREE.MeshNormalMaterial'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.MeshFaceMaterial = function () { + +}; + +THREE.MeshFaceMaterial.prototype = { + + toString: function () { + + return 'THREE.MeshFaceMaterial'; + + } + +}; +/** + * @author alteredq / http://alteredqualia.com/ + * + * parameters = { + * fragment_shader: , + * vertex_shader: , + * uniforms: { "parameter1": { type: "f", value: 1.0 }, "parameter2": { type: "i" value2: 2 } }, + * shading: THREE.SmoothShading, + * blending: THREE.NormalBlending, + * wireframe: , + * wireframe_linewidth: + * } + */ + +THREE.MeshShaderMaterial = function ( parameters ) { + + this.id = THREE.MeshShaderMaterialCounter.value ++; + + this.fragment_shader = "void main() {}"; + this.vertex_shader = "void main() {}"; + this.uniforms = {}; + + this.opacity = 1; + this.shading = THREE.SmoothShading; + this.blending = THREE.NormalBlending; + + this.wireframe = false; + this.wireframe_linewidth = 1; + this.wireframe_linecap = 'round'; + this.wireframe_linejoin = 'round'; + + if ( parameters ) { + + if ( parameters.fragment_shader !== undefined ) this.fragment_shader = parameters.fragment_shader; + if ( parameters.vertex_shader !== undefined ) this.vertex_shader = parameters.vertex_shader; + + if ( parameters.uniforms !== undefined ) this.uniforms = parameters.uniforms; + + if ( parameters.shading !== undefined ) this.shading = parameters.shading; + if ( parameters.blending !== undefined ) this.blending = parameters.blending; + + if ( parameters.wireframe !== undefined ) this.wireframe = parameters.wireframe; + if ( parameters.wireframe_linewidth !== undefined ) this.wireframe_linewidth = parameters.wireframe_linewidth; + if ( parameters.wireframe_linecap !== undefined ) this.wireframe_linecap = parameters.wireframe_linecap; + if ( parameters.wireframe_linejoin !== undefined ) this.wireframe_linejoin = parameters.wireframe_linejoin; + + } + +}; + +THREE.MeshShaderMaterial.prototype = { + + toString: function () { + + return 'THREE.MeshShaderMaterial (
' + + 'id: ' + this.id + '
' + + + 'blending: ' + this.blending + '
' + + 'wireframe: ' + this.wireframe + '
' + + 'wireframe_linewidth: ' + this.wireframe_linewidth +'
' + + 'wireframe_linecap: ' + this.wireframe_linecap +'
' + + 'wireframe_linejoin: ' + this.wireframe_linejoin +'
' + + ')'; + + } + +}; + +THREE.MeshShaderMaterialCounter = { value: 0 }; +/** + * @author mr.doob / http://mrdoob.com/ + * + * parameters = { + * color: , + * map: new THREE.Texture( ), + * opacity: , + * blending: THREE.NormalBlending + * } + */ + +THREE.ParticleBasicMaterial = function ( parameters ) { + + this.color = new THREE.Color( 0xffffff ); + this.map = null; + this.opacity = 1; + this.blending = THREE.NormalBlending; + + this.offset = new THREE.Vector2(); // TODO: expose to parameters + + if ( parameters ) { + + if ( parameters.color !== undefined ) this.color.setHex( parameters.color ); + if ( parameters.map !== undefined ) this.map = parameters.map; + if ( parameters.opacity !== undefined ) this.opacity = parameters.opacity; + if ( parameters.blending !== undefined ) this.blending = parameters.blending; + + } + +}; + +THREE.ParticleBasicMaterial.prototype = { + + toString: function () { + + return 'THREE.ParticleBasicMaterial (
' + + 'color: ' + this.color + '
' + + 'map: ' + this.map + '
' + + 'opacity: ' + this.opacity + '
' + + 'blending: ' + this.blending + '
' + + ')'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + * + * parameters = { + * color: , + * opacity: , + * blending: THREE.NormalBlending + * } + */ + +THREE.ParticleCircleMaterial = function ( parameters ) { + + this.color = new THREE.Color( 0xffffff ); + this.opacity = 1; + this.blending = THREE.NormalBlending; + + if ( parameters ) { + + if ( parameters.color !== undefined ) this.color.setHex( parameters.color ); + if ( parameters.opacity !== undefined ) this.opacity = parameters.opacity; + if ( parameters.blending !== undefined ) this.blending = parameters.blending; + + } + +}; + +THREE.ParticleCircleMaterial.prototype = { + + toString: function () { + + return 'THREE.ParticleCircleMaterial (
' + + 'color: ' + this.color + '
' + + 'opacity: ' + this.opacity + '
' + + 'blending: ' + this.blending + '
' + + ')'; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + */ + +THREE.Texture = function ( image, mapping, wrap_s, wrap_t, mag_filter, min_filter ) { + + this.image = image; + + this.mapping = mapping !== undefined ? mapping : new THREE.UVMapping(); + + this.wrap_s = wrap_s !== undefined ? wrap_s : THREE.ClampToEdgeWrapping; + this.wrap_t = wrap_t !== undefined ? wrap_t : THREE.ClampToEdgeWrapping; + + this.mag_filter = mag_filter !== undefined ? mag_filter : THREE.LinearFilter; + this.min_filter = min_filter !== undefined ? min_filter : THREE.LinearMipMapLinearFilter; + +}; + +THREE.Texture.prototype = { + + clone: function () { + + return new THREE.Texture( this.image, this.mapping, this.wrap_s, this.wrap_t, this.mag_filter, this.min_filter ); + + }, + + toString: function () { + + return 'THREE.Texture (
' + + 'image: ' + this.image + '
' + + 'wrap_s: ' + this.wrap_s + '
' + + 'wrap_t: ' + this.wrap_t + '
' + + 'mag_filter: ' + this.mag_filter + '
' + + 'min_filter: ' + this.min_filter + '
' + + ')'; + + } + +}; + +THREE.MultiplyOperation = 0; +THREE.MixOperation = 1; + +THREE.RepeatWrapping = 0; +THREE.ClampToEdgeWrapping = 1; +THREE.MirroredRepeatWrapping = 2; + +THREE.NearestFilter = 3; +THREE.NearestMipMapNearestFilter = 4; +THREE.NearestMipMapLinearFilter = 5; +THREE.LinearFilter = 6; +THREE.LinearMipMapNearestFilter = 7; +THREE.LinearMipMapLinearFilter = 8; + +THREE.RGBFormat = 9; + +THREE.UnsignedByteType = 10; +THREE.RenderTexture = function ( width, height, options ) { + + this.width = width; + this.height = height; + + options = options || {}; + + this.wrap_s = options.wrap_s !== undefined ? options.wrap_s : THREE.ClampToEdgeWrapping; + this.wrap_t = options.wrap_t !== undefined ? options.wrap_t : THREE.ClampToEdgeWrapping; + + this.mag_filter = options.mag_filter !== undefined ? options.mag_filter : THREE.LinearFilter; + this.min_filter = options.min_filter !== undefined ? options.min_filter : THREE.LinearFilter; + + this.format = options.format !== undefined ? options.format : THREE.RGBFormat; + this.type = options.type !== undefined ? options.type : THREE.UnsignedByteType; + +}; +var Uniforms = { + + clone: function( uniforms_src ) { + + var u, p, parameter, parameter_src, uniforms_dst = {}; + + for ( u in uniforms_src ) { + + uniforms_dst[ u ] = {}; + + for ( p in uniforms_src[ u ] ) { + + parameter_src = uniforms_src[ u ][ p ]; + + if ( parameter_src instanceof THREE.Color || + parameter_src instanceof THREE.Vector3 || + parameter_src instanceof THREE.Texture ) { + + uniforms_dst[ u ][ p ] = parameter_src.clone(); + + } else { + + uniforms_dst[ u ][ p ] = parameter_src; + + } + + } + + } + + return uniforms_dst; + + }, + + merge: function( uniforms ) { + + var u, p, tmp, merged = {}; + + for( u = 0; u < uniforms.length; u++ ) { + + tmp = this.clone( uniforms[ u ] ); + + for ( p in tmp ) { + + merged[ p ] = tmp[ p ]; + + } + + } + + return merged; + + } + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.CubeReflectionMapping = function () { + + + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.CubeRefractionMapping = function () { + + + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.LatitudeReflectionMapping = function () { + + + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.LatitudeRefractionMapping = function () { + + + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.SphericalReflectionMapping = function () { + + + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.SphericalRefractionMapping = function () { + + + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.UVMapping = function () { + + + +}; +/** + * @author mr.doob / http://mrdoob.com/ + */ + +THREE.Scene = function () { + + this.objects = []; + this.lights = []; + this.fog = null; + + this.addObject = function ( object ) { + + var i = this.objects.indexOf( object ); + + if ( i === -1 ) { + + this.objects.push( object ); + + } + + }; + + this.removeObject = function ( object ) { + + var i = this.objects.indexOf( object ); + + if ( i !== -1 ) { + + this.objects.splice( i, 1 ); + + } + + }; + + this.addLight = function ( light ) { + + var i = this.lights.indexOf( light ); + + if ( i === -1 ) { + + this.lights.push( light ); + + } + + }; + + this.removeLight = function ( light ) { + + var i = this.lights.indexOf( light ); + + if ( i !== -1 ) { + + this.lights.splice( i, 1 ); + + } + + }; + + this.toString = function () { + + return 'THREE.Scene ( ' + this.objects + ' )'; + + }; + +}; +/** + * @author mr.doob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + */ + +THREE.Fog = function ( hex, near, far ) { + + this.color = new THREE.Color( hex ); + this.near = near || 1; + this.far = far || 1000; + +}; +/** + * @author mr.doob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + */ + +THREE.FogExp2 = function ( hex, density ) { + + this.color = new THREE.Color( hex ); + this.density = density || 0.00025; + +}; +/** + * @author supereggbert / http://www.paulbrunt.co.uk/ + * @author mrdoob / http://mrdoob.com/ + * @author alteredq / http://alteredqualia.com/ + */ + +THREE.WebGLRenderer = function ( parameters ) { + + // Currently you can use just up to 4 directional / point lights total. + // Chrome barfs on shader linking when there are more than 4 lights :( + + // The problem comes from shader using too many varying vectors. + + // This is not GPU limitation as the same shader works ok in Firefox + // and Chrome with "--use-gl=desktop" flag. + + // Difference comes from Chrome on Windows using by default ANGLE, + // thus going DirectX9 route (while FF uses OpenGL). + + // See http://code.google.com/p/chromium/issues/detail?id=63491 + + var _canvas = document.createElement( 'canvas' ), _gl, + _oldProgram = null, + _modelViewMatrix = new THREE.Matrix4(), _normalMatrix, + + _viewMatrixArray = new Float32Array(16), + _modelViewMatrixArray = new Float32Array(16), + _projectionMatrixArray = new Float32Array(16), + _normalMatrixArray = new Float32Array(9), + _objectMatrixArray = new Float32Array(16), + + // parameters defaults + + antialias = true, + clearColor = new THREE.Color( 0x000000 ), + clearAlpha = 0; + + if ( parameters ) { + + if ( parameters.antialias !== undefined ) antialias = parameters.antialias; + if ( parameters.clearColor !== undefined ) clearColor.setHex( parameters.clearColor ); + if ( parameters.clearAlpha !== undefined ) clearAlpha = parameters.clearAlpha; + + } + + this.domElement = _canvas; + this.autoClear = true; + + initGL( antialias, clearColor, clearAlpha ); + + //alert( dumpObject( getGLParams() ) ); + + this.setSize = function ( width, height ) { + + _canvas.width = width; + _canvas.height = height; + _gl.viewport( 0, 0, _canvas.width, _canvas.height ); + + }; + + this.setClearColor = function( hex, alpha ) { + + var color = new THREE.Color( hex ); + _gl.clearColor( color.r, color.g, color.b, alpha ); + + }; + + this.clear = function () { + + _gl.clear( _gl.COLOR_BUFFER_BIT | _gl.DEPTH_BUFFER_BIT ); + + }; + + this.setupLights = function ( program, lights ) { + + var l, ll, light, r = 0, g = 0, b = 0, + dcolors = [], dpositions = [], + pcolors = [], ppositions = []; + + + for ( l = 0, ll = lights.length; l < ll; l++ ) { + + light = lights[ l ]; + + if ( light instanceof THREE.AmbientLight ) { + + r += light.color.r; + g += light.color.g; + b += light.color.b; + + } else if ( light instanceof THREE.DirectionalLight ) { + + dcolors.push( light.color.r * light.intensity, + light.color.g * light.intensity, + light.color.b * light.intensity ); + + dpositions.push( light.position.x, + light.position.y, + light.position.z ); + + } else if( light instanceof THREE.PointLight ) { + + pcolors.push( light.color.r * light.intensity, + light.color.g * light.intensity, + light.color.b * light.intensity ); + + ppositions.push( light.position.x, + light.position.y, + light.position.z ); + + } + + } + + return { ambient: [ r, g, b ], directional: { colors: dcolors, positions: dpositions }, point: { colors: pcolors, positions: ppositions } }; + + }; + + this.createParticleBuffers = function( object ) { + }; + + this.createLineBuffers = function( object ) { + + var v, vl, vertex, + vertexArray = [], lineArray = [], + vertices = object.geometry.vertices; + + for ( v = 0, vl = vertices.length; v < vl; v++ ) { + + vertex = vertices[ v ].position; + vertexArray.push( vertex.x, vertex.y, vertex.z ); + + lineArray.push( v ); + + } + + if ( !vertexArray.length ) { + + return; + + } + + object.__webGLVertexBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webGLVertexBuffer ); + _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( vertexArray ), _gl.STATIC_DRAW ); + + object.__webGLLineBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, object.__webGLLineBuffer ); + _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( lineArray ), _gl.STATIC_DRAW ); + + object.__webGLLineCount = lineArray.length; + + }; + + this.createBuffers = function ( object, g ) { + + var f, fl, fi, face, vertexNormals, faceNormal, normal, uv, v1, v2, v3, v4, t1, t2, t3, t4, m, ml, i, + + faceArray = [], + lineArray = [], + + vertexArray = [], + normalArray = [], + tangentArray = [], + uvArray = [], + + vertexIndex = 0, + + geometryChunk = object.geometry.geometryChunks[ g ], + + needsSmoothNormals = bufferNeedsSmoothNormals ( geometryChunk, object ); + + for ( f = 0, fl = geometryChunk.faces.length; f < fl; f++ ) { + + fi = geometryChunk.faces[ f ]; + + face = object.geometry.faces[ fi ]; + vertexNormals = face.vertexNormals; + faceNormal = face.normal; + uv = object.geometry.uvs[ fi ]; + + if ( face instanceof THREE.Face3 ) { + + v1 = object.geometry.vertices[ face.a ].position; + v2 = object.geometry.vertices[ face.b ].position; + v3 = object.geometry.vertices[ face.c ].position; + + vertexArray.push( v1.x, v1.y, v1.z, + v2.x, v2.y, v2.z, + v3.x, v3.y, v3.z ); + + if ( object.geometry.hasTangents ) { + + t1 = object.geometry.vertices[ face.a ].tangent; + t2 = object.geometry.vertices[ face.b ].tangent; + t3 = object.geometry.vertices[ face.c ].tangent; + + tangentArray.push( t1.x, t1.y, t1.z, t1.w, + t2.x, t2.y, t2.z, t2.w, + t3.x, t3.y, t3.z, t3.w ); + + } + + if ( vertexNormals.length == 3 && needsSmoothNormals ) { + + + for ( i = 0; i < 3; i ++ ) { + + normalArray.push( vertexNormals[ i ].x, vertexNormals[ i ].y, vertexNormals[ i ].z ); + + } + + } else { + + for ( i = 0; i < 3; i ++ ) { + + normalArray.push( faceNormal.x, faceNormal.y, faceNormal.z ); + + } + + } + + if ( uv ) { + + for ( i = 0; i < 3; i ++ ) { + + uvArray.push( uv[ i ].u, uv[ i ].v ); + + } + + } + + faceArray.push( vertexIndex, vertexIndex + 1, vertexIndex + 2 ); + + // TODO: don't add lines that already exist (faces sharing edge) + + lineArray.push( vertexIndex, vertexIndex + 1, + vertexIndex, vertexIndex + 2, + vertexIndex + 1, vertexIndex + 2 ); + + vertexIndex += 3; + + } else if ( face instanceof THREE.Face4 ) { + + v1 = object.geometry.vertices[ face.a ].position; + v2 = object.geometry.vertices[ face.b ].position; + v3 = object.geometry.vertices[ face.c ].position; + v4 = object.geometry.vertices[ face.d ].position; + + vertexArray.push( v1.x, v1.y, v1.z, + v2.x, v2.y, v2.z, + v3.x, v3.y, v3.z, + v4.x, v4.y, v4.z ); + + if ( object.geometry.hasTangents ) { + + t1 = object.geometry.vertices[ face.a ].tangent; + t2 = object.geometry.vertices[ face.b ].tangent; + t3 = object.geometry.vertices[ face.c ].tangent; + t4 = object.geometry.vertices[ face.d ].tangent; + + tangentArray.push( t1.x, t1.y, t1.z, t1.w, + t2.x, t2.y, t2.z, t2.w, + t3.x, t3.y, t3.z, t3.w, + t4.x, t4.y, t4.z, t4.w ); + + } + + if ( vertexNormals.length == 4 && needsSmoothNormals ) { + + for ( i = 0; i < 4; i ++ ) { + + normalArray.push( vertexNormals[ i ].x, vertexNormals[ i ].y, vertexNormals[ i ].z ); + + } + + } else { + + for ( i = 0; i < 4; i ++ ) { + + normalArray.push( faceNormal.x, faceNormal.y, faceNormal.z ); + + } + + } + + if ( uv ) { + + for ( i = 0; i < 4; i ++ ) { + + uvArray.push( uv[ i ].u, uv[ i ].v ); + + } + + } + + faceArray.push( vertexIndex, vertexIndex + 1, vertexIndex + 2, + vertexIndex, vertexIndex + 2, vertexIndex + 3 ); + + // TODO: don't add lines that already exist (faces sharing edge) + + lineArray.push( vertexIndex, vertexIndex + 1, + vertexIndex, vertexIndex + 2, + vertexIndex, vertexIndex + 3, + vertexIndex + 1, vertexIndex + 2, + vertexIndex + 2, vertexIndex + 3 ); + + vertexIndex += 4; + + } + + } + + if ( !vertexArray.length ) { + + return; + + } + + geometryChunk.__webGLVertexBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLVertexBuffer ); + _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( vertexArray ), _gl.STATIC_DRAW ); + + geometryChunk.__webGLNormalBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLNormalBuffer ); + _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( normalArray ), _gl.STATIC_DRAW ); + + if ( object.geometry.hasTangents ) { + + geometryChunk.__webGLTangentBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLTangentBuffer ); + _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( tangentArray ), _gl.STATIC_DRAW ); + + } + + if ( uvArray.length > 0 ) { + + geometryChunk.__webGLUVBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLUVBuffer ); + _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( uvArray ), _gl.STATIC_DRAW ); + + } + + geometryChunk.__webGLFaceBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLFaceBuffer ); + _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( faceArray ), _gl.STATIC_DRAW ); + + geometryChunk.__webGLLineBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLLineBuffer ); + _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( lineArray ), _gl.STATIC_DRAW ); + + geometryChunk.__webGLFaceCount = faceArray.length; + geometryChunk.__webGLLineCount = lineArray.length; + + }; + + function setMaterialShaders( material, shaders ) { + + material.fragment_shader = shaders.fragment_shader; + material.vertex_shader = shaders.vertex_shader; + material.uniforms = Uniforms.clone( shaders.uniforms ); + + }; + + function refreshUniformsCommon( material, fog ) { + + // premultiply alpha + material.uniforms.color.value.setRGB( material.color.r * material.opacity, material.color.g * material.opacity, material.color.b * material.opacity ); + + // pure color + //material.uniforms.color.value.setHex( material.color.hex ); + + material.uniforms.opacity.value = material.opacity; + material.uniforms.map.texture = material.map; + + material.uniforms.env_map.texture = material.env_map; + material.uniforms.reflectivity.value = material.reflectivity; + material.uniforms.refraction_ratio.value = material.refraction_ratio; + material.uniforms.combine.value = material.combine; + material.uniforms.useRefract.value = material.env_map && material.env_map.mapping instanceof THREE.CubeRefractionMapping; + + if ( fog ) { + + material.uniforms.fogColor.value.setHex( fog.color.hex ); + + if ( fog instanceof THREE.Fog ) { + + material.uniforms.fogNear.value = fog.near; + material.uniforms.fogFar.value = fog.far; + + } else if ( fog instanceof THREE.FogExp2 ) { + + material.uniforms.fogDensity.value = fog.density; + + } + + } + + }; + + function refreshUniformsLine( material, fog ) { + + material.uniforms.color.value.setRGB( material.color.r * material.opacity, material.color.g * material.opacity, material.color.b * material.opacity ); + material.uniforms.opacity.value = material.opacity; + + if ( fog ) { + + material.uniforms.fogColor.value.setHex( fog.color.hex ); + + if ( fog instanceof THREE.Fog ) { + + material.uniforms.fogNear.value = fog.near; + material.uniforms.fogFar.value = fog.far; + + } else if ( fog instanceof THREE.FogExp2 ) { + + material.uniforms.fogDensity.value = fog.density; + + } + + } + + }; + + function refreshUniformsPhong( material ) { + + //material.uniforms.ambient.value.setHex( material.ambient.hex ); + //material.uniforms.specular.value.setHex( material.specular.hex ); + material.uniforms.ambient.value.setRGB( material.ambient.r, material.ambient.g, material.ambient.b ); + material.uniforms.specular.value.setRGB( material.specular.r, material.specular.g, material.specular.b ); + material.uniforms.shininess.value = material.shininess; + + }; + + + function refreshLights( material, lights ) { + + material.uniforms.enableLighting.value = lights.directional.positions.length + lights.point.positions.length; + material.uniforms.ambientLightColor.value = lights.ambient; + material.uniforms.directionalLightColor.value = lights.directional.colors; + material.uniforms.directionalLightDirection.value = lights.directional.positions; + material.uniforms.pointLightColor.value = lights.point.colors; + material.uniforms.pointLightPosition.value = lights.point.positions; + + }; + + this.renderBuffer = function ( camera, lights, fog, material, geometryChunk ) { + + var program, u, identifiers, attributes, parameters, vector_lights, maxLightCount, linewidth, primitives; + + if ( !material.program ) { + + if ( material instanceof THREE.MeshDepthMaterial ) { + + setMaterialShaders( material, THREE.ShaderLib[ 'depth' ] ); + + material.uniforms.mNear.value = camera.near; + material.uniforms.mFar.value = camera.far; + + } else if ( material instanceof THREE.MeshNormalMaterial ) { + + setMaterialShaders( material, THREE.ShaderLib[ 'normal' ] ); + + } else if ( material instanceof THREE.MeshBasicMaterial ) { + + setMaterialShaders( material, THREE.ShaderLib[ 'basic' ] ); + + refreshUniformsCommon( material, fog ); + + } else if ( material instanceof THREE.MeshLambertMaterial ) { + + setMaterialShaders( material, THREE.ShaderLib[ 'lambert' ] ); + + refreshUniformsCommon( material, fog ); + + } else if ( material instanceof THREE.MeshPhongMaterial ) { + + setMaterialShaders( material, THREE.ShaderLib[ 'phong' ] ); + + refreshUniformsCommon( material, fog ); + + } else if ( material instanceof THREE.LineBasicMaterial ) { + + setMaterialShaders( material, THREE.ShaderLib[ 'basic' ] ); + + refreshUniformsLine( material, fog ); + + } + + // heuristics to create shader parameters according to lights in the scene + // (not to blow over maxLights budget) + + maxLightCount = allocateLights( lights, 4 ); + + parameters = { fog: fog, map: material.map, env_map: material.env_map, maxDirLights: maxLightCount.directional, maxPointLights: maxLightCount.point }; + material.program = buildProgram( material.fragment_shader, material.vertex_shader, parameters ); + + identifiers = [ 'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'objectMatrix', 'cameraPosition' ]; + for( u in material.uniforms ) { + + identifiers.push(u); + + } + + cacheUniformLocations( material.program, identifiers ); + cacheAttributeLocations( material.program, [ "position", "normal", "uv", "tangent" ] ); + + } + + program = material.program; + + if( program != _oldProgram ) { + + _gl.useProgram( program ); + _oldProgram = program; + + } + + this.loadCamera( program, camera ); + this.loadMatrices( program ); + + if ( material instanceof THREE.MeshPhongMaterial || + material instanceof THREE.MeshLambertMaterial ) { + + vector_lights = this.setupLights( program, lights ); + refreshLights( material, vector_lights ); + + } + + if ( material instanceof THREE.MeshBasicMaterial || + material instanceof THREE.MeshLambertMaterial || + material instanceof THREE.MeshPhongMaterial ) { + + refreshUniformsCommon( material, fog ); + + } + + if ( material instanceof THREE.LineBasicMaterial ) { + + refreshUniformsLine( material, fog ); + } + + if ( material instanceof THREE.MeshPhongMaterial ) { + + refreshUniformsPhong( material ); + + } + + setUniforms( program, material.uniforms ); + + attributes = program.attributes; + + // vertices + + _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLVertexBuffer ); + _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 ); + _gl.enableVertexAttribArray( attributes.position ); + + // normals + + if ( attributes.normal >= 0 ) { + + _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLNormalBuffer ); + _gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 ); + _gl.enableVertexAttribArray( attributes.normal ); + + } + + // tangents + + if ( attributes.tangent >= 0 ) { + + _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLTangentBuffer ); + _gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 ); + _gl.enableVertexAttribArray( attributes.tangent ); + + } + + // uvs + + if ( attributes.uv >= 0 ) { + + if ( geometryChunk.__webGLUVBuffer ) { + + _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryChunk.__webGLUVBuffer ); + _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 ); + + _gl.enableVertexAttribArray( attributes.uv ); + + } else { + + _gl.disableVertexAttribArray( attributes.uv ); + + } + + } + + // render lines + + if ( material.wireframe || material instanceof THREE.LineBasicMaterial ) { + + linewidth = material.wireframe_linewidth !== undefined ? material.wireframe_linewidth : + material.linewidth !== undefined ? material.linewidth : 1; + + primitives = material instanceof THREE.LineBasicMaterial && geometryChunk.type == THREE.LineStrip ? _gl.LINE_STRIP : _gl.LINES; + + _gl.lineWidth( linewidth ); + _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLLineBuffer ); + _gl.drawElements( primitives, geometryChunk.__webGLLineCount, _gl.UNSIGNED_SHORT, 0 ); + + // render triangles + + } else { + + _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryChunk.__webGLFaceBuffer ); + _gl.drawElements( _gl.TRIANGLES, geometryChunk.__webGLFaceCount, _gl.UNSIGNED_SHORT, 0 ); + + } + + }; + + this.renderPass = function ( camera, lights, fog, object, geometryChunk, blending, transparent ) { + + var i, l, m, ml, material, meshMaterial; + + for ( m = 0, ml = object.materials.length; m < ml; m++ ) { + + meshMaterial = object.materials[ m ]; + + if ( meshMaterial instanceof THREE.MeshFaceMaterial ) { + + for ( i = 0, l = geometryChunk.materials.length; i < l; i++ ) { + + material = geometryChunk.materials[ i ]; + + if ( material && material.blending == blending && ( material.opacity < 1.0 == transparent ) ) { + + this.setBlending( material.blending ); + this.renderBuffer( camera, lights, fog, material, geometryChunk ); + + } + + } + + } else { + + material = meshMaterial; + if ( material && material.blending == blending && ( material.opacity < 1.0 == transparent ) ) { + + this.setBlending( material.blending ); + this.renderBuffer( camera, lights, fog, material, geometryChunk ); + + } + + } + + } + + }; + + this.render = function( scene, camera, renderTarget ) { + + var o, ol, webGLObject, object, buffer, + lights = scene.lights, + fog = scene.fog; + + this.initWebGLObjects( scene ); + + setRenderTarget( renderTarget ); + + if ( this.autoClear ) { + + this.clear(); + + } + + camera.autoUpdateMatrix && camera.updateMatrix(); + + _viewMatrixArray.set( camera.matrix.flatten() ); + _projectionMatrixArray.set( camera.projectionMatrix.flatten() ); + + // opaque pass + + for ( o = 0, ol = scene.__webGLObjects.length; o < ol; o++ ) { + + webGLObject = scene.__webGLObjects[ o ]; + + object = webGLObject.object; + buffer = webGLObject.buffer; + + if ( object.visible ) { + + this.setupMatrices( object, camera ); + this.renderPass( camera, lights, fog, object, buffer, THREE.NormalBlending, false ); + + } + + } + + // transparent pass + + for ( o = 0, ol = scene.__webGLObjects.length; o < ol; o++ ) { + + webGLObject = scene.__webGLObjects[ o ]; + + object = webGLObject.object; + buffer = webGLObject.buffer; + + if ( object.visible ) { + + this.setupMatrices( object, camera ); + + // opaque blended materials + + this.renderPass( camera, lights, fog, object, buffer, THREE.AdditiveBlending, false ); + this.renderPass( camera, lights, fog, object, buffer, THREE.SubtractiveBlending, false ); + + // transparent blended materials + + this.renderPass( camera, lights, fog, object, buffer, THREE.AdditiveBlending, true ); + this.renderPass( camera, lights, fog, object, buffer, THREE.SubtractiveBlending, true ); + + // transparent normal materials + + this.renderPass( camera, lights, fog, object, buffer, THREE.NormalBlending, true ); + + } + + } + + }; + + this.initWebGLObjects = function( scene ) { + + function add_buffer( objmap, id, buffer, object ) { + + if ( objmap[ id ] == undefined ) { + + scene.__webGLObjects.push( { buffer: buffer, object: object } ); + objmap[ id ] = 1; + + } + + }; + + var o, ol, object, g, geometryChunk, objmap; + + if ( !scene.__webGLObjects ) { + + scene.__webGLObjects = []; + scene.__webGLObjectsMap = {}; + + } + + for ( o = 0, ol = scene.objects.length; o < ol; o++ ) { + + object = scene.objects[ o ]; + + if ( scene.__webGLObjectsMap[ object.id ] == undefined ) { + + scene.__webGLObjectsMap[ object.id ] = {}; + + } + + objmap = scene.__webGLObjectsMap[ object.id ]; + + if ( object instanceof THREE.Mesh ) { + + // create separate VBOs per geometry chunk + + for ( g in object.geometry.geometryChunks ) { + + geometryChunk = object.geometry.geometryChunks[ g ]; + + // initialise VBO on the first access + + if( ! geometryChunk.__webGLVertexBuffer ) { + + this.createBuffers( object, g ); + + } + + // create separate wrapper per each use of VBO + + add_buffer( objmap, g, geometryChunk, object ); + + } + + } else if ( object instanceof THREE.Line ) { + + + if( ! object.__webGLVertexBuffer ) { + + this.createLineBuffers( object ); + + } + + add_buffer( objmap, 0, object, object ); + + + } else if ( object instanceof THREE.ParticleSystem ) { + + if( ! object.__webGLVertexBuffer ) { + + this.createParticleBuffers( object ); + + } + + add_buffer( objmap, 0, object, object ); + + + }/*else if ( object instanceof THREE.Particle ) { + + }*/ + + } + + }; + + this.removeObject = function ( scene, object ) { + + var o, ol, zobject; + + for ( o = scene.__webGLObjects.length - 1; o >= 0; o-- ) { + + zobject = scene.__webGLObjects[ o ].object; + + if ( object == zobject ) { + + scene.__webGLObjects.splice( o, 1 ); + + } + + } + + }; + + this.setupMatrices = function ( object, camera ) { + + object.autoUpdateMatrix && object.updateMatrix(); + + _modelViewMatrix.multiply( camera.matrix, object.matrix ); + _modelViewMatrixArray.set( _modelViewMatrix.flatten() ); + + _normalMatrix = THREE.Matrix4.makeInvert3x3( _modelViewMatrix ).transpose(); + _normalMatrixArray.set( _normalMatrix.m ); + + _objectMatrixArray.set( object.matrix.flatten() ); + + }; + + this.loadMatrices = function ( program ) { + + _gl.uniformMatrix4fv( program.uniforms.viewMatrix, false, _viewMatrixArray ); + _gl.uniformMatrix4fv( program.uniforms.modelViewMatrix, false, _modelViewMatrixArray ); + _gl.uniformMatrix4fv( program.uniforms.projectionMatrix, false, _projectionMatrixArray ); + _gl.uniformMatrix3fv( program.uniforms.normalMatrix, false, _normalMatrixArray ); + _gl.uniformMatrix4fv( program.uniforms.objectMatrix, false, _objectMatrixArray ); + + }; + + this.loadCamera = function( program, camera ) { + + _gl.uniform3f( program.uniforms.cameraPosition, camera.position.x, camera.position.y, camera.position.z ); + + }; + + this.setBlending = function( blending ) { + + switch ( blending ) { + + case THREE.AdditiveBlending: + + _gl.blendEquation( _gl.FUNC_ADD ); + _gl.blendFunc( _gl.ONE, _gl.ONE ); + + break; + + case THREE.SubtractiveBlending: + + //_gl.blendEquation( _gl.FUNC_SUBTRACT ); + _gl.blendFunc( _gl.DST_COLOR, _gl.ZERO ); + + break; + + default: + + _gl.blendEquation( _gl.FUNC_ADD ); + _gl.blendFunc( _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA ); + + break; + } + + }; + + this.setFaceCulling = function ( cullFace, frontFace ) { + + if ( cullFace ) { + + if ( !frontFace || frontFace == "ccw" ) { + + _gl.frontFace( _gl.CCW ); + + } else { + + _gl.frontFace( _gl.CW ); + + } + + if( cullFace == "back" ) { + + _gl.cullFace( _gl.BACK ); + + } else if( cullFace == "front" ) { + + _gl.cullFace( _gl.FRONT ); + + } else { + + _gl.cullFace( _gl.FRONT_AND_BACK ); + + } + + _gl.enable( _gl.CULL_FACE ); + + } else { + + _gl.disable( _gl.CULL_FACE ); + + } + + }; + + this.supportsVertexTextures = function() { + + return maxVertexTextures() > 0; + + }; + + function maxVertexTextures() { + + return _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); + + }; + + function initGL( antialias, clearColor, clearAlpha ) { + + try { + + _gl = _canvas.getContext( 'experimental-webgl', { antialias: antialias } ); + + } catch(e) { } + + if (!_gl) { + + alert("WebGL not supported"); + throw "cannot create webgl context"; + + } + + _gl.clearColor( 0, 0, 0, 1 ); + _gl.clearDepth( 1 ); + + _gl.enable( _gl.DEPTH_TEST ); + _gl.depthFunc( _gl.LEQUAL ); + + _gl.frontFace( _gl.CCW ); + _gl.cullFace( _gl.BACK ); + _gl.enable( _gl.CULL_FACE ); + + _gl.enable( _gl.BLEND ); + _gl.blendFunc( _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA ); + _gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha ); + + }; + + function buildProgram( fragment_shader, vertex_shader, parameters ) { + + var program = _gl.createProgram(), + + prefix_fragment = [ + "#ifdef GL_ES", + "precision highp float;", + "#endif", + + "#define MAX_DIR_LIGHTS " + parameters.maxDirLights, + "#define MAX_POINT_LIGHTS " + parameters.maxPointLights, + + parameters.fog ? "#define USE_FOG" : "", + parameters.fog instanceof THREE.FogExp2 ? "#define FOG_EXP2" : "", + + parameters.map ? "#define USE_MAP" : "", + parameters.env_map ? "#define USE_ENVMAP" : "", + + "uniform mat4 viewMatrix;", + "uniform vec3 cameraPosition;", + "" + ].join("\n"), + + prefix_vertex = [ + maxVertexTextures() > 0 ? "#define VERTEX_TEXTURES" : "", + + "#define MAX_DIR_LIGHTS " + parameters.maxDirLights, + "#define MAX_POINT_LIGHTS " + parameters.maxPointLights, + + parameters.map ? "#define USE_MAP" : "", + parameters.env_map ? "#define USE_ENVMAP" : "", + + "uniform mat4 objectMatrix;", + "uniform mat4 modelViewMatrix;", + "uniform mat4 projectionMatrix;", + "uniform mat4 viewMatrix;", + "uniform mat3 normalMatrix;", + "uniform vec3 cameraPosition;", + "attribute vec3 position;", + "attribute vec3 normal;", + "attribute vec2 uv;", + "" + ].join("\n"); + + _gl.attachShader( program, getShader( "fragment", prefix_fragment + fragment_shader ) ); + _gl.attachShader( program, getShader( "vertex", prefix_vertex + vertex_shader ) ); + + _gl.linkProgram( program ); + + if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) { + + alert( "Could not initialise shaders\n"+ + "VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" ); + + //console.log( prefix_fragment + fragment_shader ); + //console.log( prefix_vertex + vertex_shader ); + + } + + program.uniforms = {}; + program.attributes = {}; + + return program; + + }; + + function setUniforms( program, uniforms ) { + + var u, value, type, location, texture; + + for( u in uniforms ) { + + location = program.uniforms[u]; + if ( !location ) continue; + + type = uniforms[u].type; + value = uniforms[u].value; + + if( type == "i" ) { + + _gl.uniform1i( location, value ); + + } else if( type == "f" ) { + + _gl.uniform1f( location, value ); + + } else if( type == "fv" ) { + + _gl.uniform3fv( location, value ); + + } else if( type == "v2" ) { + + _gl.uniform2f( location, value.x, value.y ); + + } else if( type == "v3" ) { + + _gl.uniform3f( location, value.x, value.y, value.z ); + + } else if( type == "c" ) { + + _gl.uniform3f( location, value.r, value.g, value.b ); + + } else if( type == "t" ) { + + _gl.uniform1i( location, value ); + + texture = uniforms[u].texture; + + if ( !texture ) continue; + + if ( texture.image instanceof Array && texture.image.length == 6 ) { + + setCubeTexture( texture, value ); + + } else { + + setTexture( texture, value ); + + } + + } + + } + + }; + + function setCubeTexture( texture, slot ) { + + if ( texture.image.length == 6 ) { + + if ( !texture.image.__webGLTextureCube && + !texture.image.__cubeMapInitialized && texture.image.loadCount == 6 ) { + + texture.image.__webGLTextureCube = _gl.createTexture(); + + _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webGLTextureCube ); + + _gl.texParameteri( _gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE ); + _gl.texParameteri( _gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE ); + + _gl.texParameteri( _gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_MAG_FILTER, _gl.LINEAR ); + _gl.texParameteri( _gl.TEXTURE_CUBE_MAP, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR_MIPMAP_LINEAR ); + + for ( var i = 0; i < 6; ++i ) { + + _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image[ i ] ); + + } + + _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP ); + + _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null ); + + texture.image.__cubeMapInitialized = true; + + } + + _gl.activeTexture( _gl.TEXTURE0 + slot ); + _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webGLTextureCube ); + + } + + }; + + function setTexture( texture, slot ) { + + if ( !texture.__webGLTexture && texture.image.loaded ) { + + texture.__webGLTexture = _gl.createTexture(); + _gl.bindTexture( _gl.TEXTURE_2D, texture.__webGLTexture ); + _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, texture.image ); + + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrap_s ) ); + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrap_t ) ); + + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.mag_filter ) ); + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.min_filter ) ); + _gl.generateMipmap( _gl.TEXTURE_2D ); + _gl.bindTexture( _gl.TEXTURE_2D, null ); + + } + + _gl.activeTexture( _gl.TEXTURE0 + slot ); + _gl.bindTexture( _gl.TEXTURE_2D, texture.__webGLTexture ); + + }; + + function setRenderTarget( renderTexture ) { + + var framebuffer; + + if ( renderTexture && !renderTexture.__webGLFramebuffer ) { + renderTexture.__webGLFramebuffer = _gl.createFramebuffer(); + renderTexture.__webGLRenderbuffer = _gl.createRenderbuffer(); + renderTexture.__webGLTexture = _gl.createTexture(); + + // Setup renderbuffer + _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTexture.__webGLRenderbuffer ); + _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTexture.width, renderTexture.height ); + + // Setup texture + _gl.bindTexture( _gl.TEXTURE_2D, renderTexture.__webGLTexture ); + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, paramThreeToGL( renderTexture.wrap_s ) ); + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, paramThreeToGL( renderTexture.wrap_t ) ); + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( renderTexture.mag_filter ) ); + _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( renderTexture.min_filter ) ); + _gl.generateMipmap(_gl.TEXTURE_2D); + _gl.texImage2D( _gl.TEXTURE_2D, 0, paramThreeToGL( renderTexture.format ), renderTexture.width, renderTexture.height, 0, paramThreeToGL( renderTexture.format ), paramThreeToGL( renderTexture.type ), null); + + // Setup framebuffer + _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTexture.__webGLFramebuffer ); + _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, renderTexture.__webGLTexture, 0 ); + _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTexture.__webGLRenderbuffer); + + // Release everything + _gl.bindTexture( _gl.TEXTURE_2D, null ); + _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); + _gl.bindFramebuffer( _gl.FRAMEBUFFER, null); + } + + framebuffer = renderTexture ? renderTexture.__webGLFramebuffer : null; + _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + + } + + function cacheUniformLocations( program, identifiers ) { + + var i, l, id; + + for( i = 0, l = identifiers.length; i < l; i++ ) { + + id = identifiers[ i ]; + program.uniforms[ id ] = _gl.getUniformLocation( program, id ); + + } + + }; + + function cacheAttributeLocations( program, identifiers ) { + + var i, l, id; + + for( i = 0, l = identifiers.length; i < l; i++ ) { + + id = identifiers[ i ]; + program.attributes[ id ] = _gl.getAttribLocation( program, id ); + + } + + }; + + function getShader( type, string ) { + + var shader; + + if ( type == "fragment" ) { + + shader = _gl.createShader( _gl.FRAGMENT_SHADER ); + + } else if ( type == "vertex" ) { + + shader = _gl.createShader( _gl.VERTEX_SHADER ); + + } + + _gl.shaderSource( shader, string ); + _gl.compileShader( shader ); + + if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) { + + alert( _gl.getShaderInfoLog( shader ) ); + return null; + + } + + return shader; + + }; + + function paramThreeToGL( p ) { + + switch ( p ) { + + case THREE.RepeatWrapping: return _gl.REPEAT; break; + case THREE.ClampToEdgeWrapping: return _gl.CLAMP_TO_EDGE; break; + case THREE.MirroredRepeatWrapping: return _gl.MIRRORED_REPEAT; break; + + case THREE.NearestFilter: return _gl.NEAREST; break; + case THREE.NearestMipMapNearestFilter: return _gl.NEAREST_MIPMAP_NEAREST; break; + case THREE.NearestMipMapLinearFilter: return _gl.NEAREST_MIPMAP_LINEAR; break; + + case THREE.LinearFilter: return _gl.LINEAR; break; + case THREE.LinearMipMapNearestFilter: return _gl.LINEAR_MIPMAP_NEAREST; break; + case THREE.LinearMipMapLinearFilter: return _gl.LINEAR_MIPMAP_LINEAR; break; + + case THREE.RGBFormat: return _gl.RGB; break; + + case THREE.UnsignedByteType: return _gl.UNSIGNED_BYTE; break; + + } + + return 0; + + }; + + function materialNeedsSmoothNormals( material ) { + + return material && material.shading != undefined && material.shading == THREE.SmoothShading; + + }; + + function bufferNeedsSmoothNormals( geometryChunk, object ) { + + var m, ml, i, l, meshMaterial, needsSmoothNormals = false; + + for ( m = 0, ml = object.materials.length; m < ml; m++ ) { + + meshMaterial = object.materials[ m ]; + + if ( meshMaterial instanceof THREE.MeshFaceMaterial ) { + + for ( i = 0, l = geometryChunk.materials.length; i < l; i++ ) { + + if ( materialNeedsSmoothNormals( geometryChunk.materials[ i ] ) ) { + + needsSmoothNormals = true; + break; + + } + + } + + } else { + + if ( materialNeedsSmoothNormals( meshMaterial ) ) { + + needsSmoothNormals = true; + break; + + } + + } + + if ( needsSmoothNormals ) break; + + } + + return needsSmoothNormals; + + }; + + function allocateLights( lights, maxLights ) { + + var l, ll, light, dirLights, pointLights, maxDirLights, maxPointLights; + dirLights = pointLights = maxDirLights = maxPointLights = 0; + + for ( l = 0, ll = lights.length; l < ll; l++ ) { + + light = lights[ l ]; + + if ( light instanceof THREE.DirectionalLight ) dirLights++; + if ( light instanceof THREE.PointLight ) pointLights++; + + } + + if ( ( pointLights + dirLights ) <= maxLights ) { + + maxDirLights = dirLights; + maxPointLights = pointLights; + + } else { + + maxDirLights = Math.ceil( maxLights * dirLights / ( pointLights + dirLights ) ); + maxPointLights = maxLights - maxDirLights; + + } + + return { 'directional' : maxDirLights, 'point' : maxPointLights }; + + }; + + /* DEBUG + function getGLParams() { + + var params = { + + 'MAX_VARYING_VECTORS': _gl.getParameter( _gl.MAX_VARYING_VECTORS ), + 'MAX_VERTEX_ATTRIBS': _gl.getParameter( _gl.MAX_VERTEX_ATTRIBS ), + + 'MAX_TEXTURE_IMAGE_UNITS': _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS ), + 'MAX_VERTEX_TEXTURE_IMAGE_UNITS': _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ), + 'MAX_COMBINED_TEXTURE_IMAGE_UNITS' : _gl.getParameter( _gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ), + + 'MAX_VERTEX_UNIFORM_VECTORS': _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS ), + 'MAX_FRAGMENT_UNIFORM_VECTORS': _gl.getParameter( _gl.MAX_FRAGMENT_UNIFORM_VECTORS ) + } + + return params; + }; + + function dumpObject( obj ) { + + var p, str = ""; + for ( p in obj ) { + + str += p + ": " + obj[p] + "\n"; + + } + + return str; + } + */ + +}; + +THREE.Snippets = { + + fog_pars_fragment: [ + + "#ifdef USE_FOG", + + "uniform vec3 fogColor;", + + "#ifdef FOG_EXP2", + "uniform float fogDensity;", + "#else", + "uniform float fogNear;", + "uniform float fogFar;", + "#endif", + + "#endif" + + ].join("\n"), + + fog_fragment: [ + + "#ifdef USE_FOG", + + "float depth = gl_FragCoord.z / gl_FragCoord.w;", + + "#ifdef FOG_EXP2", + "const float LOG2 = 1.442695;", + "float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );", + "fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );", + "#else", + "float fogFactor = smoothstep( fogNear, fogFar, depth );", + "#endif", + + "gl_FragColor = mix( gl_FragColor, vec4( fogColor, 1.0 ), fogFactor );", + + "#endif" + + ].join("\n"), + + envmap_pars_fragment: [ + + "#ifdef USE_ENVMAP", + + "varying vec3 vReflect;", + "uniform float reflectivity;", + "uniform samplerCube env_map;", + "uniform int combine;", + + "#endif" + + ].join("\n"), + + envmap_fragment: [ + + "#ifdef USE_ENVMAP", + + "cubeColor = textureCube( env_map, vec3( -vReflect.x, vReflect.yz ) );", + + "if ( combine == 1 ) {", + + "gl_FragColor = mix( gl_FragColor, cubeColor, reflectivity );", + + "} else {", + + "gl_FragColor = gl_FragColor * cubeColor;", + + "}", + + "#endif" + + ].join("\n"), + + envmap_pars_vertex: [ + + "#ifdef USE_ENVMAP", + + "varying vec3 vReflect;", + "uniform float refraction_ratio;", + "uniform bool useRefract;", + + "#endif" + + ].join("\n"), + + envmap_vertex : [ + + "#ifdef USE_ENVMAP", + + "vec4 mPosition = objectMatrix * vec4( position, 1.0 );", + "vec3 nWorld = mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal;", + + "if ( useRefract ) {", + + "vReflect = refract( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ), refraction_ratio );", + + "} else {", + + "vReflect = reflect( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ) );", + + "}", + + "#endif" + + ].join("\n"), + + map_pars_fragment: [ + + "#ifdef USE_MAP", + + "varying vec2 vUv;", + "uniform sampler2D map;", + + "#endif" + + ].join("\n"), + + map_pars_vertex: [ + + "#ifdef USE_MAP", + + "varying vec2 vUv;", + + "#endif" + + ].join("\n"), + + map_fragment: [ + + "#ifdef USE_MAP", + + "mapColor = texture2D( map, vUv );", + + "#endif" + + ].join("\n"), + + map_vertex: [ + + "#ifdef USE_MAP", + + "vUv = uv;", + + "#endif" + + ].join("\n"), + + lights_pars_vertex: [ + + "uniform bool enableLighting;", + "uniform vec3 ambientLightColor;", + + "#if MAX_DIR_LIGHTS > 0", + + "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];", + "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];", + + "#endif", + + "#if MAX_POINT_LIGHTS > 0", + + "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];", + "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];", + + "#ifdef PHONG", + "varying vec3 vPointLightVector[ MAX_POINT_LIGHTS ];", + "#endif", + + "#endif" + + ].join("\n"), + + lights_vertex: [ + + "if ( !enableLighting ) {", + + "vLightWeighting = vec3( 1.0 );", + + "} else {", + + "vLightWeighting = ambientLightColor;", + + "#if MAX_DIR_LIGHTS > 0", + + "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {", + + "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );", + "float directionalLightWeighting = max( dot( transformedNormal, normalize( lDirection.xyz ) ), 0.0 );", + "vLightWeighting += directionalLightColor[ i ] * directionalLightWeighting;", + + "}", + + "#endif", + + "#if MAX_POINT_LIGHTS > 0", + + "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {", + + "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );", + "vec3 pointLightVector = normalize( lPosition.xyz - mvPosition.xyz );", + "float pointLightWeighting = max( dot( transformedNormal, pointLightVector ), 0.0 );", + "vLightWeighting += pointLightColor[ i ] * pointLightWeighting;", + + "#ifdef PHONG", + "vPointLightVector[ i ] = pointLightVector;", + "#endif", + + "}", + + "#endif", + + "}" + + ].join("\n"), + + lights_pars_fragment: [ + + "#if MAX_DIR_LIGHTS > 0", + "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];", + "#endif", + + "#if MAX_POINT_LIGHTS > 0", + "varying vec3 vPointLightVector[ MAX_POINT_LIGHTS ];", + "#endif", + + "varying vec3 vViewPosition;", + "varying vec3 vNormal;" + + ].join("\n"), + + lights_fragment: [ + + "vec3 normal = normalize( vNormal );", + "vec3 viewPosition = normalize( vViewPosition );", + + "vec4 mSpecular = vec4( specular, opacity );", + + "#if MAX_POINT_LIGHTS > 0", + + "vec4 pointDiffuse = vec4( 0.0 );", + "vec4 pointSpecular = vec4( 0.0 );", + + "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {", + + "vec3 pointVector = normalize( vPointLightVector[ i ] );", + "vec3 pointHalfVector = normalize( vPointLightVector[ i ] + vViewPosition );", + + "float pointDotNormalHalf = dot( normal, pointHalfVector );", + "float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );", + + "float pointSpecularWeight = 0.0;", + "if ( pointDotNormalHalf >= 0.0 )", + "pointSpecularWeight = pow( pointDotNormalHalf, shininess );", + + "pointDiffuse += mColor * pointDiffuseWeight;", + "pointSpecular += mSpecular * pointSpecularWeight;", + + "}", + + "#endif", + + "#if MAX_DIR_LIGHTS > 0", + + "vec4 dirDiffuse = vec4( 0.0 );", + "vec4 dirSpecular = vec4( 0.0 );" , + + "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {", + + "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );", + + "vec3 dirVector = normalize( lDirection.xyz );", + "vec3 dirHalfVector = normalize( lDirection.xyz + vViewPosition );", + + "float dirDotNormalHalf = dot( normal, dirHalfVector );", + + "float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );", + + "float dirSpecularWeight = 0.0;", + "if ( dirDotNormalHalf >= 0.0 )", + "dirSpecularWeight = pow( dirDotNormalHalf, shininess );", + + "dirDiffuse += mColor * dirDiffuseWeight;", + "dirSpecular += mSpecular * dirSpecularWeight;", + + "}", + + "#endif", + + "vec4 totalLight = vec4( ambient, opacity );", + + "#if MAX_DIR_LIGHTS > 0", + "totalLight += dirDiffuse + dirSpecular;", + "#endif", + + "#if MAX_POINT_LIGHTS > 0", + "totalLight += pointDiffuse + pointSpecular;", + "#endif" + + ].join("\n") + +}; + +THREE.UniformsLib = { + + common: { + + "color" : { type: "c", value: new THREE.Color( 0xeeeeee ) }, + "opacity" : { type: "f", value: 1 }, + "map" : { type: "t", value: 0, texture: null }, + + "env_map" : { type: "t", value: 1, texture: null }, + "useRefract" : { type: "i", value: 0 }, + "reflectivity" : { type: "f", value: 1 }, + "refraction_ratio": { type: "f", value: 0.98 }, + "combine" : { type: "i", value: 0 }, + + "fogDensity": { type: "f", value: 0.00025 }, + "fogNear" : { type: "f", value: 1 }, + "fogFar" : { type: "f", value: 2000 }, + "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) } + + }, + + lights: { + + "enableLighting" : { type: "i", value: 1 }, + "ambientLightColor" : { type: "fv", value: [] }, + "directionalLightDirection" : { type: "fv", value: [] }, + "directionalLightColor" : { type: "fv", value: [] }, + "pointLightPosition" : { type: "fv", value: [] }, + "pointLightColor" : { type: "fv", value: [] } + + } + +}; + +THREE.ShaderLib = { + + 'depth': { + + uniforms: { "mNear": { type: "f", value: 1.0 }, + "mFar" : { type: "f", value: 2000.0 } }, + + fragment_shader: [ + + "uniform float mNear;", + "uniform float mFar;", + + "void main() {", + + "float depth = gl_FragCoord.z / gl_FragCoord.w;", + "float color = 1.0 - smoothstep( mNear, mFar, depth );", + "gl_FragColor = vec4( vec3( color ), 1.0 );", + + "}" + + ].join("\n"), + + vertex_shader: [ + + "void main() {", + + "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", + + "}" + + ].join("\n") + + }, + + 'normal': { + + uniforms: { }, + + fragment_shader: [ + + "varying vec3 vNormal;", + + "void main() {", + + "gl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, 1.0 );", + + "}" + + ].join("\n"), + + vertex_shader: [ + + "varying vec3 vNormal;", + + "void main() {", + + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + "vNormal = normalize( normalMatrix * normal );", + + "gl_Position = projectionMatrix * mvPosition;", + + "}" + + ].join("\n") + + }, + + 'basic': { + + uniforms: THREE.UniformsLib[ "common" ], + + fragment_shader: [ + + "uniform vec3 color;", + "uniform float opacity;", + + THREE.Snippets[ "map_pars_fragment" ], + THREE.Snippets[ "envmap_pars_fragment" ], + THREE.Snippets[ "fog_pars_fragment" ], + + "void main() {", + + "vec4 mColor = vec4( color, opacity );", + "vec4 mapColor = vec4( 1.0 );", + "vec4 cubeColor = vec4( 1.0 );", + + THREE.Snippets[ "map_fragment" ], + + "gl_FragColor = mColor * mapColor;", + + THREE.Snippets[ "envmap_fragment" ], + THREE.Snippets[ "fog_fragment" ], + + "}" + + ].join("\n"), + + vertex_shader: [ + + THREE.Snippets[ "map_pars_vertex" ], + THREE.Snippets[ "envmap_pars_vertex" ], + + "void main() {", + + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + + THREE.Snippets[ "map_vertex" ], + THREE.Snippets[ "envmap_vertex" ], + + "gl_Position = projectionMatrix * mvPosition;", + + "}" + + ].join("\n") + + }, + + 'lambert': { + + uniforms: Uniforms.merge( [ THREE.UniformsLib[ "common" ], + THREE.UniformsLib[ "lights" ] ] ), + + fragment_shader: [ + + "uniform vec3 color;", + "uniform float opacity;", + + "varying vec3 vLightWeighting;", + + THREE.Snippets[ "map_pars_fragment" ], + THREE.Snippets[ "envmap_pars_fragment" ], + THREE.Snippets[ "fog_pars_fragment" ], + + "void main() {", + + "vec4 mColor = vec4( color, opacity );", + "vec4 mapColor = vec4( 1.0 );", + "vec4 cubeColor = vec4( 1.0 );", + + THREE.Snippets[ "map_fragment" ], + + "gl_FragColor = mColor * mapColor * vec4( vLightWeighting, 1.0 );", + + THREE.Snippets[ "envmap_fragment" ], + THREE.Snippets[ "fog_fragment" ], + + "}" + + ].join("\n"), + + vertex_shader: [ + + "varying vec3 vLightWeighting;", + + THREE.Snippets[ "map_pars_vertex" ], + THREE.Snippets[ "envmap_pars_vertex" ], + THREE.Snippets[ "lights_pars_vertex" ], + + "void main() {", + + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + + THREE.Snippets[ "map_vertex" ], + THREE.Snippets[ "envmap_vertex" ], + + "vec3 transformedNormal = normalize( normalMatrix * normal );", + + THREE.Snippets[ "lights_vertex" ], + + "gl_Position = projectionMatrix * mvPosition;", + + "}" + + ].join("\n") + + }, + + 'phong': { + + uniforms: Uniforms.merge( [ THREE.UniformsLib[ "common" ], + THREE.UniformsLib[ "lights" ], + + { "ambient" : { type: "c", value: new THREE.Color( 0x050505 ) }, + "specular" : { type: "c", value: new THREE.Color( 0x111111 ) }, + "shininess": { type: "f", value: 30 } + } + + ] ), + + fragment_shader: [ + + "uniform vec3 color;", + "uniform float opacity;", + + "uniform vec3 ambient;", + "uniform vec3 specular;", + "uniform float shininess;", + + "varying vec3 vLightWeighting;", + + THREE.Snippets[ "map_pars_fragment" ], + THREE.Snippets[ "envmap_pars_fragment" ], + THREE.Snippets[ "fog_pars_fragment" ], + THREE.Snippets[ "lights_pars_fragment" ], + + "void main() {", + + "vec4 mColor = vec4( color, opacity );", + "vec4 mapColor = vec4( 1.0 );", + "vec4 cubeColor = vec4( 1.0 );", + + THREE.Snippets[ "map_fragment" ], + THREE.Snippets[ "lights_fragment" ], + + "gl_FragColor = mapColor * totalLight * vec4( vLightWeighting, 1.0 );", + + THREE.Snippets[ "envmap_fragment" ], + THREE.Snippets[ "fog_fragment" ], + + "}" + + ].join("\n"), + + vertex_shader: [ + + "#define PHONG", + + "varying vec3 vLightWeighting;", + "varying vec3 vViewPosition;", + "varying vec3 vNormal;", + + THREE.Snippets[ "map_pars_vertex" ], + THREE.Snippets[ "envmap_pars_vertex" ], + THREE.Snippets[ "lights_pars_vertex" ], + + "void main() {", + + "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", + + THREE.Snippets[ "map_vertex" ], + THREE.Snippets[ "envmap_vertex" ], + + "#ifndef USE_ENVMAP", + "vec4 mPosition = objectMatrix * vec4( position, 1.0 );", + "#endif", + + "vViewPosition = cameraPosition - mPosition.xyz;", + + "vec3 transformedNormal = normalize( normalMatrix * normal );", + "vNormal = transformedNormal;", + + THREE.Snippets[ "lights_vertex" ], + + "gl_Position = projectionMatrix * mvPosition;", + + "}" + + ].join("\n") + + } + +}; diff --git a/examples/render_to_texture.html b/examples/render_to_texture.html new file mode 100644 index 00000000..44b8cb73 --- /dev/null +++ b/examples/render_to_texture.html @@ -0,0 +1,149 @@ + + + + three.js - shader + + + + + +
+ + + + + + + + + + + + + + + + +