From 62615a6e072fe4101189aa76eebe0960c09dc91c Mon Sep 17 00:00:00 2001 From: yushijinhun Date: Fri, 19 Jun 2020 17:37:52 +0800 Subject: [PATCH] update --- index.html | 4 ++-- js/dist/revision | 2 +- js/dist/skinview3d.bundle.js | 2 +- js/dist/skinview3d.bundle.js.map | 2 +- js/example.js | 25 +++++++------------------ 5 files changed, 12 insertions(+), 23 deletions(-) diff --git a/index.html b/index.html index fc43851..dda527b 100644 --- a/index.html +++ b/index.html @@ -108,7 +108,7 @@

Skin

- @@ -119,7 +119,7 @@

Cape

- diff --git a/js/dist/revision b/js/dist/revision index f7b4366..f90cca4 100644 --- a/js/dist/revision +++ b/js/dist/revision @@ -1 +1 @@ -0118d38a645a1f057358d2928a447219e3e97417 +34e2a3f24344c05cd33d974bffcdf118b0d66772 diff --git a/js/dist/skinview3d.bundle.js b/js/dist/skinview3d.bundle.js index 91f6239..1a14955 100644 --- a/js/dist/skinview3d.bundle.js +++ b/js/dist/skinview3d.bundle.js @@ -1,2 +1,2 @@ /* @preserve skinview3d / MIT License / https://github.com/bs-community/skinview3d */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).skinview3d={})}(this,(function(e){"use strict";const t=0,n=1,i=2,r=0,a=1,o=2,s=3;function l(){}Object.assign(l.prototype,{addEventListener:function(e,t){void 0===this._listeners&&(this._listeners={});var n=this._listeners;void 0===n[e]&&(n[e]=[]),-1===n[e].indexOf(t)&&n[e].push(t)},hasEventListener:function(e,t){if(void 0===this._listeners)return!1;var n=this._listeners;return void 0!==n[e]&&-1!==n[e].indexOf(t)},removeEventListener:function(e,t){if(void 0!==this._listeners){var n=this._listeners[e];if(void 0!==n){var i=n.indexOf(t);-1!==i&&n.splice(i,1)}}},dispatchEvent:function(e){if(void 0!==this._listeners){var t=this._listeners[e.type];if(void 0!==t){e.target=this;for(var n=t.slice(0),i=0,r=n.length;i>8&255]+c[e>>16&255]+c[e>>24&255]+"-"+c[255&t]+c[t>>8&255]+"-"+c[t>>16&15|64]+c[t>>24&255]+"-"+c[63&n|128]+c[n>>8&255]+"-"+c[n>>16&255]+c[n>>24&255]+c[255&i]+c[i>>8&255]+c[i>>16&255]+c[i>>24&255]).toUpperCase()},clamp:function(e,t,n){return Math.max(t,Math.min(n,e))},euclideanModulo:function(e,t){return(e%t+t)%t},mapLinear:function(e,t,n,i,r){return i+(e-t)*(r-i)/(n-t)},lerp:function(e,t,n){return(1-n)*e+n*t},smoothstep:function(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t))*e*(3-2*e)},smootherstep:function(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},degToRad:function(e){return e*d.DEG2RAD},radToDeg:function(e){return e*d.RAD2DEG},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))},setQuaternionFromProperEuler:function(e,t,n,i,r){var a=Math.cos,o=Math.sin,s=a(n/2),l=o(n/2),c=a((t+i)/2),h=o((t+i)/2),u=a((t-i)/2),d=o((t-i)/2),p=a((i-t)/2),f=o((i-t)/2);switch(r){case"XYX":e.set(s*h,l*u,l*d,s*c);break;case"YZY":e.set(l*d,s*h,l*u,s*c);break;case"ZXZ":e.set(l*u,l*d,s*h,s*c);break;case"XZX":e.set(s*h,l*f,l*p,s*c);break;case"YXY":e.set(l*p,s*h,l*f,s*c);break;case"ZYZ":e.set(l*f,l*p,s*h,s*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}}};function p(e,t){this.x=e||0,this.y=t||0}function f(){this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}Object.defineProperties(p.prototype,{width:{get:function(){return this.x},set:function(e){this.x=e}},height:{get:function(){return this.y},set:function(e){this.y=e}}}),Object.assign(p.prototype,{isVector2:!0,set:function(e,t){return this.x=e,this.y=t,this},setScalar:function(e){return this.x=e,this.y=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(e){return this.x=e.x,this.y=e.y,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this)},addScalar:function(e){return this.x+=e,this.y+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this)},subScalar:function(e){return this.x-=e,this.y-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this},multiply:function(e){return this.x*=e.x,this.y*=e.y,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this},divide:function(e){return this.x/=e.x,this.y/=e.y,this},divideScalar:function(e){return this.multiplyScalar(1/e)},applyMatrix3:function(e){var t=this.x,n=this.y,i=e.elements;return this.x=i[0]*t+i[3]*n+i[6],this.y=i[1]*t+i[4]*n+i[7],this},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this},clampScalar:function(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this},clampLength:function(e,t){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this},negate:function(){return this.x=-this.x,this.y=-this.y,this},dot:function(e){return this.x*e.x+this.y*e.y},cross:function(e){return this.x*e.y-this.y*e.x},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length()||1)},angle:function(){return Math.atan2(-this.y,-this.x)+Math.PI},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,n=this.y-e.y;return t*t+n*n},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this},lerpVectors:function(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this},equals:function(e){return e.x===this.x&&e.y===this.y},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e},fromBufferAttribute:function(e,t,n){return void 0!==n&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this},rotateAround:function(e,t){var n=Math.cos(t),i=Math.sin(t),r=this.x-e.x,a=this.y-e.y;return this.x=r*n-a*i+e.x,this.y=r*i+a*n+e.y,this},random:function(){return this.x=Math.random(),this.y=Math.random(),this}}),Object.assign(f.prototype,{isMatrix3:!0,set:function(e,t,n,i,r,a,o,s,l){var c=this.elements;return c[0]=e,c[1]=i,c[2]=o,c[3]=t,c[4]=r,c[5]=s,c[6]=n,c[7]=a,c[8]=l,this},identity:function(){return this.set(1,0,0,0,1,0,0,0,1),this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(e){var t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],this},extractBasis:function(e,t,n){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this},setFromMatrix4:function(e){var t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this},multiply:function(e){return this.multiplyMatrices(this,e)},premultiply:function(e){return this.multiplyMatrices(e,this)},multiplyMatrices:function(e,t){var n=e.elements,i=t.elements,r=this.elements,a=n[0],o=n[3],s=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],f=i[0],m=i[3],g=i[6],v=i[1],x=i[4],_=i[7],y=i[2],M=i[5],b=i[8];return r[0]=a*f+o*v+s*y,r[3]=a*m+o*x+s*M,r[6]=a*g+o*_+s*b,r[1]=l*f+c*v+h*y,r[4]=l*m+c*x+h*M,r[7]=l*g+c*_+h*b,r[2]=u*f+d*v+p*y,r[5]=u*m+d*x+p*M,r[8]=u*g+d*_+p*b,this},multiplyScalar:function(e){var t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this},determinant:function(){var e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],o=e[5],s=e[6],l=e[7],c=e[8];return t*a*c-t*o*l-n*r*c+n*o*s+i*r*l-i*a*s},getInverse:function(e,t){void 0!==t&&console.warn("THREE.Matrix3: .getInverse() can no longer be configured to throw on degenerate.");var n=e.elements,i=this.elements,r=n[0],a=n[1],o=n[2],s=n[3],l=n[4],c=n[5],h=n[6],u=n[7],d=n[8],p=d*l-c*u,f=c*h-d*s,m=u*s-l*h,g=r*p+a*f+o*m;if(0===g)return this.set(0,0,0,0,0,0,0,0,0);var v=1/g;return i[0]=p*v,i[1]=(o*u-d*a)*v,i[2]=(c*a-o*l)*v,i[3]=f*v,i[4]=(d*r-o*h)*v,i[5]=(o*s-c*r)*v,i[6]=m*v,i[7]=(a*h-u*r)*v,i[8]=(l*r-a*s)*v,this},transpose:function(){var e,t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this},getNormalMatrix:function(e){return this.setFromMatrix4(e).getInverse(this).transpose()},transposeIntoArray:function(e){var t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this},setUvTransform:function(e,t,n,i,r,a,o){var s=Math.cos(r),l=Math.sin(r);this.set(n*s,n*l,-n*(s*a+l*o)+a+e,-i*l,i*s,-i*(-l*a+s*o)+o+t,0,0,1)},scale:function(e,t){var n=this.elements;return n[0]*=e,n[3]*=e,n[6]*=e,n[1]*=t,n[4]*=t,n[7]*=t,this},rotate:function(e){var t=Math.cos(e),n=Math.sin(e),i=this.elements,r=i[0],a=i[3],o=i[6],s=i[1],l=i[4],c=i[7];return i[0]=t*r+n*s,i[3]=t*a+n*l,i[6]=t*o+n*c,i[1]=-n*r+t*s,i[4]=-n*a+t*l,i[7]=-n*o+t*c,this},translate:function(e,t){var n=this.elements;return n[0]+=e*n[2],n[3]+=e*n[5],n[6]+=e*n[8],n[1]+=t*n[2],n[4]+=t*n[5],n[7]+=t*n[8],this},equals:function(e){for(var t=this.elements,n=e.elements,i=0;i<9;i++)if(t[i]!==n[i])return!1;return!0},fromArray:function(e,t){void 0===t&&(t=0);for(var n=0;n<9;n++)this.elements[n]=e[n+t];return this},toArray:function(e,t){void 0===e&&(e=[]),void 0===t&&(t=0);var n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e}});var m=function(e){var t;if("undefined"==typeof HTMLCanvasElement)return e.src;if(e instanceof HTMLCanvasElement)t=e;else{void 0===u&&(u=document.createElementNS("http://www.w3.org/1999/xhtml","canvas")),u.width=e.width,u.height=e.height;var n=u.getContext("2d");e instanceof ImageData?n.putImageData(e,0,0):n.drawImage(e,0,0,e.width,e.height),t=u}return t.width>2048||t.height>2048?t.toDataURL("image/jpeg",.6):t.toDataURL("image/png")},g=0;function v(e,t,n,i,r,a,o,s,l,c){Object.defineProperty(this,"id",{value:g++}),this.uuid=d.generateUUID(),this.name="",this.image=void 0!==e?e:v.DEFAULT_IMAGE,this.mipmaps=[],this.mapping=void 0!==t?t:v.DEFAULT_MAPPING,this.wrapS=void 0!==n?n:1001,this.wrapT=void 0!==i?i:1001,this.magFilter=void 0!==r?r:1006,this.minFilter=void 0!==a?a:1008,this.anisotropy=void 0!==l?l:1,this.format=void 0!==o?o:1023,this.internalFormat=null,this.type=void 0!==s?s:1009,this.offset=new p(0,0),this.repeat=new p(1,1),this.center=new p(0,0),this.rotation=0,this.matrixAutoUpdate=!0,this.matrix=new f,this.generateMipmaps=!0,this.premultiplyAlpha=!1,this.flipY=!0,this.unpackAlignment=4,this.encoding=void 0!==c?c:3e3,this.version=0,this.onUpdate=null}function x(e,t,n,i){this.x=e||0,this.y=t||0,this.z=n||0,this.w=void 0!==i?i:1}function _(e,t,n){this.width=e,this.height=t,this.scissor=new x(0,0,e,t),this.scissorTest=!1,this.viewport=new x(0,0,e,t),n=n||{},this.texture=new v(void 0,n.mapping,n.wrapS,n.wrapT,n.magFilter,n.minFilter,n.format,n.type,n.anisotropy,n.encoding),this.texture.image={},this.texture.image.width=e,this.texture.image.height=t,this.texture.generateMipmaps=void 0!==n.generateMipmaps&&n.generateMipmaps,this.texture.minFilter=void 0!==n.minFilter?n.minFilter:1006,this.depthBuffer=void 0===n.depthBuffer||n.depthBuffer,this.stencilBuffer=void 0===n.stencilBuffer||n.stencilBuffer,this.depthTexture=void 0!==n.depthTexture?n.depthTexture:null}function y(e,t,n,i){this._x=e||0,this._y=t||0,this._z=n||0,this._w=void 0!==i?i:1}v.DEFAULT_IMAGE=void 0,v.DEFAULT_MAPPING=300,v.prototype=Object.assign(Object.create(l.prototype),{constructor:v,isTexture:!0,updateMatrix:function(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y)},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.name=e.name,this.image=e.image,this.mipmaps=e.mipmaps.slice(0),this.mapping=e.mapping,this.wrapS=e.wrapS,this.wrapT=e.wrapT,this.magFilter=e.magFilter,this.minFilter=e.minFilter,this.anisotropy=e.anisotropy,this.format=e.format,this.internalFormat=e.internalFormat,this.type=e.type,this.offset.copy(e.offset),this.repeat.copy(e.repeat),this.center.copy(e.center),this.rotation=e.rotation,this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrix.copy(e.matrix),this.generateMipmaps=e.generateMipmaps,this.premultiplyAlpha=e.premultiplyAlpha,this.flipY=e.flipY,this.unpackAlignment=e.unpackAlignment,this.encoding=e.encoding,this},toJSON:function(e){var t=void 0===e||"string"==typeof e;if(!t&&void 0!==e.textures[this.uuid])return e.textures[this.uuid];var n={metadata:{version:4.5,type:"Texture",generator:"Texture.toJSON"},uuid:this.uuid,name:this.name,mapping:this.mapping,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],center:[this.center.x,this.center.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],format:this.format,type:this.type,encoding:this.encoding,minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY,premultiplyAlpha:this.premultiplyAlpha,unpackAlignment:this.unpackAlignment};if(void 0!==this.image){var i=this.image;if(void 0===i.uuid&&(i.uuid=d.generateUUID()),!t&&void 0===e.images[i.uuid]){var r;if(Array.isArray(i)){r=[];for(var a=0,o=i.length;a1)switch(this.wrapS){case 1e3:e.x=e.x-Math.floor(e.x);break;case 1001:e.x=e.x<0?0:1;break;case 1002:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case 1e3:e.y=e.y-Math.floor(e.y);break;case 1001:e.y=e.y<0?0:1;break;case 1002:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}return this.flipY&&(e.y=1-e.y),e}}),Object.defineProperty(v.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),Object.defineProperties(x.prototype,{width:{get:function(){return this.z},set:function(e){this.z=e}},height:{get:function(){return this.w},set:function(e){this.w=e}}}),Object.assign(x.prototype,{isVector4:!0,set:function(e,t,n,i){return this.x=e,this.y=t,this.z=n,this.w=i,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this.w=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setW:function(e){return this.w=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z,this.w)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this},applyMatrix4:function(e){var t=this.x,n=this.y,i=this.z,r=this.w,a=e.elements;return this.x=a[0]*t+a[4]*n+a[8]*i+a[12]*r,this.y=a[1]*t+a[5]*n+a[9]*i+a[13]*r,this.z=a[2]*t+a[6]*n+a[10]*i+a[14]*r,this.w=a[3]*t+a[7]*n+a[11]*i+a[15]*r,this},divideScalar:function(e){return this.multiplyScalar(1/e)},setAxisAngleFromQuaternion:function(e){this.w=2*Math.acos(e.w);var t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this},setAxisAngleFromRotationMatrix:function(e){var t,n,i,r,a=e.elements,o=a[0],s=a[4],l=a[8],c=a[1],h=a[5],u=a[9],d=a[2],p=a[6],f=a[10];if(Math.abs(s-c)<.01&&Math.abs(l-d)<.01&&Math.abs(u-p)<.01){if(Math.abs(s+c)<.1&&Math.abs(l+d)<.1&&Math.abs(u+p)<.1&&Math.abs(o+h+f-3)<.1)return this.set(1,0,0,0),this;t=Math.PI;var m=(o+1)/2,g=(h+1)/2,v=(f+1)/2,x=(s+c)/4,_=(l+d)/4,y=(u+p)/4;return m>g&&m>v?m<.01?(n=0,i=.707106781,r=.707106781):(i=x/(n=Math.sqrt(m)),r=_/n):g>v?g<.01?(n=.707106781,i=0,r=.707106781):(n=x/(i=Math.sqrt(g)),r=y/i):v<.01?(n=.707106781,i=.707106781,r=0):(n=_/(r=Math.sqrt(v)),i=y/r),this.set(n,i,r,t),this}var M=Math.sqrt((p-u)*(p-u)+(l-d)*(l-d)+(c-s)*(c-s));return Math.abs(M)<.001&&(M=1),this.x=(p-u)/M,this.y=(l-d)/M,this.z=(c-s)/M,this.w=Math.acos((o+h+f-1)/2),this},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this.w=Math.min(this.w,e.w),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this.w=Math.max(this.w,e.w),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this.w=Math.max(e.w,Math.min(t.w,this.w)),this},clampScalar:function(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this.w=Math.max(e,Math.min(t,this.w)),this},clampLength:function(e,t){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this.w=this.w<0?Math.ceil(this.w):Math.floor(this.w),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this},dot:function(e){return this.x*e.x+this.y*e.y+this.z*e.z+this.w*e.w},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this.w+=(e.w-this.w)*t,this},lerpVectors:function(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this.w=e.w+(t.w-e.w)*n,this},equals:function(e){return e.x===this.x&&e.y===this.y&&e.z===this.z&&e.w===this.w},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this.z=e[t+2],this.w=e[t+3],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e[t+3]=this.w,e},fromBufferAttribute:function(e,t,n){return void 0!==n&&console.warn("THREE.Vector4: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this.w=e.getW(t),this},random:function(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this.w=Math.random(),this}}),_.prototype=Object.assign(Object.create(l.prototype),{constructor:_,isWebGLRenderTarget:!0,setSize:function(e,t){this.width===e&&this.height===t||(this.width=e,this.height=t,this.texture.image.width=e,this.texture.image.height=t,this.dispose()),this.viewport.set(0,0,e,t),this.scissor.set(0,0,e,t)},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.width=e.width,this.height=e.height,this.viewport.copy(e.viewport),this.texture=e.texture.clone(),this.depthBuffer=e.depthBuffer,this.stencilBuffer=e.stencilBuffer,this.depthTexture=e.depthTexture,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),Object.assign(y,{slerp:function(e,t,n,i){return n.copy(e).slerp(t,i)},slerpFlat:function(e,t,n,i,r,a,o){var s=n[i+0],l=n[i+1],c=n[i+2],h=n[i+3],u=r[a+0],d=r[a+1],p=r[a+2],f=r[a+3];if(h!==f||s!==u||l!==d||c!==p){var m=1-o,g=s*u+l*d+c*p+h*f,v=g>=0?1:-1,x=1-g*g;if(x>Number.EPSILON){var _=Math.sqrt(x),y=Math.atan2(_,g*v);m=Math.sin(m*y)/_,o=Math.sin(o*y)/_}var M=o*v;if(s=s*m+u*M,l=l*m+d*M,c=c*m+p*M,h=h*m+f*M,m===1-o){var b=1/Math.sqrt(s*s+l*l+c*c+h*h);s*=b,l*=b,c*=b,h*=b}}e[t]=s,e[t+1]=l,e[t+2]=c,e[t+3]=h},multiplyQuaternionsFlat:function(e,t,n,i,r,a){var o=n[i],s=n[i+1],l=n[i+2],c=n[i+3],h=r[a],u=r[a+1],d=r[a+2],p=r[a+3];return e[t]=o*p+c*h+s*d-l*u,e[t+1]=s*p+c*u+l*h-o*d,e[t+2]=l*p+c*d+o*u-s*h,e[t+3]=c*p-o*h-s*u-l*d,e}}),Object.defineProperties(y.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this._onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this._onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this._onChangeCallback()}},w:{get:function(){return this._w},set:function(e){this._w=e,this._onChangeCallback()}}}),Object.assign(y.prototype,{isQuaternion:!0,set:function(e,t,n,i){return this._x=e,this._y=t,this._z=n,this._w=i,this._onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._w)},copy:function(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this},setFromEuler:function(e,t){if(!e||!e.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var n=e._x,i=e._y,r=e._z,a=e.order,o=Math.cos,s=Math.sin,l=o(n/2),c=o(i/2),h=o(r/2),u=s(n/2),d=s(i/2),p=s(r/2);switch(a){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+a)}return!1!==t&&this._onChangeCallback(),this},setFromAxisAngle:function(e,t){var n=t/2,i=Math.sin(n);return this._x=e.x*i,this._y=e.y*i,this._z=e.z*i,this._w=Math.cos(n),this._onChangeCallback(),this},setFromRotationMatrix:function(e){var t,n=e.elements,i=n[0],r=n[4],a=n[8],o=n[1],s=n[5],l=n[9],c=n[2],h=n[6],u=n[10],d=i+s+u;return d>0?(t=.5/Math.sqrt(d+1),this._w=.25/t,this._x=(h-l)*t,this._y=(a-c)*t,this._z=(o-r)*t):i>s&&i>u?(t=2*Math.sqrt(1+i-s-u),this._w=(h-l)/t,this._x=.25*t,this._y=(r+o)/t,this._z=(a+c)/t):s>u?(t=2*Math.sqrt(1+s-i-u),this._w=(a-c)/t,this._x=(r+o)/t,this._y=.25*t,this._z=(l+h)/t):(t=2*Math.sqrt(1+u-i-s),this._w=(o-r)/t,this._x=(a+c)/t,this._y=(l+h)/t,this._z=.25*t),this._onChangeCallback(),this},setFromUnitVectors:function(e,t){var n=e.dot(t)+1;return n<1e-6?(n=0,Math.abs(e.x)>Math.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=n):(this._x=0,this._y=-e.z,this._z=e.y,this._w=n)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=n),this.normalize()},angleTo:function(e){return 2*Math.acos(Math.abs(d.clamp(this.dot(e),-1,1)))},rotateTowards:function(e,t){var n=this.angleTo(e);if(0===n)return this;var i=Math.min(1,t/n);return this.slerp(e,i),this},inverse:function(){return this.conjugate()},conjugate:function(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this},dot:function(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._w},lengthSq:function(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w},length:function(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)},normalize:function(){var e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this._onChangeCallback(),this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(e,t)):this.multiplyQuaternions(this,e)},premultiply:function(e){return this.multiplyQuaternions(e,this)},multiplyQuaternions:function(e,t){var n=e._x,i=e._y,r=e._z,a=e._w,o=t._x,s=t._y,l=t._z,c=t._w;return this._x=n*c+a*o+i*l-r*s,this._y=i*c+a*s+r*o-n*l,this._z=r*c+a*l+n*s-i*o,this._w=a*c-n*o-i*s-r*l,this._onChangeCallback(),this},slerp:function(e,t){if(0===t)return this;if(1===t)return this.copy(e);var n=this._x,i=this._y,r=this._z,a=this._w,o=a*e._w+n*e._x+i*e._y+r*e._z;if(o<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,o=-o):this.copy(e),o>=1)return this._w=a,this._x=n,this._y=i,this._z=r,this;var s=1-o*o;if(s<=Number.EPSILON){var l=1-t;return this._w=l*a+t*this._w,this._x=l*n+t*this._x,this._y=l*i+t*this._y,this._z=l*r+t*this._z,this.normalize(),this._onChangeCallback(),this}var c=Math.sqrt(s),h=Math.atan2(c,o),u=Math.sin((1-t)*h)/c,d=Math.sin(t*h)/c;return this._w=a*u+this._w*d,this._x=n*u+this._x*d,this._y=i*u+this._y*d,this._z=r*u+this._z*d,this._onChangeCallback(),this},equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w},fromArray:function(e,t){return void 0===t&&(t=0),this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e},fromBufferAttribute:function(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this},_onChange:function(e){return this._onChangeCallback=e,this},_onChangeCallback:function(){}});var M=new w,b=new y;function w(e,t,n){this.x=e||0,this.y=t||0,this.z=n||0}Object.assign(w.prototype,{isVector3:!0,set:function(e,t,n){return this.x=e,this.y=t,this.z=n,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(e,t)):(this.x*=e.x,this.y*=e.y,this.z*=e.z,this)},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this},multiplyVectors:function(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this},applyEuler:function(e){return e&&e.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(b.setFromEuler(e))},applyAxisAngle:function(e,t){return this.applyQuaternion(b.setFromAxisAngle(e,t))},applyMatrix3:function(e){var t=this.x,n=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[3]*n+r[6]*i,this.y=r[1]*t+r[4]*n+r[7]*i,this.z=r[2]*t+r[5]*n+r[8]*i,this},applyNormalMatrix:function(e){return this.applyMatrix3(e).normalize()},applyMatrix4:function(e){var t=this.x,n=this.y,i=this.z,r=e.elements,a=1/(r[3]*t+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*t+r[4]*n+r[8]*i+r[12])*a,this.y=(r[1]*t+r[5]*n+r[9]*i+r[13])*a,this.z=(r[2]*t+r[6]*n+r[10]*i+r[14])*a,this},applyQuaternion:function(e){var t=this.x,n=this.y,i=this.z,r=e.x,a=e.y,o=e.z,s=e.w,l=s*t+a*i-o*n,c=s*n+o*t-r*i,h=s*i+r*n-a*t,u=-r*t-a*n-o*i;return this.x=l*s+u*-r+c*-o-h*-a,this.y=c*s+u*-a+h*-r-l*-o,this.z=h*s+u*-o+l*-a-c*-r,this},project:function(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)},unproject:function(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)},transformDirection:function(e){var t=this.x,n=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[4]*n+r[8]*i,this.y=r[1]*t+r[5]*n+r[9]*i,this.z=r[2]*t+r[6]*n+r[10]*i,this.normalize()},divide:function(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this},divideScalar:function(e){return this.multiplyScalar(1/e)},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this},clampScalar:function(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this},clampLength:function(e,t){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this},dot:function(e){return this.x*e.x+this.y*e.y+this.z*e.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this},lerpVectors:function(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this},cross:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(e,t)):this.crossVectors(this,e)},crossVectors:function(e,t){var n=e.x,i=e.y,r=e.z,a=t.x,o=t.y,s=t.z;return this.x=i*s-r*o,this.y=r*a-n*s,this.z=n*o-i*a,this},projectOnVector:function(e){var t=e.lengthSq();if(0===t)return this.set(0,0,0);var n=e.dot(this)/t;return this.copy(e).multiplyScalar(n)},projectOnPlane:function(e){return M.copy(this).projectOnVector(e),this.sub(M)},reflect:function(e){return this.sub(M.copy(e).multiplyScalar(2*this.dot(e)))},angleTo:function(e){var t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;var n=this.dot(e)/t;return Math.acos(d.clamp(n,-1,1))},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,n=this.y-e.y,i=this.z-e.z;return t*t+n*n+i*i},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)},setFromSpherical:function(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)},setFromSphericalCoords:function(e,t,n){var i=Math.sin(t)*e;return this.x=i*Math.sin(n),this.y=Math.cos(t)*e,this.z=i*Math.cos(n),this},setFromCylindrical:function(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)},setFromCylindricalCoords:function(e,t,n){return this.x=e*Math.sin(t),this.y=n,this.z=e*Math.cos(t),this},setFromMatrixPosition:function(e){var t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this},setFromMatrixScale:function(e){var t=this.setFromMatrixColumn(e,0).length(),n=this.setFromMatrixColumn(e,1).length(),i=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=n,this.z=i,this},setFromMatrixColumn:function(e,t){return this.fromArray(e.elements,4*t)},setFromMatrix3Column:function(e,t){return this.fromArray(e.elements,3*t)},equals:function(e){return e.x===this.x&&e.y===this.y&&e.z===this.z},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this.z=e[t+2],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e},fromBufferAttribute:function(e,t,n){return void 0!==n&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this},random:function(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}});var S=new w,E=new D,T=new w(0,0,0),L=new w(1,1,1),A=new w,P=new w,C=new w;function D(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}Object.assign(D.prototype,{isMatrix4:!0,set:function(e,t,n,i,r,a,o,s,l,c,h,u,d,p,f,m){var g=this.elements;return g[0]=e,g[4]=t,g[8]=n,g[12]=i,g[1]=r,g[5]=a,g[9]=o,g[13]=s,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=f,g[15]=m,this},identity:function(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this},clone:function(){return(new D).fromArray(this.elements)},copy:function(e){var t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],this},copyPosition:function(e){var t=this.elements,n=e.elements;return t[12]=n[12],t[13]=n[13],t[14]=n[14],this},extractBasis:function(e,t,n){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this},makeBasis:function(e,t,n){return this.set(e.x,t.x,n.x,0,e.y,t.y,n.y,0,e.z,t.z,n.z,0,0,0,0,1),this},extractRotation:function(e){var t=this.elements,n=e.elements,i=1/S.setFromMatrixColumn(e,0).length(),r=1/S.setFromMatrixColumn(e,1).length(),a=1/S.setFromMatrixColumn(e,2).length();return t[0]=n[0]*i,t[1]=n[1]*i,t[2]=n[2]*i,t[3]=0,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=0,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},makeRotationFromEuler:function(e){e&&e.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var t=this.elements,n=e.x,i=e.y,r=e.z,a=Math.cos(n),o=Math.sin(n),s=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===e.order){var u=a*c,d=a*h,p=o*c,f=o*h;t[0]=s*c,t[4]=-s*h,t[8]=l,t[1]=d+p*l,t[5]=u-f*l,t[9]=-o*s,t[2]=f-u*l,t[6]=p+d*l,t[10]=a*s}else if("YXZ"===e.order){var m=s*c,g=s*h,v=l*c,x=l*h;t[0]=m+x*o,t[4]=v*o-g,t[8]=a*l,t[1]=a*h,t[5]=a*c,t[9]=-o,t[2]=g*o-v,t[6]=x+m*o,t[10]=a*s}else if("ZXY"===e.order){m=s*c,g=s*h,v=l*c,x=l*h;t[0]=m-x*o,t[4]=-a*h,t[8]=v+g*o,t[1]=g+v*o,t[5]=a*c,t[9]=x-m*o,t[2]=-a*l,t[6]=o,t[10]=a*s}else if("ZYX"===e.order){u=a*c,d=a*h,p=o*c,f=o*h;t[0]=s*c,t[4]=p*l-d,t[8]=u*l+f,t[1]=s*h,t[5]=f*l+u,t[9]=d*l-p,t[2]=-l,t[6]=o*s,t[10]=a*s}else if("YZX"===e.order){var _=a*s,y=a*l,M=o*s,b=o*l;t[0]=s*c,t[4]=b-_*h,t[8]=M*h+y,t[1]=h,t[5]=a*c,t[9]=-o*c,t[2]=-l*c,t[6]=y*h+M,t[10]=_-b*h}else if("XZY"===e.order){_=a*s,y=a*l,M=o*s,b=o*l;t[0]=s*c,t[4]=-h,t[8]=l*c,t[1]=_*h+b,t[5]=a*c,t[9]=y*h-M,t[2]=M*h-y,t[6]=o*c,t[10]=b*h+_}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},makeRotationFromQuaternion:function(e){return this.compose(T,e,L)},lookAt:function(e,t,n){var i=this.elements;return C.subVectors(e,t),0===C.lengthSq()&&(C.z=1),C.normalize(),A.crossVectors(n,C),0===A.lengthSq()&&(1===Math.abs(n.z)?C.x+=1e-4:C.z+=1e-4,C.normalize(),A.crossVectors(n,C)),A.normalize(),P.crossVectors(C,A),i[0]=A.x,i[4]=P.x,i[8]=C.x,i[1]=A.y,i[5]=P.y,i[9]=C.y,i[2]=A.z,i[6]=P.z,i[10]=C.z,this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(e,t)):this.multiplyMatrices(this,e)},premultiply:function(e){return this.multiplyMatrices(e,this)},multiplyMatrices:function(e,t){var n=e.elements,i=t.elements,r=this.elements,a=n[0],o=n[4],s=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],f=n[6],m=n[10],g=n[14],v=n[3],x=n[7],_=n[11],y=n[15],M=i[0],b=i[4],w=i[8],S=i[12],E=i[1],T=i[5],L=i[9],A=i[13],P=i[2],C=i[6],D=i[10],N=i[14],R=i[3],I=i[7],U=i[11],z=i[15];return r[0]=a*M+o*E+s*P+l*R,r[4]=a*b+o*T+s*C+l*I,r[8]=a*w+o*L+s*D+l*U,r[12]=a*S+o*A+s*N+l*z,r[1]=c*M+h*E+u*P+d*R,r[5]=c*b+h*T+u*C+d*I,r[9]=c*w+h*L+u*D+d*U,r[13]=c*S+h*A+u*N+d*z,r[2]=p*M+f*E+m*P+g*R,r[6]=p*b+f*T+m*C+g*I,r[10]=p*w+f*L+m*D+g*U,r[14]=p*S+f*A+m*N+g*z,r[3]=v*M+x*E+_*P+y*R,r[7]=v*b+x*T+_*C+y*I,r[11]=v*w+x*L+_*D+y*U,r[15]=v*S+x*A+_*N+y*z,this},multiplyScalar:function(e){var t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this},determinant:function(){var e=this.elements,t=e[0],n=e[4],i=e[8],r=e[12],a=e[1],o=e[5],s=e[9],l=e[13],c=e[2],h=e[6],u=e[10],d=e[14];return e[3]*(+r*s*h-i*l*h-r*o*u+n*l*u+i*o*d-n*s*d)+e[7]*(+t*s*d-t*l*u+r*a*u-i*a*d+i*l*c-r*s*c)+e[11]*(+t*l*h-t*o*d-r*a*h+n*a*d+r*o*c-n*l*c)+e[15]*(-i*o*c-t*s*h+t*o*u+i*a*h-n*a*u+n*s*c)},transpose:function(){var e,t=this.elements;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this},setPosition:function(e,t,n){var i=this.elements;return e.isVector3?(i[12]=e.x,i[13]=e.y,i[14]=e.z):(i[12]=e,i[13]=t,i[14]=n),this},getInverse:function(e,t){void 0!==t&&console.warn("THREE.Matrix4: .getInverse() can no longer be configured to throw on degenerate.");var n=this.elements,i=e.elements,r=i[0],a=i[1],o=i[2],s=i[3],l=i[4],c=i[5],h=i[6],u=i[7],d=i[8],p=i[9],f=i[10],m=i[11],g=i[12],v=i[13],x=i[14],_=i[15],y=p*x*u-v*f*u+v*h*m-c*x*m-p*h*_+c*f*_,M=g*f*u-d*x*u-g*h*m+l*x*m+d*h*_-l*f*_,b=d*v*u-g*p*u+g*c*m-l*v*m-d*c*_+l*p*_,w=g*p*h-d*v*h-g*c*f+l*v*f+d*c*x-l*p*x,S=r*y+a*M+o*b+s*w;if(0===S)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);var E=1/S;return n[0]=y*E,n[1]=(v*f*s-p*x*s-v*o*m+a*x*m+p*o*_-a*f*_)*E,n[2]=(c*x*s-v*h*s+v*o*u-a*x*u-c*o*_+a*h*_)*E,n[3]=(p*h*s-c*f*s-p*o*u+a*f*u+c*o*m-a*h*m)*E,n[4]=M*E,n[5]=(d*x*s-g*f*s+g*o*m-r*x*m-d*o*_+r*f*_)*E,n[6]=(g*h*s-l*x*s-g*o*u+r*x*u+l*o*_-r*h*_)*E,n[7]=(l*f*s-d*h*s+d*o*u-r*f*u-l*o*m+r*h*m)*E,n[8]=b*E,n[9]=(g*p*s-d*v*s-g*a*m+r*v*m+d*a*_-r*p*_)*E,n[10]=(l*v*s-g*c*s+g*a*u-r*v*u-l*a*_+r*c*_)*E,n[11]=(d*c*s-l*p*s-d*a*u+r*p*u+l*a*m-r*c*m)*E,n[12]=w*E,n[13]=(d*v*o-g*p*o+g*a*f-r*v*f-d*a*x+r*p*x)*E,n[14]=(g*c*o-l*v*o-g*a*h+r*v*h+l*a*x-r*c*x)*E,n[15]=(l*p*o-d*c*o+d*a*h-r*p*h-l*a*f+r*c*f)*E,this},scale:function(e){var t=this.elements,n=e.x,i=e.y,r=e.z;return t[0]*=n,t[4]*=i,t[8]*=r,t[1]*=n,t[5]*=i,t[9]*=r,t[2]*=n,t[6]*=i,t[10]*=r,t[3]*=n,t[7]*=i,t[11]*=r,this},getMaxScaleOnAxis:function(){var e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],n=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],i=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,n,i))},makeTranslation:function(e,t,n){return this.set(1,0,0,e,0,1,0,t,0,0,1,n,0,0,0,1),this},makeRotationX:function(e){var t=Math.cos(e),n=Math.sin(e);return this.set(1,0,0,0,0,t,-n,0,0,n,t,0,0,0,0,1),this},makeRotationY:function(e){var t=Math.cos(e),n=Math.sin(e);return this.set(t,0,n,0,0,1,0,0,-n,0,t,0,0,0,0,1),this},makeRotationZ:function(e){var t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,0,n,t,0,0,0,0,1,0,0,0,0,1),this},makeRotationAxis:function(e,t){var n=Math.cos(t),i=Math.sin(t),r=1-n,a=e.x,o=e.y,s=e.z,l=r*a,c=r*o;return this.set(l*a+n,l*o-i*s,l*s+i*o,0,l*o+i*s,c*o+n,c*s-i*a,0,l*s-i*o,c*s+i*a,r*s*s+n,0,0,0,0,1),this},makeScale:function(e,t,n){return this.set(e,0,0,0,0,t,0,0,0,0,n,0,0,0,0,1),this},makeShear:function(e,t,n){return this.set(1,t,n,0,e,1,n,0,e,t,1,0,0,0,0,1),this},compose:function(e,t,n){var i=this.elements,r=t._x,a=t._y,o=t._z,s=t._w,l=r+r,c=a+a,h=o+o,u=r*l,d=r*c,p=r*h,f=a*c,m=a*h,g=o*h,v=s*l,x=s*c,_=s*h,y=n.x,M=n.y,b=n.z;return i[0]=(1-(f+g))*y,i[1]=(d+_)*y,i[2]=(p-x)*y,i[3]=0,i[4]=(d-_)*M,i[5]=(1-(u+g))*M,i[6]=(m+v)*M,i[7]=0,i[8]=(p+x)*b,i[9]=(m-v)*b,i[10]=(1-(u+f))*b,i[11]=0,i[12]=e.x,i[13]=e.y,i[14]=e.z,i[15]=1,this},decompose:function(e,t,n){var i=this.elements,r=S.set(i[0],i[1],i[2]).length(),a=S.set(i[4],i[5],i[6]).length(),o=S.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),e.x=i[12],e.y=i[13],e.z=i[14],E.copy(this);var s=1/r,l=1/a,c=1/o;return E.elements[0]*=s,E.elements[1]*=s,E.elements[2]*=s,E.elements[4]*=l,E.elements[5]*=l,E.elements[6]*=l,E.elements[8]*=c,E.elements[9]*=c,E.elements[10]*=c,t.setFromRotationMatrix(E),n.x=r,n.y=a,n.z=o,this},makePerspective:function(e,t,n,i,r,a){void 0===a&&console.warn("THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.");var o=this.elements,s=2*r/(t-e),l=2*r/(n-i),c=(t+e)/(t-e),h=(n+i)/(n-i),u=-(a+r)/(a-r),d=-2*a*r/(a-r);return o[0]=s,o[4]=0,o[8]=c,o[12]=0,o[1]=0,o[5]=l,o[9]=h,o[13]=0,o[2]=0,o[6]=0,o[10]=u,o[14]=d,o[3]=0,o[7]=0,o[11]=-1,o[15]=0,this},makeOrthographic:function(e,t,n,i,r,a){var o=this.elements,s=1/(t-e),l=1/(n-i),c=1/(a-r),h=(t+e)*s,u=(n+i)*l,d=(a+r)*c;return o[0]=2*s,o[4]=0,o[8]=0,o[12]=-h,o[1]=0,o[5]=2*l,o[9]=0,o[13]=-u,o[2]=0,o[6]=0,o[10]=-2*c,o[14]=-d,o[3]=0,o[7]=0,o[11]=0,o[15]=1,this},equals:function(e){for(var t=this.elements,n=e.elements,i=0;i<16;i++)if(t[i]!==n[i])return!1;return!0},fromArray:function(e,t){void 0===t&&(t=0);for(var n=0;n<16;n++)this.elements[n]=e[n+t];return this},toArray:function(e,t){void 0===e&&(e=[]),void 0===t&&(t=0);var n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e[t+9]=n[9],e[t+10]=n[10],e[t+11]=n[11],e[t+12]=n[12],e[t+13]=n[13],e[t+14]=n[14],e[t+15]=n[15],e}});var N=new D,R=new y;function I(e,t,n,i){this._x=e||0,this._y=t||0,this._z=n||0,this._order=i||I.DefaultOrder}function U(){this.mask=1}I.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"],I.DefaultOrder="XYZ",Object.defineProperties(I.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this._onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this._onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this._onChangeCallback()}},order:{get:function(){return this._order},set:function(e){this._order=e,this._onChangeCallback()}}}),Object.assign(I.prototype,{isEuler:!0,set:function(e,t,n,i){return this._x=e,this._y=t,this._z=n,this._order=i||this._order,this._onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._order)},copy:function(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this},setFromRotationMatrix:function(e,t,n){var i=d.clamp,r=e.elements,a=r[0],o=r[4],s=r[8],l=r[1],c=r[5],h=r[9],u=r[2],p=r[6],f=r[10];switch(t=t||this._order){case"XYZ":this._y=Math.asin(i(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(-h,f),this._z=Math.atan2(-o,a)):(this._x=Math.atan2(p,c),this._z=0);break;case"YXZ":this._x=Math.asin(-i(h,-1,1)),Math.abs(h)<.9999999?(this._y=Math.atan2(s,f),this._z=Math.atan2(l,c)):(this._y=Math.atan2(-u,a),this._z=0);break;case"ZXY":this._x=Math.asin(i(p,-1,1)),Math.abs(p)<.9999999?(this._y=Math.atan2(-u,f),this._z=Math.atan2(-o,c)):(this._y=0,this._z=Math.atan2(l,a));break;case"ZYX":this._y=Math.asin(-i(u,-1,1)),Math.abs(u)<.9999999?(this._x=Math.atan2(p,f),this._z=Math.atan2(l,a)):(this._x=0,this._z=Math.atan2(-o,c));break;case"YZX":this._z=Math.asin(i(l,-1,1)),Math.abs(l)<.9999999?(this._x=Math.atan2(-h,c),this._y=Math.atan2(-u,a)):(this._x=0,this._y=Math.atan2(s,f));break;case"XZY":this._z=Math.asin(-i(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(p,c),this._y=Math.atan2(s,a)):(this._x=Math.atan2(-h,f),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+t)}return this._order=t,!1!==n&&this._onChangeCallback(),this},setFromQuaternion:function(e,t,n){return N.makeRotationFromQuaternion(e),this.setFromRotationMatrix(N,t,n)},setFromVector3:function(e,t){return this.set(e.x,e.y,e.z,t||this._order)},reorder:function(e){return R.setFromEuler(this),this.setFromQuaternion(R,e)},equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order},fromArray:function(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this._onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e},toVector3:function(e){return e?e.set(this._x,this._y,this._z):new w(this._x,this._y,this._z)},_onChange:function(e){return this._onChangeCallback=e,this},_onChangeCallback:function(){}}),Object.assign(U.prototype,{set:function(e){this.mask=1<1){for(var t=0;t1){for(var t=0;t0){i.children=[];for(s=0;s0&&(n.geometries=u),d.length>0&&(n.materials=d),p.length>0&&(n.textures=p),f.length>0&&(n.images=f),o.length>0&&(n.shapes=o)}return n.object=i,n;function m(e){var t=[];for(var n in e){var i=e[n];delete i.metadata,t.push(i)}return t}},clone:function(e){return(new this.constructor).copy(this,e)},copy:function(e,t){if(void 0===t&&(t=!0),this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(var n=0;ns)return!1}return!0}Object.assign(he.prototype,{isBox3:!0,set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromArray:function(e){for(var t=1/0,n=1/0,i=1/0,r=-1/0,a=-1/0,o=-1/0,s=0,l=e.length;sr&&(r=c),h>a&&(a=h),u>o&&(o=u)}return this.min.set(t,n,i),this.max.set(r,a,o),this},setFromBufferAttribute:function(e){for(var t=1/0,n=1/0,i=1/0,r=-1/0,a=-1/0,o=-1/0,s=0,l=e.count;sr&&(r=c),h>a&&(a=h),u>o&&(o=u)}return this.min.set(t,n,i),this.max.set(r,a,o),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,n=e.length;tthis.max.x||e.ythis.max.y||e.zthis.max.z)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z},getParameter:function(e,t){return void 0===t&&(console.warn("THREE.Box3: .getParameter() target is now required"),t=new w),t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y||e.max.zthis.max.z)},intersectsSphere:function(e){return this.clampPoint(e.center,K),K.distanceToSquared(e.center)<=e.radius*e.radius},intersectsPlane:function(e){var t,n;return e.normal.x>0?(t=e.normal.x*this.min.x,n=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,n=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,n+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,n+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,n+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,n+=e.normal.z*this.min.z),t<=-e.constant&&n>=-e.constant},intersectsTriangle:function(e){if(this.isEmpty())return!1;this.getCenter(oe),se.subVectors(this.max,oe),ee.subVectors(e.a,oe),te.subVectors(e.b,oe),ne.subVectors(e.c,oe),ie.subVectors(te,ee),re.subVectors(ne,te),ae.subVectors(ee,ne);var t=[0,-ie.z,ie.y,0,-re.z,re.y,0,-ae.z,ae.y,ie.z,0,-ie.x,re.z,0,-re.x,ae.z,0,-ae.x,-ie.y,ie.x,0,-re.y,re.x,0,-ae.y,ae.x,0];return!!ue(t,ee,te,ne,se)&&(!!ue(t=[1,0,0,0,1,0,0,0,1],ee,te,ne,se)&&(le.crossVectors(ie,re),ue(t=[le.x,le.y,le.z],ee,te,ne,se)))},clampPoint:function(e,t){return void 0===t&&(console.warn("THREE.Box3: .clampPoint() target is now required"),t=new w),t.copy(e).clamp(this.min,this.max)},distanceToPoint:function(e){return K.copy(e).clamp(this.min,this.max).sub(e).length()},getBoundingSphere:function(e){return void 0===e&&console.error("THREE.Box3: .getBoundingSphere() target is now required"),this.getCenter(e.center),e.radius=.5*this.getSize(K).length(),e},intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},applyMatrix4:function(e){return this.isEmpty()||(Q[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),Q[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),Q[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),Q[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),Q[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),Q[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),Q[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),Q[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(Q)),this},translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}});var de=new he;function pe(e,t){this.center=void 0!==e?e:new w,this.radius=void 0!==t?t:-1}Object.assign(pe.prototype,{set:function(e,t){return this.center.copy(e),this.radius=t,this},setFromPoints:function(e,t){var n=this.center;void 0!==t?n.copy(t):de.setFromPoints(e).getCenter(n);for(var i=0,r=0,a=e.length;rthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t},getBoundingBox:function(e){return void 0===e&&(console.warn("THREE.Sphere: .getBoundingBox() target is now required"),e=new he),this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)},applyMatrix4:function(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this},translate:function(e){return this.center.add(e),this},equals:function(e){return e.center.equals(this.center)&&e.radius===this.radius}});var fe=new w,me=new w,ge=new w,ve=new w,xe=new w,_e=new w,ye=new w;function Me(e,t){this.origin=void 0!==e?e:new w,this.direction=void 0!==t?t:new w(0,0,-1)}Object.assign(Me.prototype,{set:function(e,t){return this.origin.copy(e),this.direction.copy(t),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this},at:function(e,t){return void 0===t&&(console.warn("THREE.Ray: .at() target is now required"),t=new w),t.copy(this.direction).multiplyScalar(e).add(this.origin)},lookAt:function(e){return this.direction.copy(e).sub(this.origin).normalize(),this},recast:function(e){return this.origin.copy(this.at(e,fe)),this},closestPointToPoint:function(e,t){void 0===t&&(console.warn("THREE.Ray: .closestPointToPoint() target is now required"),t=new w),t.subVectors(e,this.origin);var n=t.dot(this.direction);return n<0?t.copy(this.origin):t.copy(this.direction).multiplyScalar(n).add(this.origin)},distanceToPoint:function(e){return Math.sqrt(this.distanceSqToPoint(e))},distanceSqToPoint:function(e){var t=fe.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(fe.copy(this.direction).multiplyScalar(t).add(this.origin),fe.distanceToSquared(e))},distanceSqToSegment:function(e,t,n,i){me.copy(e).add(t).multiplyScalar(.5),ge.copy(t).sub(e).normalize(),ve.copy(this.origin).sub(me);var r,a,o,s,l=.5*e.distanceTo(t),c=-this.direction.dot(ge),h=ve.dot(this.direction),u=-ve.dot(ge),d=ve.lengthSq(),p=Math.abs(1-c*c);if(p>0)if(a=c*h-u,s=l*p,(r=c*u-h)>=0)if(a>=-s)if(a<=s){var f=1/p;o=(r*=f)*(r+c*(a*=f)+2*h)+a*(c*r+a+2*u)+d}else a=l,o=-(r=Math.max(0,-(c*a+h)))*r+a*(a+2*u)+d;else a=-l,o=-(r=Math.max(0,-(c*a+h)))*r+a*(a+2*u)+d;else a<=-s?o=-(r=Math.max(0,-(-c*l+h)))*r+(a=r>0?-l:Math.min(Math.max(-l,-u),l))*(a+2*u)+d:a<=s?(r=0,o=(a=Math.min(Math.max(-l,-u),l))*(a+2*u)+d):o=-(r=Math.max(0,-(c*l+h)))*r+(a=r>0?l:Math.min(Math.max(-l,-u),l))*(a+2*u)+d;else a=c>0?-l:l,o=-(r=Math.max(0,-(c*a+h)))*r+a*(a+2*u)+d;return n&&n.copy(this.direction).multiplyScalar(r).add(this.origin),i&&i.copy(ge).multiplyScalar(a).add(me),o},intersectSphere:function(e,t){fe.subVectors(e.center,this.origin);var n=fe.dot(this.direction),i=fe.dot(fe)-n*n,r=e.radius*e.radius;if(i>r)return null;var a=Math.sqrt(r-i),o=n-a,s=n+a;return o<0&&s<0?null:o<0?this.at(s,t):this.at(o,t)},intersectsSphere:function(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius},distanceToPlane:function(e){var t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;var n=-(this.origin.dot(e.normal)+e.constant)/t;return n>=0?n:null},intersectPlane:function(e,t){var n=this.distanceToPlane(e);return null===n?null:this.at(n,t)},intersectsPlane:function(e){var t=e.distanceToPoint(this.origin);return 0===t||e.normal.dot(this.direction)*t<0},intersectBox:function(e,t){var n,i,r,a,o,s,l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(n=(e.min.x-u.x)*l,i=(e.max.x-u.x)*l):(n=(e.max.x-u.x)*l,i=(e.min.x-u.x)*l),c>=0?(r=(e.min.y-u.y)*c,a=(e.max.y-u.y)*c):(r=(e.max.y-u.y)*c,a=(e.min.y-u.y)*c),n>a||r>i?null:((r>n||n!=n)&&(n=r),(a=0?(o=(e.min.z-u.z)*h,s=(e.max.z-u.z)*h):(o=(e.max.z-u.z)*h,s=(e.min.z-u.z)*h),n>s||o>i?null:((o>n||n!=n)&&(n=o),(s=0?n:i,t)))},intersectsBox:function(e){return null!==this.intersectBox(e,fe)},intersectTriangle:function(e,t,n,i,r){xe.subVectors(t,e),_e.subVectors(n,e),ye.crossVectors(xe,_e);var a,o=this.direction.dot(ye);if(o>0){if(i)return null;a=1}else{if(!(o<0))return null;a=-1,o=-o}ve.subVectors(this.origin,e);var s=a*this.direction.dot(_e.crossVectors(ve,_e));if(s<0)return null;var l=a*this.direction.dot(xe.cross(ve));if(l<0)return null;if(s+l>o)return null;var c=-a*ve.dot(ye);return c<0?null:this.at(c/o,r)},applyMatrix4:function(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this},equals:function(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}});var be=new w,we=new w,Se=new f;function Ee(e,t){this.normal=void 0!==e?e:new w(1,0,0),this.constant=void 0!==t?t:0}Object.assign(Ee.prototype,{isPlane:!0,set:function(e,t){return this.normal.copy(e),this.constant=t,this},setComponents:function(e,t,n,i){return this.normal.set(e,t,n),this.constant=i,this},setFromNormalAndCoplanarPoint:function(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this},setFromCoplanarPoints:function(e,t,n){var i=be.subVectors(n,t).cross(we.subVectors(e,t)).normalize();return this.setFromNormalAndCoplanarPoint(i,e),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.normal.copy(e.normal),this.constant=e.constant,this},normalize:function(){var e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this},negate:function(){return this.constant*=-1,this.normal.negate(),this},distanceToPoint:function(e){return this.normal.dot(e)+this.constant},distanceToSphere:function(e){return this.distanceToPoint(e.center)-e.radius},projectPoint:function(e,t){return void 0===t&&(console.warn("THREE.Plane: .projectPoint() target is now required"),t=new w),t.copy(this.normal).multiplyScalar(-this.distanceToPoint(e)).add(e)},intersectLine:function(e,t){void 0===t&&(console.warn("THREE.Plane: .intersectLine() target is now required"),t=new w);var n=e.delta(be),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(e.start)?t.copy(e.start):void 0;var r=-(e.start.dot(this.normal)+this.constant)/i;return r<0||r>1?void 0:t.copy(n).multiplyScalar(r).add(e.start)},intersectsLine:function(e){var t=this.distanceToPoint(e.start),n=this.distanceToPoint(e.end);return t<0&&n>0||n<0&&t>0},intersectsBox:function(e){return e.intersectsPlane(this)},intersectsSphere:function(e){return e.intersectsPlane(this)},coplanarPoint:function(e){return void 0===e&&(console.warn("THREE.Plane: .coplanarPoint() target is now required"),e=new w),e.copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(e,t){var n=t||Se.getNormalMatrix(e),i=this.coplanarPoint(be).applyMatrix4(e),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this},translate:function(e){return this.constant-=e.dot(this.normal),this},equals:function(e){return e.normal.equals(this.normal)&&e.constant===this.constant}});var Te=new w,Le=new w,Ae=new w,Pe=new w,Ce=new w,De=new w,Ne=new w,Re=new w,Ie=new w,Ue=new w;function ze(e,t,n){this.a=void 0!==e?e:new w,this.b=void 0!==t?t:new w,this.c=void 0!==n?n:new w}Object.assign(ze,{getNormal:function(e,t,n,i){void 0===i&&(console.warn("THREE.Triangle: .getNormal() target is now required"),i=new w),i.subVectors(n,t),Te.subVectors(e,t),i.cross(Te);var r=i.lengthSq();return r>0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)},getBarycoord:function(e,t,n,i,r){Te.subVectors(i,t),Le.subVectors(n,t),Ae.subVectors(e,t);var a=Te.dot(Te),o=Te.dot(Le),s=Te.dot(Ae),l=Le.dot(Le),c=Le.dot(Ae),h=a*l-o*o;if(void 0===r&&(console.warn("THREE.Triangle: .getBarycoord() target is now required"),r=new w),0===h)return r.set(-2,-1,-1);var u=1/h,d=(l*s-o*c)*u,p=(a*c-o*s)*u;return r.set(1-d-p,p,d)},containsPoint:function(e,t,n,i){return ze.getBarycoord(e,t,n,i,Pe),Pe.x>=0&&Pe.y>=0&&Pe.x+Pe.y<=1},getUV:function(e,t,n,i,r,a,o,s){return this.getBarycoord(e,t,n,i,Pe),s.set(0,0),s.addScaledVector(r,Pe.x),s.addScaledVector(a,Pe.y),s.addScaledVector(o,Pe.z),s},isFrontFacing:function(e,t,n,i){return Te.subVectors(n,t),Le.subVectors(e,t),Te.cross(Le).dot(i)<0}}),Object.assign(ze.prototype,{set:function(e,t,n){return this.a.copy(e),this.b.copy(t),this.c.copy(n),this},setFromPointsAndIndices:function(e,t,n,i){return this.a.copy(e[t]),this.b.copy(e[n]),this.c.copy(e[i]),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this},getArea:function(){return Te.subVectors(this.c,this.b),Le.subVectors(this.a,this.b),.5*Te.cross(Le).length()},getMidpoint:function(e){return void 0===e&&(console.warn("THREE.Triangle: .getMidpoint() target is now required"),e=new w),e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},getNormal:function(e){return ze.getNormal(this.a,this.b,this.c,e)},getPlane:function(e){return void 0===e&&(console.warn("THREE.Triangle: .getPlane() target is now required"),e=new Ee),e.setFromCoplanarPoints(this.a,this.b,this.c)},getBarycoord:function(e,t){return ze.getBarycoord(e,this.a,this.b,this.c,t)},getUV:function(e,t,n,i,r){return ze.getUV(e,this.a,this.b,this.c,t,n,i,r)},containsPoint:function(e){return ze.containsPoint(e,this.a,this.b,this.c)},isFrontFacing:function(e){return ze.isFrontFacing(this.a,this.b,this.c,e)},intersectsBox:function(e){return e.intersectsTriangle(this)},closestPointToPoint:function(e,t){void 0===t&&(console.warn("THREE.Triangle: .closestPointToPoint() target is now required"),t=new w);var n,i,r=this.a,a=this.b,o=this.c;Ce.subVectors(a,r),De.subVectors(o,r),Re.subVectors(e,r);var s=Ce.dot(Re),l=De.dot(Re);if(s<=0&&l<=0)return t.copy(r);Ie.subVectors(e,a);var c=Ce.dot(Ie),h=De.dot(Ie);if(c>=0&&h<=c)return t.copy(a);var u=s*h-c*l;if(u<=0&&s>=0&&c<=0)return n=s/(s-c),t.copy(r).addScaledVector(Ce,n);Ue.subVectors(e,o);var d=Ce.dot(Ue),p=De.dot(Ue);if(p>=0&&d<=p)return t.copy(o);var f=d*l-s*p;if(f<=0&&l>=0&&p<=0)return i=l/(l-p),t.copy(r).addScaledVector(De,i);var m=c*p-d*h;if(m<=0&&h-c>=0&&d-p>=0)return Ne.subVectors(o,a),i=(h-c)/(h-c+(d-p)),t.copy(a).addScaledVector(Ne,i);var g=1/(m+f+u);return n=f*g,i=u*g,t.copy(r).addScaledVector(Ce,n).addScaledVector(De,i)},equals:function(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}});var Oe={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Fe={h:0,s:0,l:0},Ge={h:0,s:0,l:0};function Be(e,t,n){return void 0===t&&void 0===n?this.set(e):this.setRGB(e,t,n)}function Ve(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+6*(t-e)*n:n<.5?t:n<2/3?e+6*(t-e)*(2/3-n):e}function ke(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function He(e){return e<.0031308?12.92*e:1.055*Math.pow(e,.41666)-.055}function We(e,t,n,i,r,a){this.a=e,this.b=t,this.c=n,this.normal=i&&i.isVector3?i:new w,this.vertexNormals=Array.isArray(i)?i:[],this.color=r&&r.isColor?r:new Be,this.vertexColors=Array.isArray(r)?r:[],this.materialIndex=void 0!==a?a:0}Object.assign(Be.prototype,{isColor:!0,r:1,g:1,b:1,set:function(e){return e&&e.isColor?this.copy(e):"number"==typeof e?this.setHex(e):"string"==typeof e&&this.setStyle(e),this},setScalar:function(e){return this.r=e,this.g=e,this.b=e,this},setHex:function(e){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,this},setRGB:function(e,t,n){return this.r=e,this.g=t,this.b=n,this},setHSL:function(e,t,n){if(e=d.euclideanModulo(e,1),t=d.clamp(t,0,1),n=d.clamp(n,0,1),0===t)this.r=this.g=this.b=n;else{var i=n<=.5?n*(1+t):n+t-n*t,r=2*n-i;this.r=Ve(r,i,e+1/3),this.g=Ve(r,i,e),this.b=Ve(r,i,e-1/3)}return this},setStyle:function(e){function t(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}var n;if(n=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(e)){var i,r=n[1],a=n[2];switch(r){case"rgb":case"rgba":if(i=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a))return this.r=Math.min(255,parseInt(i[1],10))/255,this.g=Math.min(255,parseInt(i[2],10))/255,this.b=Math.min(255,parseInt(i[3],10))/255,t(i[5]),this;if(i=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a))return this.r=Math.min(100,parseInt(i[1],10))/100,this.g=Math.min(100,parseInt(i[2],10))/100,this.b=Math.min(100,parseInt(i[3],10))/100,t(i[5]),this;break;case"hsl":case"hsla":if(i=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a)){var o=parseFloat(i[1])/360,s=parseInt(i[2],10)/100,l=parseInt(i[3],10)/100;return t(i[5]),this.setHSL(o,s,l)}}}else if(n=/^\#([A-Fa-f0-9]+)$/.exec(e)){var c=n[1],h=c.length;if(3===h)return this.r=parseInt(c.charAt(0)+c.charAt(0),16)/255,this.g=parseInt(c.charAt(1)+c.charAt(1),16)/255,this.b=parseInt(c.charAt(2)+c.charAt(2),16)/255,this;if(6===h)return this.r=parseInt(c.charAt(0)+c.charAt(1),16)/255,this.g=parseInt(c.charAt(2)+c.charAt(3),16)/255,this.b=parseInt(c.charAt(4)+c.charAt(5),16)/255,this}return e&&e.length>0?this.setColorName(e):this},setColorName:function(e){var t=Oe[e];return void 0!==t?this.setHex(t):console.warn("THREE.Color: Unknown color "+e),this},clone:function(){return new this.constructor(this.r,this.g,this.b)},copy:function(e){return this.r=e.r,this.g=e.g,this.b=e.b,this},copyGammaToLinear:function(e,t){return void 0===t&&(t=2),this.r=Math.pow(e.r,t),this.g=Math.pow(e.g,t),this.b=Math.pow(e.b,t),this},copyLinearToGamma:function(e,t){void 0===t&&(t=2);var n=t>0?1/t:1;return this.r=Math.pow(e.r,n),this.g=Math.pow(e.g,n),this.b=Math.pow(e.b,n),this},convertGammaToLinear:function(e){return this.copyGammaToLinear(this,e),this},convertLinearToGamma:function(e){return this.copyLinearToGamma(this,e),this},copySRGBToLinear:function(e){return this.r=ke(e.r),this.g=ke(e.g),this.b=ke(e.b),this},copyLinearToSRGB:function(e){return this.r=He(e.r),this.g=He(e.g),this.b=He(e.b),this},convertSRGBToLinear:function(){return this.copySRGBToLinear(this),this},convertLinearToSRGB:function(){return this.copyLinearToSRGB(this),this},getHex:function(){return 255*this.r<<16^255*this.g<<8^255*this.b<<0},getHexString:function(){return("000000"+this.getHex().toString(16)).slice(-6)},getHSL:function(e){void 0===e&&(console.warn("THREE.Color: .getHSL() target is now required"),e={h:0,s:0,l:0});var t,n,i=this.r,r=this.g,a=this.b,o=Math.max(i,r,a),s=Math.min(i,r,a),l=(s+o)/2;if(s===o)t=0,n=0;else{var c=o-s;switch(n=l<=.5?c/(o+s):c/(2-o-s),o){case i:t=(r-a)/c+(r0&&(n.alphaTest=this.alphaTest),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(n.wireframe=this.wireframe),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.morphTargets&&(n.morphTargets=!0),!0===this.morphNormals&&(n.morphNormals=!0),!0===this.skinning&&(n.skinning=!0),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),"{}"!==JSON.stringify(this.userData)&&(n.userData=this.userData),t){var r=i(e.textures),a=i(e.images);r.length>0&&(n.textures=r),a.length>0&&(n.images=a)}return n},clone:function(){return(new this.constructor).copy(this)},copy:function(e){this.name=e.name,this.fog=e.fog,this.blending=e.blending,this.side=e.side,this.flatShading=e.flatShading,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;var t=e.clippingPlanes,n=null;if(null!==t){var i=t.length;n=new Array(i);for(var r=0;r!==i;++r)n[r]=t[r].clone()}return this.clippingPlanes=n,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.premultipliedAlpha=e.premultipliedAlpha,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),Object.defineProperty(Xe.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),qe.prototype=Object.create(Xe.prototype),qe.prototype.constructor=qe,qe.prototype.isMeshBasicMaterial=!0,qe.prototype.copy=function(e){return Xe.prototype.copy.call(this,e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this};var Ye=new w;function Ze(e,t,n){if(Array.isArray(e))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.name="",this.array=e,this.itemSize=t,this.count=void 0!==e?e.length/t:0,this.normalized=!0===n,this.usage=35044,this.updateRange={offset:0,count:-1},this.version=0}function Je(e,t,n){Ze.call(this,new Int8Array(e),t,n)}function Qe(e,t,n){Ze.call(this,new Uint8Array(e),t,n)}function Ke(e,t,n){Ze.call(this,new Uint8ClampedArray(e),t,n)}function $e(e,t,n){Ze.call(this,new Int16Array(e),t,n)}function et(e,t,n){Ze.call(this,new Uint16Array(e),t,n)}function tt(e,t,n){Ze.call(this,new Int32Array(e),t,n)}function nt(e,t,n){Ze.call(this,new Uint32Array(e),t,n)}function it(e,t,n){Ze.call(this,new Float32Array(e),t,n)}function rt(e,t,n){Ze.call(this,new Float64Array(e),t,n)}function at(){this.vertices=[],this.normals=[],this.colors=[],this.uvs=[],this.uvs2=[],this.groups=[],this.morphTargets={},this.skinWeights=[],this.skinIndices=[],this.boundingBox=null,this.boundingSphere=null,this.verticesNeedUpdate=!1,this.normalsNeedUpdate=!1,this.colorsNeedUpdate=!1,this.uvsNeedUpdate=!1,this.groupsNeedUpdate=!1}function ot(e){if(0===e.length)return-1/0;let t=e[0];for(let n=1,i=e.length;nt&&(t=e[n]);return t}Object.defineProperty(Ze.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),Object.assign(Ze.prototype,{isBufferAttribute:!0,onUploadCallback:function(){},setUsage:function(e){return this.usage=e,this},copy:function(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this},copyAt:function(e,t,n){e*=this.itemSize,n*=t.itemSize;for(var i=0,r=this.itemSize;i0,o=r[1]&&r[1].length>0,s=e.morphTargets,l=s.length;if(l>0){t=[];for(var c=0;c0){h=[];for(c=0;c0&&0===n.length&&console.error("THREE.DirectGeometry: Faceless geometries are not supported.");for(c=0;c65535?nt:et)(e,1):this.index=e},getAttribute:function(e){return this.attributes[e]},setAttribute:function(e,t){return this.attributes[e]=t,this},deleteAttribute:function(e){return delete this.attributes[e],this},addGroup:function(e,t,n){this.groups.push({start:e,count:t,materialIndex:void 0!==n?n:0})},clearGroups:function(){this.groups=[]},setDrawRange:function(e,t){this.drawRange.start=e,this.drawRange.count=t},applyMatrix4:function(e){var t=this.attributes.position;void 0!==t&&(t.applyMatrix4(e),t.needsUpdate=!0);var n=this.attributes.normal;if(void 0!==n){var i=(new f).getNormalMatrix(e);n.applyNormalMatrix(i),n.needsUpdate=!0}var r=this.attributes.tangent;return void 0!==r&&(r.transformDirection(e),r.needsUpdate=!0),null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},rotateX:function(e){return lt.makeRotationX(e),this.applyMatrix4(lt),this},rotateY:function(e){return lt.makeRotationY(e),this.applyMatrix4(lt),this},rotateZ:function(e){return lt.makeRotationZ(e),this.applyMatrix4(lt),this},translate:function(e,t,n){return lt.makeTranslation(e,t,n),this.applyMatrix4(lt),this},scale:function(e,t,n){return lt.makeScale(e,t,n),this.applyMatrix4(lt),this},lookAt:function(e){return ct.lookAt(e),ct.updateMatrix(),this.applyMatrix4(ct.matrix),this},center:function(){return this.computeBoundingBox(),this.boundingBox.getCenter(ht).negate(),this.translate(ht.x,ht.y,ht.z),this},setFromObject:function(e){var t=e.geometry;if(e.isPoints||e.isLine){var n=new it(3*t.vertices.length,3),i=new it(3*t.colors.length,3);if(this.setAttribute("position",n.copyVector3sArray(t.vertices)),this.setAttribute("color",i.copyColorsArray(t.colors)),t.lineDistances&&t.lineDistances.length===t.vertices.length){var r=new it(t.lineDistances.length,1);this.setAttribute("lineDistance",r.copyArray(t.lineDistances))}null!==t.boundingSphere&&(this.boundingSphere=t.boundingSphere.clone()),null!==t.boundingBox&&(this.boundingBox=t.boundingBox.clone())}else e.isMesh&&t&&t.isGeometry&&this.fromGeometry(t);return this},setFromPoints:function(e){for(var t=[],n=0,i=e.length;n0){var n=new Float32Array(3*e.normals.length);this.setAttribute("normal",new Ze(n,3).copyVector3sArray(e.normals))}if(e.colors.length>0){var i=new Float32Array(3*e.colors.length);this.setAttribute("color",new Ze(i,3).copyColorsArray(e.colors))}if(e.uvs.length>0){var r=new Float32Array(2*e.uvs.length);this.setAttribute("uv",new Ze(r,2).copyVector2sArray(e.uvs))}if(e.uvs2.length>0){var a=new Float32Array(2*e.uvs2.length);this.setAttribute("uv2",new Ze(a,2).copyVector2sArray(e.uvs2))}for(var o in this.groups=e.groups,e.morphTargets){for(var s=[],l=e.morphTargets[o],c=0,h=l.length;c0){var p=new it(4*e.skinIndices.length,4);this.setAttribute("skinIndex",p.copyVector4sArray(e.skinIndices))}if(e.skinWeights.length>0){var f=new it(4*e.skinWeights.length,4);this.setAttribute("skinWeight",f.copyVector4sArray(e.skinWeights))}return null!==e.boundingSphere&&(this.boundingSphere=e.boundingSphere.clone()),null!==e.boundingBox&&(this.boundingBox=e.boundingBox.clone()),this},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new he);var e=this.attributes.position,t=this.morphAttributes.position;if(void 0!==e){if(this.boundingBox.setFromBufferAttribute(e),t)for(var n=0,i=t.length;n0&&(e.userData=this.userData),void 0!==this.parameters){var t=this.parameters;for(var n in t)void 0!==t[n]&&(e[n]=t[n]);return e}e.data={attributes:{}};var i=this.index;null!==i&&(e.data.index={type:i.array.constructor.name,array:Array.prototype.slice.call(i.array)});var r=this.attributes;for(var n in r){var a=(d=r[n]).toJSON();""!==d.name&&(a.name=d.name),e.data.attributes[n]=a}var o={},s=!1;for(var n in this.morphAttributes){for(var l=this.morphAttributes[n],c=[],h=0,u=l.length;h0&&(o[n]=c,s=!0)}s&&(e.data.morphAttributes=o,e.data.morphTargetsRelative=this.morphTargetsRelative);var p=this.groups;p.length>0&&(e.data.groups=JSON.parse(JSON.stringify(p)));var f=this.boundingSphere;return null!==f&&(e.data.boundingSphere={center:f.center.toArray(),radius:f.radius}),e},clone:function(){return(new ft).copy(this)},copy:function(e){var t,n,i;this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var r=e.index;null!==r&&this.setIndex(r.clone());var a=e.attributes;for(t in a){var o=a[t];this.setAttribute(t,o.clone())}var s=e.morphAttributes;for(t in s){var l=[],c=s[t];for(n=0,i=c.length;nn.far?null:{distance:l,point:Dt.clone(),object:e}}function It(e,t,n,i,r,a,o,s,l,c,h,u){xt.fromBufferAttribute(r,c),_t.fromBufferAttribute(r,h),yt.fromBufferAttribute(r,u);var d=e.morphTargetInfluences;if(t.morphTargets&&a&&d){St.set(0,0,0),Et.set(0,0,0),Tt.set(0,0,0);for(var f=0,m=a.length;f0){var o=r[a[0]];if(void 0!==o)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=o.length;e0&&console.error("THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.")}},raycast:function(e,t){var n,i=this.geometry,r=this.material,a=this.matrixWorld;if(void 0!==r&&(null===i.boundingSphere&&i.computeBoundingSphere(),vt.copy(i.boundingSphere),vt.applyMatrix4(a),!1!==e.ray.intersectsSphere(vt)&&(mt.getInverse(a),gt.copy(e.ray).applyMatrix4(mt),null===i.boundingBox||!1!==gt.intersectsBox(i.boundingBox))))if(i.isBufferGeometry){var o,s,l,c,h,u,d,f,m,g=i.index,v=i.attributes.position,x=i.morphAttributes.position,_=i.morphTargetsRelative,y=i.attributes.uv,M=i.attributes.uv2,b=i.groups,w=i.drawRange;if(null!==g)if(Array.isArray(r))for(c=0,u=b.length;c0&&(L=D);for(var N=0,R=C.length;N0)for(c=0;c0&&(this.normalsNeedUpdate=!0)},computeFlatVertexNormals:function(){var e,t,n;for(this.computeFaceNormals(),e=0,t=this.faces.length;e0&&(this.normalsNeedUpdate=!0)},computeMorphNormals:function(){var e,t,n,i,r;for(n=0,i=this.faces.length;n=0;n--){var f=d[n];for(this.faces.splice(f,1),o=0,s=this.faceVertexUvs.length;o0,g=p.vertexNormals.length>0,v=1!==p.color.r||1!==p.color.g||1!==p.color.b,x=p.vertexColors.length>0,_=0;if(_=w(_,0,0),_=w(_,1,!0),_=w(_,2,!1),_=w(_,3,f),_=w(_,4,m),_=w(_,5,g),_=w(_,6,v),_=w(_,7,x),o.push(_),o.push(p.a,p.b,p.c),o.push(p.materialIndex),f){var y=this.faceVertexUvs[0][r];o.push(T(y[0]),T(y[1]),T(y[2]))}if(m&&o.push(S(p.normal)),g){var M=p.vertexNormals;o.push(S(M[0]),S(M[1]),S(M[2]))}if(v&&o.push(E(p.color)),x){var b=p.vertexColors;o.push(E(b[0]),E(b[1]),E(b[2]))}}function w(e,t,n){return n?e|1<0&&(e.data.colors=c),u.length>0&&(e.data.uvs=[u]),e.data.faces=o,e},clone:function(){return(new Gt).copy(this)},copy:function(e){var t,n,i,r,a,o;this.vertices=[],this.colors=[],this.faces=[],this.faceVertexUvs=[[]],this.morphTargets=[],this.morphNormals=[],this.skinWeights=[],this.skinIndices=[],this.lineDistances=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var s=e.vertices;for(t=0,n=s.length;t0?1:-1,c.push(A.x,A.y,A.z),h.push(s/m),h.push(1-a/g),T+=1}}for(let e=0;e0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader;var r={};for(var a in this.extensions)!0===this.extensions[a]&&(r[a]=!0);return Object.keys(r).length>0&&(t.extensions=r),t},Xt.prototype=Object.assign(Object.create(Z.prototype),{constructor:Xt,isCamera:!0,copy:function(e,t){return Z.prototype.copy.call(this,e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this},getWorldDirection:function(e){void 0===e&&(console.warn("THREE.Camera: .getWorldDirection() target is now required"),e=new w),this.updateMatrixWorld(!0);var t=this.matrixWorld.elements;return e.set(-t[8],-t[9],-t[10]).normalize()},updateMatrixWorld:function(e){Z.prototype.updateMatrixWorld.call(this,e),this.matrixWorldInverse.getInverse(this.matrixWorld)},updateWorldMatrix:function(e,t){Z.prototype.updateWorldMatrix.call(this,e,t),this.matrixWorldInverse.getInverse(this.matrixWorld)},clone:function(){return(new this.constructor).copy(this)}}),qt.prototype=Object.assign(Object.create(Xt.prototype),{constructor:qt,isPerspectiveCamera:!0,copy:function(e,t){return Xt.prototype.copy.call(this,e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=null===e.view?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this},setFocalLength:function(e){var t=.5*this.getFilmHeight()/e;this.fov=2*d.RAD2DEG*Math.atan(t),this.updateProjectionMatrix()},getFocalLength:function(){var e=Math.tan(.5*d.DEG2RAD*this.fov);return.5*this.getFilmHeight()/e},getEffectiveFOV:function(){return 2*d.RAD2DEG*Math.atan(Math.tan(.5*d.DEG2RAD*this.fov)/this.zoom)},getFilmWidth:function(){return this.filmGauge*Math.min(this.aspect,1)},getFilmHeight:function(){return this.filmGauge/Math.max(this.aspect,1)},setViewOffset:function(e,t,n,i,r,a){this.aspect=e/t,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()},clearViewOffset:function(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()},updateProjectionMatrix:function(){var e=this.near,t=e*Math.tan(.5*d.DEG2RAD*this.fov)/this.zoom,n=2*t,i=this.aspect*n,r=-.5*i,a=this.view;if(null!==this.view&&this.view.enabled){var o=a.fullWidth,s=a.fullHeight;r+=a.offsetX*i/o,t-=a.offsetY*n/s,i*=a.width/o,n*=a.height/s}var l=this.filmOffset;0!==l&&(r+=e*l/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,t,t-n,e,this.far),this.projectionMatrixInverse.getInverse(this.projectionMatrix)},toJSON:function(e){var t=Z.prototype.toJSON.call(this,e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,null!==this.view&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}}),Yt.prototype=Object.create(v.prototype),Yt.prototype.constructor=Yt,Yt.prototype.isDataTexture=!0;var Zt=new pe,Jt=new w;function Qt(e,t,n,i,r,a){this.planes=[void 0!==e?e:new Ee,void 0!==t?t:new Ee,void 0!==n?n:new Ee,void 0!==i?i:new Ee,void 0!==r?r:new Ee,void 0!==a?a:new Ee]}Object.assign(Qt.prototype,{set:function(e,t,n,i,r,a){var o=this.planes;return o[0].copy(e),o[1].copy(t),o[2].copy(n),o[3].copy(i),o[4].copy(r),o[5].copy(a),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){for(var t=this.planes,n=0;n<6;n++)t[n].copy(e.planes[n]);return this},setFromProjectionMatrix:function(e){var t=this.planes,n=e.elements,i=n[0],r=n[1],a=n[2],o=n[3],s=n[4],l=n[5],c=n[6],h=n[7],u=n[8],d=n[9],p=n[10],f=n[11],m=n[12],g=n[13],v=n[14],x=n[15];return t[0].setComponents(o-i,h-s,f-u,x-m).normalize(),t[1].setComponents(o+i,h+s,f+u,x+m).normalize(),t[2].setComponents(o+r,h+l,f+d,x+g).normalize(),t[3].setComponents(o-r,h-l,f-d,x-g).normalize(),t[4].setComponents(o-a,h-c,f-p,x-v).normalize(),t[5].setComponents(o+a,h+c,f+p,x+v).normalize(),this},intersectsObject:function(e){var t=e.geometry;return null===t.boundingSphere&&t.computeBoundingSphere(),Zt.copy(t.boundingSphere).applyMatrix4(e.matrixWorld),this.intersectsSphere(Zt)},intersectsSprite:function(e){return Zt.center.set(0,0,0),Zt.radius=.7071067811865476,Zt.applyMatrix4(e.matrixWorld),this.intersectsSphere(Zt)},intersectsSphere:function(e){for(var t=this.planes,n=e.center,i=-e.radius,r=0;r<6;r++){if(t[r].distanceToPoint(n)0?e.max.x:e.min.x,Jt.y=i.normal.y>0?e.max.y:e.min.y,Jt.z=i.normal.z>0?e.max.z:e.min.z,i.distanceToPoint(Jt)<0)return!1}return!0},containsPoint:function(e){for(var t=this.planes,n=0;n<6;n++)if(t[n].distanceToPoint(e)<0)return!1;return!0}});var Kt={common:{diffuse:{value:new Be(15658734)},opacity:{value:1},map:{value:null},uvTransform:{value:new f},uv2Transform:{value:new f},alphaMap:{value:null}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},refractionRatio:{value:.98},maxMipLevel:{value:0}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1}},emissivemap:{emissiveMap:{value:null}},bumpmap:{bumpMap:{value:null},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalScale:{value:new p(1,1)}},displacementmap:{displacementMap:{value:null},displacementScale:{value:1},displacementBias:{value:0}},roughnessmap:{roughnessMap:{value:null}},metalnessmap:{metalnessMap:{value:null}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Be(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowRadius:{},shadowMapSize:{}}},spotShadowMap:{value:[]},spotShadowMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}}},points:{diffuse:{value:new Be(15658734)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},uvTransform:{value:new f}},sprite:{diffuse:{value:new Be(15658734)},opacity:{value:1},center:{value:new p(.5,.5)},rotation:{value:0},map:{value:null},alphaMap:{value:null},uvTransform:{value:new f}}};function $t(){var e=null,t=!1,n=null;function i(r,a){!1!==t&&(n(r,a),e.requestAnimationFrame(i))}return{start:function(){!0!==t&&null!==n&&(e.requestAnimationFrame(i),t=!0)},stop:function(){t=!1},setAnimationLoop:function(e){n=e},setContext:function(t){e=t}}}function en(e,t){var n=t.isWebGL2,i=new WeakMap;return{get:function(e){return e.isInterleavedBufferAttribute&&(e=e.data),i.get(e)},remove:function(t){t.isInterleavedBufferAttribute&&(t=t.data);var n=i.get(t);n&&(e.deleteBuffer(n.buffer),i.delete(t))},update:function(t,r){t.isInterleavedBufferAttribute&&(t=t.data);var a=i.get(t);void 0===a?i.set(t,function(t,n){var i=t.array,r=t.usage,a=e.createBuffer();e.bindBuffer(n,a),e.bufferData(n,i,r),t.onUploadCallback();var o=5126;return i instanceof Float32Array?o=5126:i instanceof Float64Array?console.warn("THREE.WebGLAttributes: Unsupported data buffer format: Float64Array."):i instanceof Uint16Array?o=5123:i instanceof Int16Array?o=5122:i instanceof Uint32Array?o=5125:i instanceof Int32Array?o=5124:i instanceof Int8Array?o=5120:i instanceof Uint8Array&&(o=5121),{buffer:a,type:o,bytesPerElement:i.BYTES_PER_ELEMENT,version:t.version}}(t,r)):a.version 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\n\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\n\treturn Fr * fresnel + F0;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\n\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie(float roughness, float NoH) {\n\tfloat invAlpha = 1.0 / roughness;\n\tfloat cos2h = NoH * NoH;\n\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\n}\nfloat V_Neubelt(float NoV, float NoL) {\n\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\n}\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n\tvec3 N = geometry.normal;\n\tvec3 V = geometry.viewDir;\n\tvec3 H = normalize( V + L );\n\tfloat dotNH = saturate( dot( N, H ) );\n\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\n}\n#endif",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n return m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_maxMipLevel 8.0\n#define cubeUV_minMipLevel 4.0\n#define cubeUV_maxTileSize 256.0\n#define cubeUV_minTileSize 16.0\nfloat getFace(vec3 direction) {\n vec3 absDirection = abs(direction);\n float face = -1.0;\n if (absDirection.x > absDirection.z) {\n if (absDirection.x > absDirection.y)\n face = direction.x > 0.0 ? 0.0 : 3.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n } else {\n if (absDirection.z > absDirection.y)\n face = direction.z > 0.0 ? 2.0 : 5.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n }\n return face;\n}\nvec2 getUV(vec3 direction, float face) {\n vec2 uv;\n if (face == 0.0) {\n uv = vec2(direction.z, direction.y) / abs(direction.x); } else if (face == 1.0) {\n uv = vec2(-direction.x, -direction.z) / abs(direction.y); } else if (face == 2.0) {\n uv = vec2(-direction.x, direction.y) / abs(direction.z); } else if (face == 3.0) {\n uv = vec2(-direction.z, direction.y) / abs(direction.x); } else if (face == 4.0) {\n uv = vec2(-direction.x, direction.z) / abs(direction.y); } else {\n uv = vec2(direction.x, direction.y) / abs(direction.z); }\n return 0.5 * (uv + 1.0);\n}\nvec3 bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {\n float face = getFace(direction);\n float filterInt = max(cubeUV_minMipLevel - mipInt, 0.0);\n mipInt = max(mipInt, cubeUV_minMipLevel);\n float faceSize = exp2(mipInt);\n float texelSize = 1.0 / (3.0 * cubeUV_maxTileSize);\n vec2 uv = getUV(direction, face) * (faceSize - 1.0);\n vec2 f = fract(uv);\n uv += 0.5 - f;\n if (face > 2.0) {\n uv.y += faceSize;\n face -= 3.0;\n }\n uv.x += face * faceSize;\n if(mipInt < cubeUV_maxMipLevel){\n uv.y += 2.0 * cubeUV_maxTileSize;\n }\n uv.y += filterInt * 2.0 * cubeUV_minTileSize;\n uv.x += 3.0 * max(0.0, cubeUV_maxTileSize - 2.0 * faceSize);\n uv *= texelSize;\n vec3 tl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.x += texelSize;\n vec3 tr = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.y += texelSize;\n vec3 br = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.x -= texelSize;\n vec3 bl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n vec3 tm = mix(tl, tr, f.x);\n vec3 bm = mix(bl, br, f.x);\n return mix(tm, bm, f.y);\n}\n#define r0 1.0\n#define v0 0.339\n#define m0 -2.0\n#define r1 0.8\n#define v1 0.276\n#define m1 -1.0\n#define r4 0.4\n#define v4 0.046\n#define m4 2.0\n#define r5 0.305\n#define v5 0.016\n#define m5 3.0\n#define r6 0.21\n#define v6 0.0038\n#define m6 4.0\nfloat roughnessToMip(float roughness) {\n float mip = 0.0;\n if (roughness >= r1) {\n mip = (r0 - roughness) * (m1 - m0) / (r0 - r1) + m0;\n } else if (roughness >= r4) {\n mip = (r1 - roughness) * (m4 - m1) / (r1 - r4) + m1;\n } else if (roughness >= r5) {\n mip = (r4 - roughness) * (m5 - m4) / (r4 - r5) + m4;\n } else if (roughness >= r6) {\n mip = (r5 - roughness) * (m6 - m5) / (r5 - r6) + m5;\n } else {\n mip = -2.0 * log2(1.16 * roughness); }\n return mip;\n}\nvec4 textureCubeUV(sampler2D envMap, vec3 sampleDir, float roughness) {\n float mip = clamp(roughnessToMip(roughness), m0, cubeUV_maxMipLevel);\n float mipF = fract(mip);\n float mipInt = floor(mip);\n vec3 color0 = bilinearCubeUV(envMap, sampleDir, mipInt);\n if (mipF == 0.0) {\n return vec4(color0, 1.0);\n } else {\n vec3 color1 = bilinearCubeUV(envMap, sampleDir, mipInt + 1.0);\n return vec4(mix(color0, color1, mipF), 1.0);\n }\n}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\t\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec2 sampleUV = equirectUv( reflectVec );\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifndef ENVMAP_TYPE_CUBE_UV\n\t\tenvColor = envMapTexelToLinear( envColor );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP )\n\t#ifdef ENVMAP_MODE_REFRACTION\n\t\tuniform float refractionRatio;\n\t#endif\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t vec3 reflectVec = reflect( -viewDir, normal );\n\t\t reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t#else\n\t\t vec3 reflectVec = refract( -viewDir, normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV = equirectUv( reflectVec );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) { \n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn texture2D( gradientMap, coord ).rgb;\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\n#endif\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct ToonMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material )\t(0)",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.specularRoughness = max( roughnessFactor, 0.0525 );material.specularRoughness += geometryRoughness;\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\n#ifdef REFLECTIVITY\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#endif\n#ifdef CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheen;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n#ifdef CLEARCOAT\n\tfloat clearcoat;\n\tfloat clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tvec3 sheenColor;\n#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearcoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = ccDotNL * directLight.color;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tccIrradiance *= PI;\n\t\t#endif\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\n\t\t\tmaterial.specularRoughness,\n\t\t\tdirectLight.direction,\n\t\t\tgeometry,\n\t\t\tmaterial.sheenColor\n\t\t);\n\t#else\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\n\t#endif\n\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t\tfloat ccDotNL = ccDotNV;\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\tfloat clearcoatInv = 1.0 - clearcoatDHR;\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\n\t#ifdef CLEARCOAT\n\t\tclearcoatRadiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t#endif\n#endif",normal_fragment_begin:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( -vViewPosition, normal, mapN );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tmat3 tsn = mat3( S, T, N );\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN );\n\t#endif\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ));\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w);\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform highp sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( ( color * ( 2.51 * color + 0.03 ) ) / ( color * ( 2.43 * color + 0.59 ) + 0.14 ) );\n}",uv_pars_fragment:"#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_frag:"uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",cube_frag:"#include \nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 vReflect = vWorldDirection;\n\t#include \n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define REFLECTIVITY\n\t#define CLEARCOAT\n\t#define TRANSPARENCY\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef TRANSPARENCY\n\tuniform float transparency;\n#endif\n#ifdef REFLECTIVITY\n\tuniform float reflectivity;\n#endif\n#ifdef CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheen;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#ifdef TRANSPARENCY\n\t\tdiffuseColor.a *= saturate( 1. - transparency + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) );\n\t#endif\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}"},an={basic:{uniforms:Ht([Kt.common,Kt.specularmap,Kt.envmap,Kt.aomap,Kt.lightmap,Kt.fog]),vertexShader:rn.meshbasic_vert,fragmentShader:rn.meshbasic_frag},lambert:{uniforms:Ht([Kt.common,Kt.specularmap,Kt.envmap,Kt.aomap,Kt.lightmap,Kt.emissivemap,Kt.fog,Kt.lights,{emissive:{value:new Be(0)}}]),vertexShader:rn.meshlambert_vert,fragmentShader:rn.meshlambert_frag},phong:{uniforms:Ht([Kt.common,Kt.specularmap,Kt.envmap,Kt.aomap,Kt.lightmap,Kt.emissivemap,Kt.bumpmap,Kt.normalmap,Kt.displacementmap,Kt.fog,Kt.lights,{emissive:{value:new Be(0)},specular:{value:new Be(1118481)},shininess:{value:30}}]),vertexShader:rn.meshphong_vert,fragmentShader:rn.meshphong_frag},standard:{uniforms:Ht([Kt.common,Kt.envmap,Kt.aomap,Kt.lightmap,Kt.emissivemap,Kt.bumpmap,Kt.normalmap,Kt.displacementmap,Kt.roughnessmap,Kt.metalnessmap,Kt.fog,Kt.lights,{emissive:{value:new Be(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:rn.meshphysical_vert,fragmentShader:rn.meshphysical_frag},toon:{uniforms:Ht([Kt.common,Kt.specularmap,Kt.aomap,Kt.lightmap,Kt.emissivemap,Kt.bumpmap,Kt.normalmap,Kt.displacementmap,Kt.gradientmap,Kt.fog,Kt.lights,{emissive:{value:new Be(0)},specular:{value:new Be(1118481)},shininess:{value:30}}]),vertexShader:rn.meshtoon_vert,fragmentShader:rn.meshtoon_frag},matcap:{uniforms:Ht([Kt.common,Kt.bumpmap,Kt.normalmap,Kt.displacementmap,Kt.fog,{matcap:{value:null}}]),vertexShader:rn.meshmatcap_vert,fragmentShader:rn.meshmatcap_frag},points:{uniforms:Ht([Kt.points,Kt.fog]),vertexShader:rn.points_vert,fragmentShader:rn.points_frag},dashed:{uniforms:Ht([Kt.common,Kt.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:rn.linedashed_vert,fragmentShader:rn.linedashed_frag},depth:{uniforms:Ht([Kt.common,Kt.displacementmap]),vertexShader:rn.depth_vert,fragmentShader:rn.depth_frag},normal:{uniforms:Ht([Kt.common,Kt.bumpmap,Kt.normalmap,Kt.displacementmap,{opacity:{value:1}}]),vertexShader:rn.normal_vert,fragmentShader:rn.normal_frag},sprite:{uniforms:Ht([Kt.sprite,Kt.fog]),vertexShader:rn.sprite_vert,fragmentShader:rn.sprite_frag},background:{uniforms:{uvTransform:{value:new f},t2D:{value:null}},vertexShader:rn.background_vert,fragmentShader:rn.background_frag},cube:{uniforms:Ht([Kt.envmap,{opacity:{value:1}}]),vertexShader:rn.cube_vert,fragmentShader:rn.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:rn.equirect_vert,fragmentShader:rn.equirect_frag},distanceRGBA:{uniforms:Ht([Kt.common,Kt.displacementmap,{referencePosition:{value:new w},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:rn.distanceRGBA_vert,fragmentShader:rn.distanceRGBA_frag},shadow:{uniforms:Ht([Kt.lights,Kt.fog,{color:{value:new Be(0)},opacity:{value:1}}]),vertexShader:rn.shadow_vert,fragmentShader:rn.shadow_frag}};function on(e,t,n,i){var r,a,o=new Be(0),s=0,l=null,c=0,h=null;function u(e,n){t.buffers.color.setClear(e.r,e.g,e.b,n,i)}return{getClearColor:function(){return o},setClearColor:function(e,t){o.set(e),u(o,s=void 0!==t?t:1)},getClearAlpha:function(){return s},setClearAlpha:function(e){u(o,s=e)},render:function(t,i,d,p){var f=i.background,m=e.xr,g=m.getSession&&m.getSession();if(g&&"additive"===g.environmentBlendMode&&(f=null),null===f?u(o,s):f&&f.isColor&&(u(f,1),p=!0),(e.autoClear||p)&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),f&&(f.isCubeTexture||f.isWebGLCubeRenderTarget||306===f.mapping)){void 0===a&&((a=new Nt(new Vt(1,1,1),new jt({type:"BackgroundCubeMaterial",uniforms:kt(an.cube.uniforms),vertexShader:an.cube.vertexShader,fragmentShader:an.cube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1}))).geometry.deleteAttribute("normal"),a.geometry.deleteAttribute("uv"),a.onBeforeRender=function(e,t,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(a.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),n.update(a));var v=f.isWebGLCubeRenderTarget?f.texture:f;a.material.uniforms.envMap.value=v,a.material.uniforms.flipEnvMap.value=v.isCubeTexture?-1:1,l===f&&c===v.version&&h===e.toneMapping||(a.material.needsUpdate=!0,l=f,c=v.version,h=e.toneMapping),t.unshift(a,a.geometry,a.material,0,0,null)}else f&&f.isTexture&&(void 0===r&&((r=new Nt(new nn(2,2),new jt({type:"BackgroundMaterial",uniforms:kt(an.background.uniforms),vertexShader:an.background.vertexShader,fragmentShader:an.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1}))).geometry.deleteAttribute("normal"),Object.defineProperty(r.material,"map",{get:function(){return this.uniforms.t2D.value}}),n.update(r)),r.material.uniforms.t2D.value=f,!0===f.matrixAutoUpdate&&f.updateMatrix(),r.material.uniforms.uvTransform.value.copy(f.matrix),l===f&&c===f.version&&h===e.toneMapping||(r.material.needsUpdate=!0,l=f,c=f.version,h=e.toneMapping),t.unshift(r,r.geometry,r.material,0,0,null))}}}function sn(e,t,n,i){var r,a=i.isWebGL2;this.setMode=function(e){r=e},this.render=function(t,i){e.drawArrays(r,t,i),n.update(i,r)},this.renderInstances=function(i,o,s,l){if(0!==l){var c,h;if(a)c=e,h="drawArraysInstanced";else if(h="drawArraysInstancedANGLE",null===(c=t.get("ANGLE_instanced_arrays")))return void console.error("THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");c[h](r,o,s,l),n.update(s,r,l)}}}function ln(e,t,n){var i;function r(t){if("highp"===t){if(e.getShaderPrecisionFormat(35633,36338).precision>0&&e.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(35633,36337).precision>0&&e.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}var a="undefined"!=typeof WebGL2RenderingContext&&e instanceof WebGL2RenderingContext||"undefined"!=typeof WebGL2ComputeRenderingContext&&e instanceof WebGL2ComputeRenderingContext,o=void 0!==n.precision?n.precision:"highp",s=r(o);s!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",s,"instead."),o=s);var l=!0===n.logarithmicDepthBuffer,c=e.getParameter(34930),h=e.getParameter(35660),u=e.getParameter(3379),d=e.getParameter(34076),p=e.getParameter(34921),f=e.getParameter(36347),m=e.getParameter(36348),g=e.getParameter(36349),v=h>0,x=a||!!t.get("OES_texture_float");return{isWebGL2:a,getMaxAnisotropy:function(){if(void 0!==i)return i;var n=t.get("EXT_texture_filter_anisotropic");return i=null!==n?e.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0},getMaxPrecision:r,precision:o,logarithmicDepthBuffer:l,maxTextures:c,maxVertexTextures:h,maxTextureSize:u,maxCubemapSize:d,maxAttributes:p,maxVertexUniforms:f,maxVaryings:m,maxFragmentUniforms:g,vertexTextures:v,floatFragmentTextures:x,floatVertexTextures:v&&x,maxSamples:a?e.getParameter(36183):0}}function cn(){var e=this,t=null,n=0,i=!1,r=!1,a=new Ee,o=new f,s={value:null,needsUpdate:!1};function l(){s.value!==t&&(s.value=t,s.needsUpdate=n>0),e.numPlanes=n,e.numIntersection=0}function c(t,n,i,r){var l=null!==t?t.length:0,c=null;if(0!==l){if(c=s.value,!0!==r||null===c){var h=i+4*l,u=n.matrixWorldInverse;o.getNormalMatrix(u),(null===c||c.length65535?nt:et)(n,1);p.version=o,t.update(p,34963);var f=r.get(e);f&&t.remove(f),r.set(e,p)}return{get:function(e,t){var r=i.get(t);return r||(t.addEventListener("dispose",a),t.isBufferGeometry?r=t:t.isGeometry&&(void 0===t._bufferGeometry&&(t._bufferGeometry=(new ft).setFromObject(e)),r=t._bufferGeometry),i.set(t,r),n.memory.geometries++,r)},update:function(e){var n=e.index,i=e.attributes;for(var r in null!==n&&t.update(n,34963),i)t.update(i[r],34962);var a=e.morphAttributes;for(var r in a)for(var o=a[r],s=0,l=o.length;s0)return e;var r=t*n,a=Sn[r];if(void 0===a&&(a=new Float32Array(r),Sn[r]=a),0!==t){i.toArray(a,0);for(var o=1,s=0;o!==t;++o)s+=n,e[o].toArray(a,s)}return a}function Cn(e,t){if(e.length!==t.length)return!1;for(var n=0,i=e.length;n/gm;function Ei(e){return e.replace(Si,Ti)}function Ti(e,t){var n=rn[t];if(void 0===n)throw new Error("Can not resolve #include <"+t+">");return Ei(n)}var Li=/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,Ai=/#pragma unroll_loop_start[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}[\s]+?#pragma unroll_loop_end/g;function Pi(e){return e.replace(Ai,Di).replace(Li,Ci)}function Ci(e,t,n,i){return console.warn("WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead."),Di(e,t,n,i)}function Di(e,t,n,i){for(var r="",a=parseInt(t);a0?e.gammaFactor:1,v=n.isWebGL2?"":function(e){return[e.extensionDerivatives||e.envMapCubeUV||e.bumpMap||e.tangentSpaceNormalMap||e.clearcoatNormalMap||e.flatShading||"physical"===e.shaderID?"#extension GL_OES_standard_derivatives : enable":"",(e.extensionFragDepth||e.logarithmicDepthBuffer)&&e.rendererExtensionFragDepth?"#extension GL_EXT_frag_depth : enable":"",e.extensionDrawBuffers&&e.rendererExtensionDrawBuffers?"#extension GL_EXT_draw_buffers : require":"",(e.extensionShaderTextureLOD||e.envMap)&&e.rendererExtensionShaderTextureLod?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Mi).join("\n")}(n),x=function(e){var t=[];for(var n in e){var i=e[n];!1!==i&&t.push("#define "+n+" "+i)}return t.join("\n")}(c),_=l.createProgram();if(n.isRawShaderMaterial?((i=[x].filter(Mi).join("\n")).length>0&&(i+="\n"),(r=[v,x].filter(Mi).join("\n")).length>0&&(r+="\n")):(i=[Ni(n),"#define SHADER_NAME "+n.shaderName,x,n.instancing?"#define USE_INSTANCING":"",n.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+g,"#define MAX_BONES "+n.maxBones,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+f:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMap&&n.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",n.normalMap&&n.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.displacementMap&&n.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexUvs?"#define USE_UV":"",n.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.useVertexTexture?"#define BONE_TEXTURE":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+d:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING"," attribute mat4 instanceMatrix;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#ifdef USE_COLOR","\tattribute vec3 color;","#endif","#ifdef USE_MORPHTARGETS","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Mi).join("\n"),r=[v,Ni(n),"#define SHADER_NAME "+n.shaderName,x,n.alphaTest?"#define ALPHATEST "+n.alphaTest+(n.alphaTest%1?"":".0"):"","#define GAMMA_FACTOR "+g,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.envMap?"#define "+f:"",n.envMap?"#define "+m:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMap&&n.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",n.normalMap&&n.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.sheen?"#define USE_SHEEN":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexUvs?"#define USE_UV":"",n.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+d:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"",(n.extensionShaderTextureLOD||n.envMap)&&n.rendererExtensionShaderTextureLod?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==n.toneMapping?"#define TONE_MAPPING":"",0!==n.toneMapping?rn.tonemapping_pars_fragment:"",0!==n.toneMapping?yi("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.outputEncoding||n.mapEncoding||n.matcapEncoding||n.envMapEncoding||n.emissiveMapEncoding||n.lightMapEncoding?rn.encodings_pars_fragment:"",n.mapEncoding?_i("mapTexelToLinear",n.mapEncoding):"",n.matcapEncoding?_i("matcapTexelToLinear",n.matcapEncoding):"",n.envMapEncoding?_i("envMapTexelToLinear",n.envMapEncoding):"",n.emissiveMapEncoding?_i("emissiveMapTexelToLinear",n.emissiveMapEncoding):"",n.lightMapEncoding?_i("lightMapTexelToLinear",n.lightMapEncoding):"",n.outputEncoding?(a="linearToOutputTexel",o=n.outputEncoding,s=vi(o),"vec4 "+a+"( vec4 value ) { return LinearTo"+s[0]+s[1]+"; }"):"",n.depthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(Mi).join("\n")),h=wi(h=bi(h=Ei(h),n),n),u=wi(u=bi(u=Ei(u),n),n),h=Pi(h),u=Pi(u),n.isWebGL2&&!n.isRawShaderMaterial){var y=!1,M=/^\s*#version\s+300\s+es\s*\n/;n.isShaderMaterial&&null!==h.match(M)&&null!==u.match(M)&&(y=!0,h=h.replace(M,""),u=u.replace(M,"")),i=["#version 300 es\n","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+i,r=["#version 300 es\n","#define varying in",y?"":"out highp vec4 pc_fragColor;",y?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+r}var b,w,S=r+u,E=mi(l,35633,i+h),T=mi(l,35632,S);if(l.attachShader(_,E),l.attachShader(_,T),void 0!==n.index0AttributeName?l.bindAttribLocation(_,0,n.index0AttributeName):!0===n.morphTargets&&l.bindAttribLocation(_,0,"position"),l.linkProgram(_),e.debug.checkShaderErrors){var L=l.getProgramInfoLog(_).trim(),A=l.getShaderInfoLog(E).trim(),P=l.getShaderInfoLog(T).trim(),C=!0,D=!0;if(!1===l.getProgramParameter(_,35714)){C=!1;var N=xi(l,E,"vertex"),R=xi(l,T,"fragment");console.error("THREE.WebGLProgram: shader error: ",l.getError(),"35715",l.getProgramParameter(_,35715),"gl.getProgramInfoLog",L,N,R)}else""!==L?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",L):""!==A&&""!==P||(D=!1);D&&(this.diagnostics={runnable:C,programLog:L,vertexShader:{log:A,prefix:i},fragmentShader:{log:P,prefix:r}})}return l.deleteShader(E),l.deleteShader(T),this.getUniforms=function(){return void 0===b&&(b=new fi(l,_)),b},this.getAttributes=function(){return void 0===w&&(w=function(e,t){for(var n={},i=e.getProgramParameter(t,35721),r=0;r0,maxBones:b,useVertexTexture:o,morphTargets:i.morphTargets,morphNormals:i.morphNormals,maxMorphTargets:e.maxMorphTargets,maxMorphNormals:e.maxMorphNormals,numDirLights:u.directional.length,numPointLights:u.point.length,numSpotLights:u.spot.length,numRectAreaLights:u.rectArea.length,numHemiLights:u.hemi.length,numDirLightShadows:u.directionalShadowMap.length,numPointLightShadows:u.pointShadowMap.length,numSpotLightShadows:u.spotShadowMap.length,numClippingPlanes:m,numClipIntersection:g,dithering:i.dithering,shadowMapEnabled:e.shadowMap.enabled&&p.length>0,shadowMapType:e.shadowMap.type,toneMapping:i.toneMapped?e.toneMapping:0,physicallyCorrectLights:e.physicallyCorrectLights,premultipliedAlpha:i.premultipliedAlpha,alphaTest:i.alphaTest,doubleSided:2===i.side,flipSided:1===i.side,depthPacking:void 0!==i.depthPacking&&i.depthPacking,index0AttributeName:i.index0AttributeName,extensionDerivatives:i.extensions&&i.extensions.derivatives,extensionFragDepth:i.extensions&&i.extensions.fragDepth,extensionDrawBuffers:i.extensions&&i.extensions.drawBuffers,extensionShaderTextureLOD:i.extensions&&i.extensions.shaderTextureLOD,rendererExtensionFragDepth:r||null!==t.get("EXT_frag_depth"),rendererExtensionDrawBuffers:r||null!==t.get("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:r||null!==t.get("EXT_shader_texture_lod"),onBeforeCompile:i.onBeforeCompile}},this.getProgramCacheKey=function(t){var n=[];if(t.shaderID?n.push(t.shaderID):(n.push(t.fragmentShader),n.push(t.vertexShader)),void 0!==t.defines)for(var i in t.defines)n.push(i),n.push(t.defines[i]);if(void 0===t.isRawShaderMaterial){for(var r=0;r1&&n.sort(e||zi),i.length>1&&i.sort(t||Oi)}}}function Gi(){var e=new WeakMap;function t(n){var i=n.target;i.removeEventListener("dispose",t),e.delete(i)}return{get:function(n,i){var r,a=e.get(n);return void 0===a?(r=new Fi,e.set(n,new WeakMap),e.get(n).set(i,r),n.addEventListener("dispose",t)):void 0===(r=a.get(i))&&(r=new Fi,a.set(i,r)),r},dispose:function(){e=new WeakMap}}}function Bi(){var e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];var n;switch(t.type){case"DirectionalLight":n={direction:new w,color:new Be};break;case"SpotLight":n={position:new w,direction:new w,color:new Be,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new w,color:new Be,distance:0,decay:0};break;case"HemisphereLight":n={direction:new w,skyColor:new Be,groundColor:new Be};break;case"RectAreaLight":n={color:new Be,position:new w,halfWidth:new w,halfHeight:new w}}return e[t.id]=n,n}}}var Vi=0;function ki(e,t){return(t.castShadow?1:0)-(e.castShadow?1:0)}function Hi(){for(var e,t=new Bi,n=(e={},{get:function(t){if(void 0!==e[t.id])return e[t.id];var n;switch(t.type){case"DirectionalLight":case"SpotLight":n={shadowBias:0,shadowRadius:1,shadowMapSize:new p};break;case"PointLight":n={shadowBias:0,shadowRadius:1,shadowMapSize:new p,shadowCameraNear:1,shadowCameraFar:1e3}}return e[t.id]=n,n}}),i={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadow:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]},r=0;r<9;r++)i.probe.push(new w);var a=new w,o=new D,s=new D;return{setup:function(e,r,l){for(var c=0,h=0,u=0,d=0;d<9;d++)i.probe[d].set(0,0,0);var p=0,f=0,m=0,g=0,v=0,x=0,_=0,y=0,M=l.matrixWorldInverse;e.sort(ki),d=0;for(var b=e.length;d\nvoid main() {\n float mean = 0.0;\n float squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n for ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n #ifdef HORIZONAL_PASS\n vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n mean += distribution.x;\n squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n #else\n float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\n mean += depth;\n squared_mean += depth * depth;\n #endif\n }\n mean = mean * HALF_SAMPLE_RATE;\n squared_mean = squared_mean * HALF_SAMPLE_RATE;\n float std_dev = sqrt( squared_mean - mean * mean );\n gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),d=u.clone();d.defines.HORIZONAL_PASS=1;var f=new ft;f.setAttribute("position",new Ze(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));var m=new Nt(f,u),g=this;function v(n,i){var r=t.update(m);u.uniforms.shadow_pass.value=n.map.texture,u.uniforms.resolution.value=n.mapSize,u.uniforms.radius.value=n.radius,e.setRenderTarget(n.mapPass),e.clear(),e.renderBufferDirect(i,null,r,u,m,null),d.uniforms.shadow_pass.value=n.mapPass.texture,d.uniforms.resolution.value=n.mapSize,d.uniforms.radius.value=n.radius,e.setRenderTarget(n.map),e.clear(),e.renderBufferDirect(i,null,r,d,m,null)}function y(e,t,n){var i=e<<0|t<<1|n<<2,r=s[i];return void 0===r&&(r=new Xi({depthPacking:3201,morphTargets:e,skinning:t}),s[i]=r),r}function M(e,t,n){var i=e<<0|t<<1|n<<2,r=l[i];return void 0===r&&(r=new qi({morphTargets:e,skinning:t}),l[i]=r),r}function b(t,n,i,r,a,o,s){var l=null,u=y,d=t.customDepthMaterial;if(!0===r.isPointLight&&(u=M,d=t.customDistanceMaterial),void 0===d){var p=!1;!0===i.morphTargets&&(p=n.morphAttributes&&n.morphAttributes.position&&n.morphAttributes.position.length>0);var f=!1;!0===t.isSkinnedMesh&&(!0===i.skinning?f=!0:console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",t)),l=u(p,f,!0===t.isInstancedMesh)}else l=d;if(e.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length){var m=l.uuid,g=i.uuid,v=c[m];void 0===v&&(v={},c[m]=v);var x=v[g];void 0===x&&(x=l.clone(),v[g]=x),l=x}return l.visible=i.visible,l.wireframe=i.wireframe,l.side=3===s?null!==i.shadowSide?i.shadowSide:i.side:null!==i.shadowSide?i.shadowSide:h[i.side],l.clipShadows=i.clipShadows,l.clippingPlanes=i.clippingPlanes,l.clipIntersection=i.clipIntersection,l.wireframeLinewidth=i.wireframeLinewidth,l.linewidth=i.linewidth,!0===r.isPointLight&&!0===l.isMeshDistanceMaterial&&(l.referencePosition.setFromMatrixPosition(r.matrixWorld),l.nearDistance=a,l.farDistance=o),l}function w(n,r,a,o,s){if(!1!==n.visible){if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&3===s)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,n.matrixWorld);var l=t.update(n),c=n.material;if(Array.isArray(c))for(var h=l.groups,u=0,d=h.length;un||r.y>n)&&(r.x>n&&(a.x=Math.floor(n/y.x),r.x=a.x*y.x,x.mapSize.x=a.x),r.y>n&&(a.y=Math.floor(n/y.y),r.y=a.y*y.y,x.mapSize.y=a.y)),null===x.map&&!x.isPointLightShadow&&3===this.type){var M={minFilter:1006,magFilter:1006,format:1023};x.map=new _(r.x,r.y,M),x.map.texture.name=m.name+".shadowMap",x.mapPass=new _(r.x,r.y,M),x.camera.updateProjectionMatrix()}if(null===x.map){M={minFilter:1003,magFilter:1003,format:1023};x.map=new _(r.x,r.y,M),x.map.texture.name=m.name+".shadowMap",x.camera.updateProjectionMatrix()}e.setRenderTarget(x.map),e.clear();for(var b=x.getViewportCount(),S=0;S=1):-1!==D.indexOf("OpenGL ES")&&(C=parseFloat(/^OpenGL\ ES\ ([0-9])/.exec(D)[1]),P=C>=2);var N=null,R={},I=new x,U=new x;function z(t,n,i){var r=new Uint8Array(4),a=e.createTexture();e.bindTexture(t,a),e.texParameteri(t,10241,9728),e.texParameteri(t,10240,9728);for(var o=0;oi||e.height>i)&&(r=i/Math.max(e.width,e.height)),r<1||!0===t){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap){var a=t?d.floorPowerOfTwo:Math.floor,o=a(r*e.width),l=a(r*e.height);void 0===s&&(s=g(o,l));var c=n?g(o,l):s;return c.width=o,c.height=l,c.getContext("2d").drawImage(e,0,0,o,l),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+e.width+"x"+e.height+") to ("+o+"x"+l+")."),c}return"data"in e&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+e.width+"x"+e.height+")."),e}return e}function x(e){return d.isPowerOfTwo(e.width)&&d.isPowerOfTwo(e.height)}function _(e,t){return e.generateMipmaps&&t&&1003!==e.minFilter&&1006!==e.minFilter}function y(t,n,r,a){e.generateMipmap(t),i.get(n).__maxMipLevel=Math.log(Math.max(r,a))*Math.LOG2E}function M(n,i,r){if(!1===l)return i;if(null!==n){if(void 0!==e[n])return e[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}var a=i;return 6403===i&&(5126===r&&(a=33326),5131===r&&(a=33325),5121===r&&(a=33321)),6407===i&&(5126===r&&(a=34837),5131===r&&(a=34843),5121===r&&(a=32849)),6408===i&&(5126===r&&(a=34836),5131===r&&(a=34842),5121===r&&(a=32856)),33325!==a&&33326!==a&&34842!==a&&34836!==a||t.get("EXT_color_buffer_float"),a}function b(e){return 1003===e||1004===e||1005===e?9728:9729}function w(t){var n=t.target;n.removeEventListener("dispose",w),function(t){var n=i.get(t);if(void 0===n.__webglInit)return;e.deleteTexture(n.__webglTexture),i.remove(t)}(n),n.isVideoTexture&&f.delete(n),o.memory.textures--}function S(t){var n=t.target;n.removeEventListener("dispose",S),function(t){var n=i.get(t),r=i.get(t.texture);if(!t)return;void 0!==r.__webglTexture&&e.deleteTexture(r.__webglTexture);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLCubeRenderTarget)for(var a=0;a<6;a++)e.deleteFramebuffer(n.__webglFramebuffer[a]),n.__webglDepthbuffer&&e.deleteRenderbuffer(n.__webglDepthbuffer[a]);else e.deleteFramebuffer(n.__webglFramebuffer),n.__webglDepthbuffer&&e.deleteRenderbuffer(n.__webglDepthbuffer),n.__webglMultisampledFramebuffer&&e.deleteFramebuffer(n.__webglMultisampledFramebuffer),n.__webglColorRenderbuffer&&e.deleteRenderbuffer(n.__webglColorRenderbuffer),n.__webglDepthRenderbuffer&&e.deleteRenderbuffer(n.__webglDepthRenderbuffer);i.remove(t.texture),i.remove(t)}(n),o.memory.textures--}var E=0;function T(e,t){var r=i.get(e);if(e.isVideoTexture&&function(e){var t=o.render.frame;f.get(e)!==t&&(f.set(e,t),e.update())}(e),e.version>0&&r.__version!==e.version){var a=e.image;if(void 0===a)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined");else{if(!1!==a.complete)return void R(r,e,t);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.activeTexture(33984+t),n.bindTexture(3553,r.__webglTexture)}function L(t,r){if(6===t.image.length){var o=i.get(t);if(t.version>0&&o.__version!==t.version){N(o,t),n.activeTexture(33984+r),n.bindTexture(34067,o.__webglTexture),e.pixelStorei(37440,t.flipY);for(var s=t&&(t.isCompressedTexture||t.image[0].isCompressedTexture),c=t.image[0]&&t.image[0].isDataTexture,u=[],d=0;d<6;d++)u[d]=s||c?c?t.image[d].image:t.image[d]:v(t.image[d],!1,!0,h);var p,f=u[0],m=x(f)||l,g=a.convert(t.format),b=a.convert(t.type),w=M(t.internalFormat,g,b);if(D(34067,t,m),s){for(d=0;d<6;d++){p=u[d].mipmaps;for(var S=0;S1||i.get(a).__currentAnisotropy)&&(e.texParameterf(n,s.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,r.getMaxAnisotropy())),i.get(a).__currentAnisotropy=a.anisotropy)}}function N(t,n){void 0===t.__webglInit&&(t.__webglInit=!0,n.addEventListener("dispose",w),t.__webglTexture=e.createTexture(),o.memory.textures++)}function R(t,i,r){var o=3553;i.isDataTexture2DArray&&(o=35866),i.isDataTexture3D&&(o=32879),N(t,i),n.activeTexture(33984+r),n.bindTexture(o,t.__webglTexture),e.pixelStorei(37440,i.flipY),e.pixelStorei(37441,i.premultiplyAlpha),e.pixelStorei(3317,i.unpackAlignment);var s=function(e){return!l&&(1001!==e.wrapS||1001!==e.wrapT||1003!==e.minFilter&&1006!==e.minFilter)}(i)&&!1===x(i.image),c=v(i.image,s,!1,u),h=x(c)||l,d=a.convert(i.format),p=a.convert(i.type),f=M(i.internalFormat,d,p);D(o,i,h);var m,g=i.mipmaps;if(i.isDepthTexture)f=6402,l?f=1015===i.type?36012:1014===i.type?33190:1020===i.type?35056:33189:1015===i.type&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),1026===i.format&&6402===f&&1012!==i.type&&1014!==i.type&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),i.type=1012,p=a.convert(i.type)),1027===i.format&&6402===f&&(f=34041,1020!==i.type&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),i.type=1020,p=a.convert(i.type))),n.texImage2D(3553,0,f,c.width,c.height,0,d,p,null);else if(i.isDataTexture)if(g.length>0&&h){for(var b=0,w=g.length;b0&&h){for(b=0,w=g.length;b=c&&console.warn("THREE.WebGLTextures: Trying to use "+e+" texture units while this GPU supports only "+c),E+=1,e},this.resetTextureUnits=function(){E=0},this.setTexture2D=T,this.setTexture2DArray=function(e,t){var r=i.get(e);e.version>0&&r.__version!==e.version?R(r,e,t):(n.activeTexture(33984+t),n.bindTexture(35866,r.__webglTexture))},this.setTexture3D=function(e,t){var r=i.get(e);e.version>0&&r.__version!==e.version?R(r,e,t):(n.activeTexture(33984+t),n.bindTexture(32879,r.__webglTexture))},this.setTextureCube=L,this.setTextureCubeDynamic=A,this.setupRenderTarget=function(t){var r=i.get(t),s=i.get(t.texture);t.addEventListener("dispose",S),s.__webglTexture=e.createTexture(),o.memory.textures++;var c=!0===t.isWebGLCubeRenderTarget,h=!0===t.isWebGLMultisampleRenderTarget,u=x(t)||l;if(!l||1022!==t.texture.format||1015!==t.texture.type&&1016!==t.texture.type||(t.texture.format=1023,console.warn("THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.")),c){r.__webglFramebuffer=[];for(var d=0;d<6;d++)r.__webglFramebuffer[d]=e.createFramebuffer()}else if(r.__webglFramebuffer=e.createFramebuffer(),h)if(l){r.__webglMultisampledFramebuffer=e.createFramebuffer(),r.__webglColorRenderbuffer=e.createRenderbuffer(),e.bindRenderbuffer(36161,r.__webglColorRenderbuffer);var p=a.convert(t.texture.format),f=a.convert(t.texture.type),m=M(t.texture.internalFormat,p,f),g=O(t);e.renderbufferStorageMultisample(36161,g,m,t.width,t.height),e.bindFramebuffer(36160,r.__webglMultisampledFramebuffer),e.framebufferRenderbuffer(36160,36064,36161,r.__webglColorRenderbuffer),e.bindRenderbuffer(36161,null),t.depthBuffer&&(r.__webglDepthRenderbuffer=e.createRenderbuffer(),U(r.__webglDepthRenderbuffer,t,!0)),e.bindFramebuffer(36160,null)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.");if(c){n.bindTexture(34067,s.__webglTexture),D(34067,t.texture,u);for(d=0;d<6;d++)I(r.__webglFramebuffer[d],t,36064,34069+d);_(t.texture,u)&&y(34067,t.texture,t.width,t.height),n.bindTexture(34067,null)}else n.bindTexture(3553,s.__webglTexture),D(3553,t.texture,u),I(r.__webglFramebuffer,t,36064,3553),_(t.texture,u)&&y(3553,t.texture,t.width,t.height),n.bindTexture(3553,null);t.depthBuffer&&z(t)},this.updateRenderTargetMipmap=function(e){var t=e.texture;if(_(t,x(e)||l)){var r=e.isWebGLCubeRenderTarget?34067:3553,a=i.get(t).__webglTexture;n.bindTexture(r,a),y(r,t,e.width,e.height),n.bindTexture(r,null)}},this.updateMultisampleRenderTarget=function(t){if(t.isWebGLMultisampleRenderTarget)if(l){var n=i.get(t);e.bindFramebuffer(36008,n.__webglMultisampledFramebuffer),e.bindFramebuffer(36009,n.__webglFramebuffer);var r=t.width,a=t.height,o=16384;t.depthBuffer&&(o|=256),t.stencilBuffer&&(o|=1024),e.blitFramebuffer(0,0,r,a,0,0,r,a,o,9728),e.bindFramebuffer(36160,n.__webglMultisampledFramebuffer)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.")},this.safeSetTexture2D=function(e,t){e&&e.isWebGLRenderTarget&&(!1===F&&(console.warn("THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead."),F=!0),e=e.texture),T(e,t)},this.safeSetTextureCube=function(e,t){e&&e.isWebGLCubeRenderTarget&&(!1===G&&(console.warn("THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead."),G=!0),e=e.texture),e&&e.isCubeTexture||Array.isArray(e.image)&&6===e.image.length?L(e,t):A(e,t)}}function Qi(e,t,n){var i=n.isWebGL2;return{convert:function(e){var n;if(1009===e)return 5121;if(1017===e)return 32819;if(1018===e)return 32820;if(1019===e)return 33635;if(1010===e)return 5120;if(1011===e)return 5122;if(1012===e)return 5123;if(1013===e)return 5124;if(1014===e)return 5125;if(1015===e)return 5126;if(1016===e)return i?5131:null!==(n=t.get("OES_texture_half_float"))?n.HALF_FLOAT_OES:null;if(1021===e)return 6406;if(1022===e)return 6407;if(1023===e)return 6408;if(1024===e)return 6409;if(1025===e)return 6410;if(1026===e)return 6402;if(1027===e)return 34041;if(1028===e)return 6403;if(1029===e)return 36244;if(1030===e)return 33319;if(1031===e)return 33320;if(1032===e)return 36248;if(1033===e)return 36249;if(33776===e||33777===e||33778===e||33779===e){if(null===(n=t.get("WEBGL_compressed_texture_s3tc")))return null;if(33776===e)return n.COMPRESSED_RGB_S3TC_DXT1_EXT;if(33777===e)return n.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(33778===e)return n.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(33779===e)return n.COMPRESSED_RGBA_S3TC_DXT5_EXT}if(35840===e||35841===e||35842===e||35843===e){if(null===(n=t.get("WEBGL_compressed_texture_pvrtc")))return null;if(35840===e)return n.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(35841===e)return n.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(35842===e)return n.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(35843===e)return n.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}if(36196===e)return null!==(n=t.get("WEBGL_compressed_texture_etc1"))?n.COMPRESSED_RGB_ETC1_WEBGL:null;if((37492===e||37496===e)&&null!==(n=t.get("WEBGL_compressed_texture_etc"))){if(37492===e)return n.COMPRESSED_RGB8_ETC2;if(37496===e)return n.COMPRESSED_RGBA8_ETC2_EAC}return 37808===e||37809===e||37810===e||37811===e||37812===e||37813===e||37814===e||37815===e||37816===e||37817===e||37818===e||37819===e||37820===e||37821===e||37840===e||37841===e||37842===e||37843===e||37844===e||37845===e||37846===e||37847===e||37848===e||37849===e||37850===e||37851===e||37852===e||37853===e?null!==(n=t.get("WEBGL_compressed_texture_astc"))?e:null:36492===e?null!==(n=t.get("EXT_texture_compression_bptc"))?e:null:1020===e?i?34042:null!==(n=t.get("WEBGL_depth_texture"))?n.UNSIGNED_INT_24_8_WEBGL:null:void 0}}}function Ki(e){qt.call(this),this.cameras=e||[]}function $i(){Z.call(this),this.type="Group"}function er(){this._targetRay=null,this._grip=null}function tr(e,t){var n=this,i=null,r=1,a=null,o="local-floor",s=null,l=[],c=new Map,h=new qt;h.layers.enable(1),h.viewport=new x;var u=new qt;u.layers.enable(2),u.viewport=new x;var d=[h,u],p=new Ki;p.layers.enable(1),p.layers.enable(2);var f=null,m=null;function g(e){var t=c.get(e.inputSource);t&&t.dispatchEvent({type:e.type})}function v(){c.forEach((function(e,t){e.disconnect(t)})),c.clear(),e.setFramebuffer(null),e.setRenderTarget(e.getRenderTarget()),T.stop(),n.isPresenting=!1,n.dispatchEvent({type:"sessionend"})}function _(e){a=e,T.setContext(i),T.start(),n.isPresenting=!0,n.dispatchEvent({type:"sessionstart"})}function y(e){for(var t=i.inputSources,n=0;n=0){var c=r[s];if(void 0!==c){var h=c.normalized,u=c.itemSize;if(void 0===(b=S.get(c)))continue;var d=b.buffer,p=b.type,f=b.bytesPerElement;if(c.isInterleavedBufferAttribute){var x=c.data,y=x.stride,M=c.offset;x&&x.isInstancedInterleavedBuffer?(_.enableAttributeAndDivisor(l,x.meshPerAttribute),void 0===t._maxInstanceCount&&(t._maxInstanceCount=x.meshPerAttribute*x.count)):_.enableAttribute(l),m.bindBuffer(34962,d),_.vertexAttribPointer(l,u,p,h,y*f,M*f)}else c.isInstancedBufferAttribute?(_.enableAttributeAndDivisor(l,c.meshPerAttribute),void 0===t._maxInstanceCount&&(t._maxInstanceCount=c.meshPerAttribute*c.count)):_.enableAttribute(l),m.bindBuffer(34962,d),_.vertexAttribPointer(l,u,p,h,0,0)}else if("instanceMatrix"===s){var b;if(void 0===(b=S.get(e.instanceMatrix)))continue;d=b.buffer,p=b.type;_.enableAttributeAndDivisor(l+0,1),_.enableAttributeAndDivisor(l+1,1),_.enableAttributeAndDivisor(l+2,1),_.enableAttributeAndDivisor(l+3,1),m.bindBuffer(34962,d),m.vertexAttribPointer(l+0,4,p,!1,64,0),m.vertexAttribPointer(l+1,4,p,!1,64,16),m.vertexAttribPointer(l+2,4,p,!1,64,32),m.vertexAttribPointer(l+3,4,p,!1,64,48)}else if(void 0!==o){var w=o[s];if(void 0!==w)switch(w.length){case 2:m.vertexAttrib2fv(l,w);break;case 3:m.vertexAttrib3fv(l,w);break;case 4:m.vertexAttrib4fv(l,w);break;default:m.vertexAttrib1fv(l,w)}}}}_.disableUnusedAttributes()}(r,n,i,s),null!==c&&m.bindBuffer(34963,u.buffer));var f=null!==c?c.count:h.count,x=n.drawRange.start*d,y=n.drawRange.count*d,M=null!==a?a.start*d:0,b=null!==a?a.count*d:1/0,w=Math.max(x,M),T=Math.min(f,x+y,M+b)-1,L=Math.max(0,T-w+1);if(0!==L){if(r.isMesh)!0===i.wireframe?(_.setLineWidth(i.wireframeLinewidth*de()),p.setMode(1)):p.setMode(4);else if(r.isLine){var A=i.linewidth;void 0===A&&(A=1),_.setLineWidth(A*de()),r.isLineSegments?p.setMode(1):r.isLineLoop?p.setMode(2):p.setMode(3)}else r.isPoints?p.setMode(0):r.isSprite&&p.setMode(4);if(r.isInstancedMesh)p.renderInstances(n,w,L,r.count);else if(n.isInstancedBufferGeometry){var P=Math.min(n.instanceCount,n._maxInstanceCount);p.renderInstances(n,w,L,P)}else p.render(w,L)}},this.compile=function(e,t){(f=C.get(e,t)).init(),e.traverse((function(e){e.isLight&&(f.pushLight(e),e.castShadow&&f.pushShadow(e))})),f.setupLights(t);const n={};e.traverse((function(t){let i=t.material;if(i)if(Array.isArray(i))for(let r=0;r=0&&e.numSupportedMorphTargets++}if(e.morphNormals){e.numSupportedMorphNormals=0;for(d=0;d=0&&e.numSupportedMorphNormals++}var p=i.uniforms;(e.isShaderMaterial||e.isRawShaderMaterial)&&!0!==e.clipping||(i.numClippingPlanes=se.numPlanes,i.numIntersection=se.numIntersection,p.clippingPlanes=se.uniform),i.environment=e.isMeshStandardMaterial?t.environment:null,i.fog=t.fog,i.needsLights=function(e){return e.isMeshLambertMaterial||e.isMeshToonMaterial||e.isMeshPhongMaterial||e.isMeshStandardMaterial||e.isShadowMaterial||e.isShaderMaterial&&!0===e.lights}(e),i.lightsStateVersion=o,i.needsLights&&(p.ambientLightColor.value=r.state.ambient,p.lightProbe.value=r.state.probe,p.directionalLights.value=r.state.directional,p.directionalLightShadows.value=r.state.directionalShadow,p.spotLights.value=r.state.spot,p.spotLightShadows.value=r.state.spotShadow,p.rectAreaLights.value=r.state.rectArea,p.pointLights.value=r.state.point,p.pointLightShadows.value=r.state.pointShadow,p.hemisphereLights.value=r.state.hemi,p.directionalShadowMap.value=r.state.directionalShadowMap,p.directionalShadowMatrix.value=r.state.directionalShadowMatrix,p.spotShadowMap.value=r.state.spotShadowMap,p.spotShadowMatrix.value=r.state.spotShadowMatrix,p.pointShadowMap.value=r.state.pointShadowMap,p.pointShadowMatrix.value=r.state.pointShadowMatrix);var m=i.program.getUniforms(),g=fi.seqWithValue(m.seq,p);i.uniformsList=g}function Ae(e,t,n,i){b.resetTextureUnits();var r=t.fog,a=n.isMeshStandardMaterial?t.environment:null,o=null===k?O.outputEncoding:k.texture.encoding,s=M.get(n),l=f.state.lights;if(le&&(ce||e!==X)){var c=e===X&&n.id===W;se.setState(n.clippingPlanes,n.clipIntersection,n.clipShadows,e,s,c)}n.version===s.__version?void 0===s.program||n.fog&&s.fog!==r||s.environment!==a||s.needsLights&&s.lightsStateVersion!==l.state.version?Le(n,t,i):void 0===s.numClippingPlanes||s.numClippingPlanes===se.numPlanes&&s.numIntersection===se.numIntersection?s.outputEncoding!==o&&Le(n,t,i):Le(n,t,i):(Le(n,t,i),s.__version=n.version);var h,u,p=!1,g=!1,x=!1,y=s.program,w=y.getUniforms(),S=s.uniforms;if(_.useProgram(y.program)&&(p=!0,g=!0,x=!0),n.id!==W&&(W=n.id,g=!0),p||X!==e){if(w.setValue(m,"projectionMatrix",e.projectionMatrix),v.logarithmicDepthBuffer&&w.setValue(m,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),X!==e&&(X=e,g=!0,x=!0),n.isShaderMaterial||n.isMeshPhongMaterial||n.isMeshToonMaterial||n.isMeshStandardMaterial||n.envMap){var E=w.map.cameraPosition;void 0!==E&&E.setValue(m,ue.setFromMatrixPosition(e.matrixWorld))}(n.isMeshPhongMaterial||n.isMeshToonMaterial||n.isMeshLambertMaterial||n.isMeshBasicMaterial||n.isMeshStandardMaterial||n.isShaderMaterial)&&w.setValue(m,"isOrthographic",!0===e.isOrthographicCamera),(n.isMeshPhongMaterial||n.isMeshToonMaterial||n.isMeshLambertMaterial||n.isMeshBasicMaterial||n.isMeshStandardMaterial||n.isShaderMaterial||n.skinning)&&w.setValue(m,"viewMatrix",e.matrixWorldInverse)}if(n.skinning){w.setOptional(m,i,"bindMatrix"),w.setOptional(m,i,"bindMatrixInverse");var T=i.skeleton;if(T){var L=T.bones;if(v.floatVertexTextures){if(void 0===T.boneTexture){var P=Math.sqrt(4*L.length);P=d.ceilPowerOfTwo(P),P=Math.max(P,4);var C=new Float32Array(P*P*4);C.set(T.boneMatrices);var D=new Yt(C,P,P,1023,1015);T.boneMatrices=C,T.boneTexture=D,T.boneTextureSize=P}w.setValue(m,"boneTexture",T.boneTexture,b),w.setValue(m,"boneTextureSize",T.boneTextureSize)}else w.setOptional(m,T,"boneMatrices")}}return(g||s.receiveShadow!==i.receiveShadow)&&(s.receiveShadow=i.receiveShadow,w.setValue(m,"receiveShadow",i.receiveShadow)),g&&(w.setValue(m,"toneMappingExposure",O.toneMappingExposure),w.setValue(m,"toneMappingWhitePoint",O.toneMappingWhitePoint),s.needsLights&&(u=x,(h=S).ambientLightColor.needsUpdate=u,h.lightProbe.needsUpdate=u,h.directionalLights.needsUpdate=u,h.directionalLightShadows.needsUpdate=u,h.pointLights.needsUpdate=u,h.pointLightShadows.needsUpdate=u,h.spotLights.needsUpdate=u,h.spotLightShadows.needsUpdate=u,h.rectAreaLights.needsUpdate=u,h.hemisphereLights.needsUpdate=u),r&&n.fog&&A.refreshFogUniforms(S,r),A.refreshMaterialUniforms(S,n,a,ee,$),void 0!==S.ltc_1&&(S.ltc_1.value=Kt.LTC_1),void 0!==S.ltc_2&&(S.ltc_2.value=Kt.LTC_2),fi.upload(m,s.uniformsList,S,b)),n.isShaderMaterial&&!0===n.uniformsNeedUpdate&&(fi.upload(m,s.uniformsList,S,b),n.uniformsNeedUpdate=!1),n.isSpriteMaterial&&w.setValue(m,"center",i.center),w.setValue(m,"modelViewMatrix",i.modelViewMatrix),w.setValue(m,"normalMatrix",i.normalMatrix),w.setValue(m,"modelMatrix",i.matrixWorld),y}we.setAnimationLoop((function(e){me.isPresenting||be&&be(e)})),"undefined"!=typeof window&&we.setContext(window),this.setAnimationLoop=function(e){be=e,me.setAnimationLoop(e),we.start()},this.render=function(e,t){var n,i;if(void 0!==arguments[2]&&(console.warn("THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead."),n=arguments[2]),void 0!==arguments[3]&&(console.warn("THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead."),i=arguments[3]),t&&t.isCamera){if(!F){j.geometry=null,j.program=null,j.wireframe=!1,W=-1,X=null,!0===e.autoUpdate&&e.updateMatrixWorld(),null===t.parent&&t.updateMatrixWorld(),me.enabled&&me.isPresenting&&(t=me.getCamera(t)),e.onBeforeRender(O,e,t,n||k),(f=C.get(e,t)).init(),he.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),oe.setFromProjectionMatrix(he),ce=this.localClippingEnabled,le=se.init(this.clippingPlanes,ce,t),(u=P.get(e,t)).init(),Se(e,t,0,O.sortObjects),u.finish(),!0===O.sortObjects&&u.sort(te,ne),le&&se.beginShadows();var r=f.state.shadowsArray;ge.render(r,e,t),f.setupLights(t),le&&se.endShadows(),this.info.autoReset&&this.info.reset(),void 0!==n&&this.setRenderTarget(n),N.render(u,e,t,i);var a=u.opaque,o=u.transparent;if(e.overrideMaterial){var s=e.overrideMaterial;a.length&&Ee(a,e,t,s),o.length&&Ee(o,e,t,s)}else a.length&&Ee(a,e,t),o.length&&Ee(o,e,t);e.onAfterRender(O,e,t),null!==k&&(b.updateRenderTargetMipmap(k),b.updateMultisampleRenderTarget(k)),_.buffers.depth.setTest(!0),_.buffers.depth.setMask(!0),_.buffers.color.setMask(!0),_.setPolygonOffset(!1),u=null,f=null}}else console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.")},this.setFramebuffer=function(e){G!==e&&null===k&&m.bindFramebuffer(36160,e),G=e},this.getActiveCubeFace=function(){return B},this.getActiveMipmapLevel=function(){return V},this.getRenderTarget=function(){return k},this.setRenderTarget=function(e,t,n){k=e,B=t,V=n,e&&void 0===M.get(e).__webglFramebuffer&&b.setupRenderTarget(e);var i=G,r=!1;if(e){var a=M.get(e).__webglFramebuffer;e.isWebGLCubeRenderTarget?(i=a[t||0],r=!0):i=e.isWebGLMultisampleRenderTarget?M.get(e).__webglMultisampledFramebuffer:a,Y.copy(e.viewport),Z.copy(e.scissor),Q=e.scissorTest}else Y.copy(ie).multiplyScalar(ee).floor(),Z.copy(re).multiplyScalar(ee).floor(),Q=ae;if(H!==i&&(m.bindFramebuffer(36160,i),H=i),_.viewport(Y),_.scissor(Z),_.setScissorTest(Q),r){var o=M.get(e.texture);m.framebufferTexture2D(36160,36064,34069+(t||0),o.__webglTexture,n||0)}},this.readRenderTargetPixels=function(e,t,n,i,r,a,o){if(e&&e.isWebGLRenderTarget){var s=M.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==o&&(s=s[o]),s){var l=!1;s!==H&&(m.bindFramebuffer(36160,s),l=!0);try{var c=e.texture,h=c.format,u=c.type;if(1023!==h&&z.convert(h)!==m.getParameter(35739))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!(1009===u||z.convert(u)===m.getParameter(35738)||1015===u&&(v.isWebGL2||g.get("OES_texture_float")||g.get("WEBGL_color_buffer_float"))||1016===u&&(v.isWebGL2?g.get("EXT_color_buffer_float"):g.get("EXT_color_buffer_half_float"))))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");36053===m.checkFramebufferStatus(36160)?t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r&&m.readPixels(t,n,i,r,z.convert(h),z.convert(u),a):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{l&&m.bindFramebuffer(36160,H)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")},this.copyFramebufferToTexture=function(e,t,n){void 0===n&&(n=0);var i=Math.pow(2,-n),r=Math.floor(t.image.width*i),a=Math.floor(t.image.height*i),o=z.convert(t.format);b.setTexture2D(t,0),m.copyTexImage2D(3553,n,o,e.x,e.y,r,a,0),_.unbindTexture()},this.copyTextureToTexture=function(e,t,n,i){void 0===i&&(i=0);var r=t.image.width,a=t.image.height,o=z.convert(n.format),s=z.convert(n.type);b.setTexture2D(n,0),t.isDataTexture?m.texSubImage2D(3553,i,e.x,e.y,r,a,o,s,t.image.data):t.isCompressedTexture?m.compressedTexSubImage2D(3553,i,e.x,e.y,t.mipmaps[0].width,t.mipmaps[0].height,o,t.mipmaps[0].data):m.texSubImage2D(3553,i,e.x,e.y,o,s,t.image),0===i&&n.generateMipmaps&&m.generateMipmap(3553),_.unbindTexture()},this.initTexture=function(e){b.setTexture2D(e,0),_.unbindTexture()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}function rr(e){this.autoStart=void 0===e||e,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}function ar(e,t,n){return this.radius=void 0!==e?e:1,this.phi=void 0!==t?t:0,this.theta=void 0!==n?n:0,this}function or(e,t,n,i,r,a){return[new p(e/r,1-i/a),new p(n/r,1-i/a),new p(n/r,1-t/a),new p(e/r,1-t/a)]}function sr(e,t,n,i){return or(e,t,n,i,64,64)}function lr(e,t,n,i){return or(e,t,n,i,64,32)}function cr(e,t,n,i,r,a,o){e.faceVertexUvs[0]=[],e.faceVertexUvs[0][0]=[a[3],a[0],a[2]],e.faceVertexUvs[0][1]=[a[0],a[1],a[2]],e.faceVertexUvs[0][2]=[i[3],i[0],i[2]],e.faceVertexUvs[0][3]=[i[0],i[1],i[2]],e.faceVertexUvs[0][4]=[t[3],t[0],t[2]],e.faceVertexUvs[0][5]=[t[0],t[1],t[2]],e.faceVertexUvs[0][6]=[n[0],n[3],n[1]],e.faceVertexUvs[0][7]=[n[3],n[2],n[1]],e.faceVertexUvs[0][8]=[r[3],r[0],r[2]],e.faceVertexUvs[0][9]=[r[0],r[1],r[2]],e.faceVertexUvs[0][10]=[o[3],o[0],o[2]],e.faceVertexUvs[0][11]=[o[0],o[1],o[2]]}Ki.prototype=Object.assign(Object.create(qt.prototype),{constructor:Ki,isArrayCamera:!0}),$i.prototype=Object.assign(Object.create(Z.prototype),{constructor:$i,isGroup:!0}),Object.assign(er.prototype,{constructor:er,getTargetRaySpace:function(){return null===this._targetRay&&(this._targetRay=new $i,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1),this._targetRay},getGripSpace:function(){return null===this._grip&&(this._grip=new $i,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1),this._grip},dispatchEvent:function(e){return null!==this._targetRay&&this._targetRay.dispatchEvent(e),null!==this._grip&&this._grip.dispatchEvent(e),this},disconnect:function(e){return this.dispatchEvent({type:"disconnected",data:e}),null!==this._targetRay&&(this._targetRay.visible=!1),null!==this._grip&&(this._grip.visible=!1),this},update:function(e,t,n){var i=null,r=null,a=this._targetRay,o=this._grip;return e&&(null!==a&&null!==(i=t.getPose(e.targetRaySpace,n))&&(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale)),null!==o&&e.gripSpace&&null!==(r=t.getPose(e.gripSpace,n))&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale))),null!==a&&(a.visible=null!==i),null!==o&&(o.visible=null!==r),this}}),Object.assign(tr.prototype,l.prototype),Object.assign(rr.prototype,{start:function(){this.startTime=("undefined"==typeof performance?Date:performance).now(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0},stop:function(){this.getElapsedTime(),this.running=!1,this.autoStart=!1},getElapsedTime:function(){return this.getDelta(),this.elapsedTime},getDelta:function(){var e=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){var t=("undefined"==typeof performance?Date:performance).now();e=(t-this.oldTime)/1e3,this.oldTime=t,this.elapsedTime+=e}return e}}),Object.assign(ar.prototype,{set:function(e,t,n){return this.radius=e,this.phi=t,this.theta=n,this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.radius=e.radius,this.phi=e.phi,this.theta=e.theta,this},makeSafe:function(){return this.phi=Math.max(1e-6,Math.min(Math.PI-1e-6,this.phi)),this},setFromVector3:function(e){return this.setFromCartesianCoords(e.x,e.y,e.z)},setFromCartesianCoords:function(e,t,n){return this.radius=Math.sqrt(e*e+t*t+n*n),0===this.radius?(this.theta=0,this.phi=0):(this.theta=Math.atan2(e,n),this.phi=Math.acos(d.clamp(t/this.radius,-1,1))),this}});class hr extends $i{constructor(e,t){super(),this.innerLayer=e,this.outerLayer=t,e.name="inner",t.name="outer"}}class ur extends $i{constructor(e){super(),this.modelListeners=[],this._slim=!1;const t={map:e,side:0},n={map:e,side:2,transparent:!0,opacity:1,alphaTest:.5},i=new qe(t),r=new qe(n),a=new Bt(8,8,8,0,0,0);cr(a,sr(8,0,16,8),sr(16,0,24,8),sr(0,8,8,16),sr(8,8,16,16),sr(16,8,24,16),sr(24,8,32,16));const o=new Nt(a,i),s=new Bt(9,9,9,0,0,0);cr(s,sr(40,0,48,8),sr(48,0,56,8),sr(32,8,40,16),sr(40,8,48,16),sr(48,8,56,16),sr(56,8,64,16));const l=new Nt(s,r);l.renderOrder=-1,this.head=new hr(o,l),this.head.name="head",this.head.add(o,l),this.add(this.head);const c=new Bt(8,12,4,0,0,0);cr(c,sr(20,16,28,20),sr(28,16,36,20),sr(16,20,20,32),sr(20,20,28,32),sr(28,20,32,32),sr(32,20,40,32));const h=new Nt(c,new qe(Object.assign(Object.assign({},t),{polygonOffset:!0,polygonOffsetUnits:-1}))),u=new Bt(9,13.5,4.5,0,0,0);cr(u,sr(20,32,28,36),sr(28,32,36,36),sr(16,36,20,48),sr(20,36,28,48),sr(28,36,32,48),sr(32,36,40,48));const d=new Nt(u,new qe(Object.assign(Object.assign({},n),{polygonOffset:!0,polygonOffsetUnits:-1})));this.body=new hr(h,d),this.body.name="body",this.body.add(h,d),this.body.position.y=-10,this.add(this.body);const p=new Bt(1,1,1,0,0,0),f=new Nt(p,i);this.modelListeners.push(()=>{f.scale.x=this.slim?3:4,f.scale.y=12,f.scale.z=4,this.slim?cr(p,sr(44,16,47,20),sr(47,16,50,20),sr(40,20,44,32),sr(44,20,47,32),sr(47,20,51,32),sr(51,20,54,32)):cr(p,sr(44,16,48,20),sr(48,16,52,20),sr(40,20,44,32),sr(44,20,48,32),sr(48,20,52,32),sr(52,20,56,32)),p.uvsNeedUpdate=!0,p.elementsNeedUpdate=!0});const m=new Bt(1,1,1,0,0,0),g=new Nt(m,r);g.renderOrder=1,this.modelListeners.push(()=>{g.scale.x=this.slim?3.375:4.5,g.scale.y=13.5,g.scale.z=4.5,this.slim?cr(m,sr(44,32,47,36),sr(47,32,50,36),sr(40,36,44,48),sr(44,36,47,48),sr(47,36,51,48),sr(51,36,54,48)):cr(m,sr(44,32,48,36),sr(48,32,52,36),sr(40,36,44,48),sr(44,36,48,48),sr(48,36,52,48),sr(52,36,56,48)),m.uvsNeedUpdate=!0,m.elementsNeedUpdate=!0});const v=new $i;v.add(f,g),v.position.y=-4,this.rightArm=new hr(f,g),this.rightArm.name="rightArm",this.rightArm.add(v),this.rightArm.position.y=-6,this.modelListeners.push(()=>{this.rightArm.position.x=this.slim?-5.5:-6}),this.add(this.rightArm);const x=new Bt(1,1,1,0,0,0),_=new Nt(x,i);this.modelListeners.push(()=>{_.scale.x=this.slim?3:4,_.scale.y=12,_.scale.z=4,this.slim?cr(x,sr(36,48,39,52),sr(39,48,42,52),sr(32,52,36,64),sr(36,52,39,64),sr(39,52,43,64),sr(43,52,46,64)):cr(x,sr(36,48,40,52),sr(40,48,44,52),sr(32,52,36,64),sr(36,52,40,64),sr(40,52,44,64),sr(44,52,48,64)),x.uvsNeedUpdate=!0,x.elementsNeedUpdate=!0});const y=new Bt(1,1,1,0,0,0),M=new Nt(y,r);M.renderOrder=1,this.modelListeners.push(()=>{M.scale.x=this.slim?3.375:4.5,M.scale.y=13.5,M.scale.z=4.5,this.slim?cr(y,sr(52,48,55,52),sr(55,48,58,52),sr(48,52,52,64),sr(52,52,55,64),sr(55,52,59,64),sr(59,52,62,64)):cr(y,sr(52,48,56,52),sr(56,48,60,52),sr(48,52,52,64),sr(52,52,56,64),sr(56,52,60,64),sr(60,52,64,64)),y.uvsNeedUpdate=!0,y.elementsNeedUpdate=!0});const b=new $i;b.add(_,M),b.position.y=-4,this.leftArm=new hr(_,M),this.leftArm.name="leftArm",this.leftArm.add(b),this.leftArm.position.y=-6,this.modelListeners.push(()=>{this.leftArm.position.x=this.slim?5.5:6}),this.add(this.leftArm);const w=new Bt(4,12,4,0,0,0);cr(w,sr(4,16,8,20),sr(8,16,12,20),sr(0,20,4,32),sr(4,20,8,32),sr(8,20,12,32),sr(12,20,16,32));const S=new Nt(w,i),E=new Bt(4.5,13.5,4.5,0,0,0);cr(E,sr(4,32,8,36),sr(8,32,12,36),sr(0,36,4,48),sr(4,36,8,48),sr(8,36,12,48),sr(12,36,16,48));const T=new Nt(E,r);T.renderOrder=1;const L=new $i;L.add(S,T),L.position.y=-6,this.rightLeg=new hr(S,T),this.rightLeg.name="rightLeg",this.rightLeg.add(L),this.rightLeg.position.y=-16,this.rightLeg.position.x=-2,this.add(this.rightLeg);const A=new Bt(4,12,4,0,0,0);cr(A,sr(20,48,24,52),sr(24,48,28,52),sr(16,52,20,64),sr(20,52,24,64),sr(24,52,28,64),sr(28,52,32,64));const P=new Nt(A,i),C=new Bt(4.5,13.5,4.5,0,0,0);cr(C,sr(4,48,8,52),sr(8,48,12,52),sr(0,52,4,64),sr(4,52,8,64),sr(8,52,12,64),sr(12,52,16,64));const D=new Nt(C,r);D.renderOrder=1;const N=new $i;N.add(P,D),N.position.y=-6,this.leftLeg=new hr(P,D),this.leftLeg.name="leftLeg",this.leftLeg.add(N),this.leftLeg.position.y=-16,this.leftLeg.position.x=2,this.add(this.leftLeg),this.slim=!1}get slim(){return this._slim}set slim(e){this._slim=e,this.modelListeners.forEach(e=>e())}getBodyParts(){return this.children.filter(e=>e instanceof hr)}setInnerLayerVisible(e){this.getBodyParts().forEach(t=>t.innerLayer.visible=e)}setOuterLayerVisible(e){this.getBodyParts().forEach(t=>t.outerLayer.visible=e)}}class dr extends $i{constructor(e){super();const t=new qe({map:e,transparent:!0,opacity:1,side:2,alphaTest:.5}),n=new Bt(10,16,1,0,0,0);cr(n,lr(1,0,11,1),lr(11,0,21,1),lr(11,1,12,17),lr(12,1,22,17),lr(0,1,1,17),lr(1,1,11,17)),this.cape=new Nt(n,t),this.cape.position.y=-8,this.cape.position.z=-.5,this.add(this.cape)}}class pr extends $i{constructor(e,t){super(),this.skin=new ur(e),this.skin.name="skin",this.add(this.skin),this.cape=new dr(t),this.cape.name="cape",this.cape.position.z=-2,this.cape.position.y=-4,this.cape.rotation.x=25*Math.PI/180,this.add(this.cape)}}function fr(e,t,n){e instanceof Function?e(t,n):e.play(t,n)}class mr{constructor(e){this.speed=1,this.paused=!1,this.progress=0,this.lastTime=0,this.started=!1,this.toResetAndRemove=!1,this.animation=e}play(e,t){if(this.toResetAndRemove)return fr(this.animation,e,0),void this.remove();let n;this.started?n=t-this.lastTime:(n=0,this.started=!0),this.lastTime=t,this.paused||(this.progress+=n*this.speed),fr(this.animation,e,this.progress)}reset(){this.progress=0}remove(){}resetAndRemove(){this.toResetAndRemove=!0}}class gr{constructor(){this.handles=new Set}add(e){const t=new mr(e);return t.remove=()=>{this.handles.delete(t)},this.handles.add(t),t}play(e,t){this.handles.forEach(n=>n.play(e,t))}}class vr extends gr{constructor(){super(...arguments),this.speed=1,this.progress=0,this.clock=new rr(!0)}get animation(){return this}get paused(){return!this.clock.running}set paused(e){e?this.clock.stop():this.clock.start()}runAnimationLoop(e){0!==this.handles.size&&(this.progress+=this.clock.getDelta()*this.speed,this.play(e,this.progress))}reset(){this.progress=0}}function xr(e,t,n,i,r){for(var a=e.getImageData(t,n,i,r),o=0;ob||8*(1-f.dot(m.object.quaternion))>b)&&(m.dispatchEvent(g),d.copy(m.object.position),f.copy(m.object.quaternion),A=!1,!0)}),this.dispose=function(){m.domElement.removeEventListener("contextmenu",ce,!1),m.domElement.removeEventListener("mousedown",te,!1),m.domElement.removeEventListener("wheel",re,!1),m.domElement.removeEventListener("touchstart",oe,!1),m.domElement.removeEventListener("touchend",le,!1),m.domElement.removeEventListener("touchmove",se,!1),document.removeEventListener("mousemove",ne,!1),document.removeEventListener("mouseup",ie,!1),m.domElement.removeEventListener("keydown",ae,!1)};var m=this,g={type:"change"},v={type:"start"},x={type:"end"},_={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_PAN:4,TOUCH_DOLLY_PAN:5,TOUCH_DOLLY_ROTATE:6},M=_.NONE,b=1e-6,S=new ar,E=new ar,T=1,L=new w,A=!1,P=new p,C=new p,D=new p,N=new p,R=new p,I=new p,U=new p,z=new p,O=new p;function F(){return Math.pow(.95,m.zoomSpeed)}function G(e){E.theta-=e}function B(e){E.phi-=e}var V,k=(V=new w,function(e,t){V.setFromMatrixColumn(t,0),V.multiplyScalar(-e),L.add(V)}),H=function(){var e=new w;return function(t,n){!0===m.screenSpacePanning?e.setFromMatrixColumn(n,1):(e.setFromMatrixColumn(n,0),e.crossVectors(m.object.up,e)),e.multiplyScalar(t),L.add(e)}}(),W=function(){var e=new w;return function(t,n){var i=m.domElement;if(m.object.isPerspectiveCamera){var r=m.object.position;e.copy(r).sub(m.target);var a=e.length();a*=Math.tan(m.object.fov/2*Math.PI/180),k(2*t*a/i.clientHeight,m.object.matrix),H(2*n*a/i.clientHeight,m.object.matrix)}else m.object.isOrthographicCamera?(k(t*(m.object.right-m.object.left)/m.object.zoom/i.clientWidth,m.object.matrix),H(n*(m.object.top-m.object.bottom)/m.object.zoom/i.clientHeight,m.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),m.enablePan=!1)}}();function j(e){m.object.isPerspectiveCamera?T/=e:m.object.isOrthographicCamera?(m.object.zoom=Math.max(m.minZoom,Math.min(m.maxZoom,m.object.zoom*e)),m.object.updateProjectionMatrix(),A=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),m.enableZoom=!1)}function X(e){m.object.isPerspectiveCamera?T*=e:m.object.isOrthographicCamera?(m.object.zoom=Math.max(m.minZoom,Math.min(m.maxZoom,m.object.zoom/e)),m.object.updateProjectionMatrix(),A=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),m.enableZoom=!1)}function q(e){P.set(e.clientX,e.clientY)}function Y(e){N.set(e.clientX,e.clientY)}function Z(e){if(1==e.touches.length)P.set(e.touches[0].pageX,e.touches[0].pageY);else{var t=.5*(e.touches[0].pageX+e.touches[1].pageX),n=.5*(e.touches[0].pageY+e.touches[1].pageY);P.set(t,n)}}function J(e){if(1==e.touches.length)N.set(e.touches[0].pageX,e.touches[0].pageY);else{var t=.5*(e.touches[0].pageX+e.touches[1].pageX),n=.5*(e.touches[0].pageY+e.touches[1].pageY);N.set(t,n)}}function Q(e){var t=e.touches[0].pageX-e.touches[1].pageX,n=e.touches[0].pageY-e.touches[1].pageY,i=Math.sqrt(t*t+n*n);U.set(0,i)}function K(e){if(1==e.touches.length)C.set(e.touches[0].pageX,e.touches[0].pageY);else{var t=.5*(e.touches[0].pageX+e.touches[1].pageX),n=.5*(e.touches[0].pageY+e.touches[1].pageY);C.set(t,n)}D.subVectors(C,P).multiplyScalar(m.rotateSpeed);var i=m.domElement;G(2*Math.PI*D.x/i.clientHeight),B(2*Math.PI*D.y/i.clientHeight),P.copy(C)}function $(e){if(1==e.touches.length)R.set(e.touches[0].pageX,e.touches[0].pageY);else{var t=.5*(e.touches[0].pageX+e.touches[1].pageX),n=.5*(e.touches[0].pageY+e.touches[1].pageY);R.set(t,n)}I.subVectors(R,N).multiplyScalar(m.panSpeed),W(I.x,I.y),N.copy(R)}function ee(e){var t=e.touches[0].pageX-e.touches[1].pageX,n=e.touches[0].pageY-e.touches[1].pageY,i=Math.sqrt(t*t+n*n);z.set(0,i),O.set(0,Math.pow(z.y/U.y,m.zoomSpeed)),j(O.y),U.copy(z)}function te(e){if(!1!==m.enabled){var r;switch(e.preventDefault(),m.domElement.focus?m.domElement.focus():window.focus(),e.button){case 0:r=m.mouseButtons.LEFT;break;case 1:r=m.mouseButtons.MIDDLE;break;case 2:r=m.mouseButtons.RIGHT;break;default:r=-1}switch(r){case n:if(!1===m.enableZoom)return;!function(e){U.set(e.clientX,e.clientY)}(e),M=_.DOLLY;break;case t:if(e.ctrlKey||e.metaKey||e.shiftKey){if(!1===m.enablePan)return;Y(e),M=_.PAN}else{if(!1===m.enableRotate)return;q(e),M=_.ROTATE}break;case i:if(e.ctrlKey||e.metaKey||e.shiftKey){if(!1===m.enableRotate)return;q(e),M=_.ROTATE}else{if(!1===m.enablePan)return;Y(e),M=_.PAN}break;default:M=_.NONE}M!==_.NONE&&(document.addEventListener("mousemove",ne,!1),document.addEventListener("mouseup",ie,!1),m.dispatchEvent(v))}}function ne(e){if(!1!==m.enabled)switch(e.preventDefault(),M){case _.ROTATE:if(!1===m.enableRotate)return;!function(e){C.set(e.clientX,e.clientY),D.subVectors(C,P).multiplyScalar(m.rotateSpeed);var t=m.domElement;G(2*Math.PI*D.x/t.clientHeight),B(2*Math.PI*D.y/t.clientHeight),P.copy(C),m.update()}(e);break;case _.DOLLY:if(!1===m.enableZoom)return;!function(e){z.set(e.clientX,e.clientY),O.subVectors(z,U),O.y>0?j(F()):O.y<0&&X(F()),U.copy(z),m.update()}(e);break;case _.PAN:if(!1===m.enablePan)return;!function(e){R.set(e.clientX,e.clientY),I.subVectors(R,N).multiplyScalar(m.panSpeed),W(I.x,I.y),N.copy(R),m.update()}(e)}}function ie(e){!1!==m.enabled&&(document.removeEventListener("mousemove",ne,!1),document.removeEventListener("mouseup",ie,!1),m.dispatchEvent(x),M=_.NONE)}function re(e){!1===m.enabled||!1===m.enableZoom||M!==_.NONE&&M!==_.ROTATE||(e.preventDefault(),e.stopPropagation(),m.dispatchEvent(v),function(e){e.deltaY<0?X(F()):e.deltaY>0&&j(F()),m.update()}(e),m.dispatchEvent(x))}function ae(e){!1!==m.enabled&&!1!==m.enableKeys&&!1!==m.enablePan&&function(e){var t=!1;switch(e.keyCode){case m.keys.UP:W(0,m.keyPanSpeed),t=!0;break;case m.keys.BOTTOM:W(0,-m.keyPanSpeed),t=!0;break;case m.keys.LEFT:W(m.keyPanSpeed,0),t=!0;break;case m.keys.RIGHT:W(-m.keyPanSpeed,0),t=!0}t&&(e.preventDefault(),m.update())}(e)}function oe(e){if(!1!==m.enabled){switch(e.preventDefault(),e.touches.length){case 1:switch(m.touches.ONE){case r:if(!1===m.enableRotate)return;Z(e),M=_.TOUCH_ROTATE;break;case a:if(!1===m.enablePan)return;J(e),M=_.TOUCH_PAN;break;default:M=_.NONE}break;case 2:switch(m.touches.TWO){case o:if(!1===m.enableZoom&&!1===m.enablePan)return;!function(e){m.enableZoom&&Q(e),m.enablePan&&J(e)}(e),M=_.TOUCH_DOLLY_PAN;break;case s:if(!1===m.enableZoom&&!1===m.enableRotate)return;!function(e){m.enableZoom&&Q(e),m.enableRotate&&Z(e)}(e),M=_.TOUCH_DOLLY_ROTATE;break;default:M=_.NONE}break;default:M=_.NONE}M!==_.NONE&&m.dispatchEvent(v)}}function se(e){if(!1!==m.enabled)switch(e.preventDefault(),e.stopPropagation(),M){case _.TOUCH_ROTATE:if(!1===m.enableRotate)return;K(e),m.update();break;case _.TOUCH_PAN:if(!1===m.enablePan)return;$(e),m.update();break;case _.TOUCH_DOLLY_PAN:if(!1===m.enableZoom&&!1===m.enablePan)return;!function(e){m.enableZoom&&ee(e),m.enablePan&&$(e)}(e),m.update();break;case _.TOUCH_DOLLY_ROTATE:if(!1===m.enableZoom&&!1===m.enableRotate)return;!function(e){m.enableZoom&&ee(e),m.enableRotate&&K(e)}(e),m.update();break;default:M=_.NONE}}function le(e){!1!==m.enabled&&(m.dispatchEvent(x),M=_.NONE)}function ce(e){!1!==m.enabled&&e.preventDefault()}m.domElement.addEventListener("contextmenu",ce,!1),m.domElement.addEventListener("mousedown",te,!1),m.domElement.addEventListener("wheel",re,!1),m.domElement.addEventListener("touchstart",oe,!1),m.domElement.addEventListener("touchend",le,!1),m.domElement.addEventListener("touchmove",se,!1),m.domElement.addEventListener("keydown",ae,!1),-1===m.domElement.tabIndex&&(m.domElement.tabIndex=0),this.update()};(Mr.prototype=Object.create(l.prototype)).constructor=Mr;var br=function(e,n){Mr.call(this,e,n),this.mouseButtons.LEFT=i,this.mouseButtons.RIGHT=t,this.touches.ONE=a,this.touches.TWO=s};(br.prototype=Object.create(l.prototype)).constructor=br,e.BodyPart=hr,e.CapeObject=dr,e.CompositeAnimation=gr,e.PlayerObject=pr,e.RootAnimation=vr,e.RotatingAnimation=(e,t)=>{e.rotation.y=t},e.RunningAnimation=(e,t)=>{const n=e.skin;t*=15,n.leftLeg.rotation.x=1.3*Math.cos(t+Math.PI),n.rightLeg.rotation.x=1.3*Math.cos(t),n.leftArm.rotation.x=1.5*Math.cos(t),n.rightArm.rotation.x=1.5*Math.cos(t+Math.PI);const i=.1*Math.PI;n.leftArm.rotation.z=.1*Math.cos(t)+i,n.rightArm.rotation.z=.1*Math.cos(t+Math.PI)-i,e.position.y=Math.cos(2*t),e.position.x=.15*Math.cos(t),e.rotation.z=.01*Math.cos(t+Math.PI);const r=.3*Math.PI;e.cape.rotation.x=.1*Math.sin(2*t)+r},e.SkinObject=ur,e.SkinViewer=class{constructor(e){this.animations=new vr,this.detectModel=!0,this._disposed=!1,this._renderPaused=!1,this._skinSet=!1,this._capeSet=!1,this.domElement=e.domElement,!1===e.detectModel&&(this.detectModel=!1),this.skinImg=new Image,this.skinCanvas=document.createElement("canvas"),this.skinTexture=new v(this.skinCanvas),this.skinTexture.magFilter=1003,this.skinTexture.minFilter=1003,this.capeImg=new Image,this.capeCanvas=document.createElement("canvas"),this.capeTexture=new v(this.capeCanvas),this.capeTexture.magFilter=1003,this.capeTexture.minFilter=1003,this.scene=new J,this.camera=new qt(40),this.camera.position.y=-12,this.camera.position.z=60,this.renderer=new ir({alpha:!0}),this.domElement.appendChild(this.renderer.domElement),this.playerObject=new pr(this.skinTexture,this.capeTexture),this.playerObject.name="player",this.playerObject.skin.visible=!1,this.playerObject.cape.visible=!1,this.scene.add(this.playerObject),this.skinImg.crossOrigin="anonymous",this.skinImg.onerror=()=>console.error("Failed loading "+this.skinImg.src),this.skinImg.onload=()=>{var e,t,n,i;!function(e,t){var n=!1;if(t.width!==t.height){if(t.width!==2*t.height)throw new Error("Bad skin size: "+t.width+"x"+t.height);n=!0}var i=e.getContext("2d");if(n){var r=t.width;e.width=r,e.height=r,i.clearRect(0,0,r,r),i.drawImage(t,0,0,r,r/2),yr(i,r)}else e.width=t.width,e.height=t.height,i.clearRect(0,0,t.width,t.height),i.drawImage(t,0,0,e.width,e.height)}(this.skinCanvas,this.skinImg),this.detectModel&&(this.playerObject.skin.slim=(e=this.skinCanvas,t=_r(e.width),n=e.getContext("2d"),(i=function(e,i,r,a){return xr(n,e*t,i*t,r*t,a*t)})(50,16,2,4)||i(54,20,2,12)||i(42,48,2,4)||i(46,52,2,12))),this.skinTexture.needsUpdate=!0,this.playerObject.skin.visible=!0},this.capeImg.crossOrigin="anonymous",this.capeImg.onerror=()=>console.error("Failed loading "+this.capeImg.src),this.capeImg.onload=()=>{!function(e,t){var n=!1;if(t.width!==2*t.height){if(17*t.width!=22*t.height)throw new Error("Bad cape size: "+t.width+"x"+t.height);n=!0}var i=e.getContext("2d");if(n){var r=64*t.width/22;e.width=r,e.height=r/2}else e.width=t.width,e.height=t.height;i.clearRect(0,0,e.width,e.height),i.drawImage(t,0,0,t.width,t.height)}(this.capeCanvas,this.capeImg),this.capeTexture.needsUpdate=!0,this.playerObject.cape.visible=!0},void 0!==e.skinUrl&&(this.skinUrl=e.skinUrl),void 0!==e.capeUrl&&(this.capeUrl=e.capeUrl),this.width=void 0===e.width?300:e.width,this.height=void 0===e.height?300:e.height,window.requestAnimationFrame(()=>this.draw())}draw(){this.disposed||this._renderPaused||(this.animations.runAnimationLoop(this.playerObject),this.doRender(),window.requestAnimationFrame(()=>this.draw()))}doRender(){this.renderer.render(this.scene,this.camera)}setSize(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t)}dispose(){this._disposed=!0,this.domElement.removeChild(this.renderer.domElement),this.renderer.dispose(),this.skinTexture.dispose(),this.capeTexture.dispose()}get disposed(){return this._disposed}get renderPaused(){return this._renderPaused}set renderPaused(e){const t=!this.disposed&&!e&&this._renderPaused;this._renderPaused=e,t&&window.requestAnimationFrame(()=>this.draw())}get skinUrl(){return this._skinSet?this.skinImg.src:null}set skinUrl(e){null===e?(this._skinSet=!1,this.playerObject.skin.visible=!1):(this._skinSet=!0,this.skinImg.src=e)}get capeUrl(){return this._capeSet?this.capeImg.src:null}set capeUrl(e){null===e?(this._capeSet=!1,this.playerObject.cape.visible=!1):(this._capeSet=!0,this.capeImg.src=e)}get width(){return this.renderer.getSize(new p).width}set width(e){this.setSize(e,this.height)}get height(){return this.renderer.getSize(new p).height}set height(e){this.setSize(this.width,e)}},e.WalkingAnimation=(e,t)=>{const n=e.skin;t*=8,n.leftLeg.rotation.x=.5*Math.sin(t),n.rightLeg.rotation.x=.5*Math.sin(t+Math.PI),n.leftArm.rotation.x=.5*Math.sin(t+Math.PI),n.rightArm.rotation.x=.5*Math.sin(t);const i=.02*Math.PI;n.leftArm.rotation.z=.03*Math.cos(t)+i,n.rightArm.rotation.z=.03*Math.cos(t+Math.PI)-i,n.head.rotation.y=.2*Math.sin(t/4),n.head.rotation.x=.1*Math.sin(t/5);const r=.06*Math.PI;e.cape.rotation.x=.06*Math.sin(t/1.5)+r},e.createOrbitControls=function(e){const t=new Mr(e.camera,e.renderer.domElement);return t.enablePan=!1,t.target=new w(0,-12,0),t.minDistance=10,t.maxDistance=256,t.update(),t},e.invokeAnimation=fr,Object.defineProperty(e,"__esModule",{value:!0})}));//# sourceMappingURL=skinview3d.bundle.js.map +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).skinview3d={})}(this,(function(e){"use strict";const t=0,n=1,i=2,r=0,a=1,o=2,s=3;function l(){}Object.assign(l.prototype,{addEventListener:function(e,t){void 0===this._listeners&&(this._listeners={});var n=this._listeners;void 0===n[e]&&(n[e]=[]),-1===n[e].indexOf(t)&&n[e].push(t)},hasEventListener:function(e,t){if(void 0===this._listeners)return!1;var n=this._listeners;return void 0!==n[e]&&-1!==n[e].indexOf(t)},removeEventListener:function(e,t){if(void 0!==this._listeners){var n=this._listeners[e];if(void 0!==n){var i=n.indexOf(t);-1!==i&&n.splice(i,1)}}},dispatchEvent:function(e){if(void 0!==this._listeners){var t=this._listeners[e.type];if(void 0!==t){e.target=this;for(var n=t.slice(0),i=0,r=n.length;i>8&255]+c[e>>16&255]+c[e>>24&255]+"-"+c[255&t]+c[t>>8&255]+"-"+c[t>>16&15|64]+c[t>>24&255]+"-"+c[63&n|128]+c[n>>8&255]+"-"+c[n>>16&255]+c[n>>24&255]+c[255&i]+c[i>>8&255]+c[i>>16&255]+c[i>>24&255]).toUpperCase()},clamp:function(e,t,n){return Math.max(t,Math.min(n,e))},euclideanModulo:function(e,t){return(e%t+t)%t},mapLinear:function(e,t,n,i,r){return i+(e-t)*(r-i)/(n-t)},lerp:function(e,t,n){return(1-n)*e+n*t},smoothstep:function(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t))*e*(3-2*e)},smootherstep:function(e,t,n){return e<=t?0:e>=n?1:(e=(e-t)/(n-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},degToRad:function(e){return e*d.DEG2RAD},radToDeg:function(e){return e*d.RAD2DEG},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))},setQuaternionFromProperEuler:function(e,t,n,i,r){var a=Math.cos,o=Math.sin,s=a(n/2),l=o(n/2),c=a((t+i)/2),h=o((t+i)/2),u=a((t-i)/2),d=o((t-i)/2),p=a((i-t)/2),f=o((i-t)/2);switch(r){case"XYX":e.set(s*h,l*u,l*d,s*c);break;case"YZY":e.set(l*d,s*h,l*u,s*c);break;case"ZXZ":e.set(l*u,l*d,s*h,s*c);break;case"XZX":e.set(s*h,l*f,l*p,s*c);break;case"YXY":e.set(l*p,s*h,l*f,s*c);break;case"ZYZ":e.set(l*f,l*p,s*h,s*c);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}}};function p(e,t){this.x=e||0,this.y=t||0}function f(){this.elements=[1,0,0,0,1,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.")}Object.defineProperties(p.prototype,{width:{get:function(){return this.x},set:function(e){this.x=e}},height:{get:function(){return this.y},set:function(e){this.y=e}}}),Object.assign(p.prototype,{isVector2:!0,set:function(e,t){return this.x=e,this.y=t,this},setScalar:function(e){return this.x=e,this.y=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y)},copy:function(e){return this.x=e.x,this.y=e.y,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this)},addScalar:function(e){return this.x+=e,this.y+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this)},subScalar:function(e){return this.x-=e,this.y-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this},multiply:function(e){return this.x*=e.x,this.y*=e.y,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this},divide:function(e){return this.x/=e.x,this.y/=e.y,this},divideScalar:function(e){return this.multiplyScalar(1/e)},applyMatrix3:function(e){var t=this.x,n=this.y,i=e.elements;return this.x=i[0]*t+i[3]*n+i[6],this.y=i[1]*t+i[4]*n+i[7],this},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this},clampScalar:function(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this},clampLength:function(e,t){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this},negate:function(){return this.x=-this.x,this.y=-this.y,this},dot:function(e){return this.x*e.x+this.y*e.y},cross:function(e){return this.x*e.y-this.y*e.x},lengthSq:function(){return this.x*this.x+this.y*this.y},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)},normalize:function(){return this.divideScalar(this.length()||1)},angle:function(){return Math.atan2(-this.y,-this.x)+Math.PI},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,n=this.y-e.y;return t*t+n*n},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this},lerpVectors:function(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this},equals:function(e){return e.x===this.x&&e.y===this.y},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e},fromBufferAttribute:function(e,t,n){return void 0!==n&&console.warn("THREE.Vector2: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this},rotateAround:function(e,t){var n=Math.cos(t),i=Math.sin(t),r=this.x-e.x,a=this.y-e.y;return this.x=r*n-a*i+e.x,this.y=r*i+a*n+e.y,this},random:function(){return this.x=Math.random(),this.y=Math.random(),this}}),Object.assign(f.prototype,{isMatrix3:!0,set:function(e,t,n,i,r,a,o,s,l){var c=this.elements;return c[0]=e,c[1]=i,c[2]=o,c[3]=t,c[4]=r,c[5]=s,c[6]=n,c[7]=a,c[8]=l,this},identity:function(){return this.set(1,0,0,0,1,0,0,0,1),this},clone:function(){return(new this.constructor).fromArray(this.elements)},copy:function(e){var t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],this},extractBasis:function(e,t,n){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),n.setFromMatrix3Column(this,2),this},setFromMatrix4:function(e){var t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this},multiply:function(e){return this.multiplyMatrices(this,e)},premultiply:function(e){return this.multiplyMatrices(e,this)},multiplyMatrices:function(e,t){var n=e.elements,i=t.elements,r=this.elements,a=n[0],o=n[3],s=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],f=i[0],m=i[3],g=i[6],v=i[1],x=i[4],_=i[7],y=i[2],M=i[5],b=i[8];return r[0]=a*f+o*v+s*y,r[3]=a*m+o*x+s*M,r[6]=a*g+o*_+s*b,r[1]=l*f+c*v+h*y,r[4]=l*m+c*x+h*M,r[7]=l*g+c*_+h*b,r[2]=u*f+d*v+p*y,r[5]=u*m+d*x+p*M,r[8]=u*g+d*_+p*b,this},multiplyScalar:function(e){var t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this},determinant:function(){var e=this.elements,t=e[0],n=e[1],i=e[2],r=e[3],a=e[4],o=e[5],s=e[6],l=e[7],c=e[8];return t*a*c-t*o*l-n*r*c+n*o*s+i*r*l-i*a*s},getInverse:function(e,t){void 0!==t&&console.warn("THREE.Matrix3: .getInverse() can no longer be configured to throw on degenerate.");var n=e.elements,i=this.elements,r=n[0],a=n[1],o=n[2],s=n[3],l=n[4],c=n[5],h=n[6],u=n[7],d=n[8],p=d*l-c*u,f=c*h-d*s,m=u*s-l*h,g=r*p+a*f+o*m;if(0===g)return this.set(0,0,0,0,0,0,0,0,0);var v=1/g;return i[0]=p*v,i[1]=(o*u-d*a)*v,i[2]=(c*a-o*l)*v,i[3]=f*v,i[4]=(d*r-o*h)*v,i[5]=(o*s-c*r)*v,i[6]=m*v,i[7]=(a*h-u*r)*v,i[8]=(l*r-a*s)*v,this},transpose:function(){var e,t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this},getNormalMatrix:function(e){return this.setFromMatrix4(e).getInverse(this).transpose()},transposeIntoArray:function(e){var t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this},setUvTransform:function(e,t,n,i,r,a,o){var s=Math.cos(r),l=Math.sin(r);this.set(n*s,n*l,-n*(s*a+l*o)+a+e,-i*l,i*s,-i*(-l*a+s*o)+o+t,0,0,1)},scale:function(e,t){var n=this.elements;return n[0]*=e,n[3]*=e,n[6]*=e,n[1]*=t,n[4]*=t,n[7]*=t,this},rotate:function(e){var t=Math.cos(e),n=Math.sin(e),i=this.elements,r=i[0],a=i[3],o=i[6],s=i[1],l=i[4],c=i[7];return i[0]=t*r+n*s,i[3]=t*a+n*l,i[6]=t*o+n*c,i[1]=-n*r+t*s,i[4]=-n*a+t*l,i[7]=-n*o+t*c,this},translate:function(e,t){var n=this.elements;return n[0]+=e*n[2],n[3]+=e*n[5],n[6]+=e*n[8],n[1]+=t*n[2],n[4]+=t*n[5],n[7]+=t*n[8],this},equals:function(e){for(var t=this.elements,n=e.elements,i=0;i<9;i++)if(t[i]!==n[i])return!1;return!0},fromArray:function(e,t){void 0===t&&(t=0);for(var n=0;n<9;n++)this.elements[n]=e[n+t];return this},toArray:function(e,t){void 0===e&&(e=[]),void 0===t&&(t=0);var n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e}});var m=function(e){var t;if("undefined"==typeof HTMLCanvasElement)return e.src;if(e instanceof HTMLCanvasElement)t=e;else{void 0===u&&(u=document.createElementNS("http://www.w3.org/1999/xhtml","canvas")),u.width=e.width,u.height=e.height;var n=u.getContext("2d");e instanceof ImageData?n.putImageData(e,0,0):n.drawImage(e,0,0,e.width,e.height),t=u}return t.width>2048||t.height>2048?t.toDataURL("image/jpeg",.6):t.toDataURL("image/png")},g=0;function v(e,t,n,i,r,a,o,s,l,c){Object.defineProperty(this,"id",{value:g++}),this.uuid=d.generateUUID(),this.name="",this.image=void 0!==e?e:v.DEFAULT_IMAGE,this.mipmaps=[],this.mapping=void 0!==t?t:v.DEFAULT_MAPPING,this.wrapS=void 0!==n?n:1001,this.wrapT=void 0!==i?i:1001,this.magFilter=void 0!==r?r:1006,this.minFilter=void 0!==a?a:1008,this.anisotropy=void 0!==l?l:1,this.format=void 0!==o?o:1023,this.internalFormat=null,this.type=void 0!==s?s:1009,this.offset=new p(0,0),this.repeat=new p(1,1),this.center=new p(0,0),this.rotation=0,this.matrixAutoUpdate=!0,this.matrix=new f,this.generateMipmaps=!0,this.premultiplyAlpha=!1,this.flipY=!0,this.unpackAlignment=4,this.encoding=void 0!==c?c:3e3,this.version=0,this.onUpdate=null}function x(e,t,n,i){this.x=e||0,this.y=t||0,this.z=n||0,this.w=void 0!==i?i:1}function _(e,t,n){this.width=e,this.height=t,this.scissor=new x(0,0,e,t),this.scissorTest=!1,this.viewport=new x(0,0,e,t),n=n||{},this.texture=new v(void 0,n.mapping,n.wrapS,n.wrapT,n.magFilter,n.minFilter,n.format,n.type,n.anisotropy,n.encoding),this.texture.image={},this.texture.image.width=e,this.texture.image.height=t,this.texture.generateMipmaps=void 0!==n.generateMipmaps&&n.generateMipmaps,this.texture.minFilter=void 0!==n.minFilter?n.minFilter:1006,this.depthBuffer=void 0===n.depthBuffer||n.depthBuffer,this.stencilBuffer=void 0===n.stencilBuffer||n.stencilBuffer,this.depthTexture=void 0!==n.depthTexture?n.depthTexture:null}function y(e,t,n,i){this._x=e||0,this._y=t||0,this._z=n||0,this._w=void 0!==i?i:1}v.DEFAULT_IMAGE=void 0,v.DEFAULT_MAPPING=300,v.prototype=Object.assign(Object.create(l.prototype),{constructor:v,isTexture:!0,updateMatrix:function(){this.matrix.setUvTransform(this.offset.x,this.offset.y,this.repeat.x,this.repeat.y,this.rotation,this.center.x,this.center.y)},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.name=e.name,this.image=e.image,this.mipmaps=e.mipmaps.slice(0),this.mapping=e.mapping,this.wrapS=e.wrapS,this.wrapT=e.wrapT,this.magFilter=e.magFilter,this.minFilter=e.minFilter,this.anisotropy=e.anisotropy,this.format=e.format,this.internalFormat=e.internalFormat,this.type=e.type,this.offset.copy(e.offset),this.repeat.copy(e.repeat),this.center.copy(e.center),this.rotation=e.rotation,this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrix.copy(e.matrix),this.generateMipmaps=e.generateMipmaps,this.premultiplyAlpha=e.premultiplyAlpha,this.flipY=e.flipY,this.unpackAlignment=e.unpackAlignment,this.encoding=e.encoding,this},toJSON:function(e){var t=void 0===e||"string"==typeof e;if(!t&&void 0!==e.textures[this.uuid])return e.textures[this.uuid];var n={metadata:{version:4.5,type:"Texture",generator:"Texture.toJSON"},uuid:this.uuid,name:this.name,mapping:this.mapping,repeat:[this.repeat.x,this.repeat.y],offset:[this.offset.x,this.offset.y],center:[this.center.x,this.center.y],rotation:this.rotation,wrap:[this.wrapS,this.wrapT],format:this.format,type:this.type,encoding:this.encoding,minFilter:this.minFilter,magFilter:this.magFilter,anisotropy:this.anisotropy,flipY:this.flipY,premultiplyAlpha:this.premultiplyAlpha,unpackAlignment:this.unpackAlignment};if(void 0!==this.image){var i=this.image;if(void 0===i.uuid&&(i.uuid=d.generateUUID()),!t&&void 0===e.images[i.uuid]){var r;if(Array.isArray(i)){r=[];for(var a=0,o=i.length;a1)switch(this.wrapS){case 1e3:e.x=e.x-Math.floor(e.x);break;case 1001:e.x=e.x<0?0:1;break;case 1002:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case 1e3:e.y=e.y-Math.floor(e.y);break;case 1001:e.y=e.y<0?0:1;break;case 1002:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}return this.flipY&&(e.y=1-e.y),e}}),Object.defineProperty(v.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),Object.defineProperties(x.prototype,{width:{get:function(){return this.z},set:function(e){this.z=e}},height:{get:function(){return this.w},set:function(e){this.w=e}}}),Object.assign(x.prototype,{isVector4:!0,set:function(e,t,n,i){return this.x=e,this.y=t,this.z=n,this.w=i,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this.w=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setW:function(e){return this.w=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;case 3:return this.w;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z,this.w)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this},applyMatrix4:function(e){var t=this.x,n=this.y,i=this.z,r=this.w,a=e.elements;return this.x=a[0]*t+a[4]*n+a[8]*i+a[12]*r,this.y=a[1]*t+a[5]*n+a[9]*i+a[13]*r,this.z=a[2]*t+a[6]*n+a[10]*i+a[14]*r,this.w=a[3]*t+a[7]*n+a[11]*i+a[15]*r,this},divideScalar:function(e){return this.multiplyScalar(1/e)},setAxisAngleFromQuaternion:function(e){this.w=2*Math.acos(e.w);var t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this},setAxisAngleFromRotationMatrix:function(e){var t,n,i,r,a=e.elements,o=a[0],s=a[4],l=a[8],c=a[1],h=a[5],u=a[9],d=a[2],p=a[6],f=a[10];if(Math.abs(s-c)<.01&&Math.abs(l-d)<.01&&Math.abs(u-p)<.01){if(Math.abs(s+c)<.1&&Math.abs(l+d)<.1&&Math.abs(u+p)<.1&&Math.abs(o+h+f-3)<.1)return this.set(1,0,0,0),this;t=Math.PI;var m=(o+1)/2,g=(h+1)/2,v=(f+1)/2,x=(s+c)/4,_=(l+d)/4,y=(u+p)/4;return m>g&&m>v?m<.01?(n=0,i=.707106781,r=.707106781):(i=x/(n=Math.sqrt(m)),r=_/n):g>v?g<.01?(n=.707106781,i=0,r=.707106781):(n=x/(i=Math.sqrt(g)),r=y/i):v<.01?(n=.707106781,i=.707106781,r=0):(n=_/(r=Math.sqrt(v)),i=y/r),this.set(n,i,r,t),this}var M=Math.sqrt((p-u)*(p-u)+(l-d)*(l-d)+(c-s)*(c-s));return Math.abs(M)<.001&&(M=1),this.x=(p-u)/M,this.y=(l-d)/M,this.z=(c-s)/M,this.w=Math.acos((o+h+f-1)/2),this},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this.w=Math.min(this.w,e.w),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this.w=Math.max(this.w,e.w),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this.w=Math.max(e.w,Math.min(t.w,this.w)),this},clampScalar:function(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this.w=Math.max(e,Math.min(t,this.w)),this},clampLength:function(e,t){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this.w=Math.floor(this.w),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this.w=Math.ceil(this.w),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this.w=Math.round(this.w),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this.w=this.w<0?Math.ceil(this.w):Math.floor(this.w),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this.w=-this.w,this},dot:function(e){return this.x*e.x+this.y*e.y+this.z*e.z+this.w*e.w},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)+Math.abs(this.w)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this.w+=(e.w-this.w)*t,this},lerpVectors:function(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this.w=e.w+(t.w-e.w)*n,this},equals:function(e){return e.x===this.x&&e.y===this.y&&e.z===this.z&&e.w===this.w},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this.z=e[t+2],this.w=e[t+3],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e[t+3]=this.w,e},fromBufferAttribute:function(e,t,n){return void 0!==n&&console.warn("THREE.Vector4: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this.w=e.getW(t),this},random:function(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this.w=Math.random(),this}}),_.prototype=Object.assign(Object.create(l.prototype),{constructor:_,isWebGLRenderTarget:!0,setSize:function(e,t){this.width===e&&this.height===t||(this.width=e,this.height=t,this.texture.image.width=e,this.texture.image.height=t,this.dispose()),this.viewport.set(0,0,e,t),this.scissor.set(0,0,e,t)},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.width=e.width,this.height=e.height,this.viewport.copy(e.viewport),this.texture=e.texture.clone(),this.depthBuffer=e.depthBuffer,this.stencilBuffer=e.stencilBuffer,this.depthTexture=e.depthTexture,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),Object.assign(y,{slerp:function(e,t,n,i){return n.copy(e).slerp(t,i)},slerpFlat:function(e,t,n,i,r,a,o){var s=n[i+0],l=n[i+1],c=n[i+2],h=n[i+3],u=r[a+0],d=r[a+1],p=r[a+2],f=r[a+3];if(h!==f||s!==u||l!==d||c!==p){var m=1-o,g=s*u+l*d+c*p+h*f,v=g>=0?1:-1,x=1-g*g;if(x>Number.EPSILON){var _=Math.sqrt(x),y=Math.atan2(_,g*v);m=Math.sin(m*y)/_,o=Math.sin(o*y)/_}var M=o*v;if(s=s*m+u*M,l=l*m+d*M,c=c*m+p*M,h=h*m+f*M,m===1-o){var b=1/Math.sqrt(s*s+l*l+c*c+h*h);s*=b,l*=b,c*=b,h*=b}}e[t]=s,e[t+1]=l,e[t+2]=c,e[t+3]=h},multiplyQuaternionsFlat:function(e,t,n,i,r,a){var o=n[i],s=n[i+1],l=n[i+2],c=n[i+3],h=r[a],u=r[a+1],d=r[a+2],p=r[a+3];return e[t]=o*p+c*h+s*d-l*u,e[t+1]=s*p+c*u+l*h-o*d,e[t+2]=l*p+c*d+o*u-s*h,e[t+3]=c*p-o*h-s*u-l*d,e}}),Object.defineProperties(y.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this._onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this._onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this._onChangeCallback()}},w:{get:function(){return this._w},set:function(e){this._w=e,this._onChangeCallback()}}}),Object.assign(y.prototype,{isQuaternion:!0,set:function(e,t,n,i){return this._x=e,this._y=t,this._z=n,this._w=i,this._onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._w)},copy:function(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this},setFromEuler:function(e,t){if(!e||!e.isEuler)throw new Error("THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.");var n=e._x,i=e._y,r=e._z,a=e.order,o=Math.cos,s=Math.sin,l=o(n/2),c=o(i/2),h=o(r/2),u=s(n/2),d=s(i/2),p=s(r/2);switch(a){case"XYZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"YXZ":this._x=u*c*h+l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"ZXY":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h-u*d*p;break;case"ZYX":this._x=u*c*h-l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h+u*d*p;break;case"YZX":this._x=u*c*h+l*d*p,this._y=l*d*h+u*c*p,this._z=l*c*p-u*d*h,this._w=l*c*h-u*d*p;break;case"XZY":this._x=u*c*h-l*d*p,this._y=l*d*h-u*c*p,this._z=l*c*p+u*d*h,this._w=l*c*h+u*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+a)}return!1!==t&&this._onChangeCallback(),this},setFromAxisAngle:function(e,t){var n=t/2,i=Math.sin(n);return this._x=e.x*i,this._y=e.y*i,this._z=e.z*i,this._w=Math.cos(n),this._onChangeCallback(),this},setFromRotationMatrix:function(e){var t,n=e.elements,i=n[0],r=n[4],a=n[8],o=n[1],s=n[5],l=n[9],c=n[2],h=n[6],u=n[10],d=i+s+u;return d>0?(t=.5/Math.sqrt(d+1),this._w=.25/t,this._x=(h-l)*t,this._y=(a-c)*t,this._z=(o-r)*t):i>s&&i>u?(t=2*Math.sqrt(1+i-s-u),this._w=(h-l)/t,this._x=.25*t,this._y=(r+o)/t,this._z=(a+c)/t):s>u?(t=2*Math.sqrt(1+s-i-u),this._w=(a-c)/t,this._x=(r+o)/t,this._y=.25*t,this._z=(l+h)/t):(t=2*Math.sqrt(1+u-i-s),this._w=(o-r)/t,this._x=(a+c)/t,this._y=(l+h)/t,this._z=.25*t),this._onChangeCallback(),this},setFromUnitVectors:function(e,t){var n=e.dot(t)+1;return n<1e-6?(n=0,Math.abs(e.x)>Math.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=n):(this._x=0,this._y=-e.z,this._z=e.y,this._w=n)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=n),this.normalize()},angleTo:function(e){return 2*Math.acos(Math.abs(d.clamp(this.dot(e),-1,1)))},rotateTowards:function(e,t){var n=this.angleTo(e);if(0===n)return this;var i=Math.min(1,t/n);return this.slerp(e,i),this},inverse:function(){return this.conjugate()},conjugate:function(){return this._x*=-1,this._y*=-1,this._z*=-1,this._onChangeCallback(),this},dot:function(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._w},lengthSq:function(){return this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w},length:function(){return Math.sqrt(this._x*this._x+this._y*this._y+this._z*this._z+this._w*this._w)},normalize:function(){var e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this._onChangeCallback(),this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead."),this.multiplyQuaternions(e,t)):this.multiplyQuaternions(this,e)},premultiply:function(e){return this.multiplyQuaternions(e,this)},multiplyQuaternions:function(e,t){var n=e._x,i=e._y,r=e._z,a=e._w,o=t._x,s=t._y,l=t._z,c=t._w;return this._x=n*c+a*o+i*l-r*s,this._y=i*c+a*s+r*o-n*l,this._z=r*c+a*l+n*s-i*o,this._w=a*c-n*o-i*s-r*l,this._onChangeCallback(),this},slerp:function(e,t){if(0===t)return this;if(1===t)return this.copy(e);var n=this._x,i=this._y,r=this._z,a=this._w,o=a*e._w+n*e._x+i*e._y+r*e._z;if(o<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,o=-o):this.copy(e),o>=1)return this._w=a,this._x=n,this._y=i,this._z=r,this;var s=1-o*o;if(s<=Number.EPSILON){var l=1-t;return this._w=l*a+t*this._w,this._x=l*n+t*this._x,this._y=l*i+t*this._y,this._z=l*r+t*this._z,this.normalize(),this._onChangeCallback(),this}var c=Math.sqrt(s),h=Math.atan2(c,o),u=Math.sin((1-t)*h)/c,d=Math.sin(t*h)/c;return this._w=a*u+this._w*d,this._x=n*u+this._x*d,this._y=i*u+this._y*d,this._z=r*u+this._z*d,this._onChangeCallback(),this},equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w},fromArray:function(e,t){return void 0===t&&(t=0),this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e},fromBufferAttribute:function(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this},_onChange:function(e){return this._onChangeCallback=e,this},_onChangeCallback:function(){}});var M=new w,b=new y;function w(e,t,n){this.x=e||0,this.y=t||0,this.z=n||0}Object.assign(w.prototype,{isVector3:!0,set:function(e,t,n){return this.x=e,this.y=t,this.z=n,this},setScalar:function(e){return this.x=e,this.y=e,this.z=e,this},setX:function(e){return this.x=e,this},setY:function(e){return this.y=e,this},setZ:function(e){return this.z=e,this},setComponent:function(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this},getComponent:function(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}},clone:function(){return new this.constructor(this.x,this.y,this.z)},copy:function(e){return this.x=e.x,this.y=e.y,this.z=e.z,this},add:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead."),this.addVectors(e,t)):(this.x+=e.x,this.y+=e.y,this.z+=e.z,this)},addScalar:function(e){return this.x+=e,this.y+=e,this.z+=e,this},addVectors:function(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this},addScaledVector:function(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this},sub:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead."),this.subVectors(e,t)):(this.x-=e.x,this.y-=e.y,this.z-=e.z,this)},subScalar:function(e){return this.x-=e,this.y-=e,this.z-=e,this},subVectors:function(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead."),this.multiplyVectors(e,t)):(this.x*=e.x,this.y*=e.y,this.z*=e.z,this)},multiplyScalar:function(e){return this.x*=e,this.y*=e,this.z*=e,this},multiplyVectors:function(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this},applyEuler:function(e){return e&&e.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(b.setFromEuler(e))},applyAxisAngle:function(e,t){return this.applyQuaternion(b.setFromAxisAngle(e,t))},applyMatrix3:function(e){var t=this.x,n=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[3]*n+r[6]*i,this.y=r[1]*t+r[4]*n+r[7]*i,this.z=r[2]*t+r[5]*n+r[8]*i,this},applyNormalMatrix:function(e){return this.applyMatrix3(e).normalize()},applyMatrix4:function(e){var t=this.x,n=this.y,i=this.z,r=e.elements,a=1/(r[3]*t+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*t+r[4]*n+r[8]*i+r[12])*a,this.y=(r[1]*t+r[5]*n+r[9]*i+r[13])*a,this.z=(r[2]*t+r[6]*n+r[10]*i+r[14])*a,this},applyQuaternion:function(e){var t=this.x,n=this.y,i=this.z,r=e.x,a=e.y,o=e.z,s=e.w,l=s*t+a*i-o*n,c=s*n+o*t-r*i,h=s*i+r*n-a*t,u=-r*t-a*n-o*i;return this.x=l*s+u*-r+c*-o-h*-a,this.y=c*s+u*-a+h*-r-l*-o,this.z=h*s+u*-o+l*-a-c*-r,this},project:function(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)},unproject:function(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)},transformDirection:function(e){var t=this.x,n=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[4]*n+r[8]*i,this.y=r[1]*t+r[5]*n+r[9]*i,this.z=r[2]*t+r[6]*n+r[10]*i,this.normalize()},divide:function(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this},divideScalar:function(e){return this.multiplyScalar(1/e)},min:function(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this},max:function(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this},clamp:function(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this},clampScalar:function(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this},clampLength:function(e,t){var n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(e,Math.min(t,n)))},floor:function(){return this.x=Math.floor(this.x),this.y=Math.floor(this.y),this.z=Math.floor(this.z),this},ceil:function(){return this.x=Math.ceil(this.x),this.y=Math.ceil(this.y),this.z=Math.ceil(this.z),this},round:function(){return this.x=Math.round(this.x),this.y=Math.round(this.y),this.z=Math.round(this.z),this},roundToZero:function(){return this.x=this.x<0?Math.ceil(this.x):Math.floor(this.x),this.y=this.y<0?Math.ceil(this.y):Math.floor(this.y),this.z=this.z<0?Math.ceil(this.z):Math.floor(this.z),this},negate:function(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this},dot:function(e){return this.x*e.x+this.y*e.y+this.z*e.z},lengthSq:function(){return this.x*this.x+this.y*this.y+this.z*this.z},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z)},manhattanLength:function(){return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z)},normalize:function(){return this.divideScalar(this.length()||1)},setLength:function(e){return this.normalize().multiplyScalar(e)},lerp:function(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this},lerpVectors:function(e,t,n){return this.x=e.x+(t.x-e.x)*n,this.y=e.y+(t.y-e.y)*n,this.z=e.z+(t.z-e.z)*n,this},cross:function(e,t){return void 0!==t?(console.warn("THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead."),this.crossVectors(e,t)):this.crossVectors(this,e)},crossVectors:function(e,t){var n=e.x,i=e.y,r=e.z,a=t.x,o=t.y,s=t.z;return this.x=i*s-r*o,this.y=r*a-n*s,this.z=n*o-i*a,this},projectOnVector:function(e){var t=e.lengthSq();if(0===t)return this.set(0,0,0);var n=e.dot(this)/t;return this.copy(e).multiplyScalar(n)},projectOnPlane:function(e){return M.copy(this).projectOnVector(e),this.sub(M)},reflect:function(e){return this.sub(M.copy(e).multiplyScalar(2*this.dot(e)))},angleTo:function(e){var t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;var n=this.dot(e)/t;return Math.acos(d.clamp(n,-1,1))},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,n=this.y-e.y,i=this.z-e.z;return t*t+n*n+i*i},manhattanDistanceTo:function(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)},setFromSpherical:function(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)},setFromSphericalCoords:function(e,t,n){var i=Math.sin(t)*e;return this.x=i*Math.sin(n),this.y=Math.cos(t)*e,this.z=i*Math.cos(n),this},setFromCylindrical:function(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)},setFromCylindricalCoords:function(e,t,n){return this.x=e*Math.sin(t),this.y=n,this.z=e*Math.cos(t),this},setFromMatrixPosition:function(e){var t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this},setFromMatrixScale:function(e){var t=this.setFromMatrixColumn(e,0).length(),n=this.setFromMatrixColumn(e,1).length(),i=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=n,this.z=i,this},setFromMatrixColumn:function(e,t){return this.fromArray(e.elements,4*t)},setFromMatrix3Column:function(e,t){return this.fromArray(e.elements,3*t)},equals:function(e){return e.x===this.x&&e.y===this.y&&e.z===this.z},fromArray:function(e,t){return void 0===t&&(t=0),this.x=e[t],this.y=e[t+1],this.z=e[t+2],this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e},fromBufferAttribute:function(e,t,n){return void 0!==n&&console.warn("THREE.Vector3: offset has been removed from .fromBufferAttribute()."),this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this},random:function(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}});var S=new w,E=new D,T=new w(0,0,0),L=new w(1,1,1),A=new w,P=new w,C=new w;function D(){this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],arguments.length>0&&console.error("THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.")}Object.assign(D.prototype,{isMatrix4:!0,set:function(e,t,n,i,r,a,o,s,l,c,h,u,d,p,f,m){var g=this.elements;return g[0]=e,g[4]=t,g[8]=n,g[12]=i,g[1]=r,g[5]=a,g[9]=o,g[13]=s,g[2]=l,g[6]=c,g[10]=h,g[14]=u,g[3]=d,g[7]=p,g[11]=f,g[15]=m,this},identity:function(){return this.set(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1),this},clone:function(){return(new D).fromArray(this.elements)},copy:function(e){var t=this.elements,n=e.elements;return t[0]=n[0],t[1]=n[1],t[2]=n[2],t[3]=n[3],t[4]=n[4],t[5]=n[5],t[6]=n[6],t[7]=n[7],t[8]=n[8],t[9]=n[9],t[10]=n[10],t[11]=n[11],t[12]=n[12],t[13]=n[13],t[14]=n[14],t[15]=n[15],this},copyPosition:function(e){var t=this.elements,n=e.elements;return t[12]=n[12],t[13]=n[13],t[14]=n[14],this},extractBasis:function(e,t,n){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this},makeBasis:function(e,t,n){return this.set(e.x,t.x,n.x,0,e.y,t.y,n.y,0,e.z,t.z,n.z,0,0,0,0,1),this},extractRotation:function(e){var t=this.elements,n=e.elements,i=1/S.setFromMatrixColumn(e,0).length(),r=1/S.setFromMatrixColumn(e,1).length(),a=1/S.setFromMatrixColumn(e,2).length();return t[0]=n[0]*i,t[1]=n[1]*i,t[2]=n[2]*i,t[3]=0,t[4]=n[4]*r,t[5]=n[5]*r,t[6]=n[6]*r,t[7]=0,t[8]=n[8]*a,t[9]=n[9]*a,t[10]=n[10]*a,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},makeRotationFromEuler:function(e){e&&e.isEuler||console.error("THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.");var t=this.elements,n=e.x,i=e.y,r=e.z,a=Math.cos(n),o=Math.sin(n),s=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===e.order){var u=a*c,d=a*h,p=o*c,f=o*h;t[0]=s*c,t[4]=-s*h,t[8]=l,t[1]=d+p*l,t[5]=u-f*l,t[9]=-o*s,t[2]=f-u*l,t[6]=p+d*l,t[10]=a*s}else if("YXZ"===e.order){var m=s*c,g=s*h,v=l*c,x=l*h;t[0]=m+x*o,t[4]=v*o-g,t[8]=a*l,t[1]=a*h,t[5]=a*c,t[9]=-o,t[2]=g*o-v,t[6]=x+m*o,t[10]=a*s}else if("ZXY"===e.order){m=s*c,g=s*h,v=l*c,x=l*h;t[0]=m-x*o,t[4]=-a*h,t[8]=v+g*o,t[1]=g+v*o,t[5]=a*c,t[9]=x-m*o,t[2]=-a*l,t[6]=o,t[10]=a*s}else if("ZYX"===e.order){u=a*c,d=a*h,p=o*c,f=o*h;t[0]=s*c,t[4]=p*l-d,t[8]=u*l+f,t[1]=s*h,t[5]=f*l+u,t[9]=d*l-p,t[2]=-l,t[6]=o*s,t[10]=a*s}else if("YZX"===e.order){var _=a*s,y=a*l,M=o*s,b=o*l;t[0]=s*c,t[4]=b-_*h,t[8]=M*h+y,t[1]=h,t[5]=a*c,t[9]=-o*c,t[2]=-l*c,t[6]=y*h+M,t[10]=_-b*h}else if("XZY"===e.order){_=a*s,y=a*l,M=o*s,b=o*l;t[0]=s*c,t[4]=-h,t[8]=l*c,t[1]=_*h+b,t[5]=a*c,t[9]=y*h-M,t[2]=M*h-y,t[6]=o*c,t[10]=b*h+_}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},makeRotationFromQuaternion:function(e){return this.compose(T,e,L)},lookAt:function(e,t,n){var i=this.elements;return C.subVectors(e,t),0===C.lengthSq()&&(C.z=1),C.normalize(),A.crossVectors(n,C),0===A.lengthSq()&&(1===Math.abs(n.z)?C.x+=1e-4:C.z+=1e-4,C.normalize(),A.crossVectors(n,C)),A.normalize(),P.crossVectors(C,A),i[0]=A.x,i[4]=P.x,i[8]=C.x,i[1]=A.y,i[5]=P.y,i[9]=C.y,i[2]=A.z,i[6]=P.z,i[10]=C.z,this},multiply:function(e,t){return void 0!==t?(console.warn("THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead."),this.multiplyMatrices(e,t)):this.multiplyMatrices(this,e)},premultiply:function(e){return this.multiplyMatrices(e,this)},multiplyMatrices:function(e,t){var n=e.elements,i=t.elements,r=this.elements,a=n[0],o=n[4],s=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],f=n[6],m=n[10],g=n[14],v=n[3],x=n[7],_=n[11],y=n[15],M=i[0],b=i[4],w=i[8],S=i[12],E=i[1],T=i[5],L=i[9],A=i[13],P=i[2],C=i[6],D=i[10],N=i[14],R=i[3],I=i[7],z=i[11],O=i[15];return r[0]=a*M+o*E+s*P+l*R,r[4]=a*b+o*T+s*C+l*I,r[8]=a*w+o*L+s*D+l*z,r[12]=a*S+o*A+s*N+l*O,r[1]=c*M+h*E+u*P+d*R,r[5]=c*b+h*T+u*C+d*I,r[9]=c*w+h*L+u*D+d*z,r[13]=c*S+h*A+u*N+d*O,r[2]=p*M+f*E+m*P+g*R,r[6]=p*b+f*T+m*C+g*I,r[10]=p*w+f*L+m*D+g*z,r[14]=p*S+f*A+m*N+g*O,r[3]=v*M+x*E+_*P+y*R,r[7]=v*b+x*T+_*C+y*I,r[11]=v*w+x*L+_*D+y*z,r[15]=v*S+x*A+_*N+y*O,this},multiplyScalar:function(e){var t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this},determinant:function(){var e=this.elements,t=e[0],n=e[4],i=e[8],r=e[12],a=e[1],o=e[5],s=e[9],l=e[13],c=e[2],h=e[6],u=e[10],d=e[14];return e[3]*(+r*s*h-i*l*h-r*o*u+n*l*u+i*o*d-n*s*d)+e[7]*(+t*s*d-t*l*u+r*a*u-i*a*d+i*l*c-r*s*c)+e[11]*(+t*l*h-t*o*d-r*a*h+n*a*d+r*o*c-n*l*c)+e[15]*(-i*o*c-t*s*h+t*o*u+i*a*h-n*a*u+n*s*c)},transpose:function(){var e,t=this.elements;return e=t[1],t[1]=t[4],t[4]=e,e=t[2],t[2]=t[8],t[8]=e,e=t[6],t[6]=t[9],t[9]=e,e=t[3],t[3]=t[12],t[12]=e,e=t[7],t[7]=t[13],t[13]=e,e=t[11],t[11]=t[14],t[14]=e,this},setPosition:function(e,t,n){var i=this.elements;return e.isVector3?(i[12]=e.x,i[13]=e.y,i[14]=e.z):(i[12]=e,i[13]=t,i[14]=n),this},getInverse:function(e,t){void 0!==t&&console.warn("THREE.Matrix4: .getInverse() can no longer be configured to throw on degenerate.");var n=this.elements,i=e.elements,r=i[0],a=i[1],o=i[2],s=i[3],l=i[4],c=i[5],h=i[6],u=i[7],d=i[8],p=i[9],f=i[10],m=i[11],g=i[12],v=i[13],x=i[14],_=i[15],y=p*x*u-v*f*u+v*h*m-c*x*m-p*h*_+c*f*_,M=g*f*u-d*x*u-g*h*m+l*x*m+d*h*_-l*f*_,b=d*v*u-g*p*u+g*c*m-l*v*m-d*c*_+l*p*_,w=g*p*h-d*v*h-g*c*f+l*v*f+d*c*x-l*p*x,S=r*y+a*M+o*b+s*w;if(0===S)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);var E=1/S;return n[0]=y*E,n[1]=(v*f*s-p*x*s-v*o*m+a*x*m+p*o*_-a*f*_)*E,n[2]=(c*x*s-v*h*s+v*o*u-a*x*u-c*o*_+a*h*_)*E,n[3]=(p*h*s-c*f*s-p*o*u+a*f*u+c*o*m-a*h*m)*E,n[4]=M*E,n[5]=(d*x*s-g*f*s+g*o*m-r*x*m-d*o*_+r*f*_)*E,n[6]=(g*h*s-l*x*s-g*o*u+r*x*u+l*o*_-r*h*_)*E,n[7]=(l*f*s-d*h*s+d*o*u-r*f*u-l*o*m+r*h*m)*E,n[8]=b*E,n[9]=(g*p*s-d*v*s-g*a*m+r*v*m+d*a*_-r*p*_)*E,n[10]=(l*v*s-g*c*s+g*a*u-r*v*u-l*a*_+r*c*_)*E,n[11]=(d*c*s-l*p*s-d*a*u+r*p*u+l*a*m-r*c*m)*E,n[12]=w*E,n[13]=(d*v*o-g*p*o+g*a*f-r*v*f-d*a*x+r*p*x)*E,n[14]=(g*c*o-l*v*o-g*a*h+r*v*h+l*a*x-r*c*x)*E,n[15]=(l*p*o-d*c*o+d*a*h-r*p*h-l*a*f+r*c*f)*E,this},scale:function(e){var t=this.elements,n=e.x,i=e.y,r=e.z;return t[0]*=n,t[4]*=i,t[8]*=r,t[1]*=n,t[5]*=i,t[9]*=r,t[2]*=n,t[6]*=i,t[10]*=r,t[3]*=n,t[7]*=i,t[11]*=r,this},getMaxScaleOnAxis:function(){var e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],n=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],i=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,n,i))},makeTranslation:function(e,t,n){return this.set(1,0,0,e,0,1,0,t,0,0,1,n,0,0,0,1),this},makeRotationX:function(e){var t=Math.cos(e),n=Math.sin(e);return this.set(1,0,0,0,0,t,-n,0,0,n,t,0,0,0,0,1),this},makeRotationY:function(e){var t=Math.cos(e),n=Math.sin(e);return this.set(t,0,n,0,0,1,0,0,-n,0,t,0,0,0,0,1),this},makeRotationZ:function(e){var t=Math.cos(e),n=Math.sin(e);return this.set(t,-n,0,0,n,t,0,0,0,0,1,0,0,0,0,1),this},makeRotationAxis:function(e,t){var n=Math.cos(t),i=Math.sin(t),r=1-n,a=e.x,o=e.y,s=e.z,l=r*a,c=r*o;return this.set(l*a+n,l*o-i*s,l*s+i*o,0,l*o+i*s,c*o+n,c*s-i*a,0,l*s-i*o,c*s+i*a,r*s*s+n,0,0,0,0,1),this},makeScale:function(e,t,n){return this.set(e,0,0,0,0,t,0,0,0,0,n,0,0,0,0,1),this},makeShear:function(e,t,n){return this.set(1,t,n,0,e,1,n,0,e,t,1,0,0,0,0,1),this},compose:function(e,t,n){var i=this.elements,r=t._x,a=t._y,o=t._z,s=t._w,l=r+r,c=a+a,h=o+o,u=r*l,d=r*c,p=r*h,f=a*c,m=a*h,g=o*h,v=s*l,x=s*c,_=s*h,y=n.x,M=n.y,b=n.z;return i[0]=(1-(f+g))*y,i[1]=(d+_)*y,i[2]=(p-x)*y,i[3]=0,i[4]=(d-_)*M,i[5]=(1-(u+g))*M,i[6]=(m+v)*M,i[7]=0,i[8]=(p+x)*b,i[9]=(m-v)*b,i[10]=(1-(u+f))*b,i[11]=0,i[12]=e.x,i[13]=e.y,i[14]=e.z,i[15]=1,this},decompose:function(e,t,n){var i=this.elements,r=S.set(i[0],i[1],i[2]).length(),a=S.set(i[4],i[5],i[6]).length(),o=S.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),e.x=i[12],e.y=i[13],e.z=i[14],E.copy(this);var s=1/r,l=1/a,c=1/o;return E.elements[0]*=s,E.elements[1]*=s,E.elements[2]*=s,E.elements[4]*=l,E.elements[5]*=l,E.elements[6]*=l,E.elements[8]*=c,E.elements[9]*=c,E.elements[10]*=c,t.setFromRotationMatrix(E),n.x=r,n.y=a,n.z=o,this},makePerspective:function(e,t,n,i,r,a){void 0===a&&console.warn("THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.");var o=this.elements,s=2*r/(t-e),l=2*r/(n-i),c=(t+e)/(t-e),h=(n+i)/(n-i),u=-(a+r)/(a-r),d=-2*a*r/(a-r);return o[0]=s,o[4]=0,o[8]=c,o[12]=0,o[1]=0,o[5]=l,o[9]=h,o[13]=0,o[2]=0,o[6]=0,o[10]=u,o[14]=d,o[3]=0,o[7]=0,o[11]=-1,o[15]=0,this},makeOrthographic:function(e,t,n,i,r,a){var o=this.elements,s=1/(t-e),l=1/(n-i),c=1/(a-r),h=(t+e)*s,u=(n+i)*l,d=(a+r)*c;return o[0]=2*s,o[4]=0,o[8]=0,o[12]=-h,o[1]=0,o[5]=2*l,o[9]=0,o[13]=-u,o[2]=0,o[6]=0,o[10]=-2*c,o[14]=-d,o[3]=0,o[7]=0,o[11]=0,o[15]=1,this},equals:function(e){for(var t=this.elements,n=e.elements,i=0;i<16;i++)if(t[i]!==n[i])return!1;return!0},fromArray:function(e,t){void 0===t&&(t=0);for(var n=0;n<16;n++)this.elements[n]=e[n+t];return this},toArray:function(e,t){void 0===e&&(e=[]),void 0===t&&(t=0);var n=this.elements;return e[t]=n[0],e[t+1]=n[1],e[t+2]=n[2],e[t+3]=n[3],e[t+4]=n[4],e[t+5]=n[5],e[t+6]=n[6],e[t+7]=n[7],e[t+8]=n[8],e[t+9]=n[9],e[t+10]=n[10],e[t+11]=n[11],e[t+12]=n[12],e[t+13]=n[13],e[t+14]=n[14],e[t+15]=n[15],e}});var N=new D,R=new y;function I(e,t,n,i){this._x=e||0,this._y=t||0,this._z=n||0,this._order=i||I.DefaultOrder}function z(){this.mask=1}I.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"],I.DefaultOrder="XYZ",Object.defineProperties(I.prototype,{x:{get:function(){return this._x},set:function(e){this._x=e,this._onChangeCallback()}},y:{get:function(){return this._y},set:function(e){this._y=e,this._onChangeCallback()}},z:{get:function(){return this._z},set:function(e){this._z=e,this._onChangeCallback()}},order:{get:function(){return this._order},set:function(e){this._order=e,this._onChangeCallback()}}}),Object.assign(I.prototype,{isEuler:!0,set:function(e,t,n,i){return this._x=e,this._y=t,this._z=n,this._order=i||this._order,this._onChangeCallback(),this},clone:function(){return new this.constructor(this._x,this._y,this._z,this._order)},copy:function(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this},setFromRotationMatrix:function(e,t,n){var i=d.clamp,r=e.elements,a=r[0],o=r[4],s=r[8],l=r[1],c=r[5],h=r[9],u=r[2],p=r[6],f=r[10];switch(t=t||this._order){case"XYZ":this._y=Math.asin(i(s,-1,1)),Math.abs(s)<.9999999?(this._x=Math.atan2(-h,f),this._z=Math.atan2(-o,a)):(this._x=Math.atan2(p,c),this._z=0);break;case"YXZ":this._x=Math.asin(-i(h,-1,1)),Math.abs(h)<.9999999?(this._y=Math.atan2(s,f),this._z=Math.atan2(l,c)):(this._y=Math.atan2(-u,a),this._z=0);break;case"ZXY":this._x=Math.asin(i(p,-1,1)),Math.abs(p)<.9999999?(this._y=Math.atan2(-u,f),this._z=Math.atan2(-o,c)):(this._y=0,this._z=Math.atan2(l,a));break;case"ZYX":this._y=Math.asin(-i(u,-1,1)),Math.abs(u)<.9999999?(this._x=Math.atan2(p,f),this._z=Math.atan2(l,a)):(this._x=0,this._z=Math.atan2(-o,c));break;case"YZX":this._z=Math.asin(i(l,-1,1)),Math.abs(l)<.9999999?(this._x=Math.atan2(-h,c),this._y=Math.atan2(-u,a)):(this._x=0,this._y=Math.atan2(s,f));break;case"XZY":this._z=Math.asin(-i(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(p,c),this._y=Math.atan2(s,a)):(this._x=Math.atan2(-h,f),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+t)}return this._order=t,!1!==n&&this._onChangeCallback(),this},setFromQuaternion:function(e,t,n){return N.makeRotationFromQuaternion(e),this.setFromRotationMatrix(N,t,n)},setFromVector3:function(e,t){return this.set(e.x,e.y,e.z,t||this._order)},reorder:function(e){return R.setFromEuler(this),this.setFromQuaternion(R,e)},equals:function(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order},fromArray:function(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this._onChangeCallback(),this},toArray:function(e,t){return void 0===e&&(e=[]),void 0===t&&(t=0),e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e},toVector3:function(e){return e?e.set(this._x,this._y,this._z):new w(this._x,this._y,this._z)},_onChange:function(e){return this._onChangeCallback=e,this},_onChangeCallback:function(){}}),Object.assign(z.prototype,{set:function(e){this.mask=1<1){for(var t=0;t1){for(var t=0;t0){i.children=[];for(s=0;s0&&(n.geometries=u),d.length>0&&(n.materials=d),p.length>0&&(n.textures=p),f.length>0&&(n.images=f),o.length>0&&(n.shapes=o)}return n.object=i,n;function m(e){var t=[];for(var n in e){var i=e[n];delete i.metadata,t.push(i)}return t}},clone:function(e){return(new this.constructor).copy(this,e)},copy:function(e,t){if(void 0===t&&(t=!0),this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(var n=0;ns)return!1}return!0}Object.assign(he.prototype,{isBox3:!0,set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromArray:function(e){for(var t=1/0,n=1/0,i=1/0,r=-1/0,a=-1/0,o=-1/0,s=0,l=e.length;sr&&(r=c),h>a&&(a=h),u>o&&(o=u)}return this.min.set(t,n,i),this.max.set(r,a,o),this},setFromBufferAttribute:function(e){for(var t=1/0,n=1/0,i=1/0,r=-1/0,a=-1/0,o=-1/0,s=0,l=e.count;sr&&(r=c),h>a&&(a=h),u>o&&(o=u)}return this.min.set(t,n,i),this.max.set(r,a,o),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,n=e.length;tthis.max.x||e.ythis.max.y||e.zthis.max.z)},containsBox:function(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z},getParameter:function(e,t){return void 0===t&&(console.warn("THREE.Box3: .getParameter() target is now required"),t=new w),t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y||e.max.zthis.max.z)},intersectsSphere:function(e){return this.clampPoint(e.center,K),K.distanceToSquared(e.center)<=e.radius*e.radius},intersectsPlane:function(e){var t,n;return e.normal.x>0?(t=e.normal.x*this.min.x,n=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,n=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,n+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,n+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,n+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,n+=e.normal.z*this.min.z),t<=-e.constant&&n>=-e.constant},intersectsTriangle:function(e){if(this.isEmpty())return!1;this.getCenter(oe),se.subVectors(this.max,oe),ee.subVectors(e.a,oe),te.subVectors(e.b,oe),ne.subVectors(e.c,oe),ie.subVectors(te,ee),re.subVectors(ne,te),ae.subVectors(ee,ne);var t=[0,-ie.z,ie.y,0,-re.z,re.y,0,-ae.z,ae.y,ie.z,0,-ie.x,re.z,0,-re.x,ae.z,0,-ae.x,-ie.y,ie.x,0,-re.y,re.x,0,-ae.y,ae.x,0];return!!ue(t,ee,te,ne,se)&&(!!ue(t=[1,0,0,0,1,0,0,0,1],ee,te,ne,se)&&(le.crossVectors(ie,re),ue(t=[le.x,le.y,le.z],ee,te,ne,se)))},clampPoint:function(e,t){return void 0===t&&(console.warn("THREE.Box3: .clampPoint() target is now required"),t=new w),t.copy(e).clamp(this.min,this.max)},distanceToPoint:function(e){return K.copy(e).clamp(this.min,this.max).sub(e).length()},getBoundingSphere:function(e){return void 0===e&&console.error("THREE.Box3: .getBoundingSphere() target is now required"),this.getCenter(e.center),e.radius=.5*this.getSize(K).length(),e},intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),this},applyMatrix4:function(e){return this.isEmpty()||(Q[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),Q[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),Q[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),Q[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),Q[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),Q[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),Q[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),Q[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(Q)),this},translate:function(e){return this.min.add(e),this.max.add(e),this},equals:function(e){return e.min.equals(this.min)&&e.max.equals(this.max)}});var de=new he;function pe(e,t){this.center=void 0!==e?e:new w,this.radius=void 0!==t?t:-1}Object.assign(pe.prototype,{set:function(e,t){return this.center.copy(e),this.radius=t,this},setFromPoints:function(e,t){var n=this.center;void 0!==t?n.copy(t):de.setFromPoints(e).getCenter(n);for(var i=0,r=0,a=e.length;rthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t},getBoundingBox:function(e){return void 0===e&&(console.warn("THREE.Sphere: .getBoundingBox() target is now required"),e=new he),this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)},applyMatrix4:function(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this},translate:function(e){return this.center.add(e),this},equals:function(e){return e.center.equals(this.center)&&e.radius===this.radius}});var fe=new w,me=new w,ge=new w,ve=new w,xe=new w,_e=new w,ye=new w;function Me(e,t){this.origin=void 0!==e?e:new w,this.direction=void 0!==t?t:new w(0,0,-1)}Object.assign(Me.prototype,{set:function(e,t){return this.origin.copy(e),this.direction.copy(t),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this},at:function(e,t){return void 0===t&&(console.warn("THREE.Ray: .at() target is now required"),t=new w),t.copy(this.direction).multiplyScalar(e).add(this.origin)},lookAt:function(e){return this.direction.copy(e).sub(this.origin).normalize(),this},recast:function(e){return this.origin.copy(this.at(e,fe)),this},closestPointToPoint:function(e,t){void 0===t&&(console.warn("THREE.Ray: .closestPointToPoint() target is now required"),t=new w),t.subVectors(e,this.origin);var n=t.dot(this.direction);return n<0?t.copy(this.origin):t.copy(this.direction).multiplyScalar(n).add(this.origin)},distanceToPoint:function(e){return Math.sqrt(this.distanceSqToPoint(e))},distanceSqToPoint:function(e){var t=fe.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(fe.copy(this.direction).multiplyScalar(t).add(this.origin),fe.distanceToSquared(e))},distanceSqToSegment:function(e,t,n,i){me.copy(e).add(t).multiplyScalar(.5),ge.copy(t).sub(e).normalize(),ve.copy(this.origin).sub(me);var r,a,o,s,l=.5*e.distanceTo(t),c=-this.direction.dot(ge),h=ve.dot(this.direction),u=-ve.dot(ge),d=ve.lengthSq(),p=Math.abs(1-c*c);if(p>0)if(a=c*h-u,s=l*p,(r=c*u-h)>=0)if(a>=-s)if(a<=s){var f=1/p;o=(r*=f)*(r+c*(a*=f)+2*h)+a*(c*r+a+2*u)+d}else a=l,o=-(r=Math.max(0,-(c*a+h)))*r+a*(a+2*u)+d;else a=-l,o=-(r=Math.max(0,-(c*a+h)))*r+a*(a+2*u)+d;else a<=-s?o=-(r=Math.max(0,-(-c*l+h)))*r+(a=r>0?-l:Math.min(Math.max(-l,-u),l))*(a+2*u)+d:a<=s?(r=0,o=(a=Math.min(Math.max(-l,-u),l))*(a+2*u)+d):o=-(r=Math.max(0,-(c*l+h)))*r+(a=r>0?l:Math.min(Math.max(-l,-u),l))*(a+2*u)+d;else a=c>0?-l:l,o=-(r=Math.max(0,-(c*a+h)))*r+a*(a+2*u)+d;return n&&n.copy(this.direction).multiplyScalar(r).add(this.origin),i&&i.copy(ge).multiplyScalar(a).add(me),o},intersectSphere:function(e,t){fe.subVectors(e.center,this.origin);var n=fe.dot(this.direction),i=fe.dot(fe)-n*n,r=e.radius*e.radius;if(i>r)return null;var a=Math.sqrt(r-i),o=n-a,s=n+a;return o<0&&s<0?null:o<0?this.at(s,t):this.at(o,t)},intersectsSphere:function(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius},distanceToPlane:function(e){var t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;var n=-(this.origin.dot(e.normal)+e.constant)/t;return n>=0?n:null},intersectPlane:function(e,t){var n=this.distanceToPlane(e);return null===n?null:this.at(n,t)},intersectsPlane:function(e){var t=e.distanceToPoint(this.origin);return 0===t||e.normal.dot(this.direction)*t<0},intersectBox:function(e,t){var n,i,r,a,o,s,l=1/this.direction.x,c=1/this.direction.y,h=1/this.direction.z,u=this.origin;return l>=0?(n=(e.min.x-u.x)*l,i=(e.max.x-u.x)*l):(n=(e.max.x-u.x)*l,i=(e.min.x-u.x)*l),c>=0?(r=(e.min.y-u.y)*c,a=(e.max.y-u.y)*c):(r=(e.max.y-u.y)*c,a=(e.min.y-u.y)*c),n>a||r>i?null:((r>n||n!=n)&&(n=r),(a=0?(o=(e.min.z-u.z)*h,s=(e.max.z-u.z)*h):(o=(e.max.z-u.z)*h,s=(e.min.z-u.z)*h),n>s||o>i?null:((o>n||n!=n)&&(n=o),(s=0?n:i,t)))},intersectsBox:function(e){return null!==this.intersectBox(e,fe)},intersectTriangle:function(e,t,n,i,r){xe.subVectors(t,e),_e.subVectors(n,e),ye.crossVectors(xe,_e);var a,o=this.direction.dot(ye);if(o>0){if(i)return null;a=1}else{if(!(o<0))return null;a=-1,o=-o}ve.subVectors(this.origin,e);var s=a*this.direction.dot(_e.crossVectors(ve,_e));if(s<0)return null;var l=a*this.direction.dot(xe.cross(ve));if(l<0)return null;if(s+l>o)return null;var c=-a*ve.dot(ye);return c<0?null:this.at(c/o,r)},applyMatrix4:function(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this},equals:function(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}});var be=new w,we=new w,Se=new f;function Ee(e,t){this.normal=void 0!==e?e:new w(1,0,0),this.constant=void 0!==t?t:0}Object.assign(Ee.prototype,{isPlane:!0,set:function(e,t){return this.normal.copy(e),this.constant=t,this},setComponents:function(e,t,n,i){return this.normal.set(e,t,n),this.constant=i,this},setFromNormalAndCoplanarPoint:function(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this},setFromCoplanarPoints:function(e,t,n){var i=be.subVectors(n,t).cross(we.subVectors(e,t)).normalize();return this.setFromNormalAndCoplanarPoint(i,e),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.normal.copy(e.normal),this.constant=e.constant,this},normalize:function(){var e=1/this.normal.length();return this.normal.multiplyScalar(e),this.constant*=e,this},negate:function(){return this.constant*=-1,this.normal.negate(),this},distanceToPoint:function(e){return this.normal.dot(e)+this.constant},distanceToSphere:function(e){return this.distanceToPoint(e.center)-e.radius},projectPoint:function(e,t){return void 0===t&&(console.warn("THREE.Plane: .projectPoint() target is now required"),t=new w),t.copy(this.normal).multiplyScalar(-this.distanceToPoint(e)).add(e)},intersectLine:function(e,t){void 0===t&&(console.warn("THREE.Plane: .intersectLine() target is now required"),t=new w);var n=e.delta(be),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(e.start)?t.copy(e.start):void 0;var r=-(e.start.dot(this.normal)+this.constant)/i;return r<0||r>1?void 0:t.copy(n).multiplyScalar(r).add(e.start)},intersectsLine:function(e){var t=this.distanceToPoint(e.start),n=this.distanceToPoint(e.end);return t<0&&n>0||n<0&&t>0},intersectsBox:function(e){return e.intersectsPlane(this)},intersectsSphere:function(e){return e.intersectsPlane(this)},coplanarPoint:function(e){return void 0===e&&(console.warn("THREE.Plane: .coplanarPoint() target is now required"),e=new w),e.copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(e,t){var n=t||Se.getNormalMatrix(e),i=this.coplanarPoint(be).applyMatrix4(e),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.dot(r),this},translate:function(e){return this.constant-=e.dot(this.normal),this},equals:function(e){return e.normal.equals(this.normal)&&e.constant===this.constant}});var Te=new w,Le=new w,Ae=new w,Pe=new w,Ce=new w,De=new w,Ne=new w,Re=new w,Ie=new w,ze=new w;function Oe(e,t,n){this.a=void 0!==e?e:new w,this.b=void 0!==t?t:new w,this.c=void 0!==n?n:new w}Object.assign(Oe,{getNormal:function(e,t,n,i){void 0===i&&(console.warn("THREE.Triangle: .getNormal() target is now required"),i=new w),i.subVectors(n,t),Te.subVectors(e,t),i.cross(Te);var r=i.lengthSq();return r>0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)},getBarycoord:function(e,t,n,i,r){Te.subVectors(i,t),Le.subVectors(n,t),Ae.subVectors(e,t);var a=Te.dot(Te),o=Te.dot(Le),s=Te.dot(Ae),l=Le.dot(Le),c=Le.dot(Ae),h=a*l-o*o;if(void 0===r&&(console.warn("THREE.Triangle: .getBarycoord() target is now required"),r=new w),0===h)return r.set(-2,-1,-1);var u=1/h,d=(l*s-o*c)*u,p=(a*c-o*s)*u;return r.set(1-d-p,p,d)},containsPoint:function(e,t,n,i){return Oe.getBarycoord(e,t,n,i,Pe),Pe.x>=0&&Pe.y>=0&&Pe.x+Pe.y<=1},getUV:function(e,t,n,i,r,a,o,s){return this.getBarycoord(e,t,n,i,Pe),s.set(0,0),s.addScaledVector(r,Pe.x),s.addScaledVector(a,Pe.y),s.addScaledVector(o,Pe.z),s},isFrontFacing:function(e,t,n,i){return Te.subVectors(n,t),Le.subVectors(e,t),Te.cross(Le).dot(i)<0}}),Object.assign(Oe.prototype,{set:function(e,t,n){return this.a.copy(e),this.b.copy(t),this.c.copy(n),this},setFromPointsAndIndices:function(e,t,n,i){return this.a.copy(e[t]),this.b.copy(e[n]),this.c.copy(e[i]),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this},getArea:function(){return Te.subVectors(this.c,this.b),Le.subVectors(this.a,this.b),.5*Te.cross(Le).length()},getMidpoint:function(e){return void 0===e&&(console.warn("THREE.Triangle: .getMidpoint() target is now required"),e=new w),e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},getNormal:function(e){return Oe.getNormal(this.a,this.b,this.c,e)},getPlane:function(e){return void 0===e&&(console.warn("THREE.Triangle: .getPlane() target is now required"),e=new Ee),e.setFromCoplanarPoints(this.a,this.b,this.c)},getBarycoord:function(e,t){return Oe.getBarycoord(e,this.a,this.b,this.c,t)},getUV:function(e,t,n,i,r){return Oe.getUV(e,this.a,this.b,this.c,t,n,i,r)},containsPoint:function(e){return Oe.containsPoint(e,this.a,this.b,this.c)},isFrontFacing:function(e){return Oe.isFrontFacing(this.a,this.b,this.c,e)},intersectsBox:function(e){return e.intersectsTriangle(this)},closestPointToPoint:function(e,t){void 0===t&&(console.warn("THREE.Triangle: .closestPointToPoint() target is now required"),t=new w);var n,i,r=this.a,a=this.b,o=this.c;Ce.subVectors(a,r),De.subVectors(o,r),Re.subVectors(e,r);var s=Ce.dot(Re),l=De.dot(Re);if(s<=0&&l<=0)return t.copy(r);Ie.subVectors(e,a);var c=Ce.dot(Ie),h=De.dot(Ie);if(c>=0&&h<=c)return t.copy(a);var u=s*h-c*l;if(u<=0&&s>=0&&c<=0)return n=s/(s-c),t.copy(r).addScaledVector(Ce,n);ze.subVectors(e,o);var d=Ce.dot(ze),p=De.dot(ze);if(p>=0&&d<=p)return t.copy(o);var f=d*l-s*p;if(f<=0&&l>=0&&p<=0)return i=l/(l-p),t.copy(r).addScaledVector(De,i);var m=c*p-d*h;if(m<=0&&h-c>=0&&d-p>=0)return Ne.subVectors(o,a),i=(h-c)/(h-c+(d-p)),t.copy(a).addScaledVector(Ne,i);var g=1/(m+f+u);return n=f*g,i=u*g,t.copy(r).addScaledVector(Ce,n).addScaledVector(De,i)},equals:function(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}});var Ue={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074},Fe={h:0,s:0,l:0},Ge={h:0,s:0,l:0};function Be(e,t,n){return void 0===t&&void 0===n?this.set(e):this.setRGB(e,t,n)}function Ve(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+6*(t-e)*n:n<.5?t:n<2/3?e+6*(t-e)*(2/3-n):e}function ke(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function He(e){return e<.0031308?12.92*e:1.055*Math.pow(e,.41666)-.055}function We(e,t,n,i,r,a){this.a=e,this.b=t,this.c=n,this.normal=i&&i.isVector3?i:new w,this.vertexNormals=Array.isArray(i)?i:[],this.color=r&&r.isColor?r:new Be,this.vertexColors=Array.isArray(r)?r:[],this.materialIndex=void 0!==a?a:0}Object.assign(Be.prototype,{isColor:!0,r:1,g:1,b:1,set:function(e){return e&&e.isColor?this.copy(e):"number"==typeof e?this.setHex(e):"string"==typeof e&&this.setStyle(e),this},setScalar:function(e){return this.r=e,this.g=e,this.b=e,this},setHex:function(e){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,this},setRGB:function(e,t,n){return this.r=e,this.g=t,this.b=n,this},setHSL:function(e,t,n){if(e=d.euclideanModulo(e,1),t=d.clamp(t,0,1),n=d.clamp(n,0,1),0===t)this.r=this.g=this.b=n;else{var i=n<=.5?n*(1+t):n+t-n*t,r=2*n-i;this.r=Ve(r,i,e+1/3),this.g=Ve(r,i,e),this.b=Ve(r,i,e-1/3)}return this},setStyle:function(e){function t(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}var n;if(n=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(e)){var i,r=n[1],a=n[2];switch(r){case"rgb":case"rgba":if(i=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a))return this.r=Math.min(255,parseInt(i[1],10))/255,this.g=Math.min(255,parseInt(i[2],10))/255,this.b=Math.min(255,parseInt(i[3],10))/255,t(i[5]),this;if(i=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a))return this.r=Math.min(100,parseInt(i[1],10))/100,this.g=Math.min(100,parseInt(i[2],10))/100,this.b=Math.min(100,parseInt(i[3],10))/100,t(i[5]),this;break;case"hsl":case"hsla":if(i=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(a)){var o=parseFloat(i[1])/360,s=parseInt(i[2],10)/100,l=parseInt(i[3],10)/100;return t(i[5]),this.setHSL(o,s,l)}}}else if(n=/^\#([A-Fa-f0-9]+)$/.exec(e)){var c=n[1],h=c.length;if(3===h)return this.r=parseInt(c.charAt(0)+c.charAt(0),16)/255,this.g=parseInt(c.charAt(1)+c.charAt(1),16)/255,this.b=parseInt(c.charAt(2)+c.charAt(2),16)/255,this;if(6===h)return this.r=parseInt(c.charAt(0)+c.charAt(1),16)/255,this.g=parseInt(c.charAt(2)+c.charAt(3),16)/255,this.b=parseInt(c.charAt(4)+c.charAt(5),16)/255,this}return e&&e.length>0?this.setColorName(e):this},setColorName:function(e){var t=Ue[e];return void 0!==t?this.setHex(t):console.warn("THREE.Color: Unknown color "+e),this},clone:function(){return new this.constructor(this.r,this.g,this.b)},copy:function(e){return this.r=e.r,this.g=e.g,this.b=e.b,this},copyGammaToLinear:function(e,t){return void 0===t&&(t=2),this.r=Math.pow(e.r,t),this.g=Math.pow(e.g,t),this.b=Math.pow(e.b,t),this},copyLinearToGamma:function(e,t){void 0===t&&(t=2);var n=t>0?1/t:1;return this.r=Math.pow(e.r,n),this.g=Math.pow(e.g,n),this.b=Math.pow(e.b,n),this},convertGammaToLinear:function(e){return this.copyGammaToLinear(this,e),this},convertLinearToGamma:function(e){return this.copyLinearToGamma(this,e),this},copySRGBToLinear:function(e){return this.r=ke(e.r),this.g=ke(e.g),this.b=ke(e.b),this},copyLinearToSRGB:function(e){return this.r=He(e.r),this.g=He(e.g),this.b=He(e.b),this},convertSRGBToLinear:function(){return this.copySRGBToLinear(this),this},convertLinearToSRGB:function(){return this.copyLinearToSRGB(this),this},getHex:function(){return 255*this.r<<16^255*this.g<<8^255*this.b<<0},getHexString:function(){return("000000"+this.getHex().toString(16)).slice(-6)},getHSL:function(e){void 0===e&&(console.warn("THREE.Color: .getHSL() target is now required"),e={h:0,s:0,l:0});var t,n,i=this.r,r=this.g,a=this.b,o=Math.max(i,r,a),s=Math.min(i,r,a),l=(s+o)/2;if(s===o)t=0,n=0;else{var c=o-s;switch(n=l<=.5?c/(o+s):c/(2-o-s),o){case i:t=(r-a)/c+(r0&&(n.alphaTest=this.alphaTest),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(n.wireframe=this.wireframe),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.morphTargets&&(n.morphTargets=!0),!0===this.morphNormals&&(n.morphNormals=!0),!0===this.skinning&&(n.skinning=!0),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),"{}"!==JSON.stringify(this.userData)&&(n.userData=this.userData),t){var r=i(e.textures),a=i(e.images);r.length>0&&(n.textures=r),a.length>0&&(n.images=a)}return n},clone:function(){return(new this.constructor).copy(this)},copy:function(e){this.name=e.name,this.fog=e.fog,this.blending=e.blending,this.side=e.side,this.flatShading=e.flatShading,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;var t=e.clippingPlanes,n=null;if(null!==t){var i=t.length;n=new Array(i);for(var r=0;r!==i;++r)n[r]=t[r].clone()}return this.clippingPlanes=n,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.premultipliedAlpha=e.premultipliedAlpha,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),Object.defineProperty(Xe.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),qe.prototype=Object.create(Xe.prototype),qe.prototype.constructor=qe,qe.prototype.isMeshBasicMaterial=!0,qe.prototype.copy=function(e){return Xe.prototype.copy.call(this,e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this};var Ye=new w;function Ze(e,t,n){if(Array.isArray(e))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.name="",this.array=e,this.itemSize=t,this.count=void 0!==e?e.length/t:0,this.normalized=!0===n,this.usage=35044,this.updateRange={offset:0,count:-1},this.version=0}function Je(e,t,n){Ze.call(this,new Int8Array(e),t,n)}function Qe(e,t,n){Ze.call(this,new Uint8Array(e),t,n)}function Ke(e,t,n){Ze.call(this,new Uint8ClampedArray(e),t,n)}function $e(e,t,n){Ze.call(this,new Int16Array(e),t,n)}function et(e,t,n){Ze.call(this,new Uint16Array(e),t,n)}function tt(e,t,n){Ze.call(this,new Int32Array(e),t,n)}function nt(e,t,n){Ze.call(this,new Uint32Array(e),t,n)}function it(e,t,n){Ze.call(this,new Float32Array(e),t,n)}function rt(e,t,n){Ze.call(this,new Float64Array(e),t,n)}function at(){this.vertices=[],this.normals=[],this.colors=[],this.uvs=[],this.uvs2=[],this.groups=[],this.morphTargets={},this.skinWeights=[],this.skinIndices=[],this.boundingBox=null,this.boundingSphere=null,this.verticesNeedUpdate=!1,this.normalsNeedUpdate=!1,this.colorsNeedUpdate=!1,this.uvsNeedUpdate=!1,this.groupsNeedUpdate=!1}function ot(e){if(0===e.length)return-1/0;let t=e[0];for(let n=1,i=e.length;nt&&(t=e[n]);return t}Object.defineProperty(Ze.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),Object.assign(Ze.prototype,{isBufferAttribute:!0,onUploadCallback:function(){},setUsage:function(e){return this.usage=e,this},copy:function(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this},copyAt:function(e,t,n){e*=this.itemSize,n*=t.itemSize;for(var i=0,r=this.itemSize;i0,o=r[1]&&r[1].length>0,s=e.morphTargets,l=s.length;if(l>0){t=[];for(var c=0;c0){h=[];for(c=0;c0&&0===n.length&&console.error("THREE.DirectGeometry: Faceless geometries are not supported.");for(c=0;c65535?nt:et)(e,1):this.index=e},getAttribute:function(e){return this.attributes[e]},setAttribute:function(e,t){return this.attributes[e]=t,this},deleteAttribute:function(e){return delete this.attributes[e],this},addGroup:function(e,t,n){this.groups.push({start:e,count:t,materialIndex:void 0!==n?n:0})},clearGroups:function(){this.groups=[]},setDrawRange:function(e,t){this.drawRange.start=e,this.drawRange.count=t},applyMatrix4:function(e){var t=this.attributes.position;void 0!==t&&(t.applyMatrix4(e),t.needsUpdate=!0);var n=this.attributes.normal;if(void 0!==n){var i=(new f).getNormalMatrix(e);n.applyNormalMatrix(i),n.needsUpdate=!0}var r=this.attributes.tangent;return void 0!==r&&(r.transformDirection(e),r.needsUpdate=!0),null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},rotateX:function(e){return lt.makeRotationX(e),this.applyMatrix4(lt),this},rotateY:function(e){return lt.makeRotationY(e),this.applyMatrix4(lt),this},rotateZ:function(e){return lt.makeRotationZ(e),this.applyMatrix4(lt),this},translate:function(e,t,n){return lt.makeTranslation(e,t,n),this.applyMatrix4(lt),this},scale:function(e,t,n){return lt.makeScale(e,t,n),this.applyMatrix4(lt),this},lookAt:function(e){return ct.lookAt(e),ct.updateMatrix(),this.applyMatrix4(ct.matrix),this},center:function(){return this.computeBoundingBox(),this.boundingBox.getCenter(ht).negate(),this.translate(ht.x,ht.y,ht.z),this},setFromObject:function(e){var t=e.geometry;if(e.isPoints||e.isLine){var n=new it(3*t.vertices.length,3),i=new it(3*t.colors.length,3);if(this.setAttribute("position",n.copyVector3sArray(t.vertices)),this.setAttribute("color",i.copyColorsArray(t.colors)),t.lineDistances&&t.lineDistances.length===t.vertices.length){var r=new it(t.lineDistances.length,1);this.setAttribute("lineDistance",r.copyArray(t.lineDistances))}null!==t.boundingSphere&&(this.boundingSphere=t.boundingSphere.clone()),null!==t.boundingBox&&(this.boundingBox=t.boundingBox.clone())}else e.isMesh&&t&&t.isGeometry&&this.fromGeometry(t);return this},setFromPoints:function(e){for(var t=[],n=0,i=e.length;n0){var n=new Float32Array(3*e.normals.length);this.setAttribute("normal",new Ze(n,3).copyVector3sArray(e.normals))}if(e.colors.length>0){var i=new Float32Array(3*e.colors.length);this.setAttribute("color",new Ze(i,3).copyColorsArray(e.colors))}if(e.uvs.length>0){var r=new Float32Array(2*e.uvs.length);this.setAttribute("uv",new Ze(r,2).copyVector2sArray(e.uvs))}if(e.uvs2.length>0){var a=new Float32Array(2*e.uvs2.length);this.setAttribute("uv2",new Ze(a,2).copyVector2sArray(e.uvs2))}for(var o in this.groups=e.groups,e.morphTargets){for(var s=[],l=e.morphTargets[o],c=0,h=l.length;c0){var p=new it(4*e.skinIndices.length,4);this.setAttribute("skinIndex",p.copyVector4sArray(e.skinIndices))}if(e.skinWeights.length>0){var f=new it(4*e.skinWeights.length,4);this.setAttribute("skinWeight",f.copyVector4sArray(e.skinWeights))}return null!==e.boundingSphere&&(this.boundingSphere=e.boundingSphere.clone()),null!==e.boundingBox&&(this.boundingBox=e.boundingBox.clone()),this},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new he);var e=this.attributes.position,t=this.morphAttributes.position;if(void 0!==e){if(this.boundingBox.setFromBufferAttribute(e),t)for(var n=0,i=t.length;n0&&(e.userData=this.userData),void 0!==this.parameters){var t=this.parameters;for(var n in t)void 0!==t[n]&&(e[n]=t[n]);return e}e.data={attributes:{}};var i=this.index;null!==i&&(e.data.index={type:i.array.constructor.name,array:Array.prototype.slice.call(i.array)});var r=this.attributes;for(var n in r){var a=(d=r[n]).toJSON();""!==d.name&&(a.name=d.name),e.data.attributes[n]=a}var o={},s=!1;for(var n in this.morphAttributes){for(var l=this.morphAttributes[n],c=[],h=0,u=l.length;h0&&(o[n]=c,s=!0)}s&&(e.data.morphAttributes=o,e.data.morphTargetsRelative=this.morphTargetsRelative);var p=this.groups;p.length>0&&(e.data.groups=JSON.parse(JSON.stringify(p)));var f=this.boundingSphere;return null!==f&&(e.data.boundingSphere={center:f.center.toArray(),radius:f.radius}),e},clone:function(){return(new ft).copy(this)},copy:function(e){var t,n,i;this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var r=e.index;null!==r&&this.setIndex(r.clone());var a=e.attributes;for(t in a){var o=a[t];this.setAttribute(t,o.clone())}var s=e.morphAttributes;for(t in s){var l=[],c=s[t];for(n=0,i=c.length;nn.far?null:{distance:l,point:Dt.clone(),object:e}}function It(e,t,n,i,r,a,o,s,l,c,h,u){xt.fromBufferAttribute(r,c),_t.fromBufferAttribute(r,h),yt.fromBufferAttribute(r,u);var d=e.morphTargetInfluences;if(t.morphTargets&&a&&d){St.set(0,0,0),Et.set(0,0,0),Tt.set(0,0,0);for(var f=0,m=a.length;f0){var o=r[a[0]];if(void 0!==o)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=o.length;e0&&console.error("THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.")}},raycast:function(e,t){var n,i=this.geometry,r=this.material,a=this.matrixWorld;if(void 0!==r&&(null===i.boundingSphere&&i.computeBoundingSphere(),vt.copy(i.boundingSphere),vt.applyMatrix4(a),!1!==e.ray.intersectsSphere(vt)&&(mt.getInverse(a),gt.copy(e.ray).applyMatrix4(mt),null===i.boundingBox||!1!==gt.intersectsBox(i.boundingBox))))if(i.isBufferGeometry){var o,s,l,c,h,u,d,f,m,g=i.index,v=i.attributes.position,x=i.morphAttributes.position,_=i.morphTargetsRelative,y=i.attributes.uv,M=i.attributes.uv2,b=i.groups,w=i.drawRange;if(null!==g)if(Array.isArray(r))for(c=0,u=b.length;c0&&(L=D);for(var N=0,R=C.length;N0)for(c=0;c0&&(this.normalsNeedUpdate=!0)},computeFlatVertexNormals:function(){var e,t,n;for(this.computeFaceNormals(),e=0,t=this.faces.length;e0&&(this.normalsNeedUpdate=!0)},computeMorphNormals:function(){var e,t,n,i,r;for(n=0,i=this.faces.length;n=0;n--){var f=d[n];for(this.faces.splice(f,1),o=0,s=this.faceVertexUvs.length;o0,g=p.vertexNormals.length>0,v=1!==p.color.r||1!==p.color.g||1!==p.color.b,x=p.vertexColors.length>0,_=0;if(_=w(_,0,0),_=w(_,1,!0),_=w(_,2,!1),_=w(_,3,f),_=w(_,4,m),_=w(_,5,g),_=w(_,6,v),_=w(_,7,x),o.push(_),o.push(p.a,p.b,p.c),o.push(p.materialIndex),f){var y=this.faceVertexUvs[0][r];o.push(T(y[0]),T(y[1]),T(y[2]))}if(m&&o.push(S(p.normal)),g){var M=p.vertexNormals;o.push(S(M[0]),S(M[1]),S(M[2]))}if(v&&o.push(E(p.color)),x){var b=p.vertexColors;o.push(E(b[0]),E(b[1]),E(b[2]))}}function w(e,t,n){return n?e|1<0&&(e.data.colors=c),u.length>0&&(e.data.uvs=[u]),e.data.faces=o,e},clone:function(){return(new Gt).copy(this)},copy:function(e){var t,n,i,r,a,o;this.vertices=[],this.colors=[],this.faces=[],this.faceVertexUvs=[[]],this.morphTargets=[],this.morphNormals=[],this.skinWeights=[],this.skinIndices=[],this.lineDistances=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var s=e.vertices;for(t=0,n=s.length;t0?1:-1,c.push(A.x,A.y,A.z),h.push(s/m),h.push(1-a/g),T+=1}}for(let e=0;e0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader;var r={};for(var a in this.extensions)!0===this.extensions[a]&&(r[a]=!0);return Object.keys(r).length>0&&(t.extensions=r),t},Xt.prototype=Object.assign(Object.create(Z.prototype),{constructor:Xt,isCamera:!0,copy:function(e,t){return Z.prototype.copy.call(this,e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this},getWorldDirection:function(e){void 0===e&&(console.warn("THREE.Camera: .getWorldDirection() target is now required"),e=new w),this.updateMatrixWorld(!0);var t=this.matrixWorld.elements;return e.set(-t[8],-t[9],-t[10]).normalize()},updateMatrixWorld:function(e){Z.prototype.updateMatrixWorld.call(this,e),this.matrixWorldInverse.getInverse(this.matrixWorld)},updateWorldMatrix:function(e,t){Z.prototype.updateWorldMatrix.call(this,e,t),this.matrixWorldInverse.getInverse(this.matrixWorld)},clone:function(){return(new this.constructor).copy(this)}}),qt.prototype=Object.assign(Object.create(Xt.prototype),{constructor:qt,isPerspectiveCamera:!0,copy:function(e,t){return Xt.prototype.copy.call(this,e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=null===e.view?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this},setFocalLength:function(e){var t=.5*this.getFilmHeight()/e;this.fov=2*d.RAD2DEG*Math.atan(t),this.updateProjectionMatrix()},getFocalLength:function(){var e=Math.tan(.5*d.DEG2RAD*this.fov);return.5*this.getFilmHeight()/e},getEffectiveFOV:function(){return 2*d.RAD2DEG*Math.atan(Math.tan(.5*d.DEG2RAD*this.fov)/this.zoom)},getFilmWidth:function(){return this.filmGauge*Math.min(this.aspect,1)},getFilmHeight:function(){return this.filmGauge/Math.max(this.aspect,1)},setViewOffset:function(e,t,n,i,r,a){this.aspect=e/t,null===this.view&&(this.view={enabled:!0,fullWidth:1,fullHeight:1,offsetX:0,offsetY:0,width:1,height:1}),this.view.enabled=!0,this.view.fullWidth=e,this.view.fullHeight=t,this.view.offsetX=n,this.view.offsetY=i,this.view.width=r,this.view.height=a,this.updateProjectionMatrix()},clearViewOffset:function(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()},updateProjectionMatrix:function(){var e=this.near,t=e*Math.tan(.5*d.DEG2RAD*this.fov)/this.zoom,n=2*t,i=this.aspect*n,r=-.5*i,a=this.view;if(null!==this.view&&this.view.enabled){var o=a.fullWidth,s=a.fullHeight;r+=a.offsetX*i/o,t-=a.offsetY*n/s,i*=a.width/o,n*=a.height/s}var l=this.filmOffset;0!==l&&(r+=e*l/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,t,t-n,e,this.far),this.projectionMatrixInverse.getInverse(this.projectionMatrix)},toJSON:function(e){var t=Z.prototype.toJSON.call(this,e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,null!==this.view&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}}),Yt.prototype=Object.create(v.prototype),Yt.prototype.constructor=Yt,Yt.prototype.isDataTexture=!0;var Zt=new pe,Jt=new w;function Qt(e,t,n,i,r,a){this.planes=[void 0!==e?e:new Ee,void 0!==t?t:new Ee,void 0!==n?n:new Ee,void 0!==i?i:new Ee,void 0!==r?r:new Ee,void 0!==a?a:new Ee]}Object.assign(Qt.prototype,{set:function(e,t,n,i,r,a){var o=this.planes;return o[0].copy(e),o[1].copy(t),o[2].copy(n),o[3].copy(i),o[4].copy(r),o[5].copy(a),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){for(var t=this.planes,n=0;n<6;n++)t[n].copy(e.planes[n]);return this},setFromProjectionMatrix:function(e){var t=this.planes,n=e.elements,i=n[0],r=n[1],a=n[2],o=n[3],s=n[4],l=n[5],c=n[6],h=n[7],u=n[8],d=n[9],p=n[10],f=n[11],m=n[12],g=n[13],v=n[14],x=n[15];return t[0].setComponents(o-i,h-s,f-u,x-m).normalize(),t[1].setComponents(o+i,h+s,f+u,x+m).normalize(),t[2].setComponents(o+r,h+l,f+d,x+g).normalize(),t[3].setComponents(o-r,h-l,f-d,x-g).normalize(),t[4].setComponents(o-a,h-c,f-p,x-v).normalize(),t[5].setComponents(o+a,h+c,f+p,x+v).normalize(),this},intersectsObject:function(e){var t=e.geometry;return null===t.boundingSphere&&t.computeBoundingSphere(),Zt.copy(t.boundingSphere).applyMatrix4(e.matrixWorld),this.intersectsSphere(Zt)},intersectsSprite:function(e){return Zt.center.set(0,0,0),Zt.radius=.7071067811865476,Zt.applyMatrix4(e.matrixWorld),this.intersectsSphere(Zt)},intersectsSphere:function(e){for(var t=this.planes,n=e.center,i=-e.radius,r=0;r<6;r++){if(t[r].distanceToPoint(n)0?e.max.x:e.min.x,Jt.y=i.normal.y>0?e.max.y:e.min.y,Jt.z=i.normal.z>0?e.max.z:e.min.z,i.distanceToPoint(Jt)<0)return!1}return!0},containsPoint:function(e){for(var t=this.planes,n=0;n<6;n++)if(t[n].distanceToPoint(e)<0)return!1;return!0}});var Kt={common:{diffuse:{value:new Be(15658734)},opacity:{value:1},map:{value:null},uvTransform:{value:new f},uv2Transform:{value:new f},alphaMap:{value:null}},specularmap:{specularMap:{value:null}},envmap:{envMap:{value:null},flipEnvMap:{value:-1},reflectivity:{value:1},refractionRatio:{value:.98},maxMipLevel:{value:0}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1}},emissivemap:{emissiveMap:{value:null}},bumpmap:{bumpMap:{value:null},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalScale:{value:new p(1,1)}},displacementmap:{displacementMap:{value:null},displacementScale:{value:1},displacementBias:{value:0}},roughnessmap:{roughnessMap:{value:null}},metalnessmap:{metalnessMap:{value:null}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Be(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowBias:{},shadowRadius:{},shadowMapSize:{}}},spotShadowMap:{value:[]},spotShadowMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowBias:{},shadowRadius:{},shadowMapSize:{},shadowCameraNear:{},shadowCameraFar:{}}},pointShadowMap:{value:[]},pointShadowMatrix:{value:[]},hemisphereLights:{value:[],properties:{direction:{},skyColor:{},groundColor:{}}},rectAreaLights:{value:[],properties:{color:{},position:{},width:{},height:{}}}},points:{diffuse:{value:new Be(15658734)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},uvTransform:{value:new f}},sprite:{diffuse:{value:new Be(15658734)},opacity:{value:1},center:{value:new p(.5,.5)},rotation:{value:0},map:{value:null},alphaMap:{value:null},uvTransform:{value:new f}}};function $t(){var e=null,t=!1,n=null;function i(r,a){!1!==t&&(n(r,a),e.requestAnimationFrame(i))}return{start:function(){!0!==t&&null!==n&&(e.requestAnimationFrame(i),t=!0)},stop:function(){t=!1},setAnimationLoop:function(e){n=e},setContext:function(t){e=t}}}function en(e,t){var n=t.isWebGL2,i=new WeakMap;return{get:function(e){return e.isInterleavedBufferAttribute&&(e=e.data),i.get(e)},remove:function(t){t.isInterleavedBufferAttribute&&(t=t.data);var n=i.get(t);n&&(e.deleteBuffer(n.buffer),i.delete(t))},update:function(t,r){t.isInterleavedBufferAttribute&&(t=t.data);var a=i.get(t);void 0===a?i.set(t,function(t,n){var i=t.array,r=t.usage,a=e.createBuffer();e.bindBuffer(n,a),e.bufferData(n,i,r),t.onUploadCallback();var o=5126;return i instanceof Float32Array?o=5126:i instanceof Float64Array?console.warn("THREE.WebGLAttributes: Unsupported data buffer format: Float64Array."):i instanceof Uint16Array?o=5123:i instanceof Int16Array?o=5122:i instanceof Uint32Array?o=5125:i instanceof Int32Array?o=5124:i instanceof Int8Array?o=5120:i instanceof Uint8Array&&(o=5121),{buffer:a,type:o,bytesPerElement:i.BYTES_PER_ELEMENT,version:t.version}}(t,r)):a.version 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\n#else\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t}\n\treturn 1.0;\n#endif\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\n\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\n\treturn Fr * fresnel + F0;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\n\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\treturn specularColor * brdf.x + brdf.y;\n}\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie(float roughness, float NoH) {\n\tfloat invAlpha = 1.0 / roughness;\n\tfloat cos2h = NoH * NoH;\n\tfloat sin2h = max(1.0 - cos2h, 0.0078125);\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\n}\nfloat V_Neubelt(float NoV, float NoL) {\n\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\n}\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n\tvec3 N = geometry.normal;\n\tvec3 V = geometry.viewDir;\n\tvec3 H = normalize( V + L );\n\tfloat dotNH = saturate( dot( N, H ) );\n\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\n}\n#endif",bumpmap_pars_fragment:"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_pars_vertex:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif",color_vertex:"#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif",common:"#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n return m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_maxMipLevel 8.0\n#define cubeUV_minMipLevel 4.0\n#define cubeUV_maxTileSize 256.0\n#define cubeUV_minTileSize 16.0\nfloat getFace(vec3 direction) {\n vec3 absDirection = abs(direction);\n float face = -1.0;\n if (absDirection.x > absDirection.z) {\n if (absDirection.x > absDirection.y)\n face = direction.x > 0.0 ? 0.0 : 3.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n } else {\n if (absDirection.z > absDirection.y)\n face = direction.z > 0.0 ? 2.0 : 5.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n }\n return face;\n}\nvec2 getUV(vec3 direction, float face) {\n vec2 uv;\n if (face == 0.0) {\n uv = vec2(direction.z, direction.y) / abs(direction.x); } else if (face == 1.0) {\n uv = vec2(-direction.x, -direction.z) / abs(direction.y); } else if (face == 2.0) {\n uv = vec2(-direction.x, direction.y) / abs(direction.z); } else if (face == 3.0) {\n uv = vec2(-direction.z, direction.y) / abs(direction.x); } else if (face == 4.0) {\n uv = vec2(-direction.x, direction.z) / abs(direction.y); } else {\n uv = vec2(direction.x, direction.y) / abs(direction.z); }\n return 0.5 * (uv + 1.0);\n}\nvec3 bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {\n float face = getFace(direction);\n float filterInt = max(cubeUV_minMipLevel - mipInt, 0.0);\n mipInt = max(mipInt, cubeUV_minMipLevel);\n float faceSize = exp2(mipInt);\n float texelSize = 1.0 / (3.0 * cubeUV_maxTileSize);\n vec2 uv = getUV(direction, face) * (faceSize - 1.0);\n vec2 f = fract(uv);\n uv += 0.5 - f;\n if (face > 2.0) {\n uv.y += faceSize;\n face -= 3.0;\n }\n uv.x += face * faceSize;\n if(mipInt < cubeUV_maxMipLevel){\n uv.y += 2.0 * cubeUV_maxTileSize;\n }\n uv.y += filterInt * 2.0 * cubeUV_minTileSize;\n uv.x += 3.0 * max(0.0, cubeUV_maxTileSize - 2.0 * faceSize);\n uv *= texelSize;\n vec3 tl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.x += texelSize;\n vec3 tr = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.y += texelSize;\n vec3 br = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.x -= texelSize;\n vec3 bl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n vec3 tm = mix(tl, tr, f.x);\n vec3 bm = mix(bl, br, f.x);\n return mix(tm, bm, f.y);\n}\n#define r0 1.0\n#define v0 0.339\n#define m0 -2.0\n#define r1 0.8\n#define v1 0.276\n#define m1 -1.0\n#define r4 0.4\n#define v4 0.046\n#define m4 2.0\n#define r5 0.305\n#define v5 0.016\n#define m5 3.0\n#define r6 0.21\n#define v6 0.0038\n#define m6 4.0\nfloat roughnessToMip(float roughness) {\n float mip = 0.0;\n if (roughness >= r1) {\n mip = (r0 - roughness) * (m1 - m0) / (r0 - r1) + m0;\n } else if (roughness >= r4) {\n mip = (r1 - roughness) * (m4 - m1) / (r1 - r4) + m1;\n } else if (roughness >= r5) {\n mip = (r4 - roughness) * (m5 - m4) / (r4 - r5) + m4;\n } else if (roughness >= r6) {\n mip = (r5 - roughness) * (m6 - m5) / (r5 - r6) + m5;\n } else {\n mip = -2.0 * log2(1.16 * roughness); }\n return mip;\n}\nvec4 textureCubeUV(sampler2D envMap, vec3 sampleDir, float roughness) {\n float mip = clamp(roughnessToMip(roughness), m0, cubeUV_maxMipLevel);\n float mipF = fract(mip);\n float mipInt = floor(mip);\n vec3 color0 = bilinearCubeUV(envMap, sampleDir, mipInt);\n if (mipF == 0.0) {\n return vec4(color0, 1.0);\n } else {\n vec3 color1 = bilinearCubeUV(envMap, sampleDir, mipInt + 1.0);\n return vec4(mix(color0, color1, mipF), 1.0);\n }\n}\n#endif",defaultnormal_vertex:"vec3 transformedNormal = objectNormal;\n#ifdef USE_INSTANCING\n\tmat3 m = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\ttransformedNormal = m * transformedNormal;\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",encodings_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",encodings_pars_fragment:"\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\n}",envmap_fragment:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\t\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec2 sampleUV = equirectUv( reflectVec );\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifndef ENVMAP_TYPE_CUBE_UV\n\t\tenvColor = envMapTexelToLinear( envColor );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif",envmap_common_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif",envmap_pars_fragment:"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif",envmap_physical_pars_fragment:"#if defined( USE_ENVMAP )\n\t#ifdef ENVMAP_MODE_REFRACTION\n\t\tuniform float refractionRatio;\n\t#endif\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t vec3 reflectVec = reflect( -viewDir, normal );\n\t\t reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t#else\n\t\t vec3 reflectVec = refract( -viewDir, normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV = equirectUv( reflectVec );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif",envmap_vertex:"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) { \n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif",fog_vertex:"#ifdef USE_FOG\n\tfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n\tvarying float fogDepth;\n#endif",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif",fog_pars_fragment:"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif",gradientmap_pars_fragment:"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn texture2D( gradientMap, coord ).rgb;\n\t#else\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t#endif\n}",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n#endif",lightmap_pars_fragment:"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif",lights_lambert_vertex:"vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry );\n#ifdef DOUBLE_SIDED\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\n#endif\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n#endif",lights_pars_begin:"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif",lights_toon_fragment:"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_toon_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct ToonMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n#define Material_LightProbeLOD( material )\t(0)",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;",lights_phong_pars_fragment:"varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.specularRoughness = max( roughnessFactor, 0.0525 );material.specularRoughness += geometryRoughness;\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\n#ifdef REFLECTIVITY\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#endif\n#ifdef CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheen;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n#ifdef CLEARCOAT\n\tfloat clearcoat;\n\tfloat clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tvec3 sheenColor;\n#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearcoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = ccDotNL * directLight.color;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tccIrradiance *= PI;\n\t\t#endif\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\n\t\t\tmaterial.specularRoughness,\n\t\t\tdirectLight.direction,\n\t\t\tgeometry,\n\t\t\tmaterial.sheenColor\n\t\t);\n\t#else\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\n\t#endif\n\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef CLEARCOAT\n\t\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\t\tfloat ccDotNL = ccDotNV;\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\t#else\n\t\tfloat clearcoatDHR = 0.0;\n\t#endif\n\tfloat clearcoatInv = 1.0 - clearcoatDHR;\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\treflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}",lights_fragment_begin:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n#ifdef CLEARCOAT\n\tgeometry.clearcoatNormal = clearcoatNormal;\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif",lights_fragment_maps:"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\n\t#ifdef CLEARCOAT\n\t\tclearcoatRadiance += getLightProbeIndirectRadiance( geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif",map_particle_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n#endif\n#ifdef USE_MAP\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif",map_particle_pars_fragment:"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\tuniform mat3 uvTransform;\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t#endif\n#endif",normal_fragment_begin:"#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\t#ifdef USE_TANGENT\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t#endif\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\t\t#endif\n\t#endif\n#endif\nvec3 geometryNormal = normal;",normal_fragment_maps:"#ifdef OBJECTSPACE_NORMALMAP\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( TANGENTSPACE_NORMALMAP )\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\t#ifdef USE_TANGENT\n\t\tnormal = normalize( vTBN * mapN );\n\t#else\n\t\tnormal = perturbNormal2Arb( -vViewPosition, normal, mapN );\n\t#endif\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef OBJECTSPACE_NORMALMAP\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tmat3 tsn = mat3( S, T, N );\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef CLEARCOAT\n\tvec3 clearcoatNormal = geometryNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\t#ifdef USE_TANGENT\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\t#else\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN );\n\t#endif\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif",packing:"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ));\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w);\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif",project_vertex:"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;",dithering_fragment:"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif",dithering_pars_fragment:"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n#endif",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}",skinbase_vertex:"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif",skinning_pars_vertex:"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform highp sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif",skinning_vertex:"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif",skinnormal_vertex:"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif",specularmap_fragment:"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif",specularmap_pars_fragment:"#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif",tonemapping_fragment:"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif",tonemapping_pars_fragment:"#ifndef saturate\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( ( color * ( 2.51 * color + 0.03 ) ) / ( color * ( 2.43 * color + 0.59 ) + 0.14 ) );\n}",uv_pars_fragment:"#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#ifdef USE_UV\n\t#ifdef UVS_VERTEX_ONLY\n\t\tvec2 vUv;\n\t#else\n\t\tvarying vec2 vUv;\n\t#endif\n\tuniform mat3 uvTransform;\n#endif",uv_vertex:"#ifdef USE_UV\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif",uv2_pars_fragment:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif",uv2_pars_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\tuniform mat3 uv2Transform;\n#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif",background_frag:"uniform sampler2D t2D;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}",background_vert:"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}",cube_frag:"#include \nuniform float opacity;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 vReflect = vWorldDirection;\n\t#include \n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\t#include \n\t#include \n}",cube_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}",depth_frag:"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}",depth_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvHighPrecisionZW = gl_Position.zw;\n}",distanceRGBA_frag:"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main () {\n\t#include \n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \n\t#include \n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include \n\t\t#include \n\t\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvWorldPosition = worldPosition.xyz;\n}",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\tgl_FragColor = mapTexelToLinear( texColor );\n\t#include \n\t#include \n}",equirect_vert:"varying vec3 vWorldDirection;\n#include \nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}",linedashed_frag:"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshbasic_vert:"#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef USE_ENVMAP\n\t#include \n\t#include \n\t#include \n\t#include \n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\t#else\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\t#endif\n\t#include \n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_frag:"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\t#else\n\t\tvec4 matcapColor = vec4( 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshmatcap_vert:"#define MATCAP\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#ifndef FLAT_SHADED\n\t\tvNormal = normalize( transformedNormal );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n}",meshtoon_frag:"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshtoon_vert:"#define TOON\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",meshphong_frag:"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include \n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphong_vert:"#define PHONG\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_frag:"#define STANDARD\n#ifdef PHYSICAL\n\t#define REFLECTIVITY\n\t#define CLEARCOAT\n\t#define TRANSPARENCY\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef TRANSPARENCY\n\tuniform float transparency;\n#endif\n#ifdef REFLECTIVITY\n\tuniform float reflectivity;\n#endif\n#ifdef CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheen;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#ifdef TRANSPARENCY\n\t\tdiffuseColor.a *= saturate( 1. - transparency + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) );\n\t#endif\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",meshphysical_vert:"#define STANDARD\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\tvViewPosition = - mvPosition.xyz;\n\t#include \n\t#include \n\t#include \n}",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n\t#include \n}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n}",shadow_frag:"uniform vec3 color;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}",sprite_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include \n\t#include \n\t#include \n}",sprite_vert:"uniform float rotation;\nuniform vec2 center;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}"},an={basic:{uniforms:Ht([Kt.common,Kt.specularmap,Kt.envmap,Kt.aomap,Kt.lightmap,Kt.fog]),vertexShader:rn.meshbasic_vert,fragmentShader:rn.meshbasic_frag},lambert:{uniforms:Ht([Kt.common,Kt.specularmap,Kt.envmap,Kt.aomap,Kt.lightmap,Kt.emissivemap,Kt.fog,Kt.lights,{emissive:{value:new Be(0)}}]),vertexShader:rn.meshlambert_vert,fragmentShader:rn.meshlambert_frag},phong:{uniforms:Ht([Kt.common,Kt.specularmap,Kt.envmap,Kt.aomap,Kt.lightmap,Kt.emissivemap,Kt.bumpmap,Kt.normalmap,Kt.displacementmap,Kt.fog,Kt.lights,{emissive:{value:new Be(0)},specular:{value:new Be(1118481)},shininess:{value:30}}]),vertexShader:rn.meshphong_vert,fragmentShader:rn.meshphong_frag},standard:{uniforms:Ht([Kt.common,Kt.envmap,Kt.aomap,Kt.lightmap,Kt.emissivemap,Kt.bumpmap,Kt.normalmap,Kt.displacementmap,Kt.roughnessmap,Kt.metalnessmap,Kt.fog,Kt.lights,{emissive:{value:new Be(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:rn.meshphysical_vert,fragmentShader:rn.meshphysical_frag},toon:{uniforms:Ht([Kt.common,Kt.specularmap,Kt.aomap,Kt.lightmap,Kt.emissivemap,Kt.bumpmap,Kt.normalmap,Kt.displacementmap,Kt.gradientmap,Kt.fog,Kt.lights,{emissive:{value:new Be(0)},specular:{value:new Be(1118481)},shininess:{value:30}}]),vertexShader:rn.meshtoon_vert,fragmentShader:rn.meshtoon_frag},matcap:{uniforms:Ht([Kt.common,Kt.bumpmap,Kt.normalmap,Kt.displacementmap,Kt.fog,{matcap:{value:null}}]),vertexShader:rn.meshmatcap_vert,fragmentShader:rn.meshmatcap_frag},points:{uniforms:Ht([Kt.points,Kt.fog]),vertexShader:rn.points_vert,fragmentShader:rn.points_frag},dashed:{uniforms:Ht([Kt.common,Kt.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:rn.linedashed_vert,fragmentShader:rn.linedashed_frag},depth:{uniforms:Ht([Kt.common,Kt.displacementmap]),vertexShader:rn.depth_vert,fragmentShader:rn.depth_frag},normal:{uniforms:Ht([Kt.common,Kt.bumpmap,Kt.normalmap,Kt.displacementmap,{opacity:{value:1}}]),vertexShader:rn.normal_vert,fragmentShader:rn.normal_frag},sprite:{uniforms:Ht([Kt.sprite,Kt.fog]),vertexShader:rn.sprite_vert,fragmentShader:rn.sprite_frag},background:{uniforms:{uvTransform:{value:new f},t2D:{value:null}},vertexShader:rn.background_vert,fragmentShader:rn.background_frag},cube:{uniforms:Ht([Kt.envmap,{opacity:{value:1}}]),vertexShader:rn.cube_vert,fragmentShader:rn.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:rn.equirect_vert,fragmentShader:rn.equirect_frag},distanceRGBA:{uniforms:Ht([Kt.common,Kt.displacementmap,{referencePosition:{value:new w},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:rn.distanceRGBA_vert,fragmentShader:rn.distanceRGBA_frag},shadow:{uniforms:Ht([Kt.lights,Kt.fog,{color:{value:new Be(0)},opacity:{value:1}}]),vertexShader:rn.shadow_vert,fragmentShader:rn.shadow_frag}};function on(e,t,n,i){var r,a,o=new Be(0),s=0,l=null,c=0,h=null;function u(e,n){t.buffers.color.setClear(e.r,e.g,e.b,n,i)}return{getClearColor:function(){return o},setClearColor:function(e,t){o.set(e),u(o,s=void 0!==t?t:1)},getClearAlpha:function(){return s},setClearAlpha:function(e){u(o,s=e)},render:function(t,i,d,p){var f=i.background,m=e.xr,g=m.getSession&&m.getSession();if(g&&"additive"===g.environmentBlendMode&&(f=null),null===f?u(o,s):f&&f.isColor&&(u(f,1),p=!0),(e.autoClear||p)&&e.clear(e.autoClearColor,e.autoClearDepth,e.autoClearStencil),f&&(f.isCubeTexture||f.isWebGLCubeRenderTarget||306===f.mapping)){void 0===a&&((a=new Nt(new Vt(1,1,1),new jt({type:"BackgroundCubeMaterial",uniforms:kt(an.cube.uniforms),vertexShader:an.cube.vertexShader,fragmentShader:an.cube.fragmentShader,side:1,depthTest:!1,depthWrite:!1,fog:!1}))).geometry.deleteAttribute("normal"),a.geometry.deleteAttribute("uv"),a.onBeforeRender=function(e,t,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(a.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),n.update(a));var v=f.isWebGLCubeRenderTarget?f.texture:f;a.material.uniforms.envMap.value=v,a.material.uniforms.flipEnvMap.value=v.isCubeTexture?-1:1,l===f&&c===v.version&&h===e.toneMapping||(a.material.needsUpdate=!0,l=f,c=v.version,h=e.toneMapping),t.unshift(a,a.geometry,a.material,0,0,null)}else f&&f.isTexture&&(void 0===r&&((r=new Nt(new nn(2,2),new jt({type:"BackgroundMaterial",uniforms:kt(an.background.uniforms),vertexShader:an.background.vertexShader,fragmentShader:an.background.fragmentShader,side:0,depthTest:!1,depthWrite:!1,fog:!1}))).geometry.deleteAttribute("normal"),Object.defineProperty(r.material,"map",{get:function(){return this.uniforms.t2D.value}}),n.update(r)),r.material.uniforms.t2D.value=f,!0===f.matrixAutoUpdate&&f.updateMatrix(),r.material.uniforms.uvTransform.value.copy(f.matrix),l===f&&c===f.version&&h===e.toneMapping||(r.material.needsUpdate=!0,l=f,c=f.version,h=e.toneMapping),t.unshift(r,r.geometry,r.material,0,0,null))}}}function sn(e,t,n,i){var r,a=i.isWebGL2;this.setMode=function(e){r=e},this.render=function(t,i){e.drawArrays(r,t,i),n.update(i,r)},this.renderInstances=function(i,o,s,l){if(0!==l){var c,h;if(a)c=e,h="drawArraysInstanced";else if(h="drawArraysInstancedANGLE",null===(c=t.get("ANGLE_instanced_arrays")))return void console.error("THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.");c[h](r,o,s,l),n.update(s,r,l)}}}function ln(e,t,n){var i;function r(t){if("highp"===t){if(e.getShaderPrecisionFormat(35633,36338).precision>0&&e.getShaderPrecisionFormat(35632,36338).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(35633,36337).precision>0&&e.getShaderPrecisionFormat(35632,36337).precision>0?"mediump":"lowp"}var a="undefined"!=typeof WebGL2RenderingContext&&e instanceof WebGL2RenderingContext||"undefined"!=typeof WebGL2ComputeRenderingContext&&e instanceof WebGL2ComputeRenderingContext,o=void 0!==n.precision?n.precision:"highp",s=r(o);s!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",s,"instead."),o=s);var l=!0===n.logarithmicDepthBuffer,c=e.getParameter(34930),h=e.getParameter(35660),u=e.getParameter(3379),d=e.getParameter(34076),p=e.getParameter(34921),f=e.getParameter(36347),m=e.getParameter(36348),g=e.getParameter(36349),v=h>0,x=a||!!t.get("OES_texture_float");return{isWebGL2:a,getMaxAnisotropy:function(){if(void 0!==i)return i;var n=t.get("EXT_texture_filter_anisotropic");return i=null!==n?e.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0},getMaxPrecision:r,precision:o,logarithmicDepthBuffer:l,maxTextures:c,maxVertexTextures:h,maxTextureSize:u,maxCubemapSize:d,maxAttributes:p,maxVertexUniforms:f,maxVaryings:m,maxFragmentUniforms:g,vertexTextures:v,floatFragmentTextures:x,floatVertexTextures:v&&x,maxSamples:a?e.getParameter(36183):0}}function cn(){var e=this,t=null,n=0,i=!1,r=!1,a=new Ee,o=new f,s={value:null,needsUpdate:!1};function l(){s.value!==t&&(s.value=t,s.needsUpdate=n>0),e.numPlanes=n,e.numIntersection=0}function c(t,n,i,r){var l=null!==t?t.length:0,c=null;if(0!==l){if(c=s.value,!0!==r||null===c){var h=i+4*l,u=n.matrixWorldInverse;o.getNormalMatrix(u),(null===c||c.length65535?nt:et)(n,1);p.version=o,t.update(p,34963);var f=r.get(e);f&&t.remove(f),r.set(e,p)}return{get:function(e,t){var r=i.get(t);return r||(t.addEventListener("dispose",a),t.isBufferGeometry?r=t:t.isGeometry&&(void 0===t._bufferGeometry&&(t._bufferGeometry=(new ft).setFromObject(e)),r=t._bufferGeometry),i.set(t,r),n.memory.geometries++,r)},update:function(e){var n=e.index,i=e.attributes;for(var r in null!==n&&t.update(n,34963),i)t.update(i[r],34962);var a=e.morphAttributes;for(var r in a)for(var o=a[r],s=0,l=o.length;s0)return e;var r=t*n,a=Sn[r];if(void 0===a&&(a=new Float32Array(r),Sn[r]=a),0!==t){i.toArray(a,0);for(var o=1,s=0;o!==t;++o)s+=n,e[o].toArray(a,s)}return a}function Cn(e,t){if(e.length!==t.length)return!1;for(var n=0,i=e.length;n/gm;function Ei(e){return e.replace(Si,Ti)}function Ti(e,t){var n=rn[t];if(void 0===n)throw new Error("Can not resolve #include <"+t+">");return Ei(n)}var Li=/#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,Ai=/#pragma unroll_loop_start[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}[\s]+?#pragma unroll_loop_end/g;function Pi(e){return e.replace(Ai,Di).replace(Li,Ci)}function Ci(e,t,n,i){return console.warn("WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead."),Di(e,t,n,i)}function Di(e,t,n,i){for(var r="",a=parseInt(t);a0?e.gammaFactor:1,v=n.isWebGL2?"":function(e){return[e.extensionDerivatives||e.envMapCubeUV||e.bumpMap||e.tangentSpaceNormalMap||e.clearcoatNormalMap||e.flatShading||"physical"===e.shaderID?"#extension GL_OES_standard_derivatives : enable":"",(e.extensionFragDepth||e.logarithmicDepthBuffer)&&e.rendererExtensionFragDepth?"#extension GL_EXT_frag_depth : enable":"",e.extensionDrawBuffers&&e.rendererExtensionDrawBuffers?"#extension GL_EXT_draw_buffers : require":"",(e.extensionShaderTextureLOD||e.envMap)&&e.rendererExtensionShaderTextureLod?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Mi).join("\n")}(n),x=function(e){var t=[];for(var n in e){var i=e[n];!1!==i&&t.push("#define "+n+" "+i)}return t.join("\n")}(c),_=l.createProgram();if(n.isRawShaderMaterial?((i=[x].filter(Mi).join("\n")).length>0&&(i+="\n"),(r=[v,x].filter(Mi).join("\n")).length>0&&(r+="\n")):(i=[Ni(n),"#define SHADER_NAME "+n.shaderName,x,n.instancing?"#define USE_INSTANCING":"",n.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+g,"#define MAX_BONES "+n.maxBones,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+f:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMap&&n.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",n.normalMap&&n.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.displacementMap&&n.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexUvs?"#define USE_UV":"",n.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.useVertexTexture?"#define BONE_TEXTURE":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+d:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;","#ifdef USE_INSTANCING"," attribute mat4 instanceMatrix;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#ifdef USE_COLOR","\tattribute vec3 color;","#endif","#ifdef USE_MORPHTARGETS","\tattribute vec3 morphTarget0;","\tattribute vec3 morphTarget1;","\tattribute vec3 morphTarget2;","\tattribute vec3 morphTarget3;","\t#ifdef USE_MORPHNORMALS","\t\tattribute vec3 morphNormal0;","\t\tattribute vec3 morphNormal1;","\t\tattribute vec3 morphNormal2;","\t\tattribute vec3 morphNormal3;","\t#else","\t\tattribute vec3 morphTarget4;","\t\tattribute vec3 morphTarget5;","\t\tattribute vec3 morphTarget6;","\t\tattribute vec3 morphTarget7;","\t#endif","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(Mi).join("\n"),r=[v,Ni(n),"#define SHADER_NAME "+n.shaderName,x,n.alphaTest?"#define ALPHATEST "+n.alphaTest+(n.alphaTest%1?"":".0"):"","#define GAMMA_FACTOR "+g,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.envMap?"#define "+f:"",n.envMap?"#define "+m:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMap&&n.objectSpaceNormalMap?"#define OBJECTSPACE_NORMALMAP":"",n.normalMap&&n.tangentSpaceNormalMap?"#define TANGENTSPACE_NORMALMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.sheen?"#define USE_SHEEN":"",n.vertexTangents?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexUvs?"#define USE_UV":"",n.uvsVertexOnly?"#define UVS_VERTEX_ONLY":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+d:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.logarithmicDepthBuffer&&n.rendererExtensionFragDepth?"#define USE_LOGDEPTHBUF_EXT":"",(n.extensionShaderTextureLOD||n.envMap)&&n.rendererExtensionShaderTextureLod?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",0!==n.toneMapping?"#define TONE_MAPPING":"",0!==n.toneMapping?rn.tonemapping_pars_fragment:"",0!==n.toneMapping?yi("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.outputEncoding||n.mapEncoding||n.matcapEncoding||n.envMapEncoding||n.emissiveMapEncoding||n.lightMapEncoding?rn.encodings_pars_fragment:"",n.mapEncoding?_i("mapTexelToLinear",n.mapEncoding):"",n.matcapEncoding?_i("matcapTexelToLinear",n.matcapEncoding):"",n.envMapEncoding?_i("envMapTexelToLinear",n.envMapEncoding):"",n.emissiveMapEncoding?_i("emissiveMapTexelToLinear",n.emissiveMapEncoding):"",n.lightMapEncoding?_i("lightMapTexelToLinear",n.lightMapEncoding):"",n.outputEncoding?(a="linearToOutputTexel",o=n.outputEncoding,s=vi(o),"vec4 "+a+"( vec4 value ) { return LinearTo"+s[0]+s[1]+"; }"):"",n.depthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(Mi).join("\n")),h=wi(h=bi(h=Ei(h),n),n),u=wi(u=bi(u=Ei(u),n),n),h=Pi(h),u=Pi(u),n.isWebGL2&&!n.isRawShaderMaterial){var y=!1,M=/^\s*#version\s+300\s+es\s*\n/;n.isShaderMaterial&&null!==h.match(M)&&null!==u.match(M)&&(y=!0,h=h.replace(M,""),u=u.replace(M,"")),i=["#version 300 es\n","#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+i,r=["#version 300 es\n","#define varying in",y?"":"out highp vec4 pc_fragColor;",y?"":"#define gl_FragColor pc_fragColor","#define gl_FragDepthEXT gl_FragDepth","#define texture2D texture","#define textureCube texture","#define texture2DProj textureProj","#define texture2DLodEXT textureLod","#define texture2DProjLodEXT textureProjLod","#define textureCubeLodEXT textureLod","#define texture2DGradEXT textureGrad","#define texture2DProjGradEXT textureProjGrad","#define textureCubeGradEXT textureGrad"].join("\n")+"\n"+r}var b,w,S=r+u,E=mi(l,35633,i+h),T=mi(l,35632,S);if(l.attachShader(_,E),l.attachShader(_,T),void 0!==n.index0AttributeName?l.bindAttribLocation(_,0,n.index0AttributeName):!0===n.morphTargets&&l.bindAttribLocation(_,0,"position"),l.linkProgram(_),e.debug.checkShaderErrors){var L=l.getProgramInfoLog(_).trim(),A=l.getShaderInfoLog(E).trim(),P=l.getShaderInfoLog(T).trim(),C=!0,D=!0;if(!1===l.getProgramParameter(_,35714)){C=!1;var N=xi(l,E,"vertex"),R=xi(l,T,"fragment");console.error("THREE.WebGLProgram: shader error: ",l.getError(),"35715",l.getProgramParameter(_,35715),"gl.getProgramInfoLog",L,N,R)}else""!==L?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",L):""!==A&&""!==P||(D=!1);D&&(this.diagnostics={runnable:C,programLog:L,vertexShader:{log:A,prefix:i},fragmentShader:{log:P,prefix:r}})}return l.deleteShader(E),l.deleteShader(T),this.getUniforms=function(){return void 0===b&&(b=new fi(l,_)),b},this.getAttributes=function(){return void 0===w&&(w=function(e,t){for(var n={},i=e.getProgramParameter(t,35721),r=0;r0,maxBones:b,useVertexTexture:o,morphTargets:i.morphTargets,morphNormals:i.morphNormals,maxMorphTargets:e.maxMorphTargets,maxMorphNormals:e.maxMorphNormals,numDirLights:u.directional.length,numPointLights:u.point.length,numSpotLights:u.spot.length,numRectAreaLights:u.rectArea.length,numHemiLights:u.hemi.length,numDirLightShadows:u.directionalShadowMap.length,numPointLightShadows:u.pointShadowMap.length,numSpotLightShadows:u.spotShadowMap.length,numClippingPlanes:m,numClipIntersection:g,dithering:i.dithering,shadowMapEnabled:e.shadowMap.enabled&&p.length>0,shadowMapType:e.shadowMap.type,toneMapping:i.toneMapped?e.toneMapping:0,physicallyCorrectLights:e.physicallyCorrectLights,premultipliedAlpha:i.premultipliedAlpha,alphaTest:i.alphaTest,doubleSided:2===i.side,flipSided:1===i.side,depthPacking:void 0!==i.depthPacking&&i.depthPacking,index0AttributeName:i.index0AttributeName,extensionDerivatives:i.extensions&&i.extensions.derivatives,extensionFragDepth:i.extensions&&i.extensions.fragDepth,extensionDrawBuffers:i.extensions&&i.extensions.drawBuffers,extensionShaderTextureLOD:i.extensions&&i.extensions.shaderTextureLOD,rendererExtensionFragDepth:r||null!==t.get("EXT_frag_depth"),rendererExtensionDrawBuffers:r||null!==t.get("WEBGL_draw_buffers"),rendererExtensionShaderTextureLod:r||null!==t.get("EXT_shader_texture_lod"),onBeforeCompile:i.onBeforeCompile}},this.getProgramCacheKey=function(t){var n=[];if(t.shaderID?n.push(t.shaderID):(n.push(t.fragmentShader),n.push(t.vertexShader)),void 0!==t.defines)for(var i in t.defines)n.push(i),n.push(t.defines[i]);if(void 0===t.isRawShaderMaterial){for(var r=0;r1&&n.sort(e||Oi),i.length>1&&i.sort(t||Ui)}}}function Gi(){var e=new WeakMap;function t(n){var i=n.target;i.removeEventListener("dispose",t),e.delete(i)}return{get:function(n,i){var r,a=e.get(n);return void 0===a?(r=new Fi,e.set(n,new WeakMap),e.get(n).set(i,r),n.addEventListener("dispose",t)):void 0===(r=a.get(i))&&(r=new Fi,a.set(i,r)),r},dispose:function(){e=new WeakMap}}}function Bi(){var e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];var n;switch(t.type){case"DirectionalLight":n={direction:new w,color:new Be};break;case"SpotLight":n={position:new w,direction:new w,color:new Be,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new w,color:new Be,distance:0,decay:0};break;case"HemisphereLight":n={direction:new w,skyColor:new Be,groundColor:new Be};break;case"RectAreaLight":n={color:new Be,position:new w,halfWidth:new w,halfHeight:new w}}return e[t.id]=n,n}}}var Vi=0;function ki(e,t){return(t.castShadow?1:0)-(e.castShadow?1:0)}function Hi(){for(var e,t=new Bi,n=(e={},{get:function(t){if(void 0!==e[t.id])return e[t.id];var n;switch(t.type){case"DirectionalLight":case"SpotLight":n={shadowBias:0,shadowRadius:1,shadowMapSize:new p};break;case"PointLight":n={shadowBias:0,shadowRadius:1,shadowMapSize:new p,shadowCameraNear:1,shadowCameraFar:1e3}}return e[t.id]=n,n}}),i={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1},ambient:[0,0,0],probe:[],directional:[],directionalShadow:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadow:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],point:[],pointShadow:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]},r=0;r<9;r++)i.probe.push(new w);var a=new w,o=new D,s=new D;return{setup:function(e,r,l){for(var c=0,h=0,u=0,d=0;d<9;d++)i.probe[d].set(0,0,0);var p=0,f=0,m=0,g=0,v=0,x=0,_=0,y=0,M=l.matrixWorldInverse;e.sort(ki),d=0;for(var b=e.length;d\nvoid main() {\n float mean = 0.0;\n float squared_mean = 0.0;\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n for ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n #ifdef HORIZONAL_PASS\n vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n mean += distribution.x;\n squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n #else\n float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\n mean += depth;\n squared_mean += depth * depth;\n #endif\n }\n mean = mean * HALF_SAMPLE_RATE;\n squared_mean = squared_mean * HALF_SAMPLE_RATE;\n float std_dev = sqrt( squared_mean - mean * mean );\n gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}"}),d=u.clone();d.defines.HORIZONAL_PASS=1;var f=new ft;f.setAttribute("position",new Ze(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));var m=new Nt(f,u),g=this;function v(n,i){var r=t.update(m);u.uniforms.shadow_pass.value=n.map.texture,u.uniforms.resolution.value=n.mapSize,u.uniforms.radius.value=n.radius,e.setRenderTarget(n.mapPass),e.clear(),e.renderBufferDirect(i,null,r,u,m,null),d.uniforms.shadow_pass.value=n.mapPass.texture,d.uniforms.resolution.value=n.mapSize,d.uniforms.radius.value=n.radius,e.setRenderTarget(n.map),e.clear(),e.renderBufferDirect(i,null,r,d,m,null)}function y(e,t,n){var i=e<<0|t<<1|n<<2,r=s[i];return void 0===r&&(r=new Xi({depthPacking:3201,morphTargets:e,skinning:t}),s[i]=r),r}function M(e,t,n){var i=e<<0|t<<1|n<<2,r=l[i];return void 0===r&&(r=new qi({morphTargets:e,skinning:t}),l[i]=r),r}function b(t,n,i,r,a,o,s){var l=null,u=y,d=t.customDepthMaterial;if(!0===r.isPointLight&&(u=M,d=t.customDistanceMaterial),void 0===d){var p=!1;!0===i.morphTargets&&(p=n.morphAttributes&&n.morphAttributes.position&&n.morphAttributes.position.length>0);var f=!1;!0===t.isSkinnedMesh&&(!0===i.skinning?f=!0:console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",t)),l=u(p,f,!0===t.isInstancedMesh)}else l=d;if(e.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length){var m=l.uuid,g=i.uuid,v=c[m];void 0===v&&(v={},c[m]=v);var x=v[g];void 0===x&&(x=l.clone(),v[g]=x),l=x}return l.visible=i.visible,l.wireframe=i.wireframe,l.side=3===s?null!==i.shadowSide?i.shadowSide:i.side:null!==i.shadowSide?i.shadowSide:h[i.side],l.clipShadows=i.clipShadows,l.clippingPlanes=i.clippingPlanes,l.clipIntersection=i.clipIntersection,l.wireframeLinewidth=i.wireframeLinewidth,l.linewidth=i.linewidth,!0===r.isPointLight&&!0===l.isMeshDistanceMaterial&&(l.referencePosition.setFromMatrixPosition(r.matrixWorld),l.nearDistance=a,l.farDistance=o),l}function w(n,r,a,o,s){if(!1!==n.visible){if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&3===s)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(a.matrixWorldInverse,n.matrixWorld);var l=t.update(n),c=n.material;if(Array.isArray(c))for(var h=l.groups,u=0,d=h.length;un||r.y>n)&&(r.x>n&&(a.x=Math.floor(n/y.x),r.x=a.x*y.x,x.mapSize.x=a.x),r.y>n&&(a.y=Math.floor(n/y.y),r.y=a.y*y.y,x.mapSize.y=a.y)),null===x.map&&!x.isPointLightShadow&&3===this.type){var M={minFilter:1006,magFilter:1006,format:1023};x.map=new _(r.x,r.y,M),x.map.texture.name=m.name+".shadowMap",x.mapPass=new _(r.x,r.y,M),x.camera.updateProjectionMatrix()}if(null===x.map){M={minFilter:1003,magFilter:1003,format:1023};x.map=new _(r.x,r.y,M),x.map.texture.name=m.name+".shadowMap",x.camera.updateProjectionMatrix()}e.setRenderTarget(x.map),e.clear();for(var b=x.getViewportCount(),S=0;S=1):-1!==D.indexOf("OpenGL ES")&&(C=parseFloat(/^OpenGL\ ES\ ([0-9])/.exec(D)[1]),P=C>=2);var N=null,R={},I=new x,z=new x;function O(t,n,i){var r=new Uint8Array(4),a=e.createTexture();e.bindTexture(t,a),e.texParameteri(t,10241,9728),e.texParameteri(t,10240,9728);for(var o=0;oi||e.height>i)&&(r=i/Math.max(e.width,e.height)),r<1||!0===t){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap){var a=t?d.floorPowerOfTwo:Math.floor,o=a(r*e.width),l=a(r*e.height);void 0===s&&(s=g(o,l));var c=n?g(o,l):s;return c.width=o,c.height=l,c.getContext("2d").drawImage(e,0,0,o,l),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+e.width+"x"+e.height+") to ("+o+"x"+l+")."),c}return"data"in e&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+e.width+"x"+e.height+")."),e}return e}function x(e){return d.isPowerOfTwo(e.width)&&d.isPowerOfTwo(e.height)}function _(e,t){return e.generateMipmaps&&t&&1003!==e.minFilter&&1006!==e.minFilter}function y(t,n,r,a){e.generateMipmap(t),i.get(n).__maxMipLevel=Math.log(Math.max(r,a))*Math.LOG2E}function M(n,i,r){if(!1===l)return i;if(null!==n){if(void 0!==e[n])return e[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}var a=i;return 6403===i&&(5126===r&&(a=33326),5131===r&&(a=33325),5121===r&&(a=33321)),6407===i&&(5126===r&&(a=34837),5131===r&&(a=34843),5121===r&&(a=32849)),6408===i&&(5126===r&&(a=34836),5131===r&&(a=34842),5121===r&&(a=32856)),33325!==a&&33326!==a&&34842!==a&&34836!==a||t.get("EXT_color_buffer_float"),a}function b(e){return 1003===e||1004===e||1005===e?9728:9729}function w(t){var n=t.target;n.removeEventListener("dispose",w),function(t){var n=i.get(t);if(void 0===n.__webglInit)return;e.deleteTexture(n.__webglTexture),i.remove(t)}(n),n.isVideoTexture&&f.delete(n),o.memory.textures--}function S(t){var n=t.target;n.removeEventListener("dispose",S),function(t){var n=i.get(t),r=i.get(t.texture);if(!t)return;void 0!==r.__webglTexture&&e.deleteTexture(r.__webglTexture);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLCubeRenderTarget)for(var a=0;a<6;a++)e.deleteFramebuffer(n.__webglFramebuffer[a]),n.__webglDepthbuffer&&e.deleteRenderbuffer(n.__webglDepthbuffer[a]);else e.deleteFramebuffer(n.__webglFramebuffer),n.__webglDepthbuffer&&e.deleteRenderbuffer(n.__webglDepthbuffer),n.__webglMultisampledFramebuffer&&e.deleteFramebuffer(n.__webglMultisampledFramebuffer),n.__webglColorRenderbuffer&&e.deleteRenderbuffer(n.__webglColorRenderbuffer),n.__webglDepthRenderbuffer&&e.deleteRenderbuffer(n.__webglDepthRenderbuffer);i.remove(t.texture),i.remove(t)}(n),o.memory.textures--}var E=0;function T(e,t){var r=i.get(e);if(e.isVideoTexture&&function(e){var t=o.render.frame;f.get(e)!==t&&(f.set(e,t),e.update())}(e),e.version>0&&r.__version!==e.version){var a=e.image;if(void 0===a)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined");else{if(!1!==a.complete)return void R(r,e,t);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.activeTexture(33984+t),n.bindTexture(3553,r.__webglTexture)}function L(t,r){if(6===t.image.length){var o=i.get(t);if(t.version>0&&o.__version!==t.version){N(o,t),n.activeTexture(33984+r),n.bindTexture(34067,o.__webglTexture),e.pixelStorei(37440,t.flipY);for(var s=t&&(t.isCompressedTexture||t.image[0].isCompressedTexture),c=t.image[0]&&t.image[0].isDataTexture,u=[],d=0;d<6;d++)u[d]=s||c?c?t.image[d].image:t.image[d]:v(t.image[d],!1,!0,h);var p,f=u[0],m=x(f)||l,g=a.convert(t.format),b=a.convert(t.type),w=M(t.internalFormat,g,b);if(D(34067,t,m),s){for(d=0;d<6;d++){p=u[d].mipmaps;for(var S=0;S1||i.get(a).__currentAnisotropy)&&(e.texParameterf(n,s.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,r.getMaxAnisotropy())),i.get(a).__currentAnisotropy=a.anisotropy)}}function N(t,n){void 0===t.__webglInit&&(t.__webglInit=!0,n.addEventListener("dispose",w),t.__webglTexture=e.createTexture(),o.memory.textures++)}function R(t,i,r){var o=3553;i.isDataTexture2DArray&&(o=35866),i.isDataTexture3D&&(o=32879),N(t,i),n.activeTexture(33984+r),n.bindTexture(o,t.__webglTexture),e.pixelStorei(37440,i.flipY),e.pixelStorei(37441,i.premultiplyAlpha),e.pixelStorei(3317,i.unpackAlignment);var s=function(e){return!l&&(1001!==e.wrapS||1001!==e.wrapT||1003!==e.minFilter&&1006!==e.minFilter)}(i)&&!1===x(i.image),c=v(i.image,s,!1,u),h=x(c)||l,d=a.convert(i.format),p=a.convert(i.type),f=M(i.internalFormat,d,p);D(o,i,h);var m,g=i.mipmaps;if(i.isDepthTexture)f=6402,l?f=1015===i.type?36012:1014===i.type?33190:1020===i.type?35056:33189:1015===i.type&&console.error("WebGLRenderer: Floating point depth texture requires WebGL2."),1026===i.format&&6402===f&&1012!==i.type&&1014!==i.type&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),i.type=1012,p=a.convert(i.type)),1027===i.format&&6402===f&&(f=34041,1020!==i.type&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),i.type=1020,p=a.convert(i.type))),n.texImage2D(3553,0,f,c.width,c.height,0,d,p,null);else if(i.isDataTexture)if(g.length>0&&h){for(var b=0,w=g.length;b0&&h){for(b=0,w=g.length;b=c&&console.warn("THREE.WebGLTextures: Trying to use "+e+" texture units while this GPU supports only "+c),E+=1,e},this.resetTextureUnits=function(){E=0},this.setTexture2D=T,this.setTexture2DArray=function(e,t){var r=i.get(e);e.version>0&&r.__version!==e.version?R(r,e,t):(n.activeTexture(33984+t),n.bindTexture(35866,r.__webglTexture))},this.setTexture3D=function(e,t){var r=i.get(e);e.version>0&&r.__version!==e.version?R(r,e,t):(n.activeTexture(33984+t),n.bindTexture(32879,r.__webglTexture))},this.setTextureCube=L,this.setTextureCubeDynamic=A,this.setupRenderTarget=function(t){var r=i.get(t),s=i.get(t.texture);t.addEventListener("dispose",S),s.__webglTexture=e.createTexture(),o.memory.textures++;var c=!0===t.isWebGLCubeRenderTarget,h=!0===t.isWebGLMultisampleRenderTarget,u=x(t)||l;if(!l||1022!==t.texture.format||1015!==t.texture.type&&1016!==t.texture.type||(t.texture.format=1023,console.warn("THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.")),c){r.__webglFramebuffer=[];for(var d=0;d<6;d++)r.__webglFramebuffer[d]=e.createFramebuffer()}else if(r.__webglFramebuffer=e.createFramebuffer(),h)if(l){r.__webglMultisampledFramebuffer=e.createFramebuffer(),r.__webglColorRenderbuffer=e.createRenderbuffer(),e.bindRenderbuffer(36161,r.__webglColorRenderbuffer);var p=a.convert(t.texture.format),f=a.convert(t.texture.type),m=M(t.texture.internalFormat,p,f),g=U(t);e.renderbufferStorageMultisample(36161,g,m,t.width,t.height),e.bindFramebuffer(36160,r.__webglMultisampledFramebuffer),e.framebufferRenderbuffer(36160,36064,36161,r.__webglColorRenderbuffer),e.bindRenderbuffer(36161,null),t.depthBuffer&&(r.__webglDepthRenderbuffer=e.createRenderbuffer(),z(r.__webglDepthRenderbuffer,t,!0)),e.bindFramebuffer(36160,null)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.");if(c){n.bindTexture(34067,s.__webglTexture),D(34067,t.texture,u);for(d=0;d<6;d++)I(r.__webglFramebuffer[d],t,36064,34069+d);_(t.texture,u)&&y(34067,t.texture,t.width,t.height),n.bindTexture(34067,null)}else n.bindTexture(3553,s.__webglTexture),D(3553,t.texture,u),I(r.__webglFramebuffer,t,36064,3553),_(t.texture,u)&&y(3553,t.texture,t.width,t.height),n.bindTexture(3553,null);t.depthBuffer&&O(t)},this.updateRenderTargetMipmap=function(e){var t=e.texture;if(_(t,x(e)||l)){var r=e.isWebGLCubeRenderTarget?34067:3553,a=i.get(t).__webglTexture;n.bindTexture(r,a),y(r,t,e.width,e.height),n.bindTexture(r,null)}},this.updateMultisampleRenderTarget=function(t){if(t.isWebGLMultisampleRenderTarget)if(l){var n=i.get(t);e.bindFramebuffer(36008,n.__webglMultisampledFramebuffer),e.bindFramebuffer(36009,n.__webglFramebuffer);var r=t.width,a=t.height,o=16384;t.depthBuffer&&(o|=256),t.stencilBuffer&&(o|=1024),e.blitFramebuffer(0,0,r,a,0,0,r,a,o,9728),e.bindFramebuffer(36160,n.__webglMultisampledFramebuffer)}else console.warn("THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.")},this.safeSetTexture2D=function(e,t){e&&e.isWebGLRenderTarget&&(!1===F&&(console.warn("THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead."),F=!0),e=e.texture),T(e,t)},this.safeSetTextureCube=function(e,t){e&&e.isWebGLCubeRenderTarget&&(!1===G&&(console.warn("THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead."),G=!0),e=e.texture),e&&e.isCubeTexture||Array.isArray(e.image)&&6===e.image.length?L(e,t):A(e,t)}}function Qi(e,t,n){var i=n.isWebGL2;return{convert:function(e){var n;if(1009===e)return 5121;if(1017===e)return 32819;if(1018===e)return 32820;if(1019===e)return 33635;if(1010===e)return 5120;if(1011===e)return 5122;if(1012===e)return 5123;if(1013===e)return 5124;if(1014===e)return 5125;if(1015===e)return 5126;if(1016===e)return i?5131:null!==(n=t.get("OES_texture_half_float"))?n.HALF_FLOAT_OES:null;if(1021===e)return 6406;if(1022===e)return 6407;if(1023===e)return 6408;if(1024===e)return 6409;if(1025===e)return 6410;if(1026===e)return 6402;if(1027===e)return 34041;if(1028===e)return 6403;if(1029===e)return 36244;if(1030===e)return 33319;if(1031===e)return 33320;if(1032===e)return 36248;if(1033===e)return 36249;if(33776===e||33777===e||33778===e||33779===e){if(null===(n=t.get("WEBGL_compressed_texture_s3tc")))return null;if(33776===e)return n.COMPRESSED_RGB_S3TC_DXT1_EXT;if(33777===e)return n.COMPRESSED_RGBA_S3TC_DXT1_EXT;if(33778===e)return n.COMPRESSED_RGBA_S3TC_DXT3_EXT;if(33779===e)return n.COMPRESSED_RGBA_S3TC_DXT5_EXT}if(35840===e||35841===e||35842===e||35843===e){if(null===(n=t.get("WEBGL_compressed_texture_pvrtc")))return null;if(35840===e)return n.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;if(35841===e)return n.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;if(35842===e)return n.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;if(35843===e)return n.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG}if(36196===e)return null!==(n=t.get("WEBGL_compressed_texture_etc1"))?n.COMPRESSED_RGB_ETC1_WEBGL:null;if((37492===e||37496===e)&&null!==(n=t.get("WEBGL_compressed_texture_etc"))){if(37492===e)return n.COMPRESSED_RGB8_ETC2;if(37496===e)return n.COMPRESSED_RGBA8_ETC2_EAC}return 37808===e||37809===e||37810===e||37811===e||37812===e||37813===e||37814===e||37815===e||37816===e||37817===e||37818===e||37819===e||37820===e||37821===e||37840===e||37841===e||37842===e||37843===e||37844===e||37845===e||37846===e||37847===e||37848===e||37849===e||37850===e||37851===e||37852===e||37853===e?null!==(n=t.get("WEBGL_compressed_texture_astc"))?e:null:36492===e?null!==(n=t.get("EXT_texture_compression_bptc"))?e:null:1020===e?i?34042:null!==(n=t.get("WEBGL_depth_texture"))?n.UNSIGNED_INT_24_8_WEBGL:null:void 0}}}function Ki(e){qt.call(this),this.cameras=e||[]}function $i(){Z.call(this),this.type="Group"}function er(){this._targetRay=null,this._grip=null}function tr(e,t){var n=this,i=null,r=1,a=null,o="local-floor",s=null,l=[],c=new Map,h=new qt;h.layers.enable(1),h.viewport=new x;var u=new qt;u.layers.enable(2),u.viewport=new x;var d=[h,u],p=new Ki;p.layers.enable(1),p.layers.enable(2);var f=null,m=null;function g(e){var t=c.get(e.inputSource);t&&t.dispatchEvent({type:e.type})}function v(){c.forEach((function(e,t){e.disconnect(t)})),c.clear(),e.setFramebuffer(null),e.setRenderTarget(e.getRenderTarget()),T.stop(),n.isPresenting=!1,n.dispatchEvent({type:"sessionend"})}function _(e){a=e,T.setContext(i),T.start(),n.isPresenting=!0,n.dispatchEvent({type:"sessionstart"})}function y(e){for(var t=i.inputSources,n=0;n=0){var c=r[s];if(void 0!==c){var h=c.normalized,u=c.itemSize;if(void 0===(b=S.get(c)))continue;var d=b.buffer,p=b.type,f=b.bytesPerElement;if(c.isInterleavedBufferAttribute){var x=c.data,y=x.stride,M=c.offset;x&&x.isInstancedInterleavedBuffer?(_.enableAttributeAndDivisor(l,x.meshPerAttribute),void 0===t._maxInstanceCount&&(t._maxInstanceCount=x.meshPerAttribute*x.count)):_.enableAttribute(l),m.bindBuffer(34962,d),_.vertexAttribPointer(l,u,p,h,y*f,M*f)}else c.isInstancedBufferAttribute?(_.enableAttributeAndDivisor(l,c.meshPerAttribute),void 0===t._maxInstanceCount&&(t._maxInstanceCount=c.meshPerAttribute*c.count)):_.enableAttribute(l),m.bindBuffer(34962,d),_.vertexAttribPointer(l,u,p,h,0,0)}else if("instanceMatrix"===s){var b;if(void 0===(b=S.get(e.instanceMatrix)))continue;d=b.buffer,p=b.type;_.enableAttributeAndDivisor(l+0,1),_.enableAttributeAndDivisor(l+1,1),_.enableAttributeAndDivisor(l+2,1),_.enableAttributeAndDivisor(l+3,1),m.bindBuffer(34962,d),m.vertexAttribPointer(l+0,4,p,!1,64,0),m.vertexAttribPointer(l+1,4,p,!1,64,16),m.vertexAttribPointer(l+2,4,p,!1,64,32),m.vertexAttribPointer(l+3,4,p,!1,64,48)}else if(void 0!==o){var w=o[s];if(void 0!==w)switch(w.length){case 2:m.vertexAttrib2fv(l,w);break;case 3:m.vertexAttrib3fv(l,w);break;case 4:m.vertexAttrib4fv(l,w);break;default:m.vertexAttrib1fv(l,w)}}}}_.disableUnusedAttributes()}(r,n,i,s),null!==c&&m.bindBuffer(34963,u.buffer));var f=null!==c?c.count:h.count,x=n.drawRange.start*d,y=n.drawRange.count*d,M=null!==a?a.start*d:0,b=null!==a?a.count*d:1/0,w=Math.max(x,M),T=Math.min(f,x+y,M+b)-1,L=Math.max(0,T-w+1);if(0!==L){if(r.isMesh)!0===i.wireframe?(_.setLineWidth(i.wireframeLinewidth*de()),p.setMode(1)):p.setMode(4);else if(r.isLine){var A=i.linewidth;void 0===A&&(A=1),_.setLineWidth(A*de()),r.isLineSegments?p.setMode(1):r.isLineLoop?p.setMode(2):p.setMode(3)}else r.isPoints?p.setMode(0):r.isSprite&&p.setMode(4);if(r.isInstancedMesh)p.renderInstances(n,w,L,r.count);else if(n.isInstancedBufferGeometry){var P=Math.min(n.instanceCount,n._maxInstanceCount);p.renderInstances(n,w,L,P)}else p.render(w,L)}},this.compile=function(e,t){(f=C.get(e,t)).init(),e.traverse((function(e){e.isLight&&(f.pushLight(e),e.castShadow&&f.pushShadow(e))})),f.setupLights(t);const n={};e.traverse((function(t){let i=t.material;if(i)if(Array.isArray(i))for(let r=0;r=0&&e.numSupportedMorphTargets++}if(e.morphNormals){e.numSupportedMorphNormals=0;for(d=0;d=0&&e.numSupportedMorphNormals++}var p=i.uniforms;(e.isShaderMaterial||e.isRawShaderMaterial)&&!0!==e.clipping||(i.numClippingPlanes=se.numPlanes,i.numIntersection=se.numIntersection,p.clippingPlanes=se.uniform),i.environment=e.isMeshStandardMaterial?t.environment:null,i.fog=t.fog,i.needsLights=function(e){return e.isMeshLambertMaterial||e.isMeshToonMaterial||e.isMeshPhongMaterial||e.isMeshStandardMaterial||e.isShadowMaterial||e.isShaderMaterial&&!0===e.lights}(e),i.lightsStateVersion=o,i.needsLights&&(p.ambientLightColor.value=r.state.ambient,p.lightProbe.value=r.state.probe,p.directionalLights.value=r.state.directional,p.directionalLightShadows.value=r.state.directionalShadow,p.spotLights.value=r.state.spot,p.spotLightShadows.value=r.state.spotShadow,p.rectAreaLights.value=r.state.rectArea,p.pointLights.value=r.state.point,p.pointLightShadows.value=r.state.pointShadow,p.hemisphereLights.value=r.state.hemi,p.directionalShadowMap.value=r.state.directionalShadowMap,p.directionalShadowMatrix.value=r.state.directionalShadowMatrix,p.spotShadowMap.value=r.state.spotShadowMap,p.spotShadowMatrix.value=r.state.spotShadowMatrix,p.pointShadowMap.value=r.state.pointShadowMap,p.pointShadowMatrix.value=r.state.pointShadowMatrix);var m=i.program.getUniforms(),g=fi.seqWithValue(m.seq,p);i.uniformsList=g}function Ae(e,t,n,i){b.resetTextureUnits();var r=t.fog,a=n.isMeshStandardMaterial?t.environment:null,o=null===k?U.outputEncoding:k.texture.encoding,s=M.get(n),l=f.state.lights;if(le&&(ce||e!==X)){var c=e===X&&n.id===W;se.setState(n.clippingPlanes,n.clipIntersection,n.clipShadows,e,s,c)}n.version===s.__version?void 0===s.program||n.fog&&s.fog!==r||s.environment!==a||s.needsLights&&s.lightsStateVersion!==l.state.version?Le(n,t,i):void 0===s.numClippingPlanes||s.numClippingPlanes===se.numPlanes&&s.numIntersection===se.numIntersection?s.outputEncoding!==o&&Le(n,t,i):Le(n,t,i):(Le(n,t,i),s.__version=n.version);var h,u,p=!1,g=!1,x=!1,y=s.program,w=y.getUniforms(),S=s.uniforms;if(_.useProgram(y.program)&&(p=!0,g=!0,x=!0),n.id!==W&&(W=n.id,g=!0),p||X!==e){if(w.setValue(m,"projectionMatrix",e.projectionMatrix),v.logarithmicDepthBuffer&&w.setValue(m,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),X!==e&&(X=e,g=!0,x=!0),n.isShaderMaterial||n.isMeshPhongMaterial||n.isMeshToonMaterial||n.isMeshStandardMaterial||n.envMap){var E=w.map.cameraPosition;void 0!==E&&E.setValue(m,ue.setFromMatrixPosition(e.matrixWorld))}(n.isMeshPhongMaterial||n.isMeshToonMaterial||n.isMeshLambertMaterial||n.isMeshBasicMaterial||n.isMeshStandardMaterial||n.isShaderMaterial)&&w.setValue(m,"isOrthographic",!0===e.isOrthographicCamera),(n.isMeshPhongMaterial||n.isMeshToonMaterial||n.isMeshLambertMaterial||n.isMeshBasicMaterial||n.isMeshStandardMaterial||n.isShaderMaterial||n.skinning)&&w.setValue(m,"viewMatrix",e.matrixWorldInverse)}if(n.skinning){w.setOptional(m,i,"bindMatrix"),w.setOptional(m,i,"bindMatrixInverse");var T=i.skeleton;if(T){var L=T.bones;if(v.floatVertexTextures){if(void 0===T.boneTexture){var P=Math.sqrt(4*L.length);P=d.ceilPowerOfTwo(P),P=Math.max(P,4);var C=new Float32Array(P*P*4);C.set(T.boneMatrices);var D=new Yt(C,P,P,1023,1015);T.boneMatrices=C,T.boneTexture=D,T.boneTextureSize=P}w.setValue(m,"boneTexture",T.boneTexture,b),w.setValue(m,"boneTextureSize",T.boneTextureSize)}else w.setOptional(m,T,"boneMatrices")}}return(g||s.receiveShadow!==i.receiveShadow)&&(s.receiveShadow=i.receiveShadow,w.setValue(m,"receiveShadow",i.receiveShadow)),g&&(w.setValue(m,"toneMappingExposure",U.toneMappingExposure),w.setValue(m,"toneMappingWhitePoint",U.toneMappingWhitePoint),s.needsLights&&(u=x,(h=S).ambientLightColor.needsUpdate=u,h.lightProbe.needsUpdate=u,h.directionalLights.needsUpdate=u,h.directionalLightShadows.needsUpdate=u,h.pointLights.needsUpdate=u,h.pointLightShadows.needsUpdate=u,h.spotLights.needsUpdate=u,h.spotLightShadows.needsUpdate=u,h.rectAreaLights.needsUpdate=u,h.hemisphereLights.needsUpdate=u),r&&n.fog&&A.refreshFogUniforms(S,r),A.refreshMaterialUniforms(S,n,a,ee,$),void 0!==S.ltc_1&&(S.ltc_1.value=Kt.LTC_1),void 0!==S.ltc_2&&(S.ltc_2.value=Kt.LTC_2),fi.upload(m,s.uniformsList,S,b)),n.isShaderMaterial&&!0===n.uniformsNeedUpdate&&(fi.upload(m,s.uniformsList,S,b),n.uniformsNeedUpdate=!1),n.isSpriteMaterial&&w.setValue(m,"center",i.center),w.setValue(m,"modelViewMatrix",i.modelViewMatrix),w.setValue(m,"normalMatrix",i.normalMatrix),w.setValue(m,"modelMatrix",i.matrixWorld),y}we.setAnimationLoop((function(e){me.isPresenting||be&&be(e)})),"undefined"!=typeof window&&we.setContext(window),this.setAnimationLoop=function(e){be=e,me.setAnimationLoop(e),we.start()},this.render=function(e,t){var n,i;if(void 0!==arguments[2]&&(console.warn("THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead."),n=arguments[2]),void 0!==arguments[3]&&(console.warn("THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead."),i=arguments[3]),t&&t.isCamera){if(!F){j.geometry=null,j.program=null,j.wireframe=!1,W=-1,X=null,!0===e.autoUpdate&&e.updateMatrixWorld(),null===t.parent&&t.updateMatrixWorld(),me.enabled&&me.isPresenting&&(t=me.getCamera(t)),e.onBeforeRender(U,e,t,n||k),(f=C.get(e,t)).init(),he.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),oe.setFromProjectionMatrix(he),ce=this.localClippingEnabled,le=se.init(this.clippingPlanes,ce,t),(u=P.get(e,t)).init(),Se(e,t,0,U.sortObjects),u.finish(),!0===U.sortObjects&&u.sort(te,ne),le&&se.beginShadows();var r=f.state.shadowsArray;ge.render(r,e,t),f.setupLights(t),le&&se.endShadows(),this.info.autoReset&&this.info.reset(),void 0!==n&&this.setRenderTarget(n),N.render(u,e,t,i);var a=u.opaque,o=u.transparent;if(e.overrideMaterial){var s=e.overrideMaterial;a.length&&Ee(a,e,t,s),o.length&&Ee(o,e,t,s)}else a.length&&Ee(a,e,t),o.length&&Ee(o,e,t);e.onAfterRender(U,e,t),null!==k&&(b.updateRenderTargetMipmap(k),b.updateMultisampleRenderTarget(k)),_.buffers.depth.setTest(!0),_.buffers.depth.setMask(!0),_.buffers.color.setMask(!0),_.setPolygonOffset(!1),u=null,f=null}}else console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.")},this.setFramebuffer=function(e){G!==e&&null===k&&m.bindFramebuffer(36160,e),G=e},this.getActiveCubeFace=function(){return B},this.getActiveMipmapLevel=function(){return V},this.getRenderTarget=function(){return k},this.setRenderTarget=function(e,t,n){k=e,B=t,V=n,e&&void 0===M.get(e).__webglFramebuffer&&b.setupRenderTarget(e);var i=G,r=!1;if(e){var a=M.get(e).__webglFramebuffer;e.isWebGLCubeRenderTarget?(i=a[t||0],r=!0):i=e.isWebGLMultisampleRenderTarget?M.get(e).__webglMultisampledFramebuffer:a,Y.copy(e.viewport),Z.copy(e.scissor),Q=e.scissorTest}else Y.copy(ie).multiplyScalar(ee).floor(),Z.copy(re).multiplyScalar(ee).floor(),Q=ae;if(H!==i&&(m.bindFramebuffer(36160,i),H=i),_.viewport(Y),_.scissor(Z),_.setScissorTest(Q),r){var o=M.get(e.texture);m.framebufferTexture2D(36160,36064,34069+(t||0),o.__webglTexture,n||0)}},this.readRenderTargetPixels=function(e,t,n,i,r,a,o){if(e&&e.isWebGLRenderTarget){var s=M.get(e).__webglFramebuffer;if(e.isWebGLCubeRenderTarget&&void 0!==o&&(s=s[o]),s){var l=!1;s!==H&&(m.bindFramebuffer(36160,s),l=!0);try{var c=e.texture,h=c.format,u=c.type;if(1023!==h&&O.convert(h)!==m.getParameter(35739))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!(1009===u||O.convert(u)===m.getParameter(35738)||1015===u&&(v.isWebGL2||g.get("OES_texture_float")||g.get("WEBGL_color_buffer_float"))||1016===u&&(v.isWebGL2?g.get("EXT_color_buffer_float"):g.get("EXT_color_buffer_half_float"))))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");36053===m.checkFramebufferStatus(36160)?t>=0&&t<=e.width-i&&n>=0&&n<=e.height-r&&m.readPixels(t,n,i,r,O.convert(h),O.convert(u),a):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{l&&m.bindFramebuffer(36160,H)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")},this.copyFramebufferToTexture=function(e,t,n){void 0===n&&(n=0);var i=Math.pow(2,-n),r=Math.floor(t.image.width*i),a=Math.floor(t.image.height*i),o=O.convert(t.format);b.setTexture2D(t,0),m.copyTexImage2D(3553,n,o,e.x,e.y,r,a,0),_.unbindTexture()},this.copyTextureToTexture=function(e,t,n,i){void 0===i&&(i=0);var r=t.image.width,a=t.image.height,o=O.convert(n.format),s=O.convert(n.type);b.setTexture2D(n,0),t.isDataTexture?m.texSubImage2D(3553,i,e.x,e.y,r,a,o,s,t.image.data):t.isCompressedTexture?m.compressedTexSubImage2D(3553,i,e.x,e.y,t.mipmaps[0].width,t.mipmaps[0].height,o,t.mipmaps[0].data):m.texSubImage2D(3553,i,e.x,e.y,o,s,t.image),0===i&&n.generateMipmaps&&m.generateMipmap(3553),_.unbindTexture()},this.initTexture=function(e){b.setTexture2D(e,0),_.unbindTexture()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}function rr(e){this.autoStart=void 0===e||e,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}function ar(e,t,n){return this.radius=void 0!==e?e:1,this.phi=void 0!==t?t:0,this.theta=void 0!==n?n:0,this}function or(e,t,n,i,r,a){return[new p(e/r,1-i/a),new p(n/r,1-i/a),new p(n/r,1-t/a),new p(e/r,1-t/a)]}function sr(e,t,n,i){return or(e,t,n,i,64,64)}function lr(e,t,n,i){return or(e,t,n,i,64,32)}function cr(e,t,n,i,r,a,o){e.faceVertexUvs[0]=[],e.faceVertexUvs[0][0]=[a[3],a[0],a[2]],e.faceVertexUvs[0][1]=[a[0],a[1],a[2]],e.faceVertexUvs[0][2]=[i[3],i[0],i[2]],e.faceVertexUvs[0][3]=[i[0],i[1],i[2]],e.faceVertexUvs[0][4]=[t[3],t[0],t[2]],e.faceVertexUvs[0][5]=[t[0],t[1],t[2]],e.faceVertexUvs[0][6]=[n[0],n[3],n[1]],e.faceVertexUvs[0][7]=[n[3],n[2],n[1]],e.faceVertexUvs[0][8]=[r[3],r[0],r[2]],e.faceVertexUvs[0][9]=[r[0],r[1],r[2]],e.faceVertexUvs[0][10]=[o[3],o[0],o[2]],e.faceVertexUvs[0][11]=[o[0],o[1],o[2]]}Ki.prototype=Object.assign(Object.create(qt.prototype),{constructor:Ki,isArrayCamera:!0}),$i.prototype=Object.assign(Object.create(Z.prototype),{constructor:$i,isGroup:!0}),Object.assign(er.prototype,{constructor:er,getTargetRaySpace:function(){return null===this._targetRay&&(this._targetRay=new $i,this._targetRay.matrixAutoUpdate=!1,this._targetRay.visible=!1),this._targetRay},getGripSpace:function(){return null===this._grip&&(this._grip=new $i,this._grip.matrixAutoUpdate=!1,this._grip.visible=!1),this._grip},dispatchEvent:function(e){return null!==this._targetRay&&this._targetRay.dispatchEvent(e),null!==this._grip&&this._grip.dispatchEvent(e),this},disconnect:function(e){return this.dispatchEvent({type:"disconnected",data:e}),null!==this._targetRay&&(this._targetRay.visible=!1),null!==this._grip&&(this._grip.visible=!1),this},update:function(e,t,n){var i=null,r=null,a=this._targetRay,o=this._grip;return e&&(null!==a&&null!==(i=t.getPose(e.targetRaySpace,n))&&(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale)),null!==o&&e.gripSpace&&null!==(r=t.getPose(e.gripSpace,n))&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale))),null!==a&&(a.visible=null!==i),null!==o&&(o.visible=null!==r),this}}),Object.assign(tr.prototype,l.prototype),Object.assign(rr.prototype,{start:function(){this.startTime=("undefined"==typeof performance?Date:performance).now(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0},stop:function(){this.getElapsedTime(),this.running=!1,this.autoStart=!1},getElapsedTime:function(){return this.getDelta(),this.elapsedTime},getDelta:function(){var e=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){var t=("undefined"==typeof performance?Date:performance).now();e=(t-this.oldTime)/1e3,this.oldTime=t,this.elapsedTime+=e}return e}}),Object.assign(ar.prototype,{set:function(e,t,n){return this.radius=e,this.phi=t,this.theta=n,this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.radius=e.radius,this.phi=e.phi,this.theta=e.theta,this},makeSafe:function(){return this.phi=Math.max(1e-6,Math.min(Math.PI-1e-6,this.phi)),this},setFromVector3:function(e){return this.setFromCartesianCoords(e.x,e.y,e.z)},setFromCartesianCoords:function(e,t,n){return this.radius=Math.sqrt(e*e+t*t+n*n),0===this.radius?(this.theta=0,this.phi=0):(this.theta=Math.atan2(e,n),this.phi=Math.acos(d.clamp(t/this.radius,-1,1))),this}});class hr extends $i{constructor(e,t){super(),this.innerLayer=e,this.outerLayer=t,e.name="inner",t.name="outer"}}class ur extends $i{constructor(e){super(),this.modelListeners=[],this.slim=!1;const t={map:e,side:0},n={map:e,side:2,transparent:!0,opacity:1,alphaTest:.5},i=new qe(t),r=new qe(n),a=new Bt(8,8,8,0,0,0);cr(a,sr(8,0,16,8),sr(16,0,24,8),sr(0,8,8,16),sr(8,8,16,16),sr(16,8,24,16),sr(24,8,32,16));const o=new Nt(a,i),s=new Bt(9,9,9,0,0,0);cr(s,sr(40,0,48,8),sr(48,0,56,8),sr(32,8,40,16),sr(40,8,48,16),sr(48,8,56,16),sr(56,8,64,16));const l=new Nt(s,r);l.renderOrder=-1,this.head=new hr(o,l),this.head.name="head",this.head.add(o,l),this.add(this.head);const c=new Bt(8,12,4,0,0,0);cr(c,sr(20,16,28,20),sr(28,16,36,20),sr(16,20,20,32),sr(20,20,28,32),sr(28,20,32,32),sr(32,20,40,32));const h=new Nt(c,new qe(Object.assign(Object.assign({},t),{polygonOffset:!0,polygonOffsetUnits:-1}))),u=new Bt(9,13.5,4.5,0,0,0);cr(u,sr(20,32,28,36),sr(28,32,36,36),sr(16,36,20,48),sr(20,36,28,48),sr(28,36,32,48),sr(32,36,40,48));const d=new Nt(u,new qe(Object.assign(Object.assign({},n),{polygonOffset:!0,polygonOffsetUnits:-1})));this.body=new hr(h,d),this.body.name="body",this.body.add(h,d),this.body.position.y=-10,this.add(this.body);const p=new Bt(1,1,1,0,0,0),f=new Nt(p,i);this.modelListeners.push(()=>{f.scale.x=this.slim?3:4,f.scale.y=12,f.scale.z=4,this.slim?cr(p,sr(44,16,47,20),sr(47,16,50,20),sr(40,20,44,32),sr(44,20,47,32),sr(47,20,51,32),sr(51,20,54,32)):cr(p,sr(44,16,48,20),sr(48,16,52,20),sr(40,20,44,32),sr(44,20,48,32),sr(48,20,52,32),sr(52,20,56,32)),p.uvsNeedUpdate=!0,p.elementsNeedUpdate=!0});const m=new Bt(1,1,1,0,0,0),g=new Nt(m,r);g.renderOrder=1,this.modelListeners.push(()=>{g.scale.x=this.slim?3.375:4.5,g.scale.y=13.5,g.scale.z=4.5,this.slim?cr(m,sr(44,32,47,36),sr(47,32,50,36),sr(40,36,44,48),sr(44,36,47,48),sr(47,36,51,48),sr(51,36,54,48)):cr(m,sr(44,32,48,36),sr(48,32,52,36),sr(40,36,44,48),sr(44,36,48,48),sr(48,36,52,48),sr(52,36,56,48)),m.uvsNeedUpdate=!0,m.elementsNeedUpdate=!0});const v=new $i;v.add(f,g),v.position.y=-4,this.rightArm=new hr(f,g),this.rightArm.name="rightArm",this.rightArm.add(v),this.rightArm.position.y=-6,this.modelListeners.push(()=>{this.rightArm.position.x=this.slim?-5.5:-6}),this.add(this.rightArm);const x=new Bt(1,1,1,0,0,0),_=new Nt(x,i);this.modelListeners.push(()=>{_.scale.x=this.slim?3:4,_.scale.y=12,_.scale.z=4,this.slim?cr(x,sr(36,48,39,52),sr(39,48,42,52),sr(32,52,36,64),sr(36,52,39,64),sr(39,52,43,64),sr(43,52,46,64)):cr(x,sr(36,48,40,52),sr(40,48,44,52),sr(32,52,36,64),sr(36,52,40,64),sr(40,52,44,64),sr(44,52,48,64)),x.uvsNeedUpdate=!0,x.elementsNeedUpdate=!0});const y=new Bt(1,1,1,0,0,0),M=new Nt(y,r);M.renderOrder=1,this.modelListeners.push(()=>{M.scale.x=this.slim?3.375:4.5,M.scale.y=13.5,M.scale.z=4.5,this.slim?cr(y,sr(52,48,55,52),sr(55,48,58,52),sr(48,52,52,64),sr(52,52,55,64),sr(55,52,59,64),sr(59,52,62,64)):cr(y,sr(52,48,56,52),sr(56,48,60,52),sr(48,52,52,64),sr(52,52,56,64),sr(56,52,60,64),sr(60,52,64,64)),y.uvsNeedUpdate=!0,y.elementsNeedUpdate=!0});const b=new $i;b.add(_,M),b.position.y=-4,this.leftArm=new hr(_,M),this.leftArm.name="leftArm",this.leftArm.add(b),this.leftArm.position.y=-6,this.modelListeners.push(()=>{this.leftArm.position.x=this.slim?5.5:6}),this.add(this.leftArm);const w=new Bt(4,12,4,0,0,0);cr(w,sr(4,16,8,20),sr(8,16,12,20),sr(0,20,4,32),sr(4,20,8,32),sr(8,20,12,32),sr(12,20,16,32));const S=new Nt(w,i),E=new Bt(4.5,13.5,4.5,0,0,0);cr(E,sr(4,32,8,36),sr(8,32,12,36),sr(0,36,4,48),sr(4,36,8,48),sr(8,36,12,48),sr(12,36,16,48));const T=new Nt(E,r);T.renderOrder=1;const L=new $i;L.add(S,T),L.position.y=-6,this.rightLeg=new hr(S,T),this.rightLeg.name="rightLeg",this.rightLeg.add(L),this.rightLeg.position.y=-16,this.rightLeg.position.x=-2,this.add(this.rightLeg);const A=new Bt(4,12,4,0,0,0);cr(A,sr(20,48,24,52),sr(24,48,28,52),sr(16,52,20,64),sr(20,52,24,64),sr(24,52,28,64),sr(28,52,32,64));const P=new Nt(A,i),C=new Bt(4.5,13.5,4.5,0,0,0);cr(C,sr(4,48,8,52),sr(8,48,12,52),sr(0,52,4,64),sr(4,52,8,64),sr(8,52,12,64),sr(12,52,16,64));const D=new Nt(C,r);D.renderOrder=1;const N=new $i;N.add(P,D),N.position.y=-6,this.leftLeg=new hr(P,D),this.leftLeg.name="leftLeg",this.leftLeg.add(N),this.leftLeg.position.y=-16,this.leftLeg.position.x=2,this.add(this.leftLeg),this.modelType="default"}get modelType(){return this.slim?"slim":"default"}set modelType(e){this.slim="slim"===e,this.modelListeners.forEach(e=>e())}getBodyParts(){return this.children.filter(e=>e instanceof hr)}setInnerLayerVisible(e){this.getBodyParts().forEach(t=>t.innerLayer.visible=e)}setOuterLayerVisible(e){this.getBodyParts().forEach(t=>t.outerLayer.visible=e)}}class dr extends $i{constructor(e){super();const t=new qe({map:e,transparent:!0,opacity:1,side:2,alphaTest:.5}),n=new Bt(10,16,1,0,0,0);cr(n,lr(1,0,11,1),lr(11,0,21,1),lr(11,1,12,17),lr(12,1,22,17),lr(0,1,1,17),lr(1,1,11,17)),this.cape=new Nt(n,t),this.cape.position.y=-8,this.cape.position.z=-.5,this.add(this.cape)}}class pr extends $i{constructor(e,t){super(),this.skin=new ur(e),this.skin.name="skin",this.add(this.skin),this.cape=new dr(t),this.cape.name="cape",this.cape.position.z=-2,this.cape.position.y=-4,this.cape.rotation.x=25*Math.PI/180,this.add(this.cape)}}function fr(e,t,n,i,r){const a=e.getImageData(t,n,i,r);for(let e=0;efunction(e,t,n,i,r,a,o,s){const l=e.getImageData(t,n,i,r);if(s)for(let e=0;ee.clearRect(t*n,i*n,r*n,a*n);i(40,0,8,8),i(48,0,8,8),i(32,8,8,8),i(40,8,8,8),i(48,8,8,8),i(56,8,8,8)}}(e,t),i(4,16,4,4,20,48,!0),i(8,16,4,4,24,48,!0),i(0,20,4,12,24,52,!0),i(4,20,4,12,20,52,!0),i(8,20,4,12,16,52,!0),i(12,20,4,12,28,52,!0),i(44,16,4,4,36,48,!0),i(48,16,4,4,40,48,!0),i(40,20,4,12,40,52,!0),i(44,20,4,12,36,52,!0),i(48,20,4,12,32,52,!0),i(52,20,4,12,44,52,!0)}function vr(e,t){const n=function(e){if(e.width===2*e.height)return e.width/64;if(17*e.width==22*e.height)return e.width/22;if(11*e.width==23*e.height)return e.width/46;throw new Error(`Bad cape size: ${e.width}x${e.height}`)}(t);e.width=64*n,e.height=32*n;const i=e.getContext("2d");i.clearRect(0,0,e.width,e.height),i.drawImage(t,0,0,t.width,t.height)}async function xr(e){const t=document.createElement("img");return new Promise((n,i)=>{t.onload=()=>n(t),t.onerror=i,"string"==typeof e?t.src=e:(void 0!==e.crossOrigin&&(t.crossOrigin=e.crossOrigin),void 0!==e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.src=e.src)})}function _r(e){return e instanceof EventTarget||e instanceof ImageBitmap}function yr(e,t,n){e instanceof Function?e(t,n):e.play(t,n)}class Mr{constructor(e){this.speed=1,this.paused=!1,this.progress=0,this.lastTime=0,this.started=!1,this.toResetAndRemove=!1,this.animation=e}play(e,t){if(this.toResetAndRemove)return yr(this.animation,e,0),void this.remove();let n;this.started?n=t-this.lastTime:(n=0,this.started=!0),this.lastTime=t,this.paused||(this.progress+=n*this.speed),yr(this.animation,e,this.progress)}reset(){this.progress=0}remove(){}resetAndRemove(){this.toResetAndRemove=!0}}class br{constructor(){this.handles=new Set}add(e){const t=new Mr(e);return t.remove=()=>{this.handles.delete(t)},this.handles.add(t),t}play(e,t){this.handles.forEach(n=>n.play(e,t))}}class wr extends br{constructor(){super(...arguments),this.speed=1,this.progress=0,this.clock=new rr(!0)}get animation(){return this}get paused(){return!this.clock.running}set paused(e){e?this.clock.stop():this.clock.start()}runAnimationLoop(e){0!==this.handles.size&&(this.progress+=this.clock.getDelta()*this.speed,this.play(e,this.progress))}reset(){this.progress=0}}function Sr(e){return!e||!1!==e.makeVisible}class Er{constructor(e,t={}){this.animations=new wr,this._disposed=!1,this._renderPaused=!1,this.domElement=e,this.skinCanvas=document.createElement("canvas"),this.skinTexture=new v(this.skinCanvas),this.skinTexture.magFilter=1003,this.skinTexture.minFilter=1003,this.capeCanvas=document.createElement("canvas"),this.capeTexture=new v(this.capeCanvas),this.capeTexture.magFilter=1003,this.capeTexture.minFilter=1003,this.scene=new J,this.camera=new qt(40),this.camera.position.y=-12,this.camera.position.z=60,this.renderer=new ir({alpha:!0}),this.domElement.appendChild(this.renderer.domElement),this.playerObject=new pr(this.skinTexture,this.capeTexture),this.playerObject.name="player",this.playerObject.skin.visible=!1,this.playerObject.cape.visible=!1,this.scene.add(this.playerObject),window.requestAnimationFrame(()=>this.draw()),void 0!==t.skin&&this.loadSkin(t.skin),void 0!==t.cape&&this.loadCape(t.cape),void 0!==t.width&&(this.width=t.width),void 0!==t.height&&(this.height=t.height)}skinLoaded(e,t){this.skinTexture.needsUpdate=!0,this.playerObject.skin.modelType=e,Sr(t)&&(this.playerObject.skin.visible=!0)}capeLoaded(e){this.capeTexture.needsUpdate=!0,Sr(e)&&(this.playerObject.cape.visible=!0)}resetSkin(){this.playerObject.skin.visible=!1}resetCape(){this.playerObject.cape.visible=!1}draw(){this.disposed||this._renderPaused||(this.animations.runAnimationLoop(this.playerObject),this.doRender(),window.requestAnimationFrame(()=>this.draw()))}doRender(){this.renderer.render(this.scene,this.camera)}setSize(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t)}dispose(){this._disposed=!0,this.domElement.removeChild(this.renderer.domElement),this.renderer.dispose(),this.skinTexture.dispose(),this.capeTexture.dispose()}get disposed(){return this._disposed}get renderPaused(){return this._renderPaused}set renderPaused(e){const t=!this.disposed&&!e&&this._renderPaused;this._renderPaused=e,t&&window.requestAnimationFrame(()=>this.draw())}get width(){return this.renderer.getSize(new p).width}set width(e){this.setSize(e,this.height)}get height(){return this.renderer.getSize(new p).height}set height(e){this.setSize(this.width,e)}}var Tr;Tr=Er,[class{loadSkin(e,t="auto-detect",n){if(null===e)this.resetSkin();else{if(!_r(e))return xr(e).then(e=>this.loadSkin(e,t,n));{!function(e,t){let n=!1;if(t.width!==t.height){if(t.width!==2*t.height)throw new Error(`Bad skin size: ${t.width}x${t.height}`);n=!0}const i=e.getContext("2d");if(n){const n=t.width;e.width=n,e.height=n,i.clearRect(0,0,n,n),i.drawImage(t,0,0,n,n/2),gr(i,n)}else e.width=t.width,e.height=t.height,i.clearRect(0,0,t.width,t.height),i.drawImage(t,0,0,e.width,e.height)}(this.skinCanvas,e);const i="auto-detect"===t?function(e){const t=mr(e.width),n=e.getContext("2d"),i=(e,i,r,a)=>fr(n,e*t,i*t,r*t,a*t);return i(50,16,2,4)||i(54,20,2,12)||i(42,48,2,4)||i(46,52,2,12)?"slim":"default"}(this.skinCanvas):t;this.skinLoaded(i,n)}}}},class{loadCape(e,t){if(null===e)this.resetCape();else{if(!_r(e))return xr(e).then(e=>this.loadCape(e,t));vr(this.capeCanvas,e),this.capeLoaded(t)}}}].forEach(e=>{Object.getOwnPropertyNames(e.prototype).forEach(t=>{Object.defineProperty(Tr.prototype,t,Object.getOwnPropertyDescriptor(e.prototype,t))})});var Lr=function(e,l){var c,h,u,d,f;void 0===l&&console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.'),l===document&&console.error('THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.'),this.object=e,this.domElement=l,this.enabled=!0,this.target=new w,this.minDistance=0,this.maxDistance=1/0,this.minZoom=0,this.maxZoom=1/0,this.minPolarAngle=0,this.maxPolarAngle=Math.PI,this.minAzimuthAngle=-1/0,this.maxAzimuthAngle=1/0,this.enableDamping=!1,this.dampingFactor=.05,this.enableZoom=!0,this.zoomSpeed=1,this.enableRotate=!0,this.rotateSpeed=1,this.enablePan=!0,this.panSpeed=1,this.screenSpacePanning=!1,this.keyPanSpeed=7,this.autoRotate=!1,this.autoRotateSpeed=2,this.enableKeys=!0,this.keys={LEFT:37,UP:38,RIGHT:39,BOTTOM:40},this.mouseButtons={LEFT:t,MIDDLE:n,RIGHT:i},this.touches={ONE:r,TWO:o},this.target0=this.target.clone(),this.position0=this.object.position.clone(),this.zoom0=this.object.zoom,this.getPolarAngle=function(){return S.phi},this.getAzimuthalAngle=function(){return S.theta},this.saveState=function(){m.target0.copy(m.target),m.position0.copy(m.object.position),m.zoom0=m.object.zoom},this.reset=function(){m.target.copy(m.target0),m.object.position.copy(m.position0),m.object.zoom=m.zoom0,m.object.updateProjectionMatrix(),m.dispatchEvent(g),m.update(),M=_.NONE},this.update=(c=new w,h=(new y).setFromUnitVectors(e.up,new w(0,1,0)),u=h.clone().inverse(),d=new w,f=new y,function(){var e=m.object.position;return c.copy(e).sub(m.target),c.applyQuaternion(h),S.setFromVector3(c),m.autoRotate&&M===_.NONE&&G(2*Math.PI/60/60*m.autoRotateSpeed),m.enableDamping?(S.theta+=E.theta*m.dampingFactor,S.phi+=E.phi*m.dampingFactor):(S.theta+=E.theta,S.phi+=E.phi),S.theta=Math.max(m.minAzimuthAngle,Math.min(m.maxAzimuthAngle,S.theta)),S.phi=Math.max(m.minPolarAngle,Math.min(m.maxPolarAngle,S.phi)),S.makeSafe(),S.radius*=T,S.radius=Math.max(m.minDistance,Math.min(m.maxDistance,S.radius)),!0===m.enableDamping?m.target.addScaledVector(L,m.dampingFactor):m.target.add(L),c.setFromSpherical(S),c.applyQuaternion(u),e.copy(m.target).add(c),m.object.lookAt(m.target),!0===m.enableDamping?(E.theta*=1-m.dampingFactor,E.phi*=1-m.dampingFactor,L.multiplyScalar(1-m.dampingFactor)):(E.set(0,0,0),L.set(0,0,0)),T=1,!!(A||d.distanceToSquared(m.object.position)>b||8*(1-f.dot(m.object.quaternion))>b)&&(m.dispatchEvent(g),d.copy(m.object.position),f.copy(m.object.quaternion),A=!1,!0)}),this.dispose=function(){m.domElement.removeEventListener("contextmenu",ce,!1),m.domElement.removeEventListener("mousedown",te,!1),m.domElement.removeEventListener("wheel",re,!1),m.domElement.removeEventListener("touchstart",oe,!1),m.domElement.removeEventListener("touchend",le,!1),m.domElement.removeEventListener("touchmove",se,!1),document.removeEventListener("mousemove",ne,!1),document.removeEventListener("mouseup",ie,!1),m.domElement.removeEventListener("keydown",ae,!1)};var m=this,g={type:"change"},v={type:"start"},x={type:"end"},_={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_PAN:4,TOUCH_DOLLY_PAN:5,TOUCH_DOLLY_ROTATE:6},M=_.NONE,b=1e-6,S=new ar,E=new ar,T=1,L=new w,A=!1,P=new p,C=new p,D=new p,N=new p,R=new p,I=new p,z=new p,O=new p,U=new p;function F(){return Math.pow(.95,m.zoomSpeed)}function G(e){E.theta-=e}function B(e){E.phi-=e}var V,k=(V=new w,function(e,t){V.setFromMatrixColumn(t,0),V.multiplyScalar(-e),L.add(V)}),H=function(){var e=new w;return function(t,n){!0===m.screenSpacePanning?e.setFromMatrixColumn(n,1):(e.setFromMatrixColumn(n,0),e.crossVectors(m.object.up,e)),e.multiplyScalar(t),L.add(e)}}(),W=function(){var e=new w;return function(t,n){var i=m.domElement;if(m.object.isPerspectiveCamera){var r=m.object.position;e.copy(r).sub(m.target);var a=e.length();a*=Math.tan(m.object.fov/2*Math.PI/180),k(2*t*a/i.clientHeight,m.object.matrix),H(2*n*a/i.clientHeight,m.object.matrix)}else m.object.isOrthographicCamera?(k(t*(m.object.right-m.object.left)/m.object.zoom/i.clientWidth,m.object.matrix),H(n*(m.object.top-m.object.bottom)/m.object.zoom/i.clientHeight,m.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),m.enablePan=!1)}}();function j(e){m.object.isPerspectiveCamera?T/=e:m.object.isOrthographicCamera?(m.object.zoom=Math.max(m.minZoom,Math.min(m.maxZoom,m.object.zoom*e)),m.object.updateProjectionMatrix(),A=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),m.enableZoom=!1)}function X(e){m.object.isPerspectiveCamera?T*=e:m.object.isOrthographicCamera?(m.object.zoom=Math.max(m.minZoom,Math.min(m.maxZoom,m.object.zoom/e)),m.object.updateProjectionMatrix(),A=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),m.enableZoom=!1)}function q(e){P.set(e.clientX,e.clientY)}function Y(e){N.set(e.clientX,e.clientY)}function Z(e){if(1==e.touches.length)P.set(e.touches[0].pageX,e.touches[0].pageY);else{var t=.5*(e.touches[0].pageX+e.touches[1].pageX),n=.5*(e.touches[0].pageY+e.touches[1].pageY);P.set(t,n)}}function J(e){if(1==e.touches.length)N.set(e.touches[0].pageX,e.touches[0].pageY);else{var t=.5*(e.touches[0].pageX+e.touches[1].pageX),n=.5*(e.touches[0].pageY+e.touches[1].pageY);N.set(t,n)}}function Q(e){var t=e.touches[0].pageX-e.touches[1].pageX,n=e.touches[0].pageY-e.touches[1].pageY,i=Math.sqrt(t*t+n*n);z.set(0,i)}function K(e){if(1==e.touches.length)C.set(e.touches[0].pageX,e.touches[0].pageY);else{var t=.5*(e.touches[0].pageX+e.touches[1].pageX),n=.5*(e.touches[0].pageY+e.touches[1].pageY);C.set(t,n)}D.subVectors(C,P).multiplyScalar(m.rotateSpeed);var i=m.domElement;G(2*Math.PI*D.x/i.clientHeight),B(2*Math.PI*D.y/i.clientHeight),P.copy(C)}function $(e){if(1==e.touches.length)R.set(e.touches[0].pageX,e.touches[0].pageY);else{var t=.5*(e.touches[0].pageX+e.touches[1].pageX),n=.5*(e.touches[0].pageY+e.touches[1].pageY);R.set(t,n)}I.subVectors(R,N).multiplyScalar(m.panSpeed),W(I.x,I.y),N.copy(R)}function ee(e){var t=e.touches[0].pageX-e.touches[1].pageX,n=e.touches[0].pageY-e.touches[1].pageY,i=Math.sqrt(t*t+n*n);O.set(0,i),U.set(0,Math.pow(O.y/z.y,m.zoomSpeed)),j(U.y),z.copy(O)}function te(e){if(!1!==m.enabled){var r;switch(e.preventDefault(),m.domElement.focus?m.domElement.focus():window.focus(),e.button){case 0:r=m.mouseButtons.LEFT;break;case 1:r=m.mouseButtons.MIDDLE;break;case 2:r=m.mouseButtons.RIGHT;break;default:r=-1}switch(r){case n:if(!1===m.enableZoom)return;!function(e){z.set(e.clientX,e.clientY)}(e),M=_.DOLLY;break;case t:if(e.ctrlKey||e.metaKey||e.shiftKey){if(!1===m.enablePan)return;Y(e),M=_.PAN}else{if(!1===m.enableRotate)return;q(e),M=_.ROTATE}break;case i:if(e.ctrlKey||e.metaKey||e.shiftKey){if(!1===m.enableRotate)return;q(e),M=_.ROTATE}else{if(!1===m.enablePan)return;Y(e),M=_.PAN}break;default:M=_.NONE}M!==_.NONE&&(document.addEventListener("mousemove",ne,!1),document.addEventListener("mouseup",ie,!1),m.dispatchEvent(v))}}function ne(e){if(!1!==m.enabled)switch(e.preventDefault(),M){case _.ROTATE:if(!1===m.enableRotate)return;!function(e){C.set(e.clientX,e.clientY),D.subVectors(C,P).multiplyScalar(m.rotateSpeed);var t=m.domElement;G(2*Math.PI*D.x/t.clientHeight),B(2*Math.PI*D.y/t.clientHeight),P.copy(C),m.update()}(e);break;case _.DOLLY:if(!1===m.enableZoom)return;!function(e){O.set(e.clientX,e.clientY),U.subVectors(O,z),U.y>0?j(F()):U.y<0&&X(F()),z.copy(O),m.update()}(e);break;case _.PAN:if(!1===m.enablePan)return;!function(e){R.set(e.clientX,e.clientY),I.subVectors(R,N).multiplyScalar(m.panSpeed),W(I.x,I.y),N.copy(R),m.update()}(e)}}function ie(e){!1!==m.enabled&&(document.removeEventListener("mousemove",ne,!1),document.removeEventListener("mouseup",ie,!1),m.dispatchEvent(x),M=_.NONE)}function re(e){!1===m.enabled||!1===m.enableZoom||M!==_.NONE&&M!==_.ROTATE||(e.preventDefault(),e.stopPropagation(),m.dispatchEvent(v),function(e){e.deltaY<0?X(F()):e.deltaY>0&&j(F()),m.update()}(e),m.dispatchEvent(x))}function ae(e){!1!==m.enabled&&!1!==m.enableKeys&&!1!==m.enablePan&&function(e){var t=!1;switch(e.keyCode){case m.keys.UP:W(0,m.keyPanSpeed),t=!0;break;case m.keys.BOTTOM:W(0,-m.keyPanSpeed),t=!0;break;case m.keys.LEFT:W(m.keyPanSpeed,0),t=!0;break;case m.keys.RIGHT:W(-m.keyPanSpeed,0),t=!0}t&&(e.preventDefault(),m.update())}(e)}function oe(e){if(!1!==m.enabled){switch(e.preventDefault(),e.touches.length){case 1:switch(m.touches.ONE){case r:if(!1===m.enableRotate)return;Z(e),M=_.TOUCH_ROTATE;break;case a:if(!1===m.enablePan)return;J(e),M=_.TOUCH_PAN;break;default:M=_.NONE}break;case 2:switch(m.touches.TWO){case o:if(!1===m.enableZoom&&!1===m.enablePan)return;!function(e){m.enableZoom&&Q(e),m.enablePan&&J(e)}(e),M=_.TOUCH_DOLLY_PAN;break;case s:if(!1===m.enableZoom&&!1===m.enableRotate)return;!function(e){m.enableZoom&&Q(e),m.enableRotate&&Z(e)}(e),M=_.TOUCH_DOLLY_ROTATE;break;default:M=_.NONE}break;default:M=_.NONE}M!==_.NONE&&m.dispatchEvent(v)}}function se(e){if(!1!==m.enabled)switch(e.preventDefault(),e.stopPropagation(),M){case _.TOUCH_ROTATE:if(!1===m.enableRotate)return;K(e),m.update();break;case _.TOUCH_PAN:if(!1===m.enablePan)return;$(e),m.update();break;case _.TOUCH_DOLLY_PAN:if(!1===m.enableZoom&&!1===m.enablePan)return;!function(e){m.enableZoom&&ee(e),m.enablePan&&$(e)}(e),m.update();break;case _.TOUCH_DOLLY_ROTATE:if(!1===m.enableZoom&&!1===m.enableRotate)return;!function(e){m.enableZoom&&ee(e),m.enableRotate&&K(e)}(e),m.update();break;default:M=_.NONE}}function le(e){!1!==m.enabled&&(m.dispatchEvent(x),M=_.NONE)}function ce(e){!1!==m.enabled&&e.preventDefault()}m.domElement.addEventListener("contextmenu",ce,!1),m.domElement.addEventListener("mousedown",te,!1),m.domElement.addEventListener("wheel",re,!1),m.domElement.addEventListener("touchstart",oe,!1),m.domElement.addEventListener("touchend",le,!1),m.domElement.addEventListener("touchmove",se,!1),m.domElement.addEventListener("keydown",ae,!1),-1===m.domElement.tabIndex&&(m.domElement.tabIndex=0),this.update()};(Lr.prototype=Object.create(l.prototype)).constructor=Lr;var Ar=function(e,n){Lr.call(this,e,n),this.mouseButtons.LEFT=i,this.mouseButtons.RIGHT=t,this.touches.ONE=a,this.touches.TWO=s};(Ar.prototype=Object.create(l.prototype)).constructor=Ar,e.BodyPart=hr,e.CapeObject=dr,e.CompositeAnimation=br,e.PlayerObject=pr,e.RootAnimation=wr,e.RotatingAnimation=(e,t)=>{e.rotation.y=t},e.RunningAnimation=(e,t)=>{const n=e.skin;t*=15,n.leftLeg.rotation.x=1.3*Math.cos(t+Math.PI),n.rightLeg.rotation.x=1.3*Math.cos(t),n.leftArm.rotation.x=1.5*Math.cos(t),n.rightArm.rotation.x=1.5*Math.cos(t+Math.PI);const i=.1*Math.PI;n.leftArm.rotation.z=.1*Math.cos(t)+i,n.rightArm.rotation.z=.1*Math.cos(t+Math.PI)-i,e.position.y=Math.cos(2*t),e.position.x=.15*Math.cos(t),e.rotation.z=.01*Math.cos(t+Math.PI);const r=.3*Math.PI;e.cape.rotation.x=.1*Math.sin(2*t)+r},e.SkinObject=ur,e.SkinViewer=Er,e.WalkingAnimation=(e,t)=>{const n=e.skin;t*=8,n.leftLeg.rotation.x=.5*Math.sin(t),n.rightLeg.rotation.x=.5*Math.sin(t+Math.PI),n.leftArm.rotation.x=.5*Math.sin(t+Math.PI),n.rightArm.rotation.x=.5*Math.sin(t);const i=.02*Math.PI;n.leftArm.rotation.z=.03*Math.cos(t)+i,n.rightArm.rotation.z=.03*Math.cos(t+Math.PI)-i,n.head.rotation.y=.2*Math.sin(t/4),n.head.rotation.x=.1*Math.sin(t/5);const r=.06*Math.PI;e.cape.rotation.x=.06*Math.sin(t/1.5)+r},e.createOrbitControls=function(e){const t=new Lr(e.camera,e.renderer.domElement);return t.enablePan=!1,t.target=new w(0,-12,0),t.minDistance=10,t.maxDistance=256,t.update(),t},e.invokeAnimation=yr,Object.defineProperty(e,"__esModule",{value:!0})}));//# sourceMappingURL=skinview3d.bundle.js.map diff --git a/js/dist/skinview3d.bundle.js.map b/js/dist/skinview3d.bundle.js.map index a9cad5e..8d62eab 100644 --- a/js/dist/skinview3d.bundle.js.map +++ b/js/dist/skinview3d.bundle.js.map @@ -1 +1 @@ -{"version":3,"file":"skinview3d.bundle.js","sources":["../node_modules/three/src/core/EventDispatcher.js","../node_modules/three/src/math/MathUtils.js","../node_modules/three/src/math/Vector2.js","../node_modules/three/src/math/Matrix3.js","../node_modules/three/src/extras/ImageUtils.js","../node_modules/three/src/textures/Texture.js","../node_modules/three/src/math/Vector4.js","../node_modules/three/src/renderers/WebGLRenderTarget.js","../node_modules/three/src/math/Quaternion.js","../node_modules/three/src/math/Vector3.js","../node_modules/three/src/math/Matrix4.js","../node_modules/three/src/math/Euler.js","../node_modules/three/src/core/Layers.js","../node_modules/three/src/core/Object3D.js","../node_modules/three/src/scenes/Scene.js","../node_modules/three/src/math/Box3.js","../node_modules/three/src/math/Sphere.js","../node_modules/three/src/math/Ray.js","../node_modules/three/src/math/Plane.js","../node_modules/three/src/math/Triangle.js","../node_modules/three/src/math/Color.js","../node_modules/three/src/core/Face3.js","../node_modules/three/src/materials/Material.js","../node_modules/three/src/materials/MeshBasicMaterial.js","../node_modules/three/src/core/BufferAttribute.js","../node_modules/three/src/core/DirectGeometry.js","../node_modules/three/src/utils.js","../node_modules/three/src/core/BufferGeometry.js","../node_modules/three/src/objects/Mesh.js","../node_modules/three/src/core/Geometry.js","../node_modules/three/src/geometries/BoxGeometry.js","../node_modules/three/src/renderers/shaders/UniformsUtils.js","../node_modules/three/src/materials/ShaderMaterial.js","../node_modules/three/src/renderers/shaders/ShaderChunk/default_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/default_fragment.glsl.js","../node_modules/three/src/cameras/Camera.js","../node_modules/three/src/cameras/PerspectiveCamera.js","../node_modules/three/src/textures/DataTexture.js","../node_modules/three/src/math/Frustum.js","../node_modules/three/src/renderers/shaders/UniformsLib.js","../node_modules/three/src/renderers/webgl/WebGLAnimation.js","../node_modules/three/src/renderers/webgl/WebGLAttributes.js","../node_modules/three/src/geometries/PlaneGeometry.js","../node_modules/three/src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/alphamap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/aomap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/begin_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/beginnormal_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clipping_planes_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clipping_planes_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clipping_planes_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clipping_planes_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/color_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/common.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/displacementmap_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/emissivemap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/encodings_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/encodings_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/fog_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/fog_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/fog_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/gradientmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_toon_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_toon_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/logdepthbuf_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/map_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/metalnessmap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/metalnessmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_begin.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_maps.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clearcoat_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/packing.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/project_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/dithering_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/dithering_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/roughnessmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/skinbase_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/skinning_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/skinnormal_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/specularmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/tonemapping_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv2_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv2_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv2_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/background_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/background_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/cube_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/cube_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/depth_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/depth_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/distanceRGBA_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/distanceRGBA_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/equirect_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/equirect_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/linedashed_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/linedashed_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshbasic_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshbasic_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshlambert_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshlambert_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshmatcap_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshmatcap_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshtoon_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshtoon_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshphong_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshphong_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshphysical_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/normal_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/normal_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/points_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/points_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/shadow_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/shadow_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/sprite_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/sprite_vert.glsl.js","../node_modules/three/src/renderers/webgl/WebGLBackground.js","../node_modules/three/src/renderers/webgl/WebGLBufferRenderer.js","../node_modules/three/src/renderers/webgl/WebGLCapabilities.js","../node_modules/three/src/renderers/webgl/WebGLClipping.js","../node_modules/three/src/renderers/webgl/WebGLExtensions.js","../node_modules/three/src/renderers/webgl/WebGLGeometries.js","../node_modules/three/src/renderers/webgl/WebGLIndexedBufferRenderer.js","../node_modules/three/src/renderers/webgl/WebGLInfo.js","../node_modules/three/src/renderers/webgl/WebGLMorphtargets.js","../node_modules/three/src/renderers/webgl/WebGLObjects.js","../node_modules/three/src/textures/CubeTexture.js","../node_modules/three/src/textures/DataTexture2DArray.js","../node_modules/three/src/textures/DataTexture3D.js","../node_modules/three/src/renderers/shaders/ShaderLib.js","../node_modules/three/src/renderers/webgl/WebGLUniforms.js","../node_modules/three/src/renderers/webgl/WebGLShader.js","../node_modules/three/src/renderers/webgl/WebGLProgram.js","../node_modules/three/src/renderers/webgl/WebGLPrograms.js","../node_modules/three/src/renderers/webgl/WebGLProperties.js","../node_modules/three/src/renderers/webgl/WebGLRenderLists.js","../node_modules/three/src/renderers/webgl/WebGLLights.js","../node_modules/three/src/renderers/webgl/WebGLRenderStates.js","../node_modules/three/src/materials/MeshDepthMaterial.js","../node_modules/three/src/materials/MeshDistanceMaterial.js","../node_modules/three/src/renderers/webgl/WebGLShadowMap.js","../node_modules/three/src/renderers/shaders/ShaderLib/vsm_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/vsm_frag.glsl.js","../node_modules/three/src/renderers/webgl/WebGLState.js","../node_modules/three/src/renderers/webgl/WebGLTextures.js","../node_modules/three/src/renderers/webgl/WebGLUtils.js","../node_modules/three/src/cameras/ArrayCamera.js","../node_modules/three/src/objects/Group.js","../node_modules/three/src/renderers/webxr/WebXRController.js","../node_modules/three/src/renderers/webxr/WebXRManager.js","../node_modules/three/src/renderers/webgl/WebGLMaterials.js","../node_modules/three/src/renderers/WebGLRenderer.js","../node_modules/three/src/core/Clock.js","../node_modules/three/src/math/Spherical.js","../src/model.ts","../src/animation.ts","../node_modules/skinview-utils/index.js","../node_modules/three/examples/jsm/controls/OrbitControls.js","../src/viewer.ts","../src/orbit_controls.ts"],"sourcesContent":["/**\n * https://github.com/mrdoob/eventdispatcher.js/\n */\n\nfunction EventDispatcher() {}\n\nObject.assign( EventDispatcher.prototype, {\n\n\taddEventListener: function ( type, listener ) {\n\n\t\tif ( this._listeners === undefined ) this._listeners = {};\n\n\t\tvar listeners = this._listeners;\n\n\t\tif ( listeners[ type ] === undefined ) {\n\n\t\t\tlisteners[ type ] = [];\n\n\t\t}\n\n\t\tif ( listeners[ type ].indexOf( listener ) === - 1 ) {\n\n\t\t\tlisteners[ type ].push( listener );\n\n\t\t}\n\n\t},\n\n\thasEventListener: function ( type, listener ) {\n\n\t\tif ( this._listeners === undefined ) return false;\n\n\t\tvar listeners = this._listeners;\n\n\t\treturn listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;\n\n\t},\n\n\tremoveEventListener: function ( type, listener ) {\n\n\t\tif ( this._listeners === undefined ) return;\n\n\t\tvar listeners = this._listeners;\n\t\tvar listenerArray = listeners[ type ];\n\n\t\tif ( listenerArray !== undefined ) {\n\n\t\t\tvar index = listenerArray.indexOf( listener );\n\n\t\t\tif ( index !== - 1 ) {\n\n\t\t\t\tlistenerArray.splice( index, 1 );\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\tdispatchEvent: function ( event ) {\n\n\t\tif ( this._listeners === undefined ) return;\n\n\t\tvar listeners = this._listeners;\n\t\tvar listenerArray = listeners[ event.type ];\n\n\t\tif ( listenerArray !== undefined ) {\n\n\t\t\tevent.target = this;\n\n\t\t\t// Make a copy, in case listeners are removed while iterating.\n\t\t\tvar array = listenerArray.slice( 0 );\n\n\t\t\tfor ( var i = 0, l = array.length; i < l; i ++ ) {\n\n\t\t\t\tarray[ i ].call( this, event );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n} );\n\n\nexport { EventDispatcher };\n","/**\n * @author alteredq / http://alteredqualia.com/\n * @author mrdoob / http://mrdoob.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author thezwap\n */\n\nvar _lut = [];\n\nfor ( var i = 0; i < 256; i ++ ) {\n\n\t_lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );\n\n}\n\nvar MathUtils = {\n\n\tDEG2RAD: Math.PI / 180,\n\tRAD2DEG: 180 / Math.PI,\n\n\tgenerateUUID: function () {\n\n\t\t// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136\n\n\t\tvar d0 = Math.random() * 0xffffffff | 0;\n\t\tvar d1 = Math.random() * 0xffffffff | 0;\n\t\tvar d2 = Math.random() * 0xffffffff | 0;\n\t\tvar d3 = Math.random() * 0xffffffff | 0;\n\t\tvar uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +\n\t\t\t_lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +\n\t\t\t_lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +\n\t\t\t_lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];\n\n\t\t// .toUpperCase() here flattens concatenated strings to save heap memory space.\n\t\treturn uuid.toUpperCase();\n\n\t},\n\n\tclamp: function ( value, min, max ) {\n\n\t\treturn Math.max( min, Math.min( max, value ) );\n\n\t},\n\n\t// compute euclidian modulo of m % n\n\t// https://en.wikipedia.org/wiki/Modulo_operation\n\n\teuclideanModulo: function ( n, m ) {\n\n\t\treturn ( ( n % m ) + m ) % m;\n\n\t},\n\n\t// Linear mapping from range to range \n\n\tmapLinear: function ( x, a1, a2, b1, b2 ) {\n\n\t\treturn b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );\n\n\t},\n\n\t// https://en.wikipedia.org/wiki/Linear_interpolation\n\n\tlerp: function ( x, y, t ) {\n\n\t\treturn ( 1 - t ) * x + t * y;\n\n\t},\n\n\t// http://en.wikipedia.org/wiki/Smoothstep\n\n\tsmoothstep: function ( x, min, max ) {\n\n\t\tif ( x <= min ) return 0;\n\t\tif ( x >= max ) return 1;\n\n\t\tx = ( x - min ) / ( max - min );\n\n\t\treturn x * x * ( 3 - 2 * x );\n\n\t},\n\n\tsmootherstep: function ( x, min, max ) {\n\n\t\tif ( x <= min ) return 0;\n\t\tif ( x >= max ) return 1;\n\n\t\tx = ( x - min ) / ( max - min );\n\n\t\treturn x * x * x * ( x * ( x * 6 - 15 ) + 10 );\n\n\t},\n\n\t// Random integer from interval\n\n\trandInt: function ( low, high ) {\n\n\t\treturn low + Math.floor( Math.random() * ( high - low + 1 ) );\n\n\t},\n\n\t// Random float from interval\n\n\trandFloat: function ( low, high ) {\n\n\t\treturn low + Math.random() * ( high - low );\n\n\t},\n\n\t// Random float from <-range/2, range/2> interval\n\n\trandFloatSpread: function ( range ) {\n\n\t\treturn range * ( 0.5 - Math.random() );\n\n\t},\n\n\tdegToRad: function ( degrees ) {\n\n\t\treturn degrees * MathUtils.DEG2RAD;\n\n\t},\n\n\tradToDeg: function ( radians ) {\n\n\t\treturn radians * MathUtils.RAD2DEG;\n\n\t},\n\n\tisPowerOfTwo: function ( value ) {\n\n\t\treturn ( value & ( value - 1 ) ) === 0 && value !== 0;\n\n\t},\n\n\tceilPowerOfTwo: function ( value ) {\n\n\t\treturn Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );\n\n\t},\n\n\tfloorPowerOfTwo: function ( value ) {\n\n\t\treturn Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );\n\n\t},\n\n\tsetQuaternionFromProperEuler: function ( q, a, b, c, order ) {\n\n\t\t// Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles\n\n\t\t// rotations are applied to the axes in the order specified by 'order'\n\t\t// rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'\n\t\t// angles are in radians\n\n\t\tvar cos = Math.cos;\n\t\tvar sin = Math.sin;\n\n\t\tvar c2 = cos( b / 2 );\n\t\tvar s2 = sin( b / 2 );\n\n\t\tvar c13 = cos( ( a + c ) / 2 );\n\t\tvar s13 = sin( ( a + c ) / 2 );\n\n\t\tvar c1_3 = cos( ( a - c ) / 2 );\n\t\tvar s1_3 = sin( ( a - c ) / 2 );\n\n\t\tvar c3_1 = cos( ( c - a ) / 2 );\n\t\tvar s3_1 = sin( ( c - a ) / 2 );\n\n\t\tswitch ( order ) {\n\n\t\t\tcase 'XYX':\n\t\t\t\tq.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tcase 'YZY':\n\t\t\t\tq.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZXZ':\n\t\t\t\tq.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tcase 'XZX':\n\t\t\t\tq.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tcase 'YXY':\n\t\t\t\tq.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZYZ':\n\t\t\t\tq.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tconsole.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );\n\n\t\t}\n\n\t}\n\n};\n\n\nexport { MathUtils };\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author philogb / http://blog.thejit.org/\n * @author egraether / http://egraether.com/\n * @author zz85 / http://www.lab4games.net/zz85/blog\n */\n\nfunction Vector2( x, y ) {\n\n\tthis.x = x || 0;\n\tthis.y = y || 0;\n\n}\n\nObject.defineProperties( Vector2.prototype, {\n\n\t\"width\": {\n\n\t\tget: function () {\n\n\t\t\treturn this.x;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis.x = value;\n\n\t\t}\n\n\t},\n\n\t\"height\": {\n\n\t\tget: function () {\n\n\t\t\treturn this.y;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis.y = value;\n\n\t\t}\n\n\t}\n\n} );\n\nObject.assign( Vector2.prototype, {\n\n\tisVector2: true,\n\n\tset: function ( x, y ) {\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\n\t\treturn this;\n\n\t},\n\n\tsetScalar: function ( scalar ) {\n\n\t\tthis.x = scalar;\n\t\tthis.y = scalar;\n\n\t\treturn this;\n\n\t},\n\n\tsetX: function ( x ) {\n\n\t\tthis.x = x;\n\n\t\treturn this;\n\n\t},\n\n\tsetY: function ( y ) {\n\n\t\tthis.y = y;\n\n\t\treturn this;\n\n\t},\n\n\tsetComponent: function ( index, value ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: this.x = value; break;\n\t\t\tcase 1: this.y = value; break;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tgetComponent: function ( index ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: return this.x;\n\t\t\tcase 1: return this.y;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.x, this.y );\n\n\t},\n\n\tcopy: function ( v ) {\n\n\t\tthis.x = v.x;\n\t\tthis.y = v.y;\n\n\t\treturn this;\n\n\t},\n\n\tadd: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\n\t\t\treturn this.addVectors( v, w );\n\n\t\t}\n\n\t\tthis.x += v.x;\n\t\tthis.y += v.y;\n\n\t\treturn this;\n\n\t},\n\n\taddScalar: function ( s ) {\n\n\t\tthis.x += s;\n\t\tthis.y += s;\n\n\t\treturn this;\n\n\t},\n\n\taddVectors: function ( a, b ) {\n\n\t\tthis.x = a.x + b.x;\n\t\tthis.y = a.y + b.y;\n\n\t\treturn this;\n\n\t},\n\n\taddScaledVector: function ( v, s ) {\n\n\t\tthis.x += v.x * s;\n\t\tthis.y += v.y * s;\n\n\t\treturn this;\n\n\t},\n\n\tsub: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\n\t\t\treturn this.subVectors( v, w );\n\n\t\t}\n\n\t\tthis.x -= v.x;\n\t\tthis.y -= v.y;\n\n\t\treturn this;\n\n\t},\n\n\tsubScalar: function ( s ) {\n\n\t\tthis.x -= s;\n\t\tthis.y -= s;\n\n\t\treturn this;\n\n\t},\n\n\tsubVectors: function ( a, b ) {\n\n\t\tthis.x = a.x - b.x;\n\t\tthis.y = a.y - b.y;\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( v ) {\n\n\t\tthis.x *= v.x;\n\t\tthis.y *= v.y;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( scalar ) {\n\n\t\tthis.x *= scalar;\n\t\tthis.y *= scalar;\n\n\t\treturn this;\n\n\t},\n\n\tdivide: function ( v ) {\n\n\t\tthis.x /= v.x;\n\t\tthis.y /= v.y;\n\n\t\treturn this;\n\n\t},\n\n\tdivideScalar: function ( scalar ) {\n\n\t\treturn this.multiplyScalar( 1 / scalar );\n\n\t},\n\n\tapplyMatrix3: function ( m ) {\n\n\t\tvar x = this.x, y = this.y;\n\t\tvar e = m.elements;\n\n\t\tthis.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];\n\t\tthis.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];\n\n\t\treturn this;\n\n\t},\n\n\tmin: function ( v ) {\n\n\t\tthis.x = Math.min( this.x, v.x );\n\t\tthis.y = Math.min( this.y, v.y );\n\n\t\treturn this;\n\n\t},\n\n\tmax: function ( v ) {\n\n\t\tthis.x = Math.max( this.x, v.x );\n\t\tthis.y = Math.max( this.y, v.y );\n\n\t\treturn this;\n\n\t},\n\n\tclamp: function ( min, max ) {\n\n\t\t// assumes min < max, componentwise\n\n\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\n\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampScalar: function ( minVal, maxVal ) {\n\n\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\n\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampLength: function ( min, max ) {\n\n\t\tvar length = this.length();\n\n\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\n\n\t},\n\n\tfloor: function () {\n\n\t\tthis.x = Math.floor( this.x );\n\t\tthis.y = Math.floor( this.y );\n\n\t\treturn this;\n\n\t},\n\n\tceil: function () {\n\n\t\tthis.x = Math.ceil( this.x );\n\t\tthis.y = Math.ceil( this.y );\n\n\t\treturn this;\n\n\t},\n\n\tround: function () {\n\n\t\tthis.x = Math.round( this.x );\n\t\tthis.y = Math.round( this.y );\n\n\t\treturn this;\n\n\t},\n\n\troundToZero: function () {\n\n\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\n\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\n\n\t\treturn this;\n\n\t},\n\n\tnegate: function () {\n\n\t\tthis.x = - this.x;\n\t\tthis.y = - this.y;\n\n\t\treturn this;\n\n\t},\n\n\tdot: function ( v ) {\n\n\t\treturn this.x * v.x + this.y * v.y;\n\n\t},\n\n\tcross: function ( v ) {\n\n\t\treturn this.x * v.y - this.y * v.x;\n\n\t},\n\n\tlengthSq: function () {\n\n\t\treturn this.x * this.x + this.y * this.y;\n\n\t},\n\n\tlength: function () {\n\n\t\treturn Math.sqrt( this.x * this.x + this.y * this.y );\n\n\t},\n\n\tmanhattanLength: function () {\n\n\t\treturn Math.abs( this.x ) + Math.abs( this.y );\n\n\t},\n\n\tnormalize: function () {\n\n\t\treturn this.divideScalar( this.length() || 1 );\n\n\t},\n\n\tangle: function () {\n\n\t\t// computes the angle in radians with respect to the positive x-axis\n\n\t\tvar angle = Math.atan2( - this.y, - this.x ) + Math.PI;\n\n\t\treturn angle;\n\n\t},\n\n\tdistanceTo: function ( v ) {\n\n\t\treturn Math.sqrt( this.distanceToSquared( v ) );\n\n\t},\n\n\tdistanceToSquared: function ( v ) {\n\n\t\tvar dx = this.x - v.x, dy = this.y - v.y;\n\t\treturn dx * dx + dy * dy;\n\n\t},\n\n\tmanhattanDistanceTo: function ( v ) {\n\n\t\treturn Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );\n\n\t},\n\n\tsetLength: function ( length ) {\n\n\t\treturn this.normalize().multiplyScalar( length );\n\n\t},\n\n\tlerp: function ( v, alpha ) {\n\n\t\tthis.x += ( v.x - this.x ) * alpha;\n\t\tthis.y += ( v.y - this.y ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tlerpVectors: function ( v1, v2, alpha ) {\n\n\t\tthis.x = v1.x + ( v2.x - v1.x ) * alpha;\n\t\tthis.y = v1.y + ( v2.y - v1.y ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( v ) {\n\n\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) );\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis.x = array[ offset ];\n\t\tthis.y = array[ offset + 1 ];\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this.x;\n\t\tarray[ offset + 1 ] = this.y;\n\n\t\treturn array;\n\n\t},\n\n\tfromBufferAttribute: function ( attribute, index, offset ) {\n\n\t\tif ( offset !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );\n\n\t\t}\n\n\t\tthis.x = attribute.getX( index );\n\t\tthis.y = attribute.getY( index );\n\n\t\treturn this;\n\n\t},\n\n\trotateAround: function ( center, angle ) {\n\n\t\tvar c = Math.cos( angle ), s = Math.sin( angle );\n\n\t\tvar x = this.x - center.x;\n\t\tvar y = this.y - center.y;\n\n\t\tthis.x = x * c - y * s + center.x;\n\t\tthis.y = x * s + y * c + center.y;\n\n\t\treturn this;\n\n\t},\n\n\trandom: function () {\n\n\t\tthis.x = Math.random();\n\t\tthis.y = Math.random();\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Vector2 };\n","/**\n * @author alteredq / http://alteredqualia.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author bhouston / http://clara.io\n * @author tschw\n */\n\nfunction Matrix3() {\n\n\tthis.elements = [\n\n\t\t1, 0, 0,\n\t\t0, 1, 0,\n\t\t0, 0, 1\n\n\t];\n\n\tif ( arguments.length > 0 ) {\n\n\t\tconsole.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );\n\n\t}\n\n}\n\nObject.assign( Matrix3.prototype, {\n\n\tisMatrix3: true,\n\n\tset: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;\n\t\tte[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;\n\t\tte[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;\n\n\t\treturn this;\n\n\t},\n\n\tidentity: function () {\n\n\t\tthis.set(\n\n\t\t\t1, 0, 0,\n\t\t\t0, 1, 0,\n\t\t\t0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().fromArray( this.elements );\n\n\t},\n\n\tcopy: function ( m ) {\n\n\t\tvar te = this.elements;\n\t\tvar me = m.elements;\n\n\t\tte[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];\n\t\tte[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];\n\t\tte[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];\n\n\t\treturn this;\n\n\t},\n\n\textractBasis: function ( xAxis, yAxis, zAxis ) {\n\n\t\txAxis.setFromMatrix3Column( this, 0 );\n\t\tyAxis.setFromMatrix3Column( this, 1 );\n\t\tzAxis.setFromMatrix3Column( this, 2 );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromMatrix4: function ( m ) {\n\n\t\tvar me = m.elements;\n\n\t\tthis.set(\n\n\t\t\tme[ 0 ], me[ 4 ], me[ 8 ],\n\t\t\tme[ 1 ], me[ 5 ], me[ 9 ],\n\t\t\tme[ 2 ], me[ 6 ], me[ 10 ]\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( m ) {\n\n\t\treturn this.multiplyMatrices( this, m );\n\n\t},\n\n\tpremultiply: function ( m ) {\n\n\t\treturn this.multiplyMatrices( m, this );\n\n\t},\n\n\tmultiplyMatrices: function ( a, b ) {\n\n\t\tvar ae = a.elements;\n\t\tvar be = b.elements;\n\t\tvar te = this.elements;\n\n\t\tvar a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];\n\t\tvar a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];\n\t\tvar a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];\n\n\t\tvar b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];\n\t\tvar b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];\n\t\tvar b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];\n\n\t\tte[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;\n\t\tte[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;\n\t\tte[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;\n\n\t\tte[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;\n\t\tte[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;\n\t\tte[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;\n\n\t\tte[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;\n\t\tte[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;\n\t\tte[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( s ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;\n\t\tte[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;\n\t\tte[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;\n\n\t\treturn this;\n\n\t},\n\n\tdeterminant: function () {\n\n\t\tvar te = this.elements;\n\n\t\tvar a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],\n\t\t\td = te[ 3 ], e = te[ 4 ], f = te[ 5 ],\n\t\t\tg = te[ 6 ], h = te[ 7 ], i = te[ 8 ];\n\n\t\treturn a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;\n\n\t},\n\n\tgetInverse: function ( matrix, throwOnDegenerate ) {\n\n\t\tif ( throwOnDegenerate !== undefined ) {\n\n\t\t\tconsole.warn( \"THREE.Matrix3: .getInverse() can no longer be configured to throw on degenerate.\" );\n\n\t\t}\n\n\t\tvar me = matrix.elements,\n\t\t\tte = this.elements,\n\n\t\t\tn11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],\n\t\t\tn12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],\n\t\t\tn13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],\n\n\t\t\tt11 = n33 * n22 - n32 * n23,\n\t\t\tt12 = n32 * n13 - n33 * n12,\n\t\t\tt13 = n23 * n12 - n22 * n13,\n\n\t\t\tdet = n11 * t11 + n21 * t12 + n31 * t13;\n\n\t\tif ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );\n\n\t\tvar detInv = 1 / det;\n\n\t\tte[ 0 ] = t11 * detInv;\n\t\tte[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;\n\t\tte[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;\n\n\t\tte[ 3 ] = t12 * detInv;\n\t\tte[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;\n\t\tte[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;\n\n\t\tte[ 6 ] = t13 * detInv;\n\t\tte[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;\n\t\tte[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;\n\n\t\treturn this;\n\n\t},\n\n\ttranspose: function () {\n\n\t\tvar tmp, m = this.elements;\n\n\t\ttmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;\n\t\ttmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;\n\t\ttmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;\n\n\t\treturn this;\n\n\t},\n\n\tgetNormalMatrix: function ( matrix4 ) {\n\n\t\treturn this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();\n\n\t},\n\n\ttransposeIntoArray: function ( r ) {\n\n\t\tvar m = this.elements;\n\n\t\tr[ 0 ] = m[ 0 ];\n\t\tr[ 1 ] = m[ 3 ];\n\t\tr[ 2 ] = m[ 6 ];\n\t\tr[ 3 ] = m[ 1 ];\n\t\tr[ 4 ] = m[ 4 ];\n\t\tr[ 5 ] = m[ 7 ];\n\t\tr[ 6 ] = m[ 2 ];\n\t\tr[ 7 ] = m[ 5 ];\n\t\tr[ 8 ] = m[ 8 ];\n\n\t\treturn this;\n\n\t},\n\n\tsetUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {\n\n\t\tvar c = Math.cos( rotation );\n\t\tvar s = Math.sin( rotation );\n\n\t\tthis.set(\n\t\t\tsx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,\n\t\t\t- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,\n\t\t\t0, 0, 1\n\t\t);\n\n\t},\n\n\tscale: function ( sx, sy ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;\n\t\tte[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;\n\n\t\treturn this;\n\n\t},\n\n\trotate: function ( theta ) {\n\n\t\tvar c = Math.cos( theta );\n\t\tvar s = Math.sin( theta );\n\n\t\tvar te = this.elements;\n\n\t\tvar a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];\n\t\tvar a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];\n\n\t\tte[ 0 ] = c * a11 + s * a21;\n\t\tte[ 3 ] = c * a12 + s * a22;\n\t\tte[ 6 ] = c * a13 + s * a23;\n\n\t\tte[ 1 ] = - s * a11 + c * a21;\n\t\tte[ 4 ] = - s * a12 + c * a22;\n\t\tte[ 7 ] = - s * a13 + c * a23;\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( tx, ty ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];\n\t\tte[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( matrix ) {\n\n\t\tvar te = this.elements;\n\t\tvar me = matrix.elements;\n\n\t\tfor ( var i = 0; i < 9; i ++ ) {\n\n\t\t\tif ( te[ i ] !== me[ i ] ) return false;\n\n\t\t}\n\n\t\treturn true;\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tfor ( var i = 0; i < 9; i ++ ) {\n\n\t\t\tthis.elements[ i ] = array[ i + offset ];\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tvar te = this.elements;\n\n\t\tarray[ offset ] = te[ 0 ];\n\t\tarray[ offset + 1 ] = te[ 1 ];\n\t\tarray[ offset + 2 ] = te[ 2 ];\n\n\t\tarray[ offset + 3 ] = te[ 3 ];\n\t\tarray[ offset + 4 ] = te[ 4 ];\n\t\tarray[ offset + 5 ] = te[ 5 ];\n\n\t\tarray[ offset + 6 ] = te[ 6 ];\n\t\tarray[ offset + 7 ] = te[ 7 ];\n\t\tarray[ offset + 8 ] = te[ 8 ];\n\n\t\treturn array;\n\n\t}\n\n} );\n\n\nexport { Matrix3 };\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author szimek / https://github.com/szimek/\n */\n\nvar _canvas;\n\nvar ImageUtils = {\n\n\tgetDataURL: function ( image ) {\n\n\t\tvar canvas;\n\n\t\tif ( typeof HTMLCanvasElement == 'undefined' ) {\n\n\t\t\treturn image.src;\n\n\t\t} else if ( image instanceof HTMLCanvasElement ) {\n\n\t\t\tcanvas = image;\n\n\t\t} else {\n\n\t\t\tif ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );\n\n\t\t\t_canvas.width = image.width;\n\t\t\t_canvas.height = image.height;\n\n\t\t\tvar context = _canvas.getContext( '2d' );\n\n\t\t\tif ( image instanceof ImageData ) {\n\n\t\t\t\tcontext.putImageData( image, 0, 0 );\n\n\t\t\t} else {\n\n\t\t\t\tcontext.drawImage( image, 0, 0, image.width, image.height );\n\n\t\t\t}\n\n\t\t\tcanvas = _canvas;\n\n\t\t}\n\n\t\tif ( canvas.width > 2048 || canvas.height > 2048 ) {\n\n\t\t\treturn canvas.toDataURL( 'image/jpeg', 0.6 );\n\n\t\t} else {\n\n\t\t\treturn canvas.toDataURL( 'image/png' );\n\n\t\t}\n\n\t}\n\n};\n\nexport { ImageUtils };\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author szimek / https://github.com/szimek/\n */\n\nimport { EventDispatcher } from '../core/EventDispatcher.js';\nimport {\n\tMirroredRepeatWrapping,\n\tClampToEdgeWrapping,\n\tRepeatWrapping,\n\tLinearEncoding,\n\tUnsignedByteType,\n\tRGBAFormat,\n\tLinearMipmapLinearFilter,\n\tLinearFilter,\n\tUVMapping\n} from '../constants.js';\nimport { MathUtils } from '../math/MathUtils.js';\nimport { Vector2 } from '../math/Vector2.js';\nimport { Matrix3 } from '../math/Matrix3.js';\nimport { ImageUtils } from '../extras/ImageUtils.js';\n\nvar textureId = 0;\n\nfunction Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {\n\n\tObject.defineProperty( this, 'id', { value: textureId ++ } );\n\n\tthis.uuid = MathUtils.generateUUID();\n\n\tthis.name = '';\n\n\tthis.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;\n\tthis.mipmaps = [];\n\n\tthis.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;\n\n\tthis.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;\n\tthis.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;\n\n\tthis.magFilter = magFilter !== undefined ? magFilter : LinearFilter;\n\tthis.minFilter = minFilter !== undefined ? minFilter : LinearMipmapLinearFilter;\n\n\tthis.anisotropy = anisotropy !== undefined ? anisotropy : 1;\n\n\tthis.format = format !== undefined ? format : RGBAFormat;\n\tthis.internalFormat = null;\n\tthis.type = type !== undefined ? type : UnsignedByteType;\n\n\tthis.offset = new Vector2( 0, 0 );\n\tthis.repeat = new Vector2( 1, 1 );\n\tthis.center = new Vector2( 0, 0 );\n\tthis.rotation = 0;\n\n\tthis.matrixAutoUpdate = true;\n\tthis.matrix = new Matrix3();\n\n\tthis.generateMipmaps = true;\n\tthis.premultiplyAlpha = false;\n\tthis.flipY = true;\n\tthis.unpackAlignment = 4;\t// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)\n\n\t// Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.\n\t//\n\t// Also changing the encoding after already used by a Material will not automatically make the Material\n\t// update. You need to explicitly call Material.needsUpdate to trigger it to recompile.\n\tthis.encoding = encoding !== undefined ? encoding : LinearEncoding;\n\n\tthis.version = 0;\n\tthis.onUpdate = null;\n\n}\n\nTexture.DEFAULT_IMAGE = undefined;\nTexture.DEFAULT_MAPPING = UVMapping;\n\nTexture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: Texture,\n\n\tisTexture: true,\n\n\tupdateMatrix: function () {\n\n\t\tthis.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tthis.name = source.name;\n\n\t\tthis.image = source.image;\n\t\tthis.mipmaps = source.mipmaps.slice( 0 );\n\n\t\tthis.mapping = source.mapping;\n\n\t\tthis.wrapS = source.wrapS;\n\t\tthis.wrapT = source.wrapT;\n\n\t\tthis.magFilter = source.magFilter;\n\t\tthis.minFilter = source.minFilter;\n\n\t\tthis.anisotropy = source.anisotropy;\n\n\t\tthis.format = source.format;\n\t\tthis.internalFormat = source.internalFormat;\n\t\tthis.type = source.type;\n\n\t\tthis.offset.copy( source.offset );\n\t\tthis.repeat.copy( source.repeat );\n\t\tthis.center.copy( source.center );\n\t\tthis.rotation = source.rotation;\n\n\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\n\t\tthis.matrix.copy( source.matrix );\n\n\t\tthis.generateMipmaps = source.generateMipmaps;\n\t\tthis.premultiplyAlpha = source.premultiplyAlpha;\n\t\tthis.flipY = source.flipY;\n\t\tthis.unpackAlignment = source.unpackAlignment;\n\t\tthis.encoding = source.encoding;\n\n\t\treturn this;\n\n\t},\n\n\ttoJSON: function ( meta ) {\n\n\t\tvar isRootObject = ( meta === undefined || typeof meta === 'string' );\n\n\t\tif ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {\n\n\t\t\treturn meta.textures[ this.uuid ];\n\n\t\t}\n\n\t\tvar output = {\n\n\t\t\tmetadata: {\n\t\t\t\tversion: 4.5,\n\t\t\t\ttype: 'Texture',\n\t\t\t\tgenerator: 'Texture.toJSON'\n\t\t\t},\n\n\t\t\tuuid: this.uuid,\n\t\t\tname: this.name,\n\n\t\t\tmapping: this.mapping,\n\n\t\t\trepeat: [ this.repeat.x, this.repeat.y ],\n\t\t\toffset: [ this.offset.x, this.offset.y ],\n\t\t\tcenter: [ this.center.x, this.center.y ],\n\t\t\trotation: this.rotation,\n\n\t\t\twrap: [ this.wrapS, this.wrapT ],\n\n\t\t\tformat: this.format,\n\t\t\ttype: this.type,\n\t\t\tencoding: this.encoding,\n\n\t\t\tminFilter: this.minFilter,\n\t\t\tmagFilter: this.magFilter,\n\t\t\tanisotropy: this.anisotropy,\n\n\t\t\tflipY: this.flipY,\n\n\t\t\tpremultiplyAlpha: this.premultiplyAlpha,\n\t\t\tunpackAlignment: this.unpackAlignment\n\n\t\t};\n\n\t\tif ( this.image !== undefined ) {\n\n\t\t\t// TODO: Move to THREE.Image\n\n\t\t\tvar image = this.image;\n\n\t\t\tif ( image.uuid === undefined ) {\n\n\t\t\t\timage.uuid = MathUtils.generateUUID(); // UGH\n\n\t\t\t}\n\n\t\t\tif ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {\n\n\t\t\t\tvar url;\n\n\t\t\t\tif ( Array.isArray( image ) ) {\n\n\t\t\t\t\t// process array of images e.g. CubeTexture\n\n\t\t\t\t\turl = [];\n\n\t\t\t\t\tfor ( var i = 0, l = image.length; i < l; i ++ ) {\n\n\t\t\t\t\t\turl.push( ImageUtils.getDataURL( image[ i ] ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// process single image\n\n\t\t\t\t\turl = ImageUtils.getDataURL( image );\n\n\t\t\t\t}\n\n\t\t\t\tmeta.images[ image.uuid ] = {\n\t\t\t\t\tuuid: image.uuid,\n\t\t\t\t\turl: url\n\t\t\t\t};\n\n\t\t\t}\n\n\t\t\toutput.image = image.uuid;\n\n\t\t}\n\n\t\tif ( ! isRootObject ) {\n\n\t\t\tmeta.textures[ this.uuid ] = output;\n\n\t\t}\n\n\t\treturn output;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t},\n\n\ttransformUv: function ( uv ) {\n\n\t\tif ( this.mapping !== UVMapping ) return uv;\n\n\t\tuv.applyMatrix3( this.matrix );\n\n\t\tif ( uv.x < 0 || uv.x > 1 ) {\n\n\t\t\tswitch ( this.wrapS ) {\n\n\t\t\t\tcase RepeatWrapping:\n\n\t\t\t\t\tuv.x = uv.x - Math.floor( uv.x );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase ClampToEdgeWrapping:\n\n\t\t\t\t\tuv.x = uv.x < 0 ? 0 : 1;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MirroredRepeatWrapping:\n\n\t\t\t\t\tif ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {\n\n\t\t\t\t\t\tuv.x = Math.ceil( uv.x ) - uv.x;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tuv.x = uv.x - Math.floor( uv.x );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( uv.y < 0 || uv.y > 1 ) {\n\n\t\t\tswitch ( this.wrapT ) {\n\n\t\t\t\tcase RepeatWrapping:\n\n\t\t\t\t\tuv.y = uv.y - Math.floor( uv.y );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase ClampToEdgeWrapping:\n\n\t\t\t\t\tuv.y = uv.y < 0 ? 0 : 1;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MirroredRepeatWrapping:\n\n\t\t\t\t\tif ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {\n\n\t\t\t\t\t\tuv.y = Math.ceil( uv.y ) - uv.y;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tuv.y = uv.y - Math.floor( uv.y );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.flipY ) {\n\n\t\t\tuv.y = 1 - uv.y;\n\n\t\t}\n\n\t\treturn uv;\n\n\t}\n\n} );\n\nObject.defineProperty( Texture.prototype, \"needsUpdate\", {\n\n\tset: function ( value ) {\n\n\t\tif ( value === true ) this.version ++;\n\n\t}\n\n} );\n\n\nexport { Texture };\n","/**\n * @author supereggbert / http://www.paulbrunt.co.uk/\n * @author philogb / http://blog.thejit.org/\n * @author mikael emtinger / http://gomo.se/\n * @author egraether / http://egraether.com/\n * @author WestLangley / http://github.com/WestLangley\n */\n\nfunction Vector4( x, y, z, w ) {\n\n\tthis.x = x || 0;\n\tthis.y = y || 0;\n\tthis.z = z || 0;\n\tthis.w = ( w !== undefined ) ? w : 1;\n\n}\n\nObject.defineProperties( Vector4.prototype, {\n\n\t\"width\": {\n\n\t\tget: function () {\n\n\t\t\treturn this.z;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis.z = value;\n\n\t\t}\n\n\t},\n\n\t\"height\": {\n\n\t\tget: function () {\n\n\t\t\treturn this.w;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis.w = value;\n\n\t\t}\n\n\t}\n\n} );\n\nObject.assign( Vector4.prototype, {\n\n\tisVector4: true,\n\n\tset: function ( x, y, z, w ) {\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\t\tthis.w = w;\n\n\t\treturn this;\n\n\t},\n\n\tsetScalar: function ( scalar ) {\n\n\t\tthis.x = scalar;\n\t\tthis.y = scalar;\n\t\tthis.z = scalar;\n\t\tthis.w = scalar;\n\n\t\treturn this;\n\n\t},\n\n\tsetX: function ( x ) {\n\n\t\tthis.x = x;\n\n\t\treturn this;\n\n\t},\n\n\tsetY: function ( y ) {\n\n\t\tthis.y = y;\n\n\t\treturn this;\n\n\t},\n\n\tsetZ: function ( z ) {\n\n\t\tthis.z = z;\n\n\t\treturn this;\n\n\t},\n\n\tsetW: function ( w ) {\n\n\t\tthis.w = w;\n\n\t\treturn this;\n\n\t},\n\n\tsetComponent: function ( index, value ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: this.x = value; break;\n\t\t\tcase 1: this.y = value; break;\n\t\t\tcase 2: this.z = value; break;\n\t\t\tcase 3: this.w = value; break;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tgetComponent: function ( index ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: return this.x;\n\t\t\tcase 1: return this.y;\n\t\t\tcase 2: return this.z;\n\t\t\tcase 3: return this.w;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.x, this.y, this.z, this.w );\n\n\t},\n\n\tcopy: function ( v ) {\n\n\t\tthis.x = v.x;\n\t\tthis.y = v.y;\n\t\tthis.z = v.z;\n\t\tthis.w = ( v.w !== undefined ) ? v.w : 1;\n\n\t\treturn this;\n\n\t},\n\n\tadd: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\n\t\t\treturn this.addVectors( v, w );\n\n\t\t}\n\n\t\tthis.x += v.x;\n\t\tthis.y += v.y;\n\t\tthis.z += v.z;\n\t\tthis.w += v.w;\n\n\t\treturn this;\n\n\t},\n\n\taddScalar: function ( s ) {\n\n\t\tthis.x += s;\n\t\tthis.y += s;\n\t\tthis.z += s;\n\t\tthis.w += s;\n\n\t\treturn this;\n\n\t},\n\n\taddVectors: function ( a, b ) {\n\n\t\tthis.x = a.x + b.x;\n\t\tthis.y = a.y + b.y;\n\t\tthis.z = a.z + b.z;\n\t\tthis.w = a.w + b.w;\n\n\t\treturn this;\n\n\t},\n\n\taddScaledVector: function ( v, s ) {\n\n\t\tthis.x += v.x * s;\n\t\tthis.y += v.y * s;\n\t\tthis.z += v.z * s;\n\t\tthis.w += v.w * s;\n\n\t\treturn this;\n\n\t},\n\n\tsub: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\n\t\t\treturn this.subVectors( v, w );\n\n\t\t}\n\n\t\tthis.x -= v.x;\n\t\tthis.y -= v.y;\n\t\tthis.z -= v.z;\n\t\tthis.w -= v.w;\n\n\t\treturn this;\n\n\t},\n\n\tsubScalar: function ( s ) {\n\n\t\tthis.x -= s;\n\t\tthis.y -= s;\n\t\tthis.z -= s;\n\t\tthis.w -= s;\n\n\t\treturn this;\n\n\t},\n\n\tsubVectors: function ( a, b ) {\n\n\t\tthis.x = a.x - b.x;\n\t\tthis.y = a.y - b.y;\n\t\tthis.z = a.z - b.z;\n\t\tthis.w = a.w - b.w;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( scalar ) {\n\n\t\tthis.x *= scalar;\n\t\tthis.y *= scalar;\n\t\tthis.z *= scalar;\n\t\tthis.w *= scalar;\n\n\t\treturn this;\n\n\t},\n\n\tapplyMatrix4: function ( m ) {\n\n\t\tvar x = this.x, y = this.y, z = this.z, w = this.w;\n\t\tvar e = m.elements;\n\n\t\tthis.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;\n\t\tthis.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;\n\t\tthis.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;\n\t\tthis.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;\n\n\t\treturn this;\n\n\t},\n\n\tdivideScalar: function ( scalar ) {\n\n\t\treturn this.multiplyScalar( 1 / scalar );\n\n\t},\n\n\tsetAxisAngleFromQuaternion: function ( q ) {\n\n\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\n\n\t\t// q is assumed to be normalized\n\n\t\tthis.w = 2 * Math.acos( q.w );\n\n\t\tvar s = Math.sqrt( 1 - q.w * q.w );\n\n\t\tif ( s < 0.0001 ) {\n\n\t\t\tthis.x = 1;\n\t\t\tthis.y = 0;\n\t\t\tthis.z = 0;\n\n\t\t} else {\n\n\t\t\tthis.x = q.x / s;\n\t\t\tthis.y = q.y / s;\n\t\t\tthis.z = q.z / s;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetAxisAngleFromRotationMatrix: function ( m ) {\n\n\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm\n\n\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\n\n\t\tvar angle, x, y, z,\t\t// variables for result\n\t\t\tepsilon = 0.01,\t\t// margin to allow for rounding errors\n\t\t\tepsilon2 = 0.1,\t\t// margin to distinguish between 0 and 180 degrees\n\n\t\t\tte = m.elements,\n\n\t\t\tm11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],\n\t\t\tm21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],\n\t\t\tm31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];\n\n\t\tif ( ( Math.abs( m12 - m21 ) < epsilon ) &&\n\t\t ( Math.abs( m13 - m31 ) < epsilon ) &&\n\t\t ( Math.abs( m23 - m32 ) < epsilon ) ) {\n\n\t\t\t// singularity found\n\t\t\t// first check for identity matrix which must have +1 for all terms\n\t\t\t// in leading diagonal and zero in other terms\n\n\t\t\tif ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&\n\t\t\t ( Math.abs( m13 + m31 ) < epsilon2 ) &&\n\t\t\t ( Math.abs( m23 + m32 ) < epsilon2 ) &&\n\t\t\t ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {\n\n\t\t\t\t// this singularity is identity matrix so angle = 0\n\n\t\t\t\tthis.set( 1, 0, 0, 0 );\n\n\t\t\t\treturn this; // zero angle, arbitrary axis\n\n\t\t\t}\n\n\t\t\t// otherwise this singularity is angle = 180\n\n\t\t\tangle = Math.PI;\n\n\t\t\tvar xx = ( m11 + 1 ) / 2;\n\t\t\tvar yy = ( m22 + 1 ) / 2;\n\t\t\tvar zz = ( m33 + 1 ) / 2;\n\t\t\tvar xy = ( m12 + m21 ) / 4;\n\t\t\tvar xz = ( m13 + m31 ) / 4;\n\t\t\tvar yz = ( m23 + m32 ) / 4;\n\n\t\t\tif ( ( xx > yy ) && ( xx > zz ) ) {\n\n\t\t\t\t// m11 is the largest diagonal term\n\n\t\t\t\tif ( xx < epsilon ) {\n\n\t\t\t\t\tx = 0;\n\t\t\t\t\ty = 0.707106781;\n\t\t\t\t\tz = 0.707106781;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tx = Math.sqrt( xx );\n\t\t\t\t\ty = xy / x;\n\t\t\t\t\tz = xz / x;\n\n\t\t\t\t}\n\n\t\t\t} else if ( yy > zz ) {\n\n\t\t\t\t// m22 is the largest diagonal term\n\n\t\t\t\tif ( yy < epsilon ) {\n\n\t\t\t\t\tx = 0.707106781;\n\t\t\t\t\ty = 0;\n\t\t\t\t\tz = 0.707106781;\n\n\t\t\t\t} else {\n\n\t\t\t\t\ty = Math.sqrt( yy );\n\t\t\t\t\tx = xy / y;\n\t\t\t\t\tz = yz / y;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t// m33 is the largest diagonal term so base result on this\n\n\t\t\t\tif ( zz < epsilon ) {\n\n\t\t\t\t\tx = 0.707106781;\n\t\t\t\t\ty = 0.707106781;\n\t\t\t\t\tz = 0;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tz = Math.sqrt( zz );\n\t\t\t\t\tx = xz / z;\n\t\t\t\t\ty = yz / z;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.set( x, y, z, angle );\n\n\t\t\treturn this; // return 180 deg rotation\n\n\t\t}\n\n\t\t// as we have reached here there are no singularities so we can handle normally\n\n\t\tvar s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +\n\t\t ( m13 - m31 ) * ( m13 - m31 ) +\n\t\t ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize\n\n\t\tif ( Math.abs( s ) < 0.001 ) s = 1;\n\n\t\t// prevent divide by zero, should not happen if matrix is orthogonal and should be\n\t\t// caught by singularity test above, but I've left it in just in case\n\n\t\tthis.x = ( m32 - m23 ) / s;\n\t\tthis.y = ( m13 - m31 ) / s;\n\t\tthis.z = ( m21 - m12 ) / s;\n\t\tthis.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );\n\n\t\treturn this;\n\n\t},\n\n\tmin: function ( v ) {\n\n\t\tthis.x = Math.min( this.x, v.x );\n\t\tthis.y = Math.min( this.y, v.y );\n\t\tthis.z = Math.min( this.z, v.z );\n\t\tthis.w = Math.min( this.w, v.w );\n\n\t\treturn this;\n\n\t},\n\n\tmax: function ( v ) {\n\n\t\tthis.x = Math.max( this.x, v.x );\n\t\tthis.y = Math.max( this.y, v.y );\n\t\tthis.z = Math.max( this.z, v.z );\n\t\tthis.w = Math.max( this.w, v.w );\n\n\t\treturn this;\n\n\t},\n\n\tclamp: function ( min, max ) {\n\n\t\t// assumes min < max, componentwise\n\n\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\n\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\n\t\tthis.z = Math.max( min.z, Math.min( max.z, this.z ) );\n\t\tthis.w = Math.max( min.w, Math.min( max.w, this.w ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampScalar: function ( minVal, maxVal ) {\n\n\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\n\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\n\t\tthis.z = Math.max( minVal, Math.min( maxVal, this.z ) );\n\t\tthis.w = Math.max( minVal, Math.min( maxVal, this.w ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampLength: function ( min, max ) {\n\n\t\tvar length = this.length();\n\n\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\n\n\t},\n\n\tfloor: function () {\n\n\t\tthis.x = Math.floor( this.x );\n\t\tthis.y = Math.floor( this.y );\n\t\tthis.z = Math.floor( this.z );\n\t\tthis.w = Math.floor( this.w );\n\n\t\treturn this;\n\n\t},\n\n\tceil: function () {\n\n\t\tthis.x = Math.ceil( this.x );\n\t\tthis.y = Math.ceil( this.y );\n\t\tthis.z = Math.ceil( this.z );\n\t\tthis.w = Math.ceil( this.w );\n\n\t\treturn this;\n\n\t},\n\n\tround: function () {\n\n\t\tthis.x = Math.round( this.x );\n\t\tthis.y = Math.round( this.y );\n\t\tthis.z = Math.round( this.z );\n\t\tthis.w = Math.round( this.w );\n\n\t\treturn this;\n\n\t},\n\n\troundToZero: function () {\n\n\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\n\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\n\t\tthis.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );\n\t\tthis.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );\n\n\t\treturn this;\n\n\t},\n\n\tnegate: function () {\n\n\t\tthis.x = - this.x;\n\t\tthis.y = - this.y;\n\t\tthis.z = - this.z;\n\t\tthis.w = - this.w;\n\n\t\treturn this;\n\n\t},\n\n\tdot: function ( v ) {\n\n\t\treturn this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;\n\n\t},\n\n\tlengthSq: function () {\n\n\t\treturn this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;\n\n\t},\n\n\tlength: function () {\n\n\t\treturn Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );\n\n\t},\n\n\tmanhattanLength: function () {\n\n\t\treturn Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );\n\n\t},\n\n\tnormalize: function () {\n\n\t\treturn this.divideScalar( this.length() || 1 );\n\n\t},\n\n\tsetLength: function ( length ) {\n\n\t\treturn this.normalize().multiplyScalar( length );\n\n\t},\n\n\tlerp: function ( v, alpha ) {\n\n\t\tthis.x += ( v.x - this.x ) * alpha;\n\t\tthis.y += ( v.y - this.y ) * alpha;\n\t\tthis.z += ( v.z - this.z ) * alpha;\n\t\tthis.w += ( v.w - this.w ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tlerpVectors: function ( v1, v2, alpha ) {\n\n\t\tthis.x = v1.x + ( v2.x - v1.x ) * alpha;\n\t\tthis.y = v1.y + ( v2.y - v1.y ) * alpha;\n\t\tthis.z = v1.z + ( v2.z - v1.z ) * alpha;\n\t\tthis.w = v1.w + ( v2.w - v1.w ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( v ) {\n\n\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis.x = array[ offset ];\n\t\tthis.y = array[ offset + 1 ];\n\t\tthis.z = array[ offset + 2 ];\n\t\tthis.w = array[ offset + 3 ];\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this.x;\n\t\tarray[ offset + 1 ] = this.y;\n\t\tarray[ offset + 2 ] = this.z;\n\t\tarray[ offset + 3 ] = this.w;\n\n\t\treturn array;\n\n\t},\n\n\tfromBufferAttribute: function ( attribute, index, offset ) {\n\n\t\tif ( offset !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );\n\n\t\t}\n\n\t\tthis.x = attribute.getX( index );\n\t\tthis.y = attribute.getY( index );\n\t\tthis.z = attribute.getZ( index );\n\t\tthis.w = attribute.getW( index );\n\n\t\treturn this;\n\n\t},\n\n\trandom: function () {\n\n\t\tthis.x = Math.random();\n\t\tthis.y = Math.random();\n\t\tthis.z = Math.random();\n\t\tthis.w = Math.random();\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Vector4 };\n","import { EventDispatcher } from '../core/EventDispatcher.js';\nimport { Texture } from '../textures/Texture.js';\nimport { LinearFilter } from '../constants.js';\nimport { Vector4 } from '../math/Vector4.js';\n\n/**\n * @author szimek / https://github.com/szimek/\n * @author alteredq / http://alteredqualia.com/\n * @author Marius Kintel / https://github.com/kintel\n */\n\n/*\n In options, we can specify:\n * Texture parameters for an auto-generated target texture\n * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers\n*/\nfunction WebGLRenderTarget( width, height, options ) {\n\n\tthis.width = width;\n\tthis.height = height;\n\n\tthis.scissor = new Vector4( 0, 0, width, height );\n\tthis.scissorTest = false;\n\n\tthis.viewport = new Vector4( 0, 0, width, height );\n\n\toptions = options || {};\n\n\tthis.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );\n\n\tthis.texture.image = {};\n\tthis.texture.image.width = width;\n\tthis.texture.image.height = height;\n\n\tthis.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;\n\tthis.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;\n\n\tthis.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;\n\tthis.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;\n\tthis.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;\n\n}\n\nWebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: WebGLRenderTarget,\n\n\tisWebGLRenderTarget: true,\n\n\tsetSize: function ( width, height ) {\n\n\t\tif ( this.width !== width || this.height !== height ) {\n\n\t\t\tthis.width = width;\n\t\t\tthis.height = height;\n\n\t\t\tthis.texture.image.width = width;\n\t\t\tthis.texture.image.height = height;\n\n\t\t\tthis.dispose();\n\n\t\t}\n\n\t\tthis.viewport.set( 0, 0, width, height );\n\t\tthis.scissor.set( 0, 0, width, height );\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tthis.width = source.width;\n\t\tthis.height = source.height;\n\n\t\tthis.viewport.copy( source.viewport );\n\n\t\tthis.texture = source.texture.clone();\n\n\t\tthis.depthBuffer = source.depthBuffer;\n\t\tthis.stencilBuffer = source.stencilBuffer;\n\t\tthis.depthTexture = source.depthTexture;\n\n\t\treturn this;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t}\n\n} );\n\n\nexport { WebGLRenderTarget };\n","/**\n * @author mikael emtinger / http://gomo.se/\n * @author alteredq / http://alteredqualia.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author bhouston / http://clara.io\n */\n\nimport { MathUtils } from './MathUtils.js';\n\nfunction Quaternion( x, y, z, w ) {\n\n\tthis._x = x || 0;\n\tthis._y = y || 0;\n\tthis._z = z || 0;\n\tthis._w = ( w !== undefined ) ? w : 1;\n\n}\n\nObject.assign( Quaternion, {\n\n\tslerp: function ( qa, qb, qm, t ) {\n\n\t\treturn qm.copy( qa ).slerp( qb, t );\n\n\t},\n\n\tslerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {\n\n\t\t// fuzz-free, array-based Quaternion SLERP operation\n\n\t\tvar x0 = src0[ srcOffset0 + 0 ],\n\t\t\ty0 = src0[ srcOffset0 + 1 ],\n\t\t\tz0 = src0[ srcOffset0 + 2 ],\n\t\t\tw0 = src0[ srcOffset0 + 3 ],\n\n\t\t\tx1 = src1[ srcOffset1 + 0 ],\n\t\t\ty1 = src1[ srcOffset1 + 1 ],\n\t\t\tz1 = src1[ srcOffset1 + 2 ],\n\t\t\tw1 = src1[ srcOffset1 + 3 ];\n\n\t\tif ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {\n\n\t\t\tvar s = 1 - t,\n\n\t\t\t\tcos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,\n\n\t\t\t\tdir = ( cos >= 0 ? 1 : - 1 ),\n\t\t\t\tsqrSin = 1 - cos * cos;\n\n\t\t\t// Skip the Slerp for tiny steps to avoid numeric problems:\n\t\t\tif ( sqrSin > Number.EPSILON ) {\n\n\t\t\t\tvar sin = Math.sqrt( sqrSin ),\n\t\t\t\t\tlen = Math.atan2( sin, cos * dir );\n\n\t\t\t\ts = Math.sin( s * len ) / sin;\n\t\t\t\tt = Math.sin( t * len ) / sin;\n\n\t\t\t}\n\n\t\t\tvar tDir = t * dir;\n\n\t\t\tx0 = x0 * s + x1 * tDir;\n\t\t\ty0 = y0 * s + y1 * tDir;\n\t\t\tz0 = z0 * s + z1 * tDir;\n\t\t\tw0 = w0 * s + w1 * tDir;\n\n\t\t\t// Normalize in case we just did a lerp:\n\t\t\tif ( s === 1 - t ) {\n\n\t\t\t\tvar f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );\n\n\t\t\t\tx0 *= f;\n\t\t\t\ty0 *= f;\n\t\t\t\tz0 *= f;\n\t\t\t\tw0 *= f;\n\n\t\t\t}\n\n\t\t}\n\n\t\tdst[ dstOffset ] = x0;\n\t\tdst[ dstOffset + 1 ] = y0;\n\t\tdst[ dstOffset + 2 ] = z0;\n\t\tdst[ dstOffset + 3 ] = w0;\n\n\t},\n\n\tmultiplyQuaternionsFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {\n\n\t\tvar x0 = src0[ srcOffset0 ];\n\t\tvar y0 = src0[ srcOffset0 + 1 ];\n\t\tvar z0 = src0[ srcOffset0 + 2 ];\n\t\tvar w0 = src0[ srcOffset0 + 3 ];\n\n\t\tvar x1 = src1[ srcOffset1 ];\n\t\tvar y1 = src1[ srcOffset1 + 1 ];\n\t\tvar z1 = src1[ srcOffset1 + 2 ];\n\t\tvar w1 = src1[ srcOffset1 + 3 ];\n\n\t\tdst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;\n\t\tdst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;\n\t\tdst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;\n\t\tdst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;\n\n\t\treturn dst;\n\n\t}\n\n} );\n\nObject.defineProperties( Quaternion.prototype, {\n\n\tx: {\n\n\t\tget: function () {\n\n\t\t\treturn this._x;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._x = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\ty: {\n\n\t\tget: function () {\n\n\t\t\treturn this._y;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._y = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\tz: {\n\n\t\tget: function () {\n\n\t\t\treturn this._z;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._z = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\tw: {\n\n\t\tget: function () {\n\n\t\t\treturn this._w;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._w = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t}\n\n} );\n\nObject.assign( Quaternion.prototype, {\n\n\tisQuaternion: true,\n\n\tset: function ( x, y, z, w ) {\n\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._z = z;\n\t\tthis._w = w;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this._x, this._y, this._z, this._w );\n\n\t},\n\n\tcopy: function ( quaternion ) {\n\n\t\tthis._x = quaternion.x;\n\t\tthis._y = quaternion.y;\n\t\tthis._z = quaternion.z;\n\t\tthis._w = quaternion.w;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromEuler: function ( euler, update ) {\n\n\t\tif ( ! ( euler && euler.isEuler ) ) {\n\n\t\t\tthrow new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );\n\n\t\t}\n\n\t\tvar x = euler._x, y = euler._y, z = euler._z, order = euler.order;\n\n\t\t// http://www.mathworks.com/matlabcentral/fileexchange/\n\t\t// \t20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/\n\t\t//\tcontent/SpinCalc.m\n\n\t\tvar cos = Math.cos;\n\t\tvar sin = Math.sin;\n\n\t\tvar c1 = cos( x / 2 );\n\t\tvar c2 = cos( y / 2 );\n\t\tvar c3 = cos( z / 2 );\n\n\t\tvar s1 = sin( x / 2 );\n\t\tvar s2 = sin( y / 2 );\n\t\tvar s3 = sin( z / 2 );\n\n\t\tswitch ( order ) {\n\n\t\t\tcase 'XYZ':\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tcase 'YXZ':\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZXY':\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZYX':\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tcase 'YZX':\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tcase 'XZY':\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tconsole.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );\n\n\t\t}\n\n\t\tif ( update !== false ) this._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromAxisAngle: function ( axis, angle ) {\n\n\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm\n\n\t\t// assumes axis is normalized\n\n\t\tvar halfAngle = angle / 2, s = Math.sin( halfAngle );\n\n\t\tthis._x = axis.x * s;\n\t\tthis._y = axis.y * s;\n\t\tthis._z = axis.z * s;\n\t\tthis._w = Math.cos( halfAngle );\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromRotationMatrix: function ( m ) {\n\n\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm\n\n\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\n\n\t\tvar te = m.elements,\n\n\t\t\tm11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],\n\t\t\tm21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],\n\t\t\tm31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],\n\n\t\t\ttrace = m11 + m22 + m33,\n\t\t\ts;\n\n\t\tif ( trace > 0 ) {\n\n\t\t\ts = 0.5 / Math.sqrt( trace + 1.0 );\n\n\t\t\tthis._w = 0.25 / s;\n\t\t\tthis._x = ( m32 - m23 ) * s;\n\t\t\tthis._y = ( m13 - m31 ) * s;\n\t\t\tthis._z = ( m21 - m12 ) * s;\n\n\t\t} else if ( m11 > m22 && m11 > m33 ) {\n\n\t\t\ts = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );\n\n\t\t\tthis._w = ( m32 - m23 ) / s;\n\t\t\tthis._x = 0.25 * s;\n\t\t\tthis._y = ( m12 + m21 ) / s;\n\t\t\tthis._z = ( m13 + m31 ) / s;\n\n\t\t} else if ( m22 > m33 ) {\n\n\t\t\ts = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );\n\n\t\t\tthis._w = ( m13 - m31 ) / s;\n\t\t\tthis._x = ( m12 + m21 ) / s;\n\t\t\tthis._y = 0.25 * s;\n\t\t\tthis._z = ( m23 + m32 ) / s;\n\n\t\t} else {\n\n\t\t\ts = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );\n\n\t\t\tthis._w = ( m21 - m12 ) / s;\n\t\t\tthis._x = ( m13 + m31 ) / s;\n\t\t\tthis._y = ( m23 + m32 ) / s;\n\t\t\tthis._z = 0.25 * s;\n\n\t\t}\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromUnitVectors: function ( vFrom, vTo ) {\n\n\t\t// assumes direction vectors vFrom and vTo are normalized\n\n\t\tvar EPS = 0.000001;\n\n\t\tvar r = vFrom.dot( vTo ) + 1;\n\n\t\tif ( r < EPS ) {\n\n\t\t\tr = 0;\n\n\t\t\tif ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {\n\n\t\t\t\tthis._x = - vFrom.y;\n\t\t\t\tthis._y = vFrom.x;\n\t\t\t\tthis._z = 0;\n\t\t\t\tthis._w = r;\n\n\t\t\t} else {\n\n\t\t\t\tthis._x = 0;\n\t\t\t\tthis._y = - vFrom.z;\n\t\t\t\tthis._z = vFrom.y;\n\t\t\t\tthis._w = r;\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3\n\n\t\t\tthis._x = vFrom.y * vTo.z - vFrom.z * vTo.y;\n\t\t\tthis._y = vFrom.z * vTo.x - vFrom.x * vTo.z;\n\t\t\tthis._z = vFrom.x * vTo.y - vFrom.y * vTo.x;\n\t\t\tthis._w = r;\n\n\t\t}\n\n\t\treturn this.normalize();\n\n\t},\n\n\tangleTo: function ( q ) {\n\n\t\treturn 2 * Math.acos( Math.abs( MathUtils.clamp( this.dot( q ), - 1, 1 ) ) );\n\n\t},\n\n\trotateTowards: function ( q, step ) {\n\n\t\tvar angle = this.angleTo( q );\n\n\t\tif ( angle === 0 ) return this;\n\n\t\tvar t = Math.min( 1, step / angle );\n\n\t\tthis.slerp( q, t );\n\n\t\treturn this;\n\n\t},\n\n\tinverse: function () {\n\n\t\t// quaternion is assumed to have unit length\n\n\t\treturn this.conjugate();\n\n\t},\n\n\tconjugate: function () {\n\n\t\tthis._x *= - 1;\n\t\tthis._y *= - 1;\n\t\tthis._z *= - 1;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tdot: function ( v ) {\n\n\t\treturn this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;\n\n\t},\n\n\tlengthSq: function () {\n\n\t\treturn this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;\n\n\t},\n\n\tlength: function () {\n\n\t\treturn Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );\n\n\t},\n\n\tnormalize: function () {\n\n\t\tvar l = this.length();\n\n\t\tif ( l === 0 ) {\n\n\t\t\tthis._x = 0;\n\t\t\tthis._y = 0;\n\t\t\tthis._z = 0;\n\t\t\tthis._w = 1;\n\n\t\t} else {\n\n\t\t\tl = 1 / l;\n\n\t\t\tthis._x = this._x * l;\n\t\t\tthis._y = this._y * l;\n\t\t\tthis._z = this._z * l;\n\t\t\tthis._w = this._w * l;\n\n\t\t}\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( q, p ) {\n\n\t\tif ( p !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );\n\t\t\treturn this.multiplyQuaternions( q, p );\n\n\t\t}\n\n\t\treturn this.multiplyQuaternions( this, q );\n\n\t},\n\n\tpremultiply: function ( q ) {\n\n\t\treturn this.multiplyQuaternions( q, this );\n\n\t},\n\n\tmultiplyQuaternions: function ( a, b ) {\n\n\t\t// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm\n\n\t\tvar qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;\n\t\tvar qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;\n\n\t\tthis._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;\n\t\tthis._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;\n\t\tthis._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;\n\t\tthis._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tslerp: function ( qb, t ) {\n\n\t\tif ( t === 0 ) return this;\n\t\tif ( t === 1 ) return this.copy( qb );\n\n\t\tvar x = this._x, y = this._y, z = this._z, w = this._w;\n\n\t\t// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/\n\n\t\tvar cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;\n\n\t\tif ( cosHalfTheta < 0 ) {\n\n\t\t\tthis._w = - qb._w;\n\t\t\tthis._x = - qb._x;\n\t\t\tthis._y = - qb._y;\n\t\t\tthis._z = - qb._z;\n\n\t\t\tcosHalfTheta = - cosHalfTheta;\n\n\t\t} else {\n\n\t\t\tthis.copy( qb );\n\n\t\t}\n\n\t\tif ( cosHalfTheta >= 1.0 ) {\n\n\t\t\tthis._w = w;\n\t\t\tthis._x = x;\n\t\t\tthis._y = y;\n\t\t\tthis._z = z;\n\n\t\t\treturn this;\n\n\t\t}\n\n\t\tvar sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;\n\n\t\tif ( sqrSinHalfTheta <= Number.EPSILON ) {\n\n\t\t\tvar s = 1 - t;\n\t\t\tthis._w = s * w + t * this._w;\n\t\t\tthis._x = s * x + t * this._x;\n\t\t\tthis._y = s * y + t * this._y;\n\t\t\tthis._z = s * z + t * this._z;\n\n\t\t\tthis.normalize();\n\t\t\tthis._onChangeCallback();\n\n\t\t\treturn this;\n\n\t\t}\n\n\t\tvar sinHalfTheta = Math.sqrt( sqrSinHalfTheta );\n\t\tvar halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );\n\t\tvar ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,\n\t\t\tratioB = Math.sin( t * halfTheta ) / sinHalfTheta;\n\n\t\tthis._w = ( w * ratioA + this._w * ratioB );\n\t\tthis._x = ( x * ratioA + this._x * ratioB );\n\t\tthis._y = ( y * ratioA + this._y * ratioB );\n\t\tthis._z = ( z * ratioA + this._z * ratioB );\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( quaternion ) {\n\n\t\treturn ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis._x = array[ offset ];\n\t\tthis._y = array[ offset + 1 ];\n\t\tthis._z = array[ offset + 2 ];\n\t\tthis._w = array[ offset + 3 ];\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this._x;\n\t\tarray[ offset + 1 ] = this._y;\n\t\tarray[ offset + 2 ] = this._z;\n\t\tarray[ offset + 3 ] = this._w;\n\n\t\treturn array;\n\n\t},\n\n\tfromBufferAttribute: function ( attribute, index ) {\n\n\t\tthis._x = attribute.getX( index );\n\t\tthis._y = attribute.getY( index );\n\t\tthis._z = attribute.getZ( index );\n\t\tthis._w = attribute.getW( index );\n\n\t\treturn this;\n\n\t},\n\n\t_onChange: function ( callback ) {\n\n\t\tthis._onChangeCallback = callback;\n\n\t\treturn this;\n\n\t},\n\n\t_onChangeCallback: function () {}\n\n} );\n\n\nexport { Quaternion };\n","import { MathUtils } from './MathUtils.js';\nimport { Quaternion } from './Quaternion.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author kile / http://kile.stravaganza.org/\n * @author philogb / http://blog.thejit.org/\n * @author mikael emtinger / http://gomo.se/\n * @author egraether / http://egraether.com/\n * @author WestLangley / http://github.com/WestLangley\n */\n\nvar _vector = new Vector3();\nvar _quaternion = new Quaternion();\n\nfunction Vector3( x, y, z ) {\n\n\tthis.x = x || 0;\n\tthis.y = y || 0;\n\tthis.z = z || 0;\n\n}\n\nObject.assign( Vector3.prototype, {\n\n\tisVector3: true,\n\n\tset: function ( x, y, z ) {\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\n\t\treturn this;\n\n\t},\n\n\tsetScalar: function ( scalar ) {\n\n\t\tthis.x = scalar;\n\t\tthis.y = scalar;\n\t\tthis.z = scalar;\n\n\t\treturn this;\n\n\t},\n\n\tsetX: function ( x ) {\n\n\t\tthis.x = x;\n\n\t\treturn this;\n\n\t},\n\n\tsetY: function ( y ) {\n\n\t\tthis.y = y;\n\n\t\treturn this;\n\n\t},\n\n\tsetZ: function ( z ) {\n\n\t\tthis.z = z;\n\n\t\treturn this;\n\n\t},\n\n\tsetComponent: function ( index, value ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: this.x = value; break;\n\t\t\tcase 1: this.y = value; break;\n\t\t\tcase 2: this.z = value; break;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tgetComponent: function ( index ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: return this.x;\n\t\t\tcase 1: return this.y;\n\t\t\tcase 2: return this.z;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.x, this.y, this.z );\n\n\t},\n\n\tcopy: function ( v ) {\n\n\t\tthis.x = v.x;\n\t\tthis.y = v.y;\n\t\tthis.z = v.z;\n\n\t\treturn this;\n\n\t},\n\n\tadd: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\n\t\t\treturn this.addVectors( v, w );\n\n\t\t}\n\n\t\tthis.x += v.x;\n\t\tthis.y += v.y;\n\t\tthis.z += v.z;\n\n\t\treturn this;\n\n\t},\n\n\taddScalar: function ( s ) {\n\n\t\tthis.x += s;\n\t\tthis.y += s;\n\t\tthis.z += s;\n\n\t\treturn this;\n\n\t},\n\n\taddVectors: function ( a, b ) {\n\n\t\tthis.x = a.x + b.x;\n\t\tthis.y = a.y + b.y;\n\t\tthis.z = a.z + b.z;\n\n\t\treturn this;\n\n\t},\n\n\taddScaledVector: function ( v, s ) {\n\n\t\tthis.x += v.x * s;\n\t\tthis.y += v.y * s;\n\t\tthis.z += v.z * s;\n\n\t\treturn this;\n\n\t},\n\n\tsub: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\n\t\t\treturn this.subVectors( v, w );\n\n\t\t}\n\n\t\tthis.x -= v.x;\n\t\tthis.y -= v.y;\n\t\tthis.z -= v.z;\n\n\t\treturn this;\n\n\t},\n\n\tsubScalar: function ( s ) {\n\n\t\tthis.x -= s;\n\t\tthis.y -= s;\n\t\tthis.z -= s;\n\n\t\treturn this;\n\n\t},\n\n\tsubVectors: function ( a, b ) {\n\n\t\tthis.x = a.x - b.x;\n\t\tthis.y = a.y - b.y;\n\t\tthis.z = a.z - b.z;\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );\n\t\t\treturn this.multiplyVectors( v, w );\n\n\t\t}\n\n\t\tthis.x *= v.x;\n\t\tthis.y *= v.y;\n\t\tthis.z *= v.z;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( scalar ) {\n\n\t\tthis.x *= scalar;\n\t\tthis.y *= scalar;\n\t\tthis.z *= scalar;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyVectors: function ( a, b ) {\n\n\t\tthis.x = a.x * b.x;\n\t\tthis.y = a.y * b.y;\n\t\tthis.z = a.z * b.z;\n\n\t\treturn this;\n\n\t},\n\n\tapplyEuler: function ( euler ) {\n\n\t\tif ( ! ( euler && euler.isEuler ) ) {\n\n\t\t\tconsole.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );\n\n\t\t}\n\n\t\treturn this.applyQuaternion( _quaternion.setFromEuler( euler ) );\n\n\t},\n\n\tapplyAxisAngle: function ( axis, angle ) {\n\n\t\treturn this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );\n\n\t},\n\n\tapplyMatrix3: function ( m ) {\n\n\t\tvar x = this.x, y = this.y, z = this.z;\n\t\tvar e = m.elements;\n\n\t\tthis.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;\n\t\tthis.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;\n\t\tthis.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;\n\n\t\treturn this;\n\n\t},\n\n\tapplyNormalMatrix: function ( m ) {\n\n\t\treturn this.applyMatrix3( m ).normalize();\n\n\t},\n\n\tapplyMatrix4: function ( m ) {\n\n\t\tvar x = this.x, y = this.y, z = this.z;\n\t\tvar e = m.elements;\n\n\t\tvar w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );\n\n\t\tthis.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;\n\t\tthis.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;\n\t\tthis.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;\n\n\t\treturn this;\n\n\t},\n\n\tapplyQuaternion: function ( q ) {\n\n\t\tvar x = this.x, y = this.y, z = this.z;\n\t\tvar qx = q.x, qy = q.y, qz = q.z, qw = q.w;\n\n\t\t// calculate quat * vector\n\n\t\tvar ix = qw * x + qy * z - qz * y;\n\t\tvar iy = qw * y + qz * x - qx * z;\n\t\tvar iz = qw * z + qx * y - qy * x;\n\t\tvar iw = - qx * x - qy * y - qz * z;\n\n\t\t// calculate result * inverse quat\n\n\t\tthis.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;\n\t\tthis.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;\n\t\tthis.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;\n\n\t\treturn this;\n\n\t},\n\n\tproject: function ( camera ) {\n\n\t\treturn this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );\n\n\t},\n\n\tunproject: function ( camera ) {\n\n\t\treturn this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );\n\n\t},\n\n\ttransformDirection: function ( m ) {\n\n\t\t// input: THREE.Matrix4 affine matrix\n\t\t// vector interpreted as a direction\n\n\t\tvar x = this.x, y = this.y, z = this.z;\n\t\tvar e = m.elements;\n\n\t\tthis.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;\n\t\tthis.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;\n\t\tthis.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;\n\n\t\treturn this.normalize();\n\n\t},\n\n\tdivide: function ( v ) {\n\n\t\tthis.x /= v.x;\n\t\tthis.y /= v.y;\n\t\tthis.z /= v.z;\n\n\t\treturn this;\n\n\t},\n\n\tdivideScalar: function ( scalar ) {\n\n\t\treturn this.multiplyScalar( 1 / scalar );\n\n\t},\n\n\tmin: function ( v ) {\n\n\t\tthis.x = Math.min( this.x, v.x );\n\t\tthis.y = Math.min( this.y, v.y );\n\t\tthis.z = Math.min( this.z, v.z );\n\n\t\treturn this;\n\n\t},\n\n\tmax: function ( v ) {\n\n\t\tthis.x = Math.max( this.x, v.x );\n\t\tthis.y = Math.max( this.y, v.y );\n\t\tthis.z = Math.max( this.z, v.z );\n\n\t\treturn this;\n\n\t},\n\n\tclamp: function ( min, max ) {\n\n\t\t// assumes min < max, componentwise\n\n\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\n\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\n\t\tthis.z = Math.max( min.z, Math.min( max.z, this.z ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampScalar: function ( minVal, maxVal ) {\n\n\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\n\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\n\t\tthis.z = Math.max( minVal, Math.min( maxVal, this.z ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampLength: function ( min, max ) {\n\n\t\tvar length = this.length();\n\n\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\n\n\t},\n\n\tfloor: function () {\n\n\t\tthis.x = Math.floor( this.x );\n\t\tthis.y = Math.floor( this.y );\n\t\tthis.z = Math.floor( this.z );\n\n\t\treturn this;\n\n\t},\n\n\tceil: function () {\n\n\t\tthis.x = Math.ceil( this.x );\n\t\tthis.y = Math.ceil( this.y );\n\t\tthis.z = Math.ceil( this.z );\n\n\t\treturn this;\n\n\t},\n\n\tround: function () {\n\n\t\tthis.x = Math.round( this.x );\n\t\tthis.y = Math.round( this.y );\n\t\tthis.z = Math.round( this.z );\n\n\t\treturn this;\n\n\t},\n\n\troundToZero: function () {\n\n\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\n\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\n\t\tthis.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );\n\n\t\treturn this;\n\n\t},\n\n\tnegate: function () {\n\n\t\tthis.x = - this.x;\n\t\tthis.y = - this.y;\n\t\tthis.z = - this.z;\n\n\t\treturn this;\n\n\t},\n\n\tdot: function ( v ) {\n\n\t\treturn this.x * v.x + this.y * v.y + this.z * v.z;\n\n\t},\n\n\t// TODO lengthSquared?\n\n\tlengthSq: function () {\n\n\t\treturn this.x * this.x + this.y * this.y + this.z * this.z;\n\n\t},\n\n\tlength: function () {\n\n\t\treturn Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );\n\n\t},\n\n\tmanhattanLength: function () {\n\n\t\treturn Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );\n\n\t},\n\n\tnormalize: function () {\n\n\t\treturn this.divideScalar( this.length() || 1 );\n\n\t},\n\n\tsetLength: function ( length ) {\n\n\t\treturn this.normalize().multiplyScalar( length );\n\n\t},\n\n\tlerp: function ( v, alpha ) {\n\n\t\tthis.x += ( v.x - this.x ) * alpha;\n\t\tthis.y += ( v.y - this.y ) * alpha;\n\t\tthis.z += ( v.z - this.z ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tlerpVectors: function ( v1, v2, alpha ) {\n\n\t\tthis.x = v1.x + ( v2.x - v1.x ) * alpha;\n\t\tthis.y = v1.y + ( v2.y - v1.y ) * alpha;\n\t\tthis.z = v1.z + ( v2.z - v1.z ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tcross: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );\n\t\t\treturn this.crossVectors( v, w );\n\n\t\t}\n\n\t\treturn this.crossVectors( this, v );\n\n\t},\n\n\tcrossVectors: function ( a, b ) {\n\n\t\tvar ax = a.x, ay = a.y, az = a.z;\n\t\tvar bx = b.x, by = b.y, bz = b.z;\n\n\t\tthis.x = ay * bz - az * by;\n\t\tthis.y = az * bx - ax * bz;\n\t\tthis.z = ax * by - ay * bx;\n\n\t\treturn this;\n\n\t},\n\n\tprojectOnVector: function ( v ) {\n\n\t\tvar denominator = v.lengthSq();\n\n\t\tif ( denominator === 0 ) return this.set( 0, 0, 0 );\n\n\t\tvar scalar = v.dot( this ) / denominator;\n\n\t\treturn this.copy( v ).multiplyScalar( scalar );\n\n\t},\n\n\tprojectOnPlane: function ( planeNormal ) {\n\n\t\t_vector.copy( this ).projectOnVector( planeNormal );\n\n\t\treturn this.sub( _vector );\n\n\t},\n\n\treflect: function ( normal ) {\n\n\t\t// reflect incident vector off plane orthogonal to normal\n\t\t// normal is assumed to have unit length\n\n\t\treturn this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );\n\n\t},\n\n\tangleTo: function ( v ) {\n\n\t\tvar denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );\n\n\t\tif ( denominator === 0 ) return Math.PI / 2;\n\n\t\tvar theta = this.dot( v ) / denominator;\n\n\t\t// clamp, to handle numerical problems\n\n\t\treturn Math.acos( MathUtils.clamp( theta, - 1, 1 ) );\n\n\t},\n\n\tdistanceTo: function ( v ) {\n\n\t\treturn Math.sqrt( this.distanceToSquared( v ) );\n\n\t},\n\n\tdistanceToSquared: function ( v ) {\n\n\t\tvar dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;\n\n\t\treturn dx * dx + dy * dy + dz * dz;\n\n\t},\n\n\tmanhattanDistanceTo: function ( v ) {\n\n\t\treturn Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );\n\n\t},\n\n\tsetFromSpherical: function ( s ) {\n\n\t\treturn this.setFromSphericalCoords( s.radius, s.phi, s.theta );\n\n\t},\n\n\tsetFromSphericalCoords: function ( radius, phi, theta ) {\n\n\t\tvar sinPhiRadius = Math.sin( phi ) * radius;\n\n\t\tthis.x = sinPhiRadius * Math.sin( theta );\n\t\tthis.y = Math.cos( phi ) * radius;\n\t\tthis.z = sinPhiRadius * Math.cos( theta );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromCylindrical: function ( c ) {\n\n\t\treturn this.setFromCylindricalCoords( c.radius, c.theta, c.y );\n\n\t},\n\n\tsetFromCylindricalCoords: function ( radius, theta, y ) {\n\n\t\tthis.x = radius * Math.sin( theta );\n\t\tthis.y = y;\n\t\tthis.z = radius * Math.cos( theta );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromMatrixPosition: function ( m ) {\n\n\t\tvar e = m.elements;\n\n\t\tthis.x = e[ 12 ];\n\t\tthis.y = e[ 13 ];\n\t\tthis.z = e[ 14 ];\n\n\t\treturn this;\n\n\t},\n\n\tsetFromMatrixScale: function ( m ) {\n\n\t\tvar sx = this.setFromMatrixColumn( m, 0 ).length();\n\t\tvar sy = this.setFromMatrixColumn( m, 1 ).length();\n\t\tvar sz = this.setFromMatrixColumn( m, 2 ).length();\n\n\t\tthis.x = sx;\n\t\tthis.y = sy;\n\t\tthis.z = sz;\n\n\t\treturn this;\n\n\t},\n\n\tsetFromMatrixColumn: function ( m, index ) {\n\n\t\treturn this.fromArray( m.elements, index * 4 );\n\n\t},\n\n\tsetFromMatrix3Column: function ( m, index ) {\n\n\t\treturn this.fromArray( m.elements, index * 3 );\n\n\t},\n\n\tequals: function ( v ) {\n\n\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis.x = array[ offset ];\n\t\tthis.y = array[ offset + 1 ];\n\t\tthis.z = array[ offset + 2 ];\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this.x;\n\t\tarray[ offset + 1 ] = this.y;\n\t\tarray[ offset + 2 ] = this.z;\n\n\t\treturn array;\n\n\t},\n\n\tfromBufferAttribute: function ( attribute, index, offset ) {\n\n\t\tif ( offset !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );\n\n\t\t}\n\n\t\tthis.x = attribute.getX( index );\n\t\tthis.y = attribute.getY( index );\n\t\tthis.z = attribute.getZ( index );\n\n\t\treturn this;\n\n\t},\n\n\trandom: function () {\n\n\t\tthis.x = Math.random();\n\t\tthis.y = Math.random();\n\t\tthis.z = Math.random();\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Vector3 };\n","import { Vector3 } from './Vector3.js';\n\nvar _v1 = new Vector3();\nvar _m1 = new Matrix4();\nvar _zero = new Vector3( 0, 0, 0 );\nvar _one = new Vector3( 1, 1, 1 );\nvar _x = new Vector3();\nvar _y = new Vector3();\nvar _z = new Vector3();\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author supereggbert / http://www.paulbrunt.co.uk/\n * @author philogb / http://blog.thejit.org/\n * @author jordi_ros / http://plattsoft.com\n * @author D1plo1d / http://github.com/D1plo1d\n * @author alteredq / http://alteredqualia.com/\n * @author mikael emtinger / http://gomo.se/\n * @author timknip / http://www.floorplanner.com/\n * @author bhouston / http://clara.io\n * @author WestLangley / http://github.com/WestLangley\n */\n\nfunction Matrix4() {\n\n\tthis.elements = [\n\n\t\t1, 0, 0, 0,\n\t\t0, 1, 0, 0,\n\t\t0, 0, 1, 0,\n\t\t0, 0, 0, 1\n\n\t];\n\n\tif ( arguments.length > 0 ) {\n\n\t\tconsole.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );\n\n\t}\n\n}\n\nObject.assign( Matrix4.prototype, {\n\n\tisMatrix4: true,\n\n\tset: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;\n\t\tte[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;\n\t\tte[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;\n\t\tte[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;\n\n\t\treturn this;\n\n\t},\n\n\tidentity: function () {\n\n\t\tthis.set(\n\n\t\t\t1, 0, 0, 0,\n\t\t\t0, 1, 0, 0,\n\t\t\t0, 0, 1, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new Matrix4().fromArray( this.elements );\n\n\t},\n\n\tcopy: function ( m ) {\n\n\t\tvar te = this.elements;\n\t\tvar me = m.elements;\n\n\t\tte[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];\n\t\tte[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];\n\t\tte[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];\n\t\tte[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];\n\n\t\treturn this;\n\n\t},\n\n\tcopyPosition: function ( m ) {\n\n\t\tvar te = this.elements, me = m.elements;\n\n\t\tte[ 12 ] = me[ 12 ];\n\t\tte[ 13 ] = me[ 13 ];\n\t\tte[ 14 ] = me[ 14 ];\n\n\t\treturn this;\n\n\t},\n\n\textractBasis: function ( xAxis, yAxis, zAxis ) {\n\n\t\txAxis.setFromMatrixColumn( this, 0 );\n\t\tyAxis.setFromMatrixColumn( this, 1 );\n\t\tzAxis.setFromMatrixColumn( this, 2 );\n\n\t\treturn this;\n\n\t},\n\n\tmakeBasis: function ( xAxis, yAxis, zAxis ) {\n\n\t\tthis.set(\n\t\t\txAxis.x, yAxis.x, zAxis.x, 0,\n\t\t\txAxis.y, yAxis.y, zAxis.y, 0,\n\t\t\txAxis.z, yAxis.z, zAxis.z, 0,\n\t\t\t0, 0, 0, 1\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\textractRotation: function ( m ) {\n\n\t\t// this method does not support reflection matrices\n\n\t\tvar te = this.elements;\n\t\tvar me = m.elements;\n\n\t\tvar scaleX = 1 / _v1.setFromMatrixColumn( m, 0 ).length();\n\t\tvar scaleY = 1 / _v1.setFromMatrixColumn( m, 1 ).length();\n\t\tvar scaleZ = 1 / _v1.setFromMatrixColumn( m, 2 ).length();\n\n\t\tte[ 0 ] = me[ 0 ] * scaleX;\n\t\tte[ 1 ] = me[ 1 ] * scaleX;\n\t\tte[ 2 ] = me[ 2 ] * scaleX;\n\t\tte[ 3 ] = 0;\n\n\t\tte[ 4 ] = me[ 4 ] * scaleY;\n\t\tte[ 5 ] = me[ 5 ] * scaleY;\n\t\tte[ 6 ] = me[ 6 ] * scaleY;\n\t\tte[ 7 ] = 0;\n\n\t\tte[ 8 ] = me[ 8 ] * scaleZ;\n\t\tte[ 9 ] = me[ 9 ] * scaleZ;\n\t\tte[ 10 ] = me[ 10 ] * scaleZ;\n\t\tte[ 11 ] = 0;\n\n\t\tte[ 12 ] = 0;\n\t\tte[ 13 ] = 0;\n\t\tte[ 14 ] = 0;\n\t\tte[ 15 ] = 1;\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationFromEuler: function ( euler ) {\n\n\t\tif ( ! ( euler && euler.isEuler ) ) {\n\n\t\t\tconsole.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );\n\n\t\t}\n\n\t\tvar te = this.elements;\n\n\t\tvar x = euler.x, y = euler.y, z = euler.z;\n\t\tvar a = Math.cos( x ), b = Math.sin( x );\n\t\tvar c = Math.cos( y ), d = Math.sin( y );\n\t\tvar e = Math.cos( z ), f = Math.sin( z );\n\n\t\tif ( euler.order === 'XYZ' ) {\n\n\t\t\tvar ae = a * e, af = a * f, be = b * e, bf = b * f;\n\n\t\t\tte[ 0 ] = c * e;\n\t\t\tte[ 4 ] = - c * f;\n\t\t\tte[ 8 ] = d;\n\n\t\t\tte[ 1 ] = af + be * d;\n\t\t\tte[ 5 ] = ae - bf * d;\n\t\t\tte[ 9 ] = - b * c;\n\n\t\t\tte[ 2 ] = bf - ae * d;\n\t\t\tte[ 6 ] = be + af * d;\n\t\t\tte[ 10 ] = a * c;\n\n\t\t} else if ( euler.order === 'YXZ' ) {\n\n\t\t\tvar ce = c * e, cf = c * f, de = d * e, df = d * f;\n\n\t\t\tte[ 0 ] = ce + df * b;\n\t\t\tte[ 4 ] = de * b - cf;\n\t\t\tte[ 8 ] = a * d;\n\n\t\t\tte[ 1 ] = a * f;\n\t\t\tte[ 5 ] = a * e;\n\t\t\tte[ 9 ] = - b;\n\n\t\t\tte[ 2 ] = cf * b - de;\n\t\t\tte[ 6 ] = df + ce * b;\n\t\t\tte[ 10 ] = a * c;\n\n\t\t} else if ( euler.order === 'ZXY' ) {\n\n\t\t\tvar ce = c * e, cf = c * f, de = d * e, df = d * f;\n\n\t\t\tte[ 0 ] = ce - df * b;\n\t\t\tte[ 4 ] = - a * f;\n\t\t\tte[ 8 ] = de + cf * b;\n\n\t\t\tte[ 1 ] = cf + de * b;\n\t\t\tte[ 5 ] = a * e;\n\t\t\tte[ 9 ] = df - ce * b;\n\n\t\t\tte[ 2 ] = - a * d;\n\t\t\tte[ 6 ] = b;\n\t\t\tte[ 10 ] = a * c;\n\n\t\t} else if ( euler.order === 'ZYX' ) {\n\n\t\t\tvar ae = a * e, af = a * f, be = b * e, bf = b * f;\n\n\t\t\tte[ 0 ] = c * e;\n\t\t\tte[ 4 ] = be * d - af;\n\t\t\tte[ 8 ] = ae * d + bf;\n\n\t\t\tte[ 1 ] = c * f;\n\t\t\tte[ 5 ] = bf * d + ae;\n\t\t\tte[ 9 ] = af * d - be;\n\n\t\t\tte[ 2 ] = - d;\n\t\t\tte[ 6 ] = b * c;\n\t\t\tte[ 10 ] = a * c;\n\n\t\t} else if ( euler.order === 'YZX' ) {\n\n\t\t\tvar ac = a * c, ad = a * d, bc = b * c, bd = b * d;\n\n\t\t\tte[ 0 ] = c * e;\n\t\t\tte[ 4 ] = bd - ac * f;\n\t\t\tte[ 8 ] = bc * f + ad;\n\n\t\t\tte[ 1 ] = f;\n\t\t\tte[ 5 ] = a * e;\n\t\t\tte[ 9 ] = - b * e;\n\n\t\t\tte[ 2 ] = - d * e;\n\t\t\tte[ 6 ] = ad * f + bc;\n\t\t\tte[ 10 ] = ac - bd * f;\n\n\t\t} else if ( euler.order === 'XZY' ) {\n\n\t\t\tvar ac = a * c, ad = a * d, bc = b * c, bd = b * d;\n\n\t\t\tte[ 0 ] = c * e;\n\t\t\tte[ 4 ] = - f;\n\t\t\tte[ 8 ] = d * e;\n\n\t\t\tte[ 1 ] = ac * f + bd;\n\t\t\tte[ 5 ] = a * e;\n\t\t\tte[ 9 ] = ad * f - bc;\n\n\t\t\tte[ 2 ] = bc * f - ad;\n\t\t\tte[ 6 ] = b * e;\n\t\t\tte[ 10 ] = bd * f + ac;\n\n\t\t}\n\n\t\t// bottom row\n\t\tte[ 3 ] = 0;\n\t\tte[ 7 ] = 0;\n\t\tte[ 11 ] = 0;\n\n\t\t// last column\n\t\tte[ 12 ] = 0;\n\t\tte[ 13 ] = 0;\n\t\tte[ 14 ] = 0;\n\t\tte[ 15 ] = 1;\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationFromQuaternion: function ( q ) {\n\n\t\treturn this.compose( _zero, q, _one );\n\n\t},\n\n\tlookAt: function ( eye, target, up ) {\n\n\t\tvar te = this.elements;\n\n\t\t_z.subVectors( eye, target );\n\n\t\tif ( _z.lengthSq() === 0 ) {\n\n\t\t\t// eye and target are in the same position\n\n\t\t\t_z.z = 1;\n\n\t\t}\n\n\t\t_z.normalize();\n\t\t_x.crossVectors( up, _z );\n\n\t\tif ( _x.lengthSq() === 0 ) {\n\n\t\t\t// up and z are parallel\n\n\t\t\tif ( Math.abs( up.z ) === 1 ) {\n\n\t\t\t\t_z.x += 0.0001;\n\n\t\t\t} else {\n\n\t\t\t\t_z.z += 0.0001;\n\n\t\t\t}\n\n\t\t\t_z.normalize();\n\t\t\t_x.crossVectors( up, _z );\n\n\t\t}\n\n\t\t_x.normalize();\n\t\t_y.crossVectors( _z, _x );\n\n\t\tte[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;\n\t\tte[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;\n\t\tte[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( m, n ) {\n\n\t\tif ( n !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );\n\t\t\treturn this.multiplyMatrices( m, n );\n\n\t\t}\n\n\t\treturn this.multiplyMatrices( this, m );\n\n\t},\n\n\tpremultiply: function ( m ) {\n\n\t\treturn this.multiplyMatrices( m, this );\n\n\t},\n\n\tmultiplyMatrices: function ( a, b ) {\n\n\t\tvar ae = a.elements;\n\t\tvar be = b.elements;\n\t\tvar te = this.elements;\n\n\t\tvar a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];\n\t\tvar a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];\n\t\tvar a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];\n\t\tvar a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];\n\n\t\tvar b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];\n\t\tvar b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];\n\t\tvar b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];\n\t\tvar b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];\n\n\t\tte[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;\n\t\tte[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;\n\t\tte[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;\n\t\tte[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;\n\n\t\tte[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;\n\t\tte[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;\n\t\tte[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;\n\t\tte[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;\n\n\t\tte[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;\n\t\tte[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;\n\t\tte[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;\n\t\tte[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;\n\n\t\tte[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;\n\t\tte[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;\n\t\tte[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;\n\t\tte[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( s ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;\n\t\tte[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;\n\t\tte[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;\n\t\tte[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;\n\n\t\treturn this;\n\n\t},\n\n\tdeterminant: function () {\n\n\t\tvar te = this.elements;\n\n\t\tvar n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];\n\t\tvar n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];\n\t\tvar n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];\n\t\tvar n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];\n\n\t\t//TODO: make this more efficient\n\t\t//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )\n\n\t\treturn (\n\t\t\tn41 * (\n\t\t\t\t+ n14 * n23 * n32\n\t\t\t\t - n13 * n24 * n32\n\t\t\t\t - n14 * n22 * n33\n\t\t\t\t + n12 * n24 * n33\n\t\t\t\t + n13 * n22 * n34\n\t\t\t\t - n12 * n23 * n34\n\t\t\t) +\n\t\t\tn42 * (\n\t\t\t\t+ n11 * n23 * n34\n\t\t\t\t - n11 * n24 * n33\n\t\t\t\t + n14 * n21 * n33\n\t\t\t\t - n13 * n21 * n34\n\t\t\t\t + n13 * n24 * n31\n\t\t\t\t - n14 * n23 * n31\n\t\t\t) +\n\t\t\tn43 * (\n\t\t\t\t+ n11 * n24 * n32\n\t\t\t\t - n11 * n22 * n34\n\t\t\t\t - n14 * n21 * n32\n\t\t\t\t + n12 * n21 * n34\n\t\t\t\t + n14 * n22 * n31\n\t\t\t\t - n12 * n24 * n31\n\t\t\t) +\n\t\t\tn44 * (\n\t\t\t\t- n13 * n22 * n31\n\t\t\t\t - n11 * n23 * n32\n\t\t\t\t + n11 * n22 * n33\n\t\t\t\t + n13 * n21 * n32\n\t\t\t\t - n12 * n21 * n33\n\t\t\t\t + n12 * n23 * n31\n\t\t\t)\n\n\t\t);\n\n\t},\n\n\ttranspose: function () {\n\n\t\tvar te = this.elements;\n\t\tvar tmp;\n\n\t\ttmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;\n\t\ttmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;\n\t\ttmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;\n\n\t\ttmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;\n\t\ttmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;\n\t\ttmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;\n\n\t\treturn this;\n\n\t},\n\n\tsetPosition: function ( x, y, z ) {\n\n\t\tvar te = this.elements;\n\n\t\tif ( x.isVector3 ) {\n\n\t\t\tte[ 12 ] = x.x;\n\t\t\tte[ 13 ] = x.y;\n\t\t\tte[ 14 ] = x.z;\n\n\t\t} else {\n\n\t\t\tte[ 12 ] = x;\n\t\t\tte[ 13 ] = y;\n\t\t\tte[ 14 ] = z;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tgetInverse: function ( m, throwOnDegenerate ) {\n\n\t\tif ( throwOnDegenerate !== undefined ) {\n\n\t\t\tconsole.warn( \"THREE.Matrix4: .getInverse() can no longer be configured to throw on degenerate.\" );\n\n\t\t}\n\n\t\t// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm\n\t\tvar te = this.elements,\n\t\t\tme = m.elements,\n\n\t\t\tn11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],\n\t\t\tn12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],\n\t\t\tn13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],\n\t\t\tn14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],\n\n\t\t\tt11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,\n\t\t\tt12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,\n\t\t\tt13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,\n\t\t\tt14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;\n\n\t\tvar det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;\n\n\t\tif ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );\n\n\t\tvar detInv = 1 / det;\n\n\t\tte[ 0 ] = t11 * detInv;\n\t\tte[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;\n\t\tte[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;\n\t\tte[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;\n\n\t\tte[ 4 ] = t12 * detInv;\n\t\tte[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;\n\t\tte[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;\n\t\tte[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;\n\n\t\tte[ 8 ] = t13 * detInv;\n\t\tte[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;\n\t\tte[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;\n\t\tte[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;\n\n\t\tte[ 12 ] = t14 * detInv;\n\t\tte[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;\n\t\tte[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;\n\t\tte[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;\n\n\t\treturn this;\n\n\t},\n\n\tscale: function ( v ) {\n\n\t\tvar te = this.elements;\n\t\tvar x = v.x, y = v.y, z = v.z;\n\n\t\tte[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;\n\t\tte[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;\n\t\tte[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;\n\t\tte[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;\n\n\t\treturn this;\n\n\t},\n\n\tgetMaxScaleOnAxis: function () {\n\n\t\tvar te = this.elements;\n\n\t\tvar scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];\n\t\tvar scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];\n\t\tvar scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];\n\n\t\treturn Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );\n\n\t},\n\n\tmakeTranslation: function ( x, y, z ) {\n\n\t\tthis.set(\n\n\t\t\t1, 0, 0, x,\n\t\t\t0, 1, 0, y,\n\t\t\t0, 0, 1, z,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationX: function ( theta ) {\n\n\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\n\n\t\tthis.set(\n\n\t\t\t1, 0, 0, 0,\n\t\t\t0, c, - s, 0,\n\t\t\t0, s, c, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationY: function ( theta ) {\n\n\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\n\n\t\tthis.set(\n\n\t\t\t c, 0, s, 0,\n\t\t\t 0, 1, 0, 0,\n\t\t\t- s, 0, c, 0,\n\t\t\t 0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationZ: function ( theta ) {\n\n\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\n\n\t\tthis.set(\n\n\t\t\tc, - s, 0, 0,\n\t\t\ts, c, 0, 0,\n\t\t\t0, 0, 1, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationAxis: function ( axis, angle ) {\n\n\t\t// Based on http://www.gamedev.net/reference/articles/article1199.asp\n\n\t\tvar c = Math.cos( angle );\n\t\tvar s = Math.sin( angle );\n\t\tvar t = 1 - c;\n\t\tvar x = axis.x, y = axis.y, z = axis.z;\n\t\tvar tx = t * x, ty = t * y;\n\n\t\tthis.set(\n\n\t\t\ttx * x + c, tx * y - s * z, tx * z + s * y, 0,\n\t\t\ttx * y + s * z, ty * y + c, ty * z - s * x, 0,\n\t\t\ttx * z - s * y, ty * z + s * x, t * z * z + c, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\t return this;\n\n\t},\n\n\tmakeScale: function ( x, y, z ) {\n\n\t\tthis.set(\n\n\t\t\tx, 0, 0, 0,\n\t\t\t0, y, 0, 0,\n\t\t\t0, 0, z, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmakeShear: function ( x, y, z ) {\n\n\t\tthis.set(\n\n\t\t\t1, y, z, 0,\n\t\t\tx, 1, z, 0,\n\t\t\tx, y, 1, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tcompose: function ( position, quaternion, scale ) {\n\n\t\tvar te = this.elements;\n\n\t\tvar x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;\n\t\tvar x2 = x + x,\ty2 = y + y, z2 = z + z;\n\t\tvar xx = x * x2, xy = x * y2, xz = x * z2;\n\t\tvar yy = y * y2, yz = y * z2, zz = z * z2;\n\t\tvar wx = w * x2, wy = w * y2, wz = w * z2;\n\n\t\tvar sx = scale.x, sy = scale.y, sz = scale.z;\n\n\t\tte[ 0 ] = ( 1 - ( yy + zz ) ) * sx;\n\t\tte[ 1 ] = ( xy + wz ) * sx;\n\t\tte[ 2 ] = ( xz - wy ) * sx;\n\t\tte[ 3 ] = 0;\n\n\t\tte[ 4 ] = ( xy - wz ) * sy;\n\t\tte[ 5 ] = ( 1 - ( xx + zz ) ) * sy;\n\t\tte[ 6 ] = ( yz + wx ) * sy;\n\t\tte[ 7 ] = 0;\n\n\t\tte[ 8 ] = ( xz + wy ) * sz;\n\t\tte[ 9 ] = ( yz - wx ) * sz;\n\t\tte[ 10 ] = ( 1 - ( xx + yy ) ) * sz;\n\t\tte[ 11 ] = 0;\n\n\t\tte[ 12 ] = position.x;\n\t\tte[ 13 ] = position.y;\n\t\tte[ 14 ] = position.z;\n\t\tte[ 15 ] = 1;\n\n\t\treturn this;\n\n\t},\n\n\tdecompose: function ( position, quaternion, scale ) {\n\n\t\tvar te = this.elements;\n\n\t\tvar sx = _v1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();\n\t\tvar sy = _v1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();\n\t\tvar sz = _v1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();\n\n\t\t// if determine is negative, we need to invert one scale\n\t\tvar det = this.determinant();\n\t\tif ( det < 0 ) sx = - sx;\n\n\t\tposition.x = te[ 12 ];\n\t\tposition.y = te[ 13 ];\n\t\tposition.z = te[ 14 ];\n\n\t\t// scale the rotation part\n\t\t_m1.copy( this );\n\n\t\tvar invSX = 1 / sx;\n\t\tvar invSY = 1 / sy;\n\t\tvar invSZ = 1 / sz;\n\n\t\t_m1.elements[ 0 ] *= invSX;\n\t\t_m1.elements[ 1 ] *= invSX;\n\t\t_m1.elements[ 2 ] *= invSX;\n\n\t\t_m1.elements[ 4 ] *= invSY;\n\t\t_m1.elements[ 5 ] *= invSY;\n\t\t_m1.elements[ 6 ] *= invSY;\n\n\t\t_m1.elements[ 8 ] *= invSZ;\n\t\t_m1.elements[ 9 ] *= invSZ;\n\t\t_m1.elements[ 10 ] *= invSZ;\n\n\t\tquaternion.setFromRotationMatrix( _m1 );\n\n\t\tscale.x = sx;\n\t\tscale.y = sy;\n\t\tscale.z = sz;\n\n\t\treturn this;\n\n\t},\n\n\tmakePerspective: function ( left, right, top, bottom, near, far ) {\n\n\t\tif ( far === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );\n\n\t\t}\n\n\t\tvar te = this.elements;\n\t\tvar x = 2 * near / ( right - left );\n\t\tvar y = 2 * near / ( top - bottom );\n\n\t\tvar a = ( right + left ) / ( right - left );\n\t\tvar b = ( top + bottom ) / ( top - bottom );\n\t\tvar c = - ( far + near ) / ( far - near );\n\t\tvar d = - 2 * far * near / ( far - near );\n\n\t\tte[ 0 ] = x;\tte[ 4 ] = 0;\tte[ 8 ] = a;\tte[ 12 ] = 0;\n\t\tte[ 1 ] = 0;\tte[ 5 ] = y;\tte[ 9 ] = b;\tte[ 13 ] = 0;\n\t\tte[ 2 ] = 0;\tte[ 6 ] = 0;\tte[ 10 ] = c;\tte[ 14 ] = d;\n\t\tte[ 3 ] = 0;\tte[ 7 ] = 0;\tte[ 11 ] = - 1;\tte[ 15 ] = 0;\n\n\t\treturn this;\n\n\t},\n\n\tmakeOrthographic: function ( left, right, top, bottom, near, far ) {\n\n\t\tvar te = this.elements;\n\t\tvar w = 1.0 / ( right - left );\n\t\tvar h = 1.0 / ( top - bottom );\n\t\tvar p = 1.0 / ( far - near );\n\n\t\tvar x = ( right + left ) * w;\n\t\tvar y = ( top + bottom ) * h;\n\t\tvar z = ( far + near ) * p;\n\n\t\tte[ 0 ] = 2 * w;\tte[ 4 ] = 0;\tte[ 8 ] = 0;\tte[ 12 ] = - x;\n\t\tte[ 1 ] = 0;\tte[ 5 ] = 2 * h;\tte[ 9 ] = 0;\tte[ 13 ] = - y;\n\t\tte[ 2 ] = 0;\tte[ 6 ] = 0;\tte[ 10 ] = - 2 * p;\tte[ 14 ] = - z;\n\t\tte[ 3 ] = 0;\tte[ 7 ] = 0;\tte[ 11 ] = 0;\tte[ 15 ] = 1;\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( matrix ) {\n\n\t\tvar te = this.elements;\n\t\tvar me = matrix.elements;\n\n\t\tfor ( var i = 0; i < 16; i ++ ) {\n\n\t\t\tif ( te[ i ] !== me[ i ] ) return false;\n\n\t\t}\n\n\t\treturn true;\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tfor ( var i = 0; i < 16; i ++ ) {\n\n\t\t\tthis.elements[ i ] = array[ i + offset ];\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tvar te = this.elements;\n\n\t\tarray[ offset ] = te[ 0 ];\n\t\tarray[ offset + 1 ] = te[ 1 ];\n\t\tarray[ offset + 2 ] = te[ 2 ];\n\t\tarray[ offset + 3 ] = te[ 3 ];\n\n\t\tarray[ offset + 4 ] = te[ 4 ];\n\t\tarray[ offset + 5 ] = te[ 5 ];\n\t\tarray[ offset + 6 ] = te[ 6 ];\n\t\tarray[ offset + 7 ] = te[ 7 ];\n\n\t\tarray[ offset + 8 ] = te[ 8 ];\n\t\tarray[ offset + 9 ] = te[ 9 ];\n\t\tarray[ offset + 10 ] = te[ 10 ];\n\t\tarray[ offset + 11 ] = te[ 11 ];\n\n\t\tarray[ offset + 12 ] = te[ 12 ];\n\t\tarray[ offset + 13 ] = te[ 13 ];\n\t\tarray[ offset + 14 ] = te[ 14 ];\n\t\tarray[ offset + 15 ] = te[ 15 ];\n\n\t\treturn array;\n\n\t}\n\n} );\n\n\nexport { Matrix4 };\n","import { Quaternion } from './Quaternion.js';\nimport { Vector3 } from './Vector3.js';\nimport { Matrix4 } from './Matrix4.js';\nimport { MathUtils } from './MathUtils.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author bhouston / http://clara.io\n */\n\nvar _matrix = new Matrix4();\nvar _quaternion = new Quaternion();\n\nfunction Euler( x, y, z, order ) {\n\n\tthis._x = x || 0;\n\tthis._y = y || 0;\n\tthis._z = z || 0;\n\tthis._order = order || Euler.DefaultOrder;\n\n}\n\nEuler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];\n\nEuler.DefaultOrder = 'XYZ';\n\nObject.defineProperties( Euler.prototype, {\n\n\tx: {\n\n\t\tget: function () {\n\n\t\t\treturn this._x;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._x = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\ty: {\n\n\t\tget: function () {\n\n\t\t\treturn this._y;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._y = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\tz: {\n\n\t\tget: function () {\n\n\t\t\treturn this._z;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._z = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\torder: {\n\n\t\tget: function () {\n\n\t\t\treturn this._order;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._order = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t}\n\n} );\n\nObject.assign( Euler.prototype, {\n\n\tisEuler: true,\n\n\tset: function ( x, y, z, order ) {\n\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._z = z;\n\t\tthis._order = order || this._order;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this._x, this._y, this._z, this._order );\n\n\t},\n\n\tcopy: function ( euler ) {\n\n\t\tthis._x = euler._x;\n\t\tthis._y = euler._y;\n\t\tthis._z = euler._z;\n\t\tthis._order = euler._order;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromRotationMatrix: function ( m, order, update ) {\n\n\t\tvar clamp = MathUtils.clamp;\n\n\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\n\n\t\tvar te = m.elements;\n\t\tvar m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];\n\t\tvar m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];\n\t\tvar m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];\n\n\t\torder = order || this._order;\n\n\t\tswitch ( order ) {\n\n\t\t\tcase 'XYZ':\n\n\t\t\t\tthis._y = Math.asin( clamp( m13, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m13 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._x = Math.atan2( - m23, m33 );\n\t\t\t\t\tthis._z = Math.atan2( - m12, m11 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._x = Math.atan2( m32, m22 );\n\t\t\t\t\tthis._z = 0;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'YXZ':\n\n\t\t\t\tthis._x = Math.asin( - clamp( m23, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m23 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._y = Math.atan2( m13, m33 );\n\t\t\t\t\tthis._z = Math.atan2( m21, m22 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._y = Math.atan2( - m31, m11 );\n\t\t\t\t\tthis._z = 0;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZXY':\n\n\t\t\t\tthis._x = Math.asin( clamp( m32, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m32 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._y = Math.atan2( - m31, m33 );\n\t\t\t\t\tthis._z = Math.atan2( - m12, m22 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._y = 0;\n\t\t\t\t\tthis._z = Math.atan2( m21, m11 );\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZYX':\n\n\t\t\t\tthis._y = Math.asin( - clamp( m31, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m31 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._x = Math.atan2( m32, m33 );\n\t\t\t\t\tthis._z = Math.atan2( m21, m11 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._x = 0;\n\t\t\t\t\tthis._z = Math.atan2( - m12, m22 );\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'YZX':\n\n\t\t\t\tthis._z = Math.asin( clamp( m21, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m21 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._x = Math.atan2( - m23, m22 );\n\t\t\t\t\tthis._y = Math.atan2( - m31, m11 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._x = 0;\n\t\t\t\t\tthis._y = Math.atan2( m13, m33 );\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'XZY':\n\n\t\t\t\tthis._z = Math.asin( - clamp( m12, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m12 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._x = Math.atan2( m32, m22 );\n\t\t\t\t\tthis._y = Math.atan2( m13, m11 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._x = Math.atan2( - m23, m33 );\n\t\t\t\t\tthis._y = 0;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tconsole.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );\n\n\t\t}\n\n\t\tthis._order = order;\n\n\t\tif ( update !== false ) this._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromQuaternion: function ( q, order, update ) {\n\n\t\t_matrix.makeRotationFromQuaternion( q );\n\n\t\treturn this.setFromRotationMatrix( _matrix, order, update );\n\n\t},\n\n\tsetFromVector3: function ( v, order ) {\n\n\t\treturn this.set( v.x, v.y, v.z, order || this._order );\n\n\t},\n\n\treorder: function ( newOrder ) {\n\n\t\t// WARNING: this discards revolution information -bhouston\n\n\t\t_quaternion.setFromEuler( this );\n\n\t\treturn this.setFromQuaternion( _quaternion, newOrder );\n\n\t},\n\n\tequals: function ( euler ) {\n\n\t\treturn ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );\n\n\t},\n\n\tfromArray: function ( array ) {\n\n\t\tthis._x = array[ 0 ];\n\t\tthis._y = array[ 1 ];\n\t\tthis._z = array[ 2 ];\n\t\tif ( array[ 3 ] !== undefined ) this._order = array[ 3 ];\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this._x;\n\t\tarray[ offset + 1 ] = this._y;\n\t\tarray[ offset + 2 ] = this._z;\n\t\tarray[ offset + 3 ] = this._order;\n\n\t\treturn array;\n\n\t},\n\n\ttoVector3: function ( optionalResult ) {\n\n\t\tif ( optionalResult ) {\n\n\t\t\treturn optionalResult.set( this._x, this._y, this._z );\n\n\t\t} else {\n\n\t\t\treturn new Vector3( this._x, this._y, this._z );\n\n\t\t}\n\n\t},\n\n\t_onChange: function ( callback ) {\n\n\t\tthis._onChangeCallback = callback;\n\n\t\treturn this;\n\n\t},\n\n\t_onChangeCallback: function () {}\n\n} );\n\n\nexport { Euler };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction Layers() {\n\n\tthis.mask = 1 | 0;\n\n}\n\nObject.assign( Layers.prototype, {\n\n\tset: function ( channel ) {\n\n\t\tthis.mask = 1 << channel | 0;\n\n\t},\n\n\tenable: function ( channel ) {\n\n\t\tthis.mask |= 1 << channel | 0;\n\n\t},\n\n\tenableAll: function () {\n\n\t\tthis.mask = 0xffffffff | 0;\n\n\t},\n\n\ttoggle: function ( channel ) {\n\n\t\tthis.mask ^= 1 << channel | 0;\n\n\t},\n\n\tdisable: function ( channel ) {\n\n\t\tthis.mask &= ~ ( 1 << channel | 0 );\n\n\t},\n\n\tdisableAll: function () {\n\n\t\tthis.mask = 0;\n\n\t},\n\n\ttest: function ( layers ) {\n\n\t\treturn ( this.mask & layers.mask ) !== 0;\n\n\t}\n\n} );\n\n\nexport { Layers };\n","import { Quaternion } from '../math/Quaternion.js';\nimport { Vector3 } from '../math/Vector3.js';\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { EventDispatcher } from './EventDispatcher.js';\nimport { Euler } from '../math/Euler.js';\nimport { Layers } from './Layers.js';\nimport { Matrix3 } from '../math/Matrix3.js';\nimport { MathUtils } from '../math/MathUtils.js';\n\nlet _object3DId = 0;\n\nconst _v1 = new Vector3();\nconst _q1 = new Quaternion();\nconst _m1 = new Matrix4();\nconst _target = new Vector3();\n\nconst _position = new Vector3();\nconst _scale = new Vector3();\nconst _quaternion = new Quaternion();\n\nconst _xAxis = new Vector3( 1, 0, 0 );\nconst _yAxis = new Vector3( 0, 1, 0 );\nconst _zAxis = new Vector3( 0, 0, 1 );\n\nconst _addedEvent = { type: 'added' };\nconst _removedEvent = { type: 'removed' };\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author mikael emtinger / http://gomo.se/\n * @author alteredq / http://alteredqualia.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author elephantatwork / www.elephantatwork.ch\n */\n\nfunction Object3D() {\n\n\tObject.defineProperty( this, 'id', { value: _object3DId ++ } );\n\n\tthis.uuid = MathUtils.generateUUID();\n\n\tthis.name = '';\n\tthis.type = 'Object3D';\n\n\tthis.parent = null;\n\tthis.children = [];\n\n\tthis.up = Object3D.DefaultUp.clone();\n\n\tvar position = new Vector3();\n\tvar rotation = new Euler();\n\tvar quaternion = new Quaternion();\n\tvar scale = new Vector3( 1, 1, 1 );\n\n\tfunction onRotationChange() {\n\n\t\tquaternion.setFromEuler( rotation, false );\n\n\t}\n\n\tfunction onQuaternionChange() {\n\n\t\trotation.setFromQuaternion( quaternion, undefined, false );\n\n\t}\n\n\trotation._onChange( onRotationChange );\n\tquaternion._onChange( onQuaternionChange );\n\n\tObject.defineProperties( this, {\n\t\tposition: {\n\t\t\tconfigurable: true,\n\t\t\tenumerable: true,\n\t\t\tvalue: position\n\t\t},\n\t\trotation: {\n\t\t\tconfigurable: true,\n\t\t\tenumerable: true,\n\t\t\tvalue: rotation\n\t\t},\n\t\tquaternion: {\n\t\t\tconfigurable: true,\n\t\t\tenumerable: true,\n\t\t\tvalue: quaternion\n\t\t},\n\t\tscale: {\n\t\t\tconfigurable: true,\n\t\t\tenumerable: true,\n\t\t\tvalue: scale\n\t\t},\n\t\tmodelViewMatrix: {\n\t\t\tvalue: new Matrix4()\n\t\t},\n\t\tnormalMatrix: {\n\t\t\tvalue: new Matrix3()\n\t\t}\n\t} );\n\n\tthis.matrix = new Matrix4();\n\tthis.matrixWorld = new Matrix4();\n\n\tthis.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;\n\tthis.matrixWorldNeedsUpdate = false;\n\n\tthis.layers = new Layers();\n\tthis.visible = true;\n\n\tthis.castShadow = false;\n\tthis.receiveShadow = false;\n\n\tthis.frustumCulled = true;\n\tthis.renderOrder = 0;\n\n\tthis.userData = {};\n\n}\n\nObject3D.DefaultUp = new Vector3( 0, 1, 0 );\nObject3D.DefaultMatrixAutoUpdate = true;\n\nObject3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: Object3D,\n\n\tisObject3D: true,\n\n\tonBeforeRender: function () {},\n\tonAfterRender: function () {},\n\n\tapplyMatrix4: function ( matrix ) {\n\n\t\tif ( this.matrixAutoUpdate ) this.updateMatrix();\n\n\t\tthis.matrix.premultiply( matrix );\n\n\t\tthis.matrix.decompose( this.position, this.quaternion, this.scale );\n\n\t},\n\n\tapplyQuaternion: function ( q ) {\n\n\t\tthis.quaternion.premultiply( q );\n\n\t\treturn this;\n\n\t},\n\n\tsetRotationFromAxisAngle: function ( axis, angle ) {\n\n\t\t// assumes axis is normalized\n\n\t\tthis.quaternion.setFromAxisAngle( axis, angle );\n\n\t},\n\n\tsetRotationFromEuler: function ( euler ) {\n\n\t\tthis.quaternion.setFromEuler( euler, true );\n\n\t},\n\n\tsetRotationFromMatrix: function ( m ) {\n\n\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\n\n\t\tthis.quaternion.setFromRotationMatrix( m );\n\n\t},\n\n\tsetRotationFromQuaternion: function ( q ) {\n\n\t\t// assumes q is normalized\n\n\t\tthis.quaternion.copy( q );\n\n\t},\n\n\trotateOnAxis: function ( axis, angle ) {\n\n\t\t// rotate object on axis in object space\n\t\t// axis is assumed to be normalized\n\n\t\t_q1.setFromAxisAngle( axis, angle );\n\n\t\tthis.quaternion.multiply( _q1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateOnWorldAxis: function ( axis, angle ) {\n\n\t\t// rotate object on axis in world space\n\t\t// axis is assumed to be normalized\n\t\t// method assumes no rotated parent\n\n\t\t_q1.setFromAxisAngle( axis, angle );\n\n\t\tthis.quaternion.premultiply( _q1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateX: function ( angle ) {\n\n\t\treturn this.rotateOnAxis( _xAxis, angle );\n\n\t},\n\n\trotateY: function ( angle ) {\n\n\t\treturn this.rotateOnAxis( _yAxis, angle );\n\n\t},\n\n\trotateZ: function ( angle ) {\n\n\t\treturn this.rotateOnAxis( _zAxis, angle );\n\n\t},\n\n\ttranslateOnAxis: function ( axis, distance ) {\n\n\t\t// translate object by distance along axis in object space\n\t\t// axis is assumed to be normalized\n\n\t\t_v1.copy( axis ).applyQuaternion( this.quaternion );\n\n\t\tthis.position.add( _v1.multiplyScalar( distance ) );\n\n\t\treturn this;\n\n\t},\n\n\ttranslateX: function ( distance ) {\n\n\t\treturn this.translateOnAxis( _xAxis, distance );\n\n\t},\n\n\ttranslateY: function ( distance ) {\n\n\t\treturn this.translateOnAxis( _yAxis, distance );\n\n\t},\n\n\ttranslateZ: function ( distance ) {\n\n\t\treturn this.translateOnAxis( _zAxis, distance );\n\n\t},\n\n\tlocalToWorld: function ( vector ) {\n\n\t\treturn vector.applyMatrix4( this.matrixWorld );\n\n\t},\n\n\tworldToLocal: function ( vector ) {\n\n\t\treturn vector.applyMatrix4( _m1.getInverse( this.matrixWorld ) );\n\n\t},\n\n\tlookAt: function ( x, y, z ) {\n\n\t\t// This method does not support objects having non-uniformly-scaled parent(s)\n\n\t\tif ( x.isVector3 ) {\n\n\t\t\t_target.copy( x );\n\n\t\t} else {\n\n\t\t\t_target.set( x, y, z );\n\n\t\t}\n\n\t\tvar parent = this.parent;\n\n\t\tthis.updateWorldMatrix( true, false );\n\n\t\t_position.setFromMatrixPosition( this.matrixWorld );\n\n\t\tif ( this.isCamera || this.isLight ) {\n\n\t\t\t_m1.lookAt( _position, _target, this.up );\n\n\t\t} else {\n\n\t\t\t_m1.lookAt( _target, _position, this.up );\n\n\t\t}\n\n\t\tthis.quaternion.setFromRotationMatrix( _m1 );\n\n\t\tif ( parent ) {\n\n\t\t\t_m1.extractRotation( parent.matrixWorld );\n\t\t\t_q1.setFromRotationMatrix( _m1 );\n\t\t\tthis.quaternion.premultiply( _q1.inverse() );\n\n\t\t}\n\n\t},\n\n\tadd: function ( object ) {\n\n\t\tif ( arguments.length > 1 ) {\n\n\t\t\tfor ( var i = 0; i < arguments.length; i ++ ) {\n\n\t\t\t\tthis.add( arguments[ i ] );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t}\n\n\t\tif ( object === this ) {\n\n\t\t\tconsole.error( \"THREE.Object3D.add: object can't be added as a child of itself.\", object );\n\t\t\treturn this;\n\n\t\t}\n\n\t\tif ( ( object && object.isObject3D ) ) {\n\n\t\t\tif ( object.parent !== null ) {\n\n\t\t\t\tobject.parent.remove( object );\n\n\t\t\t}\n\n\t\t\tobject.parent = this;\n\t\t\tthis.children.push( object );\n\n\t\t\tobject.dispatchEvent( _addedEvent );\n\n\t\t} else {\n\n\t\t\tconsole.error( \"THREE.Object3D.add: object not an instance of THREE.Object3D.\", object );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tremove: function ( object ) {\n\n\t\tif ( arguments.length > 1 ) {\n\n\t\t\tfor ( var i = 0; i < arguments.length; i ++ ) {\n\n\t\t\t\tthis.remove( arguments[ i ] );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t}\n\n\t\tvar index = this.children.indexOf( object );\n\n\t\tif ( index !== - 1 ) {\n\n\t\t\tobject.parent = null;\n\t\t\tthis.children.splice( index, 1 );\n\n\t\t\tobject.dispatchEvent( _removedEvent );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tattach: function ( object ) {\n\n\t\t// adds object as a child of this, while maintaining the object's world transform\n\n\t\tthis.updateWorldMatrix( true, false );\n\n\t\t_m1.getInverse( this.matrixWorld );\n\n\t\tif ( object.parent !== null ) {\n\n\t\t\tobject.parent.updateWorldMatrix( true, false );\n\n\t\t\t_m1.multiply( object.parent.matrixWorld );\n\n\t\t}\n\n\t\tobject.applyMatrix4( _m1 );\n\n\t\tobject.updateWorldMatrix( false, false );\n\n\t\tthis.add( object );\n\n\t\treturn this;\n\n\t},\n\n\tgetObjectById: function ( id ) {\n\n\t\treturn this.getObjectByProperty( 'id', id );\n\n\t},\n\n\tgetObjectByName: function ( name ) {\n\n\t\treturn this.getObjectByProperty( 'name', name );\n\n\t},\n\n\tgetObjectByProperty: function ( name, value ) {\n\n\t\tif ( this[ name ] === value ) return this;\n\n\t\tfor ( var i = 0, l = this.children.length; i < l; i ++ ) {\n\n\t\t\tvar child = this.children[ i ];\n\t\t\tvar object = child.getObjectByProperty( name, value );\n\n\t\t\tif ( object !== undefined ) {\n\n\t\t\t\treturn object;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn undefined;\n\n\t},\n\n\tgetWorldPosition: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tthis.updateMatrixWorld( true );\n\n\t\treturn target.setFromMatrixPosition( this.matrixWorld );\n\n\t},\n\n\tgetWorldQuaternion: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );\n\t\t\ttarget = new Quaternion();\n\n\t\t}\n\n\t\tthis.updateMatrixWorld( true );\n\n\t\tthis.matrixWorld.decompose( _position, target, _scale );\n\n\t\treturn target;\n\n\t},\n\n\tgetWorldScale: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .getWorldScale() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tthis.updateMatrixWorld( true );\n\n\t\tthis.matrixWorld.decompose( _position, _quaternion, target );\n\n\t\treturn target;\n\n\t},\n\n\tgetWorldDirection: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tthis.updateMatrixWorld( true );\n\n\t\tvar e = this.matrixWorld.elements;\n\n\t\treturn target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();\n\n\t},\n\n\traycast: function () {},\n\n\ttraverse: function ( callback ) {\n\n\t\tcallback( this );\n\n\t\tvar children = this.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tchildren[ i ].traverse( callback );\n\n\t\t}\n\n\t},\n\n\ttraverseVisible: function ( callback ) {\n\n\t\tif ( this.visible === false ) return;\n\n\t\tcallback( this );\n\n\t\tvar children = this.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tchildren[ i ].traverseVisible( callback );\n\n\t\t}\n\n\t},\n\n\ttraverseAncestors: function ( callback ) {\n\n\t\tvar parent = this.parent;\n\n\t\tif ( parent !== null ) {\n\n\t\t\tcallback( parent );\n\n\t\t\tparent.traverseAncestors( callback );\n\n\t\t}\n\n\t},\n\n\tupdateMatrix: function () {\n\n\t\tthis.matrix.compose( this.position, this.quaternion, this.scale );\n\n\t\tthis.matrixWorldNeedsUpdate = true;\n\n\t},\n\n\tupdateMatrixWorld: function ( force ) {\n\n\t\tif ( this.matrixAutoUpdate ) this.updateMatrix();\n\n\t\tif ( this.matrixWorldNeedsUpdate || force ) {\n\n\t\t\tif ( this.parent === null ) {\n\n\t\t\t\tthis.matrixWorld.copy( this.matrix );\n\n\t\t\t} else {\n\n\t\t\t\tthis.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );\n\n\t\t\t}\n\n\t\t\tthis.matrixWorldNeedsUpdate = false;\n\n\t\t\tforce = true;\n\n\t\t}\n\n\t\t// update children\n\n\t\tvar children = this.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tchildren[ i ].updateMatrixWorld( force );\n\n\t\t}\n\n\t},\n\n\tupdateWorldMatrix: function ( updateParents, updateChildren ) {\n\n\t\tvar parent = this.parent;\n\n\t\tif ( updateParents === true && parent !== null ) {\n\n\t\t\tparent.updateWorldMatrix( true, false );\n\n\t\t}\n\n\t\tif ( this.matrixAutoUpdate ) this.updateMatrix();\n\n\t\tif ( this.parent === null ) {\n\n\t\t\tthis.matrixWorld.copy( this.matrix );\n\n\t\t} else {\n\n\t\t\tthis.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );\n\n\t\t}\n\n\t\t// update children\n\n\t\tif ( updateChildren === true ) {\n\n\t\t\tvar children = this.children;\n\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\t\tchildren[ i ].updateWorldMatrix( false, true );\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\ttoJSON: function ( meta ) {\n\n\t\t// meta is a string when called from JSON.stringify\n\t\tvar isRootObject = ( meta === undefined || typeof meta === 'string' );\n\n\t\tvar output = {};\n\n\t\t// meta is a hash used to collect geometries, materials.\n\t\t// not providing it implies that this is the root object\n\t\t// being serialized.\n\t\tif ( isRootObject ) {\n\n\t\t\t// initialize meta obj\n\t\t\tmeta = {\n\t\t\t\tgeometries: {},\n\t\t\t\tmaterials: {},\n\t\t\t\ttextures: {},\n\t\t\t\timages: {},\n\t\t\t\tshapes: {}\n\t\t\t};\n\n\t\t\toutput.metadata = {\n\t\t\t\tversion: 4.5,\n\t\t\t\ttype: 'Object',\n\t\t\t\tgenerator: 'Object3D.toJSON'\n\t\t\t};\n\n\t\t}\n\n\t\t// standard Object3D serialization\n\n\t\tvar object = {};\n\n\t\tobject.uuid = this.uuid;\n\t\tobject.type = this.type;\n\n\t\tif ( this.name !== '' ) object.name = this.name;\n\t\tif ( this.castShadow === true ) object.castShadow = true;\n\t\tif ( this.receiveShadow === true ) object.receiveShadow = true;\n\t\tif ( this.visible === false ) object.visible = false;\n\t\tif ( this.frustumCulled === false ) object.frustumCulled = false;\n\t\tif ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;\n\t\tif ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;\n\n\t\tobject.layers = this.layers.mask;\n\t\tobject.matrix = this.matrix.toArray();\n\n\t\tif ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;\n\n\t\t// object specific properties\n\n\t\tif ( this.isInstancedMesh ) {\n\n\t\t\tobject.type = 'InstancedMesh';\n\t\t\tobject.count = this.count;\n\t\t\tobject.instanceMatrix = this.instanceMatrix.toJSON();\n\n\t\t}\n\n\t\t//\n\n\t\tfunction serialize( library, element ) {\n\n\t\t\tif ( library[ element.uuid ] === undefined ) {\n\n\t\t\t\tlibrary[ element.uuid ] = element.toJSON( meta );\n\n\t\t\t}\n\n\t\t\treturn element.uuid;\n\n\t\t}\n\n\t\tif ( this.isMesh || this.isLine || this.isPoints ) {\n\n\t\t\tobject.geometry = serialize( meta.geometries, this.geometry );\n\n\t\t\tvar parameters = this.geometry.parameters;\n\n\t\t\tif ( parameters !== undefined && parameters.shapes !== undefined ) {\n\n\t\t\t\tvar shapes = parameters.shapes;\n\n\t\t\t\tif ( Array.isArray( shapes ) ) {\n\n\t\t\t\t\tfor ( var i = 0, l = shapes.length; i < l; i ++ ) {\n\n\t\t\t\t\t\tvar shape = shapes[ i ];\n\n\t\t\t\t\t\tserialize( meta.shapes, shape );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tserialize( meta.shapes, shapes );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.material !== undefined ) {\n\n\t\t\tif ( Array.isArray( this.material ) ) {\n\n\t\t\t\tvar uuids = [];\n\n\t\t\t\tfor ( var i = 0, l = this.material.length; i < l; i ++ ) {\n\n\t\t\t\t\tuuids.push( serialize( meta.materials, this.material[ i ] ) );\n\n\t\t\t\t}\n\n\t\t\t\tobject.material = uuids;\n\n\t\t\t} else {\n\n\t\t\t\tobject.material = serialize( meta.materials, this.material );\n\n\t\t\t}\n\n\t\t}\n\n\t\t//\n\n\t\tif ( this.children.length > 0 ) {\n\n\t\t\tobject.children = [];\n\n\t\t\tfor ( var i = 0; i < this.children.length; i ++ ) {\n\n\t\t\t\tobject.children.push( this.children[ i ].toJSON( meta ).object );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( isRootObject ) {\n\n\t\t\tvar geometries = extractFromCache( meta.geometries );\n\t\t\tvar materials = extractFromCache( meta.materials );\n\t\t\tvar textures = extractFromCache( meta.textures );\n\t\t\tvar images = extractFromCache( meta.images );\n\t\t\tvar shapes = extractFromCache( meta.shapes );\n\n\t\t\tif ( geometries.length > 0 ) output.geometries = geometries;\n\t\t\tif ( materials.length > 0 ) output.materials = materials;\n\t\t\tif ( textures.length > 0 ) output.textures = textures;\n\t\t\tif ( images.length > 0 ) output.images = images;\n\t\t\tif ( shapes.length > 0 ) output.shapes = shapes;\n\n\t\t}\n\n\t\toutput.object = object;\n\n\t\treturn output;\n\n\t\t// extract data from the cache hash\n\t\t// remove metadata on each item\n\t\t// and return as array\n\t\tfunction extractFromCache( cache ) {\n\n\t\t\tvar values = [];\n\t\t\tfor ( var key in cache ) {\n\n\t\t\t\tvar data = cache[ key ];\n\t\t\t\tdelete data.metadata;\n\t\t\t\tvalues.push( data );\n\n\t\t\t}\n\n\t\t\treturn values;\n\n\t\t}\n\n\t},\n\n\tclone: function ( recursive ) {\n\n\t\treturn new this.constructor().copy( this, recursive );\n\n\t},\n\n\tcopy: function ( source, recursive ) {\n\n\t\tif ( recursive === undefined ) recursive = true;\n\n\t\tthis.name = source.name;\n\n\t\tthis.up.copy( source.up );\n\n\t\tthis.position.copy( source.position );\n\t\tthis.quaternion.copy( source.quaternion );\n\t\tthis.scale.copy( source.scale );\n\n\t\tthis.matrix.copy( source.matrix );\n\t\tthis.matrixWorld.copy( source.matrixWorld );\n\n\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\n\t\tthis.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;\n\n\t\tthis.layers.mask = source.layers.mask;\n\t\tthis.visible = source.visible;\n\n\t\tthis.castShadow = source.castShadow;\n\t\tthis.receiveShadow = source.receiveShadow;\n\n\t\tthis.frustumCulled = source.frustumCulled;\n\t\tthis.renderOrder = source.renderOrder;\n\n\t\tthis.userData = JSON.parse( JSON.stringify( source.userData ) );\n\n\t\tif ( recursive === true ) {\n\n\t\t\tfor ( var i = 0; i < source.children.length; i ++ ) {\n\n\t\t\t\tvar child = source.children[ i ];\n\t\t\t\tthis.add( child.clone() );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Object3D };\n","import { Object3D } from '../core/Object3D.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction Scene() {\n\n\tObject3D.call( this );\n\n\tthis.type = 'Scene';\n\n\tthis.background = null;\n\tthis.environment = null;\n\tthis.fog = null;\n\n\tthis.overrideMaterial = null;\n\n\tthis.autoUpdate = true; // checked by the renderer\n\n\tif ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {\n\n\t\t__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef\n\n\t}\n\n}\n\nScene.prototype = Object.assign( Object.create( Object3D.prototype ), {\n\n\tconstructor: Scene,\n\n\tisScene: true,\n\n\tcopy: function ( source, recursive ) {\n\n\t\tObject3D.prototype.copy.call( this, source, recursive );\n\n\t\tif ( source.background !== null ) this.background = source.background.clone();\n\t\tif ( source.environment !== null ) this.environment = source.environment.clone();\n\t\tif ( source.fog !== null ) this.fog = source.fog.clone();\n\n\t\tif ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();\n\n\t\tthis.autoUpdate = source.autoUpdate;\n\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\n\n\t\treturn this;\n\n\t},\n\n\ttoJSON: function ( meta ) {\n\n\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\n\n\t\tif ( this.background !== null ) data.object.background = this.background.toJSON( meta );\n\t\tif ( this.environment !== null ) data.object.environment = this.environment.toJSON( meta );\n\t\tif ( this.fog !== null ) data.object.fog = this.fog.toJSON();\n\n\t\treturn data;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t}\n\n} );\n\n\n\nexport { Scene };\n","import { Vector3 } from './Vector3.js';\n\nvar _points = [\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3()\n];\n\nvar _vector = new Vector3();\n\nvar _box = new Box3();\n\n// triangle centered vertices\n\nvar _v0 = new Vector3();\nvar _v1 = new Vector3();\nvar _v2 = new Vector3();\n\n// triangle edge vectors\n\nvar _f0 = new Vector3();\nvar _f1 = new Vector3();\nvar _f2 = new Vector3();\n\nvar _center = new Vector3();\nvar _extents = new Vector3();\nvar _triangleNormal = new Vector3();\nvar _testAxis = new Vector3();\n\n/**\n * @author bhouston / http://clara.io\n * @author WestLangley / http://github.com/WestLangley\n */\n\nfunction Box3( min, max ) {\n\n\tthis.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );\n\tthis.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );\n\n}\n\n\nObject.assign( Box3.prototype, {\n\n\tisBox3: true,\n\n\tset: function ( min, max ) {\n\n\t\tthis.min.copy( min );\n\t\tthis.max.copy( max );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromArray: function ( array ) {\n\n\t\tvar minX = + Infinity;\n\t\tvar minY = + Infinity;\n\t\tvar minZ = + Infinity;\n\n\t\tvar maxX = - Infinity;\n\t\tvar maxY = - Infinity;\n\t\tvar maxZ = - Infinity;\n\n\t\tfor ( var i = 0, l = array.length; i < l; i += 3 ) {\n\n\t\t\tvar x = array[ i ];\n\t\t\tvar y = array[ i + 1 ];\n\t\t\tvar z = array[ i + 2 ];\n\n\t\t\tif ( x < minX ) minX = x;\n\t\t\tif ( y < minY ) minY = y;\n\t\t\tif ( z < minZ ) minZ = z;\n\n\t\t\tif ( x > maxX ) maxX = x;\n\t\t\tif ( y > maxY ) maxY = y;\n\t\t\tif ( z > maxZ ) maxZ = z;\n\n\t\t}\n\n\t\tthis.min.set( minX, minY, minZ );\n\t\tthis.max.set( maxX, maxY, maxZ );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromBufferAttribute: function ( attribute ) {\n\n\t\tvar minX = + Infinity;\n\t\tvar minY = + Infinity;\n\t\tvar minZ = + Infinity;\n\n\t\tvar maxX = - Infinity;\n\t\tvar maxY = - Infinity;\n\t\tvar maxZ = - Infinity;\n\n\t\tfor ( var i = 0, l = attribute.count; i < l; i ++ ) {\n\n\t\t\tvar x = attribute.getX( i );\n\t\t\tvar y = attribute.getY( i );\n\t\t\tvar z = attribute.getZ( i );\n\n\t\t\tif ( x < minX ) minX = x;\n\t\t\tif ( y < minY ) minY = y;\n\t\t\tif ( z < minZ ) minZ = z;\n\n\t\t\tif ( x > maxX ) maxX = x;\n\t\t\tif ( y > maxY ) maxY = y;\n\t\t\tif ( z > maxZ ) maxZ = z;\n\n\t\t}\n\n\t\tthis.min.set( minX, minY, minZ );\n\t\tthis.max.set( maxX, maxY, maxZ );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromPoints: function ( points ) {\n\n\t\tthis.makeEmpty();\n\n\t\tfor ( var i = 0, il = points.length; i < il; i ++ ) {\n\n\t\t\tthis.expandByPoint( points[ i ] );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetFromCenterAndSize: function ( center, size ) {\n\n\t\tvar halfSize = _vector.copy( size ).multiplyScalar( 0.5 );\n\n\t\tthis.min.copy( center ).sub( halfSize );\n\t\tthis.max.copy( center ).add( halfSize );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromObject: function ( object ) {\n\n\t\tthis.makeEmpty();\n\n\t\treturn this.expandByObject( object );\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( box ) {\n\n\t\tthis.min.copy( box.min );\n\t\tthis.max.copy( box.max );\n\n\t\treturn this;\n\n\t},\n\n\tmakeEmpty: function () {\n\n\t\tthis.min.x = this.min.y = this.min.z = + Infinity;\n\t\tthis.max.x = this.max.y = this.max.z = - Infinity;\n\n\t\treturn this;\n\n\t},\n\n\tisEmpty: function () {\n\n\t\t// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes\n\n\t\treturn ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );\n\n\t},\n\n\tgetCenter: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .getCenter() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );\n\n\t},\n\n\tgetSize: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .getSize() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );\n\n\t},\n\n\texpandByPoint: function ( point ) {\n\n\t\tthis.min.min( point );\n\t\tthis.max.max( point );\n\n\t\treturn this;\n\n\t},\n\n\texpandByVector: function ( vector ) {\n\n\t\tthis.min.sub( vector );\n\t\tthis.max.add( vector );\n\n\t\treturn this;\n\n\t},\n\n\texpandByScalar: function ( scalar ) {\n\n\t\tthis.min.addScalar( - scalar );\n\t\tthis.max.addScalar( scalar );\n\n\t\treturn this;\n\n\t},\n\n\texpandByObject: function ( object ) {\n\n\t\t// Computes the world-axis-aligned bounding box of an object (including its children),\n\t\t// accounting for both the object's, and children's, world transforms\n\n\t\tobject.updateWorldMatrix( false, false );\n\n\t\tvar geometry = object.geometry;\n\n\t\tif ( geometry !== undefined ) {\n\n\t\t\tif ( geometry.boundingBox === null ) {\n\n\t\t\t\tgeometry.computeBoundingBox();\n\n\t\t\t}\n\n\t\t\t_box.copy( geometry.boundingBox );\n\t\t\t_box.applyMatrix4( object.matrixWorld );\n\n\t\t\tthis.union( _box );\n\n\t\t}\n\n\t\tvar children = object.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tthis.expandByObject( children[ i ] );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcontainsPoint: function ( point ) {\n\n\t\treturn point.x < this.min.x || point.x > this.max.x ||\n\t\t\tpoint.y < this.min.y || point.y > this.max.y ||\n\t\t\tpoint.z < this.min.z || point.z > this.max.z ? false : true;\n\n\t},\n\n\tcontainsBox: function ( box ) {\n\n\t\treturn this.min.x <= box.min.x && box.max.x <= this.max.x &&\n\t\t\tthis.min.y <= box.min.y && box.max.y <= this.max.y &&\n\t\t\tthis.min.z <= box.min.z && box.max.z <= this.max.z;\n\n\t},\n\n\tgetParameter: function ( point, target ) {\n\n\t\t// This can potentially have a divide by zero if the box\n\t\t// has a size dimension of 0.\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .getParameter() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.set(\n\t\t\t( point.x - this.min.x ) / ( this.max.x - this.min.x ),\n\t\t\t( point.y - this.min.y ) / ( this.max.y - this.min.y ),\n\t\t\t( point.z - this.min.z ) / ( this.max.z - this.min.z )\n\t\t);\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\t// using 6 splitting planes to rule out intersections.\n\t\treturn box.max.x < this.min.x || box.min.x > this.max.x ||\n\t\t\tbox.max.y < this.min.y || box.min.y > this.max.y ||\n\t\t\tbox.max.z < this.min.z || box.min.z > this.max.z ? false : true;\n\n\t},\n\n\tintersectsSphere: function ( sphere ) {\n\n\t\t// Find the point on the AABB closest to the sphere center.\n\t\tthis.clampPoint( sphere.center, _vector );\n\n\t\t// If that point is inside the sphere, the AABB and sphere intersect.\n\t\treturn _vector.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );\n\n\t},\n\n\tintersectsPlane: function ( plane ) {\n\n\t\t// We compute the minimum and maximum dot product values. If those values\n\t\t// are on the same side (back or front) of the plane, then there is no intersection.\n\n\t\tvar min, max;\n\n\t\tif ( plane.normal.x > 0 ) {\n\n\t\t\tmin = plane.normal.x * this.min.x;\n\t\t\tmax = plane.normal.x * this.max.x;\n\n\t\t} else {\n\n\t\t\tmin = plane.normal.x * this.max.x;\n\t\t\tmax = plane.normal.x * this.min.x;\n\n\t\t}\n\n\t\tif ( plane.normal.y > 0 ) {\n\n\t\t\tmin += plane.normal.y * this.min.y;\n\t\t\tmax += plane.normal.y * this.max.y;\n\n\t\t} else {\n\n\t\t\tmin += plane.normal.y * this.max.y;\n\t\t\tmax += plane.normal.y * this.min.y;\n\n\t\t}\n\n\t\tif ( plane.normal.z > 0 ) {\n\n\t\t\tmin += plane.normal.z * this.min.z;\n\t\t\tmax += plane.normal.z * this.max.z;\n\n\t\t} else {\n\n\t\t\tmin += plane.normal.z * this.max.z;\n\t\t\tmax += plane.normal.z * this.min.z;\n\n\t\t}\n\n\t\treturn ( min <= - plane.constant && max >= - plane.constant );\n\n\t},\n\n\tintersectsTriangle: function ( triangle ) {\n\n\t\tif ( this.isEmpty() ) {\n\n\t\t\treturn false;\n\n\t\t}\n\n\t\t// compute box center and extents\n\t\tthis.getCenter( _center );\n\t\t_extents.subVectors( this.max, _center );\n\n\t\t// translate triangle to aabb origin\n\t\t_v0.subVectors( triangle.a, _center );\n\t\t_v1.subVectors( triangle.b, _center );\n\t\t_v2.subVectors( triangle.c, _center );\n\n\t\t// compute edge vectors for triangle\n\t\t_f0.subVectors( _v1, _v0 );\n\t\t_f1.subVectors( _v2, _v1 );\n\t\t_f2.subVectors( _v0, _v2 );\n\n\t\t// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb\n\t\t// make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation\n\t\t// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)\n\t\tvar axes = [\n\t\t\t0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,\n\t\t\t_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,\n\t\t\t- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0\n\t\t];\n\t\tif ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {\n\n\t\t\treturn false;\n\n\t\t}\n\n\t\t// test 3 face normals from the aabb\n\t\taxes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];\n\t\tif ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {\n\n\t\t\treturn false;\n\n\t\t}\n\n\t\t// finally testing the face normal of the triangle\n\t\t// use already existing triangle edge vectors here\n\t\t_triangleNormal.crossVectors( _f0, _f1 );\n\t\taxes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];\n\n\t\treturn satForAxes( axes, _v0, _v1, _v2, _extents );\n\n\t},\n\n\tclampPoint: function ( point, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .clampPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.copy( point ).clamp( this.min, this.max );\n\n\t},\n\n\tdistanceToPoint: function ( point ) {\n\n\t\tvar clampedPoint = _vector.copy( point ).clamp( this.min, this.max );\n\n\t\treturn clampedPoint.sub( point ).length();\n\n\t},\n\n\tgetBoundingSphere: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.error( 'THREE.Box3: .getBoundingSphere() target is now required' );\n\t\t\t//target = new Sphere(); // removed to avoid cyclic dependency\n\n\t\t}\n\n\t\tthis.getCenter( target.center );\n\n\t\ttarget.radius = this.getSize( _vector ).length() * 0.5;\n\n\t\treturn target;\n\n\t},\n\n\tintersect: function ( box ) {\n\n\t\tthis.min.max( box.min );\n\t\tthis.max.min( box.max );\n\n\t\t// ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values.\n\t\tif ( this.isEmpty() ) this.makeEmpty();\n\n\t\treturn this;\n\n\t},\n\n\tunion: function ( box ) {\n\n\t\tthis.min.min( box.min );\n\t\tthis.max.max( box.max );\n\n\t\treturn this;\n\n\t},\n\n\tapplyMatrix4: function ( matrix ) {\n\n\t\t// transform of empty box is an empty box.\n\t\tif ( this.isEmpty() ) return this;\n\n\t\t// NOTE: I am using a binary pattern to specify all 2^3 combinations below\n\t\t_points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000\n\t\t_points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001\n\t\t_points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010\n\t\t_points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011\n\t\t_points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100\n\t\t_points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101\n\t\t_points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110\n\t\t_points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111\n\n\t\tthis.setFromPoints( _points );\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( offset ) {\n\n\t\tthis.min.add( offset );\n\t\tthis.max.add( offset );\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( box ) {\n\n\t\treturn box.min.equals( this.min ) && box.max.equals( this.max );\n\n\t}\n\n} );\n\nfunction satForAxes( axes, v0, v1, v2, extents ) {\n\n\tvar i, j;\n\n\tfor ( i = 0, j = axes.length - 3; i <= j; i += 3 ) {\n\n\t\t_testAxis.fromArray( axes, i );\n\t\t// project the aabb onto the seperating axis\n\t\tvar r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );\n\t\t// project all 3 vertices of the triangle onto the seperating axis\n\t\tvar p0 = v0.dot( _testAxis );\n\t\tvar p1 = v1.dot( _testAxis );\n\t\tvar p2 = v2.dot( _testAxis );\n\t\t// actual test, basically see if either of the most extreme of the triangle points intersects r\n\t\tif ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {\n\n\t\t\t// points of the projected triangle are outside the projected half-length of the aabb\n\t\t\t// the axis is seperating and we can exit\n\t\t\treturn false;\n\n\t\t}\n\n\t}\n\n\treturn true;\n\n}\n\nexport { Box3 };\n","import { Box3 } from './Box3.js';\nimport { Vector3 } from './Vector3.js';\n\nvar _box = new Box3();\n\n/**\n * @author bhouston / http://clara.io\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction Sphere( center, radius ) {\n\n\tthis.center = ( center !== undefined ) ? center : new Vector3();\n\tthis.radius = ( radius !== undefined ) ? radius : - 1;\n\n}\n\nObject.assign( Sphere.prototype, {\n\n\tset: function ( center, radius ) {\n\n\t\tthis.center.copy( center );\n\t\tthis.radius = radius;\n\n\t\treturn this;\n\n\t},\n\n\tsetFromPoints: function ( points, optionalCenter ) {\n\n\t\tvar center = this.center;\n\n\t\tif ( optionalCenter !== undefined ) {\n\n\t\t\tcenter.copy( optionalCenter );\n\n\t\t} else {\n\n\t\t\t_box.setFromPoints( points ).getCenter( center );\n\n\t\t}\n\n\t\tvar maxRadiusSq = 0;\n\n\t\tfor ( var i = 0, il = points.length; i < il; i ++ ) {\n\n\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );\n\n\t\t}\n\n\t\tthis.radius = Math.sqrt( maxRadiusSq );\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( sphere ) {\n\n\t\tthis.center.copy( sphere.center );\n\t\tthis.radius = sphere.radius;\n\n\t\treturn this;\n\n\t},\n\n\tisEmpty: function () {\n\n\t\treturn ( this.radius < 0 );\n\n\t},\n\n\tmakeEmpty: function () {\n\n\t\tthis.center.set( 0, 0, 0 );\n\t\tthis.radius = - 1;\n\n\t\treturn this;\n\n\t},\n\n\tcontainsPoint: function ( point ) {\n\n\t\treturn ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );\n\n\t},\n\n\tdistanceToPoint: function ( point ) {\n\n\t\treturn ( point.distanceTo( this.center ) - this.radius );\n\n\t},\n\n\tintersectsSphere: function ( sphere ) {\n\n\t\tvar radiusSum = this.radius + sphere.radius;\n\n\t\treturn sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\treturn box.intersectsSphere( this );\n\n\t},\n\n\tintersectsPlane: function ( plane ) {\n\n\t\treturn Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;\n\n\t},\n\n\tclampPoint: function ( point, target ) {\n\n\t\tvar deltaLengthSq = this.center.distanceToSquared( point );\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Sphere: .clampPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\ttarget.copy( point );\n\n\t\tif ( deltaLengthSq > ( this.radius * this.radius ) ) {\n\n\t\t\ttarget.sub( this.center ).normalize();\n\t\t\ttarget.multiplyScalar( this.radius ).add( this.center );\n\n\t\t}\n\n\t\treturn target;\n\n\t},\n\n\tgetBoundingBox: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );\n\t\t\ttarget = new Box3();\n\n\t\t}\n\n\t\tif ( this.isEmpty() ) {\n\n\t\t\t// Empty sphere produces empty bounding box\n\t\t\ttarget.makeEmpty();\n\t\t\treturn target;\n\n\t\t}\n\n\t\ttarget.set( this.center, this.center );\n\t\ttarget.expandByScalar( this.radius );\n\n\t\treturn target;\n\n\t},\n\n\tapplyMatrix4: function ( matrix ) {\n\n\t\tthis.center.applyMatrix4( matrix );\n\t\tthis.radius = this.radius * matrix.getMaxScaleOnAxis();\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( offset ) {\n\n\t\tthis.center.add( offset );\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( sphere ) {\n\n\t\treturn sphere.center.equals( this.center ) && ( sphere.radius === this.radius );\n\n\t}\n\n} );\n\n\nexport { Sphere };\n","import { Vector3 } from './Vector3.js';\n\nvar _vector = new Vector3();\nvar _segCenter = new Vector3();\nvar _segDir = new Vector3();\nvar _diff = new Vector3();\n\nvar _edge1 = new Vector3();\nvar _edge2 = new Vector3();\nvar _normal = new Vector3();\n\n/**\n * @author bhouston / http://clara.io\n */\n\nfunction Ray( origin, direction ) {\n\n\tthis.origin = ( origin !== undefined ) ? origin : new Vector3();\n\tthis.direction = ( direction !== undefined ) ? direction : new Vector3( 0, 0, - 1 );\n\n}\n\nObject.assign( Ray.prototype, {\n\n\tset: function ( origin, direction ) {\n\n\t\tthis.origin.copy( origin );\n\t\tthis.direction.copy( direction );\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( ray ) {\n\n\t\tthis.origin.copy( ray.origin );\n\t\tthis.direction.copy( ray.direction );\n\n\t\treturn this;\n\n\t},\n\n\tat: function ( t, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Ray: .at() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.copy( this.direction ).multiplyScalar( t ).add( this.origin );\n\n\t},\n\n\tlookAt: function ( v ) {\n\n\t\tthis.direction.copy( v ).sub( this.origin ).normalize();\n\n\t\treturn this;\n\n\t},\n\n\trecast: function ( t ) {\n\n\t\tthis.origin.copy( this.at( t, _vector ) );\n\n\t\treturn this;\n\n\t},\n\n\tclosestPointToPoint: function ( point, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\ttarget.subVectors( point, this.origin );\n\n\t\tvar directionDistance = target.dot( this.direction );\n\n\t\tif ( directionDistance < 0 ) {\n\n\t\t\treturn target.copy( this.origin );\n\n\t\t}\n\n\t\treturn target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );\n\n\t},\n\n\tdistanceToPoint: function ( point ) {\n\n\t\treturn Math.sqrt( this.distanceSqToPoint( point ) );\n\n\t},\n\n\tdistanceSqToPoint: function ( point ) {\n\n\t\tvar directionDistance = _vector.subVectors( point, this.origin ).dot( this.direction );\n\n\t\t// point behind the ray\n\n\t\tif ( directionDistance < 0 ) {\n\n\t\t\treturn this.origin.distanceToSquared( point );\n\n\t\t}\n\n\t\t_vector.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );\n\n\t\treturn _vector.distanceToSquared( point );\n\n\t},\n\n\tdistanceSqToSegment: function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {\n\n\t\t// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h\n\t\t// It returns the min distance between the ray and the segment\n\t\t// defined by v0 and v1\n\t\t// It can also set two optional targets :\n\t\t// - The closest point on the ray\n\t\t// - The closest point on the segment\n\n\t\t_segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );\n\t\t_segDir.copy( v1 ).sub( v0 ).normalize();\n\t\t_diff.copy( this.origin ).sub( _segCenter );\n\n\t\tvar segExtent = v0.distanceTo( v1 ) * 0.5;\n\t\tvar a01 = - this.direction.dot( _segDir );\n\t\tvar b0 = _diff.dot( this.direction );\n\t\tvar b1 = - _diff.dot( _segDir );\n\t\tvar c = _diff.lengthSq();\n\t\tvar det = Math.abs( 1 - a01 * a01 );\n\t\tvar s0, s1, sqrDist, extDet;\n\n\t\tif ( det > 0 ) {\n\n\t\t\t// The ray and segment are not parallel.\n\n\t\t\ts0 = a01 * b1 - b0;\n\t\t\ts1 = a01 * b0 - b1;\n\t\t\textDet = segExtent * det;\n\n\t\t\tif ( s0 >= 0 ) {\n\n\t\t\t\tif ( s1 >= - extDet ) {\n\n\t\t\t\t\tif ( s1 <= extDet ) {\n\n\t\t\t\t\t\t// region 0\n\t\t\t\t\t\t// Minimum at interior points of ray and segment.\n\n\t\t\t\t\t\tvar invDet = 1 / det;\n\t\t\t\t\t\ts0 *= invDet;\n\t\t\t\t\t\ts1 *= invDet;\n\t\t\t\t\t\tsqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// region 1\n\n\t\t\t\t\t\ts1 = segExtent;\n\t\t\t\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\n\t\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// region 5\n\n\t\t\t\t\ts1 = - segExtent;\n\t\t\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\n\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif ( s1 <= - extDet ) {\n\n\t\t\t\t\t// region 4\n\n\t\t\t\t\ts0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );\n\t\t\t\t\ts1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );\n\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t\t\t} else if ( s1 <= extDet ) {\n\n\t\t\t\t\t// region 3\n\n\t\t\t\t\ts0 = 0;\n\t\t\t\t\ts1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );\n\t\t\t\t\tsqrDist = s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// region 2\n\n\t\t\t\t\ts0 = Math.max( 0, - ( a01 * segExtent + b0 ) );\n\t\t\t\t\ts1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );\n\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// Ray and segment are parallel.\n\n\t\t\ts1 = ( a01 > 0 ) ? - segExtent : segExtent;\n\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\n\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t}\n\n\t\tif ( optionalPointOnRay ) {\n\n\t\t\toptionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );\n\n\t\t}\n\n\t\tif ( optionalPointOnSegment ) {\n\n\t\t\toptionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );\n\n\t\t}\n\n\t\treturn sqrDist;\n\n\t},\n\n\tintersectSphere: function ( sphere, target ) {\n\n\t\t_vector.subVectors( sphere.center, this.origin );\n\t\tvar tca = _vector.dot( this.direction );\n\t\tvar d2 = _vector.dot( _vector ) - tca * tca;\n\t\tvar radius2 = sphere.radius * sphere.radius;\n\n\t\tif ( d2 > radius2 ) return null;\n\n\t\tvar thc = Math.sqrt( radius2 - d2 );\n\n\t\t// t0 = first intersect point - entrance on front of sphere\n\t\tvar t0 = tca - thc;\n\n\t\t// t1 = second intersect point - exit point on back of sphere\n\t\tvar t1 = tca + thc;\n\n\t\t// test to see if both t0 and t1 are behind the ray - if so, return null\n\t\tif ( t0 < 0 && t1 < 0 ) return null;\n\n\t\t// test to see if t0 is behind the ray:\n\t\t// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,\n\t\t// in order to always return an intersect point that is in front of the ray.\n\t\tif ( t0 < 0 ) return this.at( t1, target );\n\n\t\t// else t0 is in front of the ray, so return the first collision point scaled by t0\n\t\treturn this.at( t0, target );\n\n\t},\n\n\tintersectsSphere: function ( sphere ) {\n\n\t\treturn this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );\n\n\t},\n\n\tdistanceToPlane: function ( plane ) {\n\n\t\tvar denominator = plane.normal.dot( this.direction );\n\n\t\tif ( denominator === 0 ) {\n\n\t\t\t// line is coplanar, return origin\n\t\t\tif ( plane.distanceToPoint( this.origin ) === 0 ) {\n\n\t\t\t\treturn 0;\n\n\t\t\t}\n\n\t\t\t// Null is preferable to undefined since undefined means.... it is undefined\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tvar t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;\n\n\t\t// Return if the ray never intersects the plane\n\n\t\treturn t >= 0 ? t : null;\n\n\t},\n\n\tintersectPlane: function ( plane, target ) {\n\n\t\tvar t = this.distanceToPlane( plane );\n\n\t\tif ( t === null ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\treturn this.at( t, target );\n\n\t},\n\n\tintersectsPlane: function ( plane ) {\n\n\t\t// check if the ray lies on the plane first\n\n\t\tvar distToPoint = plane.distanceToPoint( this.origin );\n\n\t\tif ( distToPoint === 0 ) {\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\tvar denominator = plane.normal.dot( this.direction );\n\n\t\tif ( denominator * distToPoint < 0 ) {\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\t// ray origin is behind the plane (and is pointing behind it)\n\n\t\treturn false;\n\n\t},\n\n\tintersectBox: function ( box, target ) {\n\n\t\tvar tmin, tmax, tymin, tymax, tzmin, tzmax;\n\n\t\tvar invdirx = 1 / this.direction.x,\n\t\t\tinvdiry = 1 / this.direction.y,\n\t\t\tinvdirz = 1 / this.direction.z;\n\n\t\tvar origin = this.origin;\n\n\t\tif ( invdirx >= 0 ) {\n\n\t\t\ttmin = ( box.min.x - origin.x ) * invdirx;\n\t\t\ttmax = ( box.max.x - origin.x ) * invdirx;\n\n\t\t} else {\n\n\t\t\ttmin = ( box.max.x - origin.x ) * invdirx;\n\t\t\ttmax = ( box.min.x - origin.x ) * invdirx;\n\n\t\t}\n\n\t\tif ( invdiry >= 0 ) {\n\n\t\t\ttymin = ( box.min.y - origin.y ) * invdiry;\n\t\t\ttymax = ( box.max.y - origin.y ) * invdiry;\n\n\t\t} else {\n\n\t\t\ttymin = ( box.max.y - origin.y ) * invdiry;\n\t\t\ttymax = ( box.min.y - origin.y ) * invdiry;\n\n\t\t}\n\n\t\tif ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;\n\n\t\t// These lines also handle the case where tmin or tmax is NaN\n\t\t// (result of 0 * Infinity). x !== x returns true if x is NaN\n\n\t\tif ( tymin > tmin || tmin !== tmin ) tmin = tymin;\n\n\t\tif ( tymax < tmax || tmax !== tmax ) tmax = tymax;\n\n\t\tif ( invdirz >= 0 ) {\n\n\t\t\ttzmin = ( box.min.z - origin.z ) * invdirz;\n\t\t\ttzmax = ( box.max.z - origin.z ) * invdirz;\n\n\t\t} else {\n\n\t\t\ttzmin = ( box.max.z - origin.z ) * invdirz;\n\t\t\ttzmax = ( box.min.z - origin.z ) * invdirz;\n\n\t\t}\n\n\t\tif ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;\n\n\t\tif ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;\n\n\t\tif ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;\n\n\t\t//return point closest to the ray (positive side)\n\n\t\tif ( tmax < 0 ) return null;\n\n\t\treturn this.at( tmin >= 0 ? tmin : tmax, target );\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\treturn this.intersectBox( box, _vector ) !== null;\n\n\t},\n\n\tintersectTriangle: function ( a, b, c, backfaceCulling, target ) {\n\n\t\t// Compute the offset origin, edges, and normal.\n\n\t\t// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h\n\n\t\t_edge1.subVectors( b, a );\n\t\t_edge2.subVectors( c, a );\n\t\t_normal.crossVectors( _edge1, _edge2 );\n\n\t\t// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,\n\t\t// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by\n\t\t// |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))\n\t\t// |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))\n\t\t// |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)\n\t\tvar DdN = this.direction.dot( _normal );\n\t\tvar sign;\n\n\t\tif ( DdN > 0 ) {\n\n\t\t\tif ( backfaceCulling ) return null;\n\t\t\tsign = 1;\n\n\t\t} else if ( DdN < 0 ) {\n\n\t\t\tsign = - 1;\n\t\t\tDdN = - DdN;\n\n\t\t} else {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t_diff.subVectors( this.origin, a );\n\t\tvar DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );\n\n\t\t// b1 < 0, no intersection\n\t\tif ( DdQxE2 < 0 ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tvar DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );\n\n\t\t// b2 < 0, no intersection\n\t\tif ( DdE1xQ < 0 ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// b1+b2 > 1, no intersection\n\t\tif ( DdQxE2 + DdE1xQ > DdN ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// Line intersects triangle, check if ray does.\n\t\tvar QdN = - sign * _diff.dot( _normal );\n\n\t\t// t < 0, no intersection\n\t\tif ( QdN < 0 ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// Ray intersects triangle.\n\t\treturn this.at( QdN / DdN, target );\n\n\t},\n\n\tapplyMatrix4: function ( matrix4 ) {\n\n\t\tthis.origin.applyMatrix4( matrix4 );\n\t\tthis.direction.transformDirection( matrix4 );\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( ray ) {\n\n\t\treturn ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );\n\n\t}\n\n} );\n\n\nexport { Ray };\n","import { Matrix3 } from './Matrix3.js';\nimport { Vector3 } from './Vector3.js';\n\n/**\n * @author bhouston / http://clara.io\n */\n\nvar _vector1 = new Vector3();\nvar _vector2 = new Vector3();\nvar _normalMatrix = new Matrix3();\n\nfunction Plane( normal, constant ) {\n\n\t// normal is assumed to be normalized\n\n\tthis.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );\n\tthis.constant = ( constant !== undefined ) ? constant : 0;\n\n}\n\nObject.assign( Plane.prototype, {\n\n\tisPlane: true,\n\n\tset: function ( normal, constant ) {\n\n\t\tthis.normal.copy( normal );\n\t\tthis.constant = constant;\n\n\t\treturn this;\n\n\t},\n\n\tsetComponents: function ( x, y, z, w ) {\n\n\t\tthis.normal.set( x, y, z );\n\t\tthis.constant = w;\n\n\t\treturn this;\n\n\t},\n\n\tsetFromNormalAndCoplanarPoint: function ( normal, point ) {\n\n\t\tthis.normal.copy( normal );\n\t\tthis.constant = - point.dot( this.normal );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromCoplanarPoints: function ( a, b, c ) {\n\n\t\tvar normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();\n\n\t\t// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?\n\n\t\tthis.setFromNormalAndCoplanarPoint( normal, a );\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( plane ) {\n\n\t\tthis.normal.copy( plane.normal );\n\t\tthis.constant = plane.constant;\n\n\t\treturn this;\n\n\t},\n\n\tnormalize: function () {\n\n\t\t// Note: will lead to a divide by zero if the plane is invalid.\n\n\t\tvar inverseNormalLength = 1.0 / this.normal.length();\n\t\tthis.normal.multiplyScalar( inverseNormalLength );\n\t\tthis.constant *= inverseNormalLength;\n\n\t\treturn this;\n\n\t},\n\n\tnegate: function () {\n\n\t\tthis.constant *= - 1;\n\t\tthis.normal.negate();\n\n\t\treturn this;\n\n\t},\n\n\tdistanceToPoint: function ( point ) {\n\n\t\treturn this.normal.dot( point ) + this.constant;\n\n\t},\n\n\tdistanceToSphere: function ( sphere ) {\n\n\t\treturn this.distanceToPoint( sphere.center ) - sphere.radius;\n\n\t},\n\n\tprojectPoint: function ( point, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Plane: .projectPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );\n\n\t},\n\n\tintersectLine: function ( line, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Plane: .intersectLine() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tvar direction = line.delta( _vector1 );\n\n\t\tvar denominator = this.normal.dot( direction );\n\n\t\tif ( denominator === 0 ) {\n\n\t\t\t// line is coplanar, return origin\n\t\t\tif ( this.distanceToPoint( line.start ) === 0 ) {\n\n\t\t\t\treturn target.copy( line.start );\n\n\t\t\t}\n\n\t\t\t// Unsure if this is the correct method to handle this case.\n\t\t\treturn undefined;\n\n\t\t}\n\n\t\tvar t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;\n\n\t\tif ( t < 0 || t > 1 ) {\n\n\t\t\treturn undefined;\n\n\t\t}\n\n\t\treturn target.copy( direction ).multiplyScalar( t ).add( line.start );\n\n\t},\n\n\tintersectsLine: function ( line ) {\n\n\t\t// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.\n\n\t\tvar startSign = this.distanceToPoint( line.start );\n\t\tvar endSign = this.distanceToPoint( line.end );\n\n\t\treturn ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\treturn box.intersectsPlane( this );\n\n\t},\n\n\tintersectsSphere: function ( sphere ) {\n\n\t\treturn sphere.intersectsPlane( this );\n\n\t},\n\n\tcoplanarPoint: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Plane: .coplanarPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.copy( this.normal ).multiplyScalar( - this.constant );\n\n\t},\n\n\tapplyMatrix4: function ( matrix, optionalNormalMatrix ) {\n\n\t\tvar normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );\n\n\t\tvar referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );\n\n\t\tvar normal = this.normal.applyMatrix3( normalMatrix ).normalize();\n\n\t\tthis.constant = - referencePoint.dot( normal );\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( offset ) {\n\n\t\tthis.constant -= offset.dot( this.normal );\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( plane ) {\n\n\t\treturn plane.normal.equals( this.normal ) && ( plane.constant === this.constant );\n\n\t}\n\n} );\n\n\nexport { Plane };\n","import { Vector3 } from './Vector3.js';\nimport { Plane } from './Plane.js';\n\n/**\n * @author bhouston / http://clara.io\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar _v0 = new Vector3();\nvar _v1 = new Vector3();\nvar _v2 = new Vector3();\nvar _v3 = new Vector3();\n\nvar _vab = new Vector3();\nvar _vac = new Vector3();\nvar _vbc = new Vector3();\nvar _vap = new Vector3();\nvar _vbp = new Vector3();\nvar _vcp = new Vector3();\n\nfunction Triangle( a, b, c ) {\n\n\tthis.a = ( a !== undefined ) ? a : new Vector3();\n\tthis.b = ( b !== undefined ) ? b : new Vector3();\n\tthis.c = ( c !== undefined ) ? c : new Vector3();\n\n}\n\nObject.assign( Triangle, {\n\n\tgetNormal: function ( a, b, c, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .getNormal() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\ttarget.subVectors( c, b );\n\t\t_v0.subVectors( a, b );\n\t\ttarget.cross( _v0 );\n\n\t\tvar targetLengthSq = target.lengthSq();\n\t\tif ( targetLengthSq > 0 ) {\n\n\t\t\treturn target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );\n\n\t\t}\n\n\t\treturn target.set( 0, 0, 0 );\n\n\t},\n\n\t// static/instance method to calculate barycentric coordinates\n\t// based on: http://www.blackpawn.com/texts/pointinpoly/default.html\n\tgetBarycoord: function ( point, a, b, c, target ) {\n\n\t\t_v0.subVectors( c, a );\n\t\t_v1.subVectors( b, a );\n\t\t_v2.subVectors( point, a );\n\n\t\tvar dot00 = _v0.dot( _v0 );\n\t\tvar dot01 = _v0.dot( _v1 );\n\t\tvar dot02 = _v0.dot( _v2 );\n\t\tvar dot11 = _v1.dot( _v1 );\n\t\tvar dot12 = _v1.dot( _v2 );\n\n\t\tvar denom = ( dot00 * dot11 - dot01 * dot01 );\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .getBarycoord() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\t// collinear or singular triangle\n\t\tif ( denom === 0 ) {\n\n\t\t\t// arbitrary location outside of triangle?\n\t\t\t// not sure if this is the best idea, maybe should be returning undefined\n\t\t\treturn target.set( - 2, - 1, - 1 );\n\n\t\t}\n\n\t\tvar invDenom = 1 / denom;\n\t\tvar u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;\n\t\tvar v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;\n\n\t\t// barycentric coordinates must always sum to 1\n\t\treturn target.set( 1 - u - v, v, u );\n\n\t},\n\n\tcontainsPoint: function ( point, a, b, c ) {\n\n\t\tTriangle.getBarycoord( point, a, b, c, _v3 );\n\n\t\treturn ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );\n\n\t},\n\n\tgetUV: function ( point, p1, p2, p3, uv1, uv2, uv3, target ) {\n\n\t\tthis.getBarycoord( point, p1, p2, p3, _v3 );\n\n\t\ttarget.set( 0, 0 );\n\t\ttarget.addScaledVector( uv1, _v3.x );\n\t\ttarget.addScaledVector( uv2, _v3.y );\n\t\ttarget.addScaledVector( uv3, _v3.z );\n\n\t\treturn target;\n\n\t},\n\n\tisFrontFacing: function ( a, b, c, direction ) {\n\n\t\t_v0.subVectors( c, b );\n\t\t_v1.subVectors( a, b );\n\n\t\t// strictly front facing\n\t\treturn ( _v0.cross( _v1 ).dot( direction ) < 0 ) ? true : false;\n\n\t}\n\n} );\n\nObject.assign( Triangle.prototype, {\n\n\tset: function ( a, b, c ) {\n\n\t\tthis.a.copy( a );\n\t\tthis.b.copy( b );\n\t\tthis.c.copy( c );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromPointsAndIndices: function ( points, i0, i1, i2 ) {\n\n\t\tthis.a.copy( points[ i0 ] );\n\t\tthis.b.copy( points[ i1 ] );\n\t\tthis.c.copy( points[ i2 ] );\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( triangle ) {\n\n\t\tthis.a.copy( triangle.a );\n\t\tthis.b.copy( triangle.b );\n\t\tthis.c.copy( triangle.c );\n\n\t\treturn this;\n\n\t},\n\n\tgetArea: function () {\n\n\t\t_v0.subVectors( this.c, this.b );\n\t\t_v1.subVectors( this.a, this.b );\n\n\t\treturn _v0.cross( _v1 ).length() * 0.5;\n\n\t},\n\n\tgetMidpoint: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .getMidpoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );\n\n\t},\n\n\tgetNormal: function ( target ) {\n\n\t\treturn Triangle.getNormal( this.a, this.b, this.c, target );\n\n\t},\n\n\tgetPlane: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .getPlane() target is now required' );\n\t\t\ttarget = new Plane();\n\n\t\t}\n\n\t\treturn target.setFromCoplanarPoints( this.a, this.b, this.c );\n\n\t},\n\n\tgetBarycoord: function ( point, target ) {\n\n\t\treturn Triangle.getBarycoord( point, this.a, this.b, this.c, target );\n\n\t},\n\n\tgetUV: function ( point, uv1, uv2, uv3, target ) {\n\n\t\treturn Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );\n\n\t},\n\n\tcontainsPoint: function ( point ) {\n\n\t\treturn Triangle.containsPoint( point, this.a, this.b, this.c );\n\n\t},\n\n\tisFrontFacing: function ( direction ) {\n\n\t\treturn Triangle.isFrontFacing( this.a, this.b, this.c, direction );\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\treturn box.intersectsTriangle( this );\n\n\t},\n\n\tclosestPointToPoint: function ( p, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tvar a = this.a, b = this.b, c = this.c;\n\t\tvar v, w;\n\n\t\t// algorithm thanks to Real-Time Collision Detection by Christer Ericson,\n\t\t// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,\n\t\t// under the accompanying license; see chapter 5.1.5 for detailed explanation.\n\t\t// basically, we're distinguishing which of the voronoi regions of the triangle\n\t\t// the point lies in with the minimum amount of redundant computation.\n\n\t\t_vab.subVectors( b, a );\n\t\t_vac.subVectors( c, a );\n\t\t_vap.subVectors( p, a );\n\t\tvar d1 = _vab.dot( _vap );\n\t\tvar d2 = _vac.dot( _vap );\n\t\tif ( d1 <= 0 && d2 <= 0 ) {\n\n\t\t\t// vertex region of A; barycentric coords (1, 0, 0)\n\t\t\treturn target.copy( a );\n\n\t\t}\n\n\t\t_vbp.subVectors( p, b );\n\t\tvar d3 = _vab.dot( _vbp );\n\t\tvar d4 = _vac.dot( _vbp );\n\t\tif ( d3 >= 0 && d4 <= d3 ) {\n\n\t\t\t// vertex region of B; barycentric coords (0, 1, 0)\n\t\t\treturn target.copy( b );\n\n\t\t}\n\n\t\tvar vc = d1 * d4 - d3 * d2;\n\t\tif ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {\n\n\t\t\tv = d1 / ( d1 - d3 );\n\t\t\t// edge region of AB; barycentric coords (1-v, v, 0)\n\t\t\treturn target.copy( a ).addScaledVector( _vab, v );\n\n\t\t}\n\n\t\t_vcp.subVectors( p, c );\n\t\tvar d5 = _vab.dot( _vcp );\n\t\tvar d6 = _vac.dot( _vcp );\n\t\tif ( d6 >= 0 && d5 <= d6 ) {\n\n\t\t\t// vertex region of C; barycentric coords (0, 0, 1)\n\t\t\treturn target.copy( c );\n\n\t\t}\n\n\t\tvar vb = d5 * d2 - d1 * d6;\n\t\tif ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {\n\n\t\t\tw = d2 / ( d2 - d6 );\n\t\t\t// edge region of AC; barycentric coords (1-w, 0, w)\n\t\t\treturn target.copy( a ).addScaledVector( _vac, w );\n\n\t\t}\n\n\t\tvar va = d3 * d6 - d5 * d4;\n\t\tif ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {\n\n\t\t\t_vbc.subVectors( c, b );\n\t\t\tw = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );\n\t\t\t// edge region of BC; barycentric coords (0, 1-w, w)\n\t\t\treturn target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC\n\n\t\t}\n\n\t\t// face region\n\t\tvar denom = 1 / ( va + vb + vc );\n\t\t// u = va * denom\n\t\tv = vb * denom;\n\t\tw = vc * denom;\n\n\t\treturn target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );\n\n\t},\n\n\tequals: function ( triangle ) {\n\n\t\treturn triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );\n\n\t}\n\n} );\n\n\nexport { Triangle };\n","import { MathUtils } from './MathUtils.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,\n\t'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,\n\t'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,\n\t'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,\n\t'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,\n\t'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,\n\t'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,\n\t'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,\n\t'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,\n\t'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,\n\t'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,\n\t'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,\n\t'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,\n\t'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,\n\t'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,\n\t'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,\n\t'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,\n\t'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,\n\t'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,\n\t'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,\n\t'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,\n\t'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,\n\t'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,\n\t'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };\n\nvar _hslA = { h: 0, s: 0, l: 0 };\nvar _hslB = { h: 0, s: 0, l: 0 };\n\nfunction Color( r, g, b ) {\n\n\tif ( g === undefined && b === undefined ) {\n\n\t\t// r is THREE.Color, hex or string\n\t\treturn this.set( r );\n\n\t}\n\n\treturn this.setRGB( r, g, b );\n\n}\n\nfunction hue2rgb( p, q, t ) {\n\n\tif ( t < 0 ) t += 1;\n\tif ( t > 1 ) t -= 1;\n\tif ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;\n\tif ( t < 1 / 2 ) return q;\n\tif ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );\n\treturn p;\n\n}\n\nfunction SRGBToLinear( c ) {\n\n\treturn ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );\n\n}\n\nfunction LinearToSRGB( c ) {\n\n\treturn ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;\n\n}\n\nObject.assign( Color.prototype, {\n\n\tisColor: true,\n\n\tr: 1, g: 1, b: 1,\n\n\tset: function ( value ) {\n\n\t\tif ( value && value.isColor ) {\n\n\t\t\tthis.copy( value );\n\n\t\t} else if ( typeof value === 'number' ) {\n\n\t\t\tthis.setHex( value );\n\n\t\t} else if ( typeof value === 'string' ) {\n\n\t\t\tthis.setStyle( value );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetScalar: function ( scalar ) {\n\n\t\tthis.r = scalar;\n\t\tthis.g = scalar;\n\t\tthis.b = scalar;\n\n\t\treturn this;\n\n\t},\n\n\tsetHex: function ( hex ) {\n\n\t\thex = Math.floor( hex );\n\n\t\tthis.r = ( hex >> 16 & 255 ) / 255;\n\t\tthis.g = ( hex >> 8 & 255 ) / 255;\n\t\tthis.b = ( hex & 255 ) / 255;\n\n\t\treturn this;\n\n\t},\n\n\tsetRGB: function ( r, g, b ) {\n\n\t\tthis.r = r;\n\t\tthis.g = g;\n\t\tthis.b = b;\n\n\t\treturn this;\n\n\t},\n\n\tsetHSL: function ( h, s, l ) {\n\n\t\t// h,s,l ranges are in 0.0 - 1.0\n\t\th = MathUtils.euclideanModulo( h, 1 );\n\t\ts = MathUtils.clamp( s, 0, 1 );\n\t\tl = MathUtils.clamp( l, 0, 1 );\n\n\t\tif ( s === 0 ) {\n\n\t\t\tthis.r = this.g = this.b = l;\n\n\t\t} else {\n\n\t\t\tvar p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );\n\t\t\tvar q = ( 2 * l ) - p;\n\n\t\t\tthis.r = hue2rgb( q, p, h + 1 / 3 );\n\t\t\tthis.g = hue2rgb( q, p, h );\n\t\t\tthis.b = hue2rgb( q, p, h - 1 / 3 );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetStyle: function ( style ) {\n\n\t\tfunction handleAlpha( string ) {\n\n\t\t\tif ( string === undefined ) return;\n\n\t\t\tif ( parseFloat( string ) < 1 ) {\n\n\t\t\t\tconsole.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );\n\n\t\t\t}\n\n\t\t}\n\n\n\t\tvar m;\n\n\t\tif ( m = /^((?:rgb|hsl)a?)\\(\\s*([^\\)]*)\\)/.exec( style ) ) {\n\n\t\t\t// rgb / hsl\n\n\t\t\tvar color;\n\t\t\tvar name = m[ 1 ];\n\t\t\tvar components = m[ 2 ];\n\n\t\t\tswitch ( name ) {\n\n\t\t\t\tcase 'rgb':\n\t\t\t\tcase 'rgba':\n\n\t\t\t\t\tif ( color = /^(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\n\n\t\t\t\t\t\t// rgb(255,0,0) rgba(255,0,0,0.5)\n\t\t\t\t\t\tthis.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;\n\t\t\t\t\t\tthis.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;\n\t\t\t\t\t\tthis.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;\n\n\t\t\t\t\t\thandleAlpha( color[ 5 ] );\n\n\t\t\t\t\t\treturn this;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( color = /^(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\n\n\t\t\t\t\t\t// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)\n\t\t\t\t\t\tthis.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;\n\t\t\t\t\t\tthis.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;\n\t\t\t\t\t\tthis.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;\n\n\t\t\t\t\t\thandleAlpha( color[ 5 ] );\n\n\t\t\t\t\t\treturn this;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'hsl':\n\t\t\t\tcase 'hsla':\n\n\t\t\t\t\tif ( color = /^([0-9]*\\.?[0-9]+)\\s*,\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\n\n\t\t\t\t\t\t// hsl(120,50%,50%) hsla(120,50%,50%,0.5)\n\t\t\t\t\t\tvar h = parseFloat( color[ 1 ] ) / 360;\n\t\t\t\t\t\tvar s = parseInt( color[ 2 ], 10 ) / 100;\n\t\t\t\t\t\tvar l = parseInt( color[ 3 ], 10 ) / 100;\n\n\t\t\t\t\t\thandleAlpha( color[ 5 ] );\n\n\t\t\t\t\t\treturn this.setHSL( h, s, l );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t} else if ( m = /^\\#([A-Fa-f0-9]+)$/.exec( style ) ) {\n\n\t\t\t// hex color\n\n\t\t\tvar hex = m[ 1 ];\n\t\t\tvar size = hex.length;\n\n\t\t\tif ( size === 3 ) {\n\n\t\t\t\t// #ff0\n\t\t\t\tthis.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;\n\t\t\t\tthis.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;\n\t\t\t\tthis.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;\n\n\t\t\t\treturn this;\n\n\t\t\t} else if ( size === 6 ) {\n\n\t\t\t\t// #ff0000\n\t\t\t\tthis.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;\n\t\t\t\tthis.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;\n\t\t\t\tthis.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;\n\n\t\t\t\treturn this;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( style && style.length > 0 ) {\n\n\t\t\treturn this.setColorName( style );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetColorName: function ( style ) {\n\n\t\t// color keywords\n\t\tvar hex = _colorKeywords[ style ];\n\n\t\tif ( hex !== undefined ) {\n\n\t\t\t// red\n\t\t\tthis.setHex( hex );\n\n\t\t} else {\n\n\t\t\t// unknown color\n\t\t\tconsole.warn( 'THREE.Color: Unknown color ' + style );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.r, this.g, this.b );\n\n\t},\n\n\tcopy: function ( color ) {\n\n\t\tthis.r = color.r;\n\t\tthis.g = color.g;\n\t\tthis.b = color.b;\n\n\t\treturn this;\n\n\t},\n\n\tcopyGammaToLinear: function ( color, gammaFactor ) {\n\n\t\tif ( gammaFactor === undefined ) gammaFactor = 2.0;\n\n\t\tthis.r = Math.pow( color.r, gammaFactor );\n\t\tthis.g = Math.pow( color.g, gammaFactor );\n\t\tthis.b = Math.pow( color.b, gammaFactor );\n\n\t\treturn this;\n\n\t},\n\n\tcopyLinearToGamma: function ( color, gammaFactor ) {\n\n\t\tif ( gammaFactor === undefined ) gammaFactor = 2.0;\n\n\t\tvar safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;\n\n\t\tthis.r = Math.pow( color.r, safeInverse );\n\t\tthis.g = Math.pow( color.g, safeInverse );\n\t\tthis.b = Math.pow( color.b, safeInverse );\n\n\t\treturn this;\n\n\t},\n\n\tconvertGammaToLinear: function ( gammaFactor ) {\n\n\t\tthis.copyGammaToLinear( this, gammaFactor );\n\n\t\treturn this;\n\n\t},\n\n\tconvertLinearToGamma: function ( gammaFactor ) {\n\n\t\tthis.copyLinearToGamma( this, gammaFactor );\n\n\t\treturn this;\n\n\t},\n\n\tcopySRGBToLinear: function ( color ) {\n\n\t\tthis.r = SRGBToLinear( color.r );\n\t\tthis.g = SRGBToLinear( color.g );\n\t\tthis.b = SRGBToLinear( color.b );\n\n\t\treturn this;\n\n\t},\n\n\tcopyLinearToSRGB: function ( color ) {\n\n\t\tthis.r = LinearToSRGB( color.r );\n\t\tthis.g = LinearToSRGB( color.g );\n\t\tthis.b = LinearToSRGB( color.b );\n\n\t\treturn this;\n\n\t},\n\n\tconvertSRGBToLinear: function () {\n\n\t\tthis.copySRGBToLinear( this );\n\n\t\treturn this;\n\n\t},\n\n\tconvertLinearToSRGB: function () {\n\n\t\tthis.copyLinearToSRGB( this );\n\n\t\treturn this;\n\n\t},\n\n\tgetHex: function () {\n\n\t\treturn ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;\n\n\t},\n\n\tgetHexString: function () {\n\n\t\treturn ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );\n\n\t},\n\n\tgetHSL: function ( target ) {\n\n\t\t// h,s,l ranges are in 0.0 - 1.0\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Color: .getHSL() target is now required' );\n\t\t\ttarget = { h: 0, s: 0, l: 0 };\n\n\t\t}\n\n\t\tvar r = this.r, g = this.g, b = this.b;\n\n\t\tvar max = Math.max( r, g, b );\n\t\tvar min = Math.min( r, g, b );\n\n\t\tvar hue, saturation;\n\t\tvar lightness = ( min + max ) / 2.0;\n\n\t\tif ( min === max ) {\n\n\t\t\thue = 0;\n\t\t\tsaturation = 0;\n\n\t\t} else {\n\n\t\t\tvar delta = max - min;\n\n\t\t\tsaturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );\n\n\t\t\tswitch ( max ) {\n\n\t\t\t\tcase r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;\n\t\t\t\tcase g: hue = ( b - r ) / delta + 2; break;\n\t\t\t\tcase b: hue = ( r - g ) / delta + 4; break;\n\n\t\t\t}\n\n\t\t\thue /= 6;\n\n\t\t}\n\n\t\ttarget.h = hue;\n\t\ttarget.s = saturation;\n\t\ttarget.l = lightness;\n\n\t\treturn target;\n\n\t},\n\n\tgetStyle: function () {\n\n\t\treturn 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';\n\n\t},\n\n\toffsetHSL: function ( h, s, l ) {\n\n\t\tthis.getHSL( _hslA );\n\n\t\t_hslA.h += h; _hslA.s += s; _hslA.l += l;\n\n\t\tthis.setHSL( _hslA.h, _hslA.s, _hslA.l );\n\n\t\treturn this;\n\n\t},\n\n\tadd: function ( color ) {\n\n\t\tthis.r += color.r;\n\t\tthis.g += color.g;\n\t\tthis.b += color.b;\n\n\t\treturn this;\n\n\t},\n\n\taddColors: function ( color1, color2 ) {\n\n\t\tthis.r = color1.r + color2.r;\n\t\tthis.g = color1.g + color2.g;\n\t\tthis.b = color1.b + color2.b;\n\n\t\treturn this;\n\n\t},\n\n\taddScalar: function ( s ) {\n\n\t\tthis.r += s;\n\t\tthis.g += s;\n\t\tthis.b += s;\n\n\t\treturn this;\n\n\t},\n\n\tsub: function ( color ) {\n\n\t\tthis.r = Math.max( 0, this.r - color.r );\n\t\tthis.g = Math.max( 0, this.g - color.g );\n\t\tthis.b = Math.max( 0, this.b - color.b );\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( color ) {\n\n\t\tthis.r *= color.r;\n\t\tthis.g *= color.g;\n\t\tthis.b *= color.b;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( s ) {\n\n\t\tthis.r *= s;\n\t\tthis.g *= s;\n\t\tthis.b *= s;\n\n\t\treturn this;\n\n\t},\n\n\tlerp: function ( color, alpha ) {\n\n\t\tthis.r += ( color.r - this.r ) * alpha;\n\t\tthis.g += ( color.g - this.g ) * alpha;\n\t\tthis.b += ( color.b - this.b ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tlerpHSL: function ( color, alpha ) {\n\n\t\tthis.getHSL( _hslA );\n\t\tcolor.getHSL( _hslB );\n\n\t\tvar h = MathUtils.lerp( _hslA.h, _hslB.h, alpha );\n\t\tvar s = MathUtils.lerp( _hslA.s, _hslB.s, alpha );\n\t\tvar l = MathUtils.lerp( _hslA.l, _hslB.l, alpha );\n\n\t\tthis.setHSL( h, s, l );\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( c ) {\n\n\t\treturn ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis.r = array[ offset ];\n\t\tthis.g = array[ offset + 1 ];\n\t\tthis.b = array[ offset + 2 ];\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this.r;\n\t\tarray[ offset + 1 ] = this.g;\n\t\tarray[ offset + 2 ] = this.b;\n\n\t\treturn array;\n\n\t},\n\n\ttoJSON: function () {\n\n\t\treturn this.getHex();\n\n\t}\n\n} );\n\nColor.NAMES = _colorKeywords;\n\nexport { Color };\n","import { Color } from '../math/Color.js';\nimport { Vector3 } from '../math/Vector3.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n */\n\nfunction Face3( a, b, c, normal, color, materialIndex ) {\n\n\tthis.a = a;\n\tthis.b = b;\n\tthis.c = c;\n\n\tthis.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();\n\tthis.vertexNormals = Array.isArray( normal ) ? normal : [];\n\n\tthis.color = ( color && color.isColor ) ? color : new Color();\n\tthis.vertexColors = Array.isArray( color ) ? color : [];\n\n\tthis.materialIndex = materialIndex !== undefined ? materialIndex : 0;\n\n}\n\nObject.assign( Face3.prototype, {\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tthis.a = source.a;\n\t\tthis.b = source.b;\n\t\tthis.c = source.c;\n\n\t\tthis.normal.copy( source.normal );\n\t\tthis.color.copy( source.color );\n\n\t\tthis.materialIndex = source.materialIndex;\n\n\t\tfor ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {\n\n\t\t\tthis.vertexNormals[ i ] = source.vertexNormals[ i ].clone();\n\n\t\t}\n\n\t\tfor ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {\n\n\t\t\tthis.vertexColors[ i ] = source.vertexColors[ i ].clone();\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Face3 };\n","import { EventDispatcher } from '../core/EventDispatcher.js';\nimport { FrontSide, FlatShading, NormalBlending, LessEqualDepth, AddEquation, OneMinusSrcAlphaFactor, SrcAlphaFactor, AlwaysStencilFunc, KeepStencilOp } from '../constants.js';\nimport { MathUtils } from '../math/MathUtils.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n */\n\nvar materialId = 0;\n\nfunction Material() {\n\n\tObject.defineProperty( this, 'id', { value: materialId ++ } );\n\n\tthis.uuid = MathUtils.generateUUID();\n\n\tthis.name = '';\n\tthis.type = 'Material';\n\n\tthis.fog = true;\n\n\tthis.blending = NormalBlending;\n\tthis.side = FrontSide;\n\tthis.flatShading = false;\n\tthis.vertexColors = false;\n\n\tthis.opacity = 1;\n\tthis.transparent = false;\n\n\tthis.blendSrc = SrcAlphaFactor;\n\tthis.blendDst = OneMinusSrcAlphaFactor;\n\tthis.blendEquation = AddEquation;\n\tthis.blendSrcAlpha = null;\n\tthis.blendDstAlpha = null;\n\tthis.blendEquationAlpha = null;\n\n\tthis.depthFunc = LessEqualDepth;\n\tthis.depthTest = true;\n\tthis.depthWrite = true;\n\n\tthis.stencilWriteMask = 0xff;\n\tthis.stencilFunc = AlwaysStencilFunc;\n\tthis.stencilRef = 0;\n\tthis.stencilFuncMask = 0xff;\n\tthis.stencilFail = KeepStencilOp;\n\tthis.stencilZFail = KeepStencilOp;\n\tthis.stencilZPass = KeepStencilOp;\n\tthis.stencilWrite = false;\n\n\tthis.clippingPlanes = null;\n\tthis.clipIntersection = false;\n\tthis.clipShadows = false;\n\n\tthis.shadowSide = null;\n\n\tthis.colorWrite = true;\n\n\tthis.precision = null; // override the renderer's default precision for this material\n\n\tthis.polygonOffset = false;\n\tthis.polygonOffsetFactor = 0;\n\tthis.polygonOffsetUnits = 0;\n\n\tthis.dithering = false;\n\n\tthis.alphaTest = 0;\n\tthis.premultipliedAlpha = false;\n\n\tthis.visible = true;\n\n\tthis.toneMapped = true;\n\n\tthis.userData = {};\n\n\tthis.version = 0;\n\n}\n\nMaterial.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: Material,\n\n\tisMaterial: true,\n\n\tonBeforeCompile: function () {},\n\n\tsetValues: function ( values ) {\n\n\t\tif ( values === undefined ) return;\n\n\t\tfor ( var key in values ) {\n\n\t\t\tvar newValue = values[ key ];\n\n\t\t\tif ( newValue === undefined ) {\n\n\t\t\t\tconsole.warn( \"THREE.Material: '\" + key + \"' parameter is undefined.\" );\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\t// for backward compatability if shading is set in the constructor\n\t\t\tif ( key === 'shading' ) {\n\n\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );\n\t\t\t\tthis.flatShading = ( newValue === FlatShading ) ? true : false;\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\tvar currentValue = this[ key ];\n\n\t\t\tif ( currentValue === undefined ) {\n\n\t\t\t\tconsole.warn( \"THREE.\" + this.type + \": '\" + key + \"' is not a property of this material.\" );\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\tif ( currentValue && currentValue.isColor ) {\n\n\t\t\t\tcurrentValue.set( newValue );\n\n\t\t\t} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {\n\n\t\t\t\tcurrentValue.copy( newValue );\n\n\t\t\t} else {\n\n\t\t\t\tthis[ key ] = newValue;\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\ttoJSON: function ( meta ) {\n\n\t\tvar isRoot = ( meta === undefined || typeof meta === 'string' );\n\n\t\tif ( isRoot ) {\n\n\t\t\tmeta = {\n\t\t\t\ttextures: {},\n\t\t\t\timages: {}\n\t\t\t};\n\n\t\t}\n\n\t\tvar data = {\n\t\t\tmetadata: {\n\t\t\t\tversion: 4.5,\n\t\t\t\ttype: 'Material',\n\t\t\t\tgenerator: 'Material.toJSON'\n\t\t\t}\n\t\t};\n\n\t\t// standard Material serialization\n\t\tdata.uuid = this.uuid;\n\t\tdata.type = this.type;\n\n\t\tif ( this.name !== '' ) data.name = this.name;\n\n\t\tif ( this.color && this.color.isColor ) data.color = this.color.getHex();\n\n\t\tif ( this.roughness !== undefined ) data.roughness = this.roughness;\n\t\tif ( this.metalness !== undefined ) data.metalness = this.metalness;\n\n\t\tif ( this.sheen && this.sheen.isColor ) data.sheen = this.sheen.getHex();\n\t\tif ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();\n\t\tif ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;\n\n\t\tif ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();\n\t\tif ( this.shininess !== undefined ) data.shininess = this.shininess;\n\t\tif ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;\n\t\tif ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;\n\n\t\tif ( this.clearcoatMap && this.clearcoatMap.isTexture ) {\n\n\t\t\tdata.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;\n\n\t\t}\n\n\t\tif ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {\n\n\t\t\tdata.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;\n\n\t\t}\n\n\t\tif ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {\n\n\t\t\tdata.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;\n\t\t\tdata.clearcoatNormalScale = this.clearcoatNormalScale.toArray();\n\n\t\t}\n\n\t\tif ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;\n\t\tif ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;\n\t\tif ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;\n\t\tif ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;\n\n\t\tif ( this.aoMap && this.aoMap.isTexture ) {\n\n\t\t\tdata.aoMap = this.aoMap.toJSON( meta ).uuid;\n\t\t\tdata.aoMapIntensity = this.aoMapIntensity;\n\n\t\t}\n\n\t\tif ( this.bumpMap && this.bumpMap.isTexture ) {\n\n\t\t\tdata.bumpMap = this.bumpMap.toJSON( meta ).uuid;\n\t\t\tdata.bumpScale = this.bumpScale;\n\n\t\t}\n\n\t\tif ( this.normalMap && this.normalMap.isTexture ) {\n\n\t\t\tdata.normalMap = this.normalMap.toJSON( meta ).uuid;\n\t\t\tdata.normalMapType = this.normalMapType;\n\t\t\tdata.normalScale = this.normalScale.toArray();\n\n\t\t}\n\n\t\tif ( this.displacementMap && this.displacementMap.isTexture ) {\n\n\t\t\tdata.displacementMap = this.displacementMap.toJSON( meta ).uuid;\n\t\t\tdata.displacementScale = this.displacementScale;\n\t\t\tdata.displacementBias = this.displacementBias;\n\n\t\t}\n\n\t\tif ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;\n\t\tif ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;\n\n\t\tif ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;\n\t\tif ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;\n\n\t\tif ( this.envMap && this.envMap.isTexture ) {\n\n\t\t\tdata.envMap = this.envMap.toJSON( meta ).uuid;\n\t\t\tdata.reflectivity = this.reflectivity; // Scale behind envMap\n\t\t\tdata.refractionRatio = this.refractionRatio;\n\n\t\t\tif ( this.combine !== undefined ) data.combine = this.combine;\n\t\t\tif ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;\n\n\t\t}\n\n\t\tif ( this.gradientMap && this.gradientMap.isTexture ) {\n\n\t\t\tdata.gradientMap = this.gradientMap.toJSON( meta ).uuid;\n\n\t\t}\n\n\t\tif ( this.size !== undefined ) data.size = this.size;\n\t\tif ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;\n\n\t\tif ( this.blending !== NormalBlending ) data.blending = this.blending;\n\t\tif ( this.flatShading === true ) data.flatShading = this.flatShading;\n\t\tif ( this.side !== FrontSide ) data.side = this.side;\n\t\tif ( this.vertexColors ) data.vertexColors = true;\n\n\t\tif ( this.opacity < 1 ) data.opacity = this.opacity;\n\t\tif ( this.transparent === true ) data.transparent = this.transparent;\n\n\t\tdata.depthFunc = this.depthFunc;\n\t\tdata.depthTest = this.depthTest;\n\t\tdata.depthWrite = this.depthWrite;\n\n\t\tdata.stencilWrite = this.stencilWrite;\n\t\tdata.stencilWriteMask = this.stencilWriteMask;\n\t\tdata.stencilFunc = this.stencilFunc;\n\t\tdata.stencilRef = this.stencilRef;\n\t\tdata.stencilFuncMask = this.stencilFuncMask;\n\t\tdata.stencilFail = this.stencilFail;\n\t\tdata.stencilZFail = this.stencilZFail;\n\t\tdata.stencilZPass = this.stencilZPass;\n\n\t\t// rotation (SpriteMaterial)\n\t\tif ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation;\n\n\t\tif ( this.polygonOffset === true ) data.polygonOffset = true;\n\t\tif ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;\n\t\tif ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;\n\n\t\tif ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth;\n\t\tif ( this.dashSize !== undefined ) data.dashSize = this.dashSize;\n\t\tif ( this.gapSize !== undefined ) data.gapSize = this.gapSize;\n\t\tif ( this.scale !== undefined ) data.scale = this.scale;\n\n\t\tif ( this.dithering === true ) data.dithering = true;\n\n\t\tif ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;\n\t\tif ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;\n\n\t\tif ( this.wireframe === true ) data.wireframe = this.wireframe;\n\t\tif ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;\n\t\tif ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;\n\t\tif ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;\n\n\t\tif ( this.morphTargets === true ) data.morphTargets = true;\n\t\tif ( this.morphNormals === true ) data.morphNormals = true;\n\t\tif ( this.skinning === true ) data.skinning = true;\n\n\t\tif ( this.visible === false ) data.visible = false;\n\n\t\tif ( this.toneMapped === false ) data.toneMapped = false;\n\n\t\tif ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;\n\n\t\t// TODO: Copied from Object3D.toJSON\n\n\t\tfunction extractFromCache( cache ) {\n\n\t\t\tvar values = [];\n\n\t\t\tfor ( var key in cache ) {\n\n\t\t\t\tvar data = cache[ key ];\n\t\t\t\tdelete data.metadata;\n\t\t\t\tvalues.push( data );\n\n\t\t\t}\n\n\t\t\treturn values;\n\n\t\t}\n\n\t\tif ( isRoot ) {\n\n\t\t\tvar textures = extractFromCache( meta.textures );\n\t\t\tvar images = extractFromCache( meta.images );\n\n\t\t\tif ( textures.length > 0 ) data.textures = textures;\n\t\t\tif ( images.length > 0 ) data.images = images;\n\n\t\t}\n\n\t\treturn data;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tthis.name = source.name;\n\n\t\tthis.fog = source.fog;\n\n\t\tthis.blending = source.blending;\n\t\tthis.side = source.side;\n\t\tthis.flatShading = source.flatShading;\n\t\tthis.vertexColors = source.vertexColors;\n\n\t\tthis.opacity = source.opacity;\n\t\tthis.transparent = source.transparent;\n\n\t\tthis.blendSrc = source.blendSrc;\n\t\tthis.blendDst = source.blendDst;\n\t\tthis.blendEquation = source.blendEquation;\n\t\tthis.blendSrcAlpha = source.blendSrcAlpha;\n\t\tthis.blendDstAlpha = source.blendDstAlpha;\n\t\tthis.blendEquationAlpha = source.blendEquationAlpha;\n\n\t\tthis.depthFunc = source.depthFunc;\n\t\tthis.depthTest = source.depthTest;\n\t\tthis.depthWrite = source.depthWrite;\n\n\t\tthis.stencilWriteMask = source.stencilWriteMask;\n\t\tthis.stencilFunc = source.stencilFunc;\n\t\tthis.stencilRef = source.stencilRef;\n\t\tthis.stencilFuncMask = source.stencilFuncMask;\n\t\tthis.stencilFail = source.stencilFail;\n\t\tthis.stencilZFail = source.stencilZFail;\n\t\tthis.stencilZPass = source.stencilZPass;\n\t\tthis.stencilWrite = source.stencilWrite;\n\n\t\tvar srcPlanes = source.clippingPlanes,\n\t\t\tdstPlanes = null;\n\n\t\tif ( srcPlanes !== null ) {\n\n\t\t\tvar n = srcPlanes.length;\n\t\t\tdstPlanes = new Array( n );\n\n\t\t\tfor ( var i = 0; i !== n; ++ i )\n\t\t\t\tdstPlanes[ i ] = srcPlanes[ i ].clone();\n\n\t\t}\n\n\t\tthis.clippingPlanes = dstPlanes;\n\t\tthis.clipIntersection = source.clipIntersection;\n\t\tthis.clipShadows = source.clipShadows;\n\n\t\tthis.shadowSide = source.shadowSide;\n\n\t\tthis.colorWrite = source.colorWrite;\n\n\t\tthis.precision = source.precision;\n\n\t\tthis.polygonOffset = source.polygonOffset;\n\t\tthis.polygonOffsetFactor = source.polygonOffsetFactor;\n\t\tthis.polygonOffsetUnits = source.polygonOffsetUnits;\n\n\t\tthis.dithering = source.dithering;\n\n\t\tthis.alphaTest = source.alphaTest;\n\t\tthis.premultipliedAlpha = source.premultipliedAlpha;\n\n\t\tthis.visible = source.visible;\n\n\t\tthis.toneMapped = source.toneMapped;\n\n\t\tthis.userData = JSON.parse( JSON.stringify( source.userData ) );\n\n\t\treturn this;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t}\n\n} );\n\nObject.defineProperty( Material.prototype, 'needsUpdate', {\n\n\tset: function ( value ) {\n\n\t\tif ( value === true ) this.version ++;\n\n\t}\n\n} );\n\nexport { Material };\n","import { Material } from './Material.js';\nimport { MultiplyOperation } from '../constants.js';\nimport { Color } from '../math/Color.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n *\n * parameters = {\n * color: ,\n * opacity: ,\n * map: new THREE.Texture( ),\n *\n * lightMap: new THREE.Texture( ),\n * lightMapIntensity: \n *\n * aoMap: new THREE.Texture( ),\n * aoMapIntensity: \n *\n * specularMap: new THREE.Texture( ),\n *\n * alphaMap: new THREE.Texture( ),\n *\n * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),\n * combine: THREE.Multiply,\n * reflectivity: ,\n * refractionRatio: ,\n *\n * depthTest: ,\n * depthWrite: ,\n *\n * wireframe: ,\n * wireframeLinewidth: ,\n *\n * skinning: ,\n * morphTargets: \n * }\n */\n\nfunction MeshBasicMaterial( parameters ) {\n\n\tMaterial.call( this );\n\n\tthis.type = 'MeshBasicMaterial';\n\n\tthis.color = new Color( 0xffffff ); // emissive\n\n\tthis.map = null;\n\n\tthis.lightMap = null;\n\tthis.lightMapIntensity = 1.0;\n\n\tthis.aoMap = null;\n\tthis.aoMapIntensity = 1.0;\n\n\tthis.specularMap = null;\n\n\tthis.alphaMap = null;\n\n\tthis.envMap = null;\n\tthis.combine = MultiplyOperation;\n\tthis.reflectivity = 1;\n\tthis.refractionRatio = 0.98;\n\n\tthis.wireframe = false;\n\tthis.wireframeLinewidth = 1;\n\tthis.wireframeLinecap = 'round';\n\tthis.wireframeLinejoin = 'round';\n\n\tthis.skinning = false;\n\tthis.morphTargets = false;\n\n\tthis.setValues( parameters );\n\n}\n\nMeshBasicMaterial.prototype = Object.create( Material.prototype );\nMeshBasicMaterial.prototype.constructor = MeshBasicMaterial;\n\nMeshBasicMaterial.prototype.isMeshBasicMaterial = true;\n\nMeshBasicMaterial.prototype.copy = function ( source ) {\n\n\tMaterial.prototype.copy.call( this, source );\n\n\tthis.color.copy( source.color );\n\n\tthis.map = source.map;\n\n\tthis.lightMap = source.lightMap;\n\tthis.lightMapIntensity = source.lightMapIntensity;\n\n\tthis.aoMap = source.aoMap;\n\tthis.aoMapIntensity = source.aoMapIntensity;\n\n\tthis.specularMap = source.specularMap;\n\n\tthis.alphaMap = source.alphaMap;\n\n\tthis.envMap = source.envMap;\n\tthis.combine = source.combine;\n\tthis.reflectivity = source.reflectivity;\n\tthis.refractionRatio = source.refractionRatio;\n\n\tthis.wireframe = source.wireframe;\n\tthis.wireframeLinewidth = source.wireframeLinewidth;\n\tthis.wireframeLinecap = source.wireframeLinecap;\n\tthis.wireframeLinejoin = source.wireframeLinejoin;\n\n\tthis.skinning = source.skinning;\n\tthis.morphTargets = source.morphTargets;\n\n\treturn this;\n\n};\n\n\nexport { MeshBasicMaterial };\n","import { Vector4 } from '../math/Vector4.js';\nimport { Vector3 } from '../math/Vector3.js';\nimport { Vector2 } from '../math/Vector2.js';\nimport { Color } from '../math/Color.js';\nimport { StaticDrawUsage } from '../constants.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar _vector = new Vector3();\n\nfunction BufferAttribute( array, itemSize, normalized ) {\n\n\tif ( Array.isArray( array ) ) {\n\n\t\tthrow new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );\n\n\t}\n\n\tthis.name = '';\n\n\tthis.array = array;\n\tthis.itemSize = itemSize;\n\tthis.count = array !== undefined ? array.length / itemSize : 0;\n\tthis.normalized = normalized === true;\n\n\tthis.usage = StaticDrawUsage;\n\tthis.updateRange = { offset: 0, count: - 1 };\n\n\tthis.version = 0;\n\n}\n\nObject.defineProperty( BufferAttribute.prototype, 'needsUpdate', {\n\n\tset: function ( value ) {\n\n\t\tif ( value === true ) this.version ++;\n\n\t}\n\n} );\n\nObject.assign( BufferAttribute.prototype, {\n\n\tisBufferAttribute: true,\n\n\tonUploadCallback: function () {},\n\n\tsetUsage: function ( value ) {\n\n\t\tthis.usage = value;\n\n\t\treturn this;\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tthis.name = source.name;\n\t\tthis.array = new source.array.constructor( source.array );\n\t\tthis.itemSize = source.itemSize;\n\t\tthis.count = source.count;\n\t\tthis.normalized = source.normalized;\n\n\t\tthis.usage = source.usage;\n\n\t\treturn this;\n\n\t},\n\n\tcopyAt: function ( index1, attribute, index2 ) {\n\n\t\tindex1 *= this.itemSize;\n\t\tindex2 *= attribute.itemSize;\n\n\t\tfor ( var i = 0, l = this.itemSize; i < l; i ++ ) {\n\n\t\t\tthis.array[ index1 + i ] = attribute.array[ index2 + i ];\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcopyArray: function ( array ) {\n\n\t\tthis.array.set( array );\n\n\t\treturn this;\n\n\t},\n\n\tcopyColorsArray: function ( colors ) {\n\n\t\tvar array = this.array, offset = 0;\n\n\t\tfor ( var i = 0, l = colors.length; i < l; i ++ ) {\n\n\t\t\tvar color = colors[ i ];\n\n\t\t\tif ( color === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );\n\t\t\t\tcolor = new Color();\n\n\t\t\t}\n\n\t\t\tarray[ offset ++ ] = color.r;\n\t\t\tarray[ offset ++ ] = color.g;\n\t\t\tarray[ offset ++ ] = color.b;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcopyVector2sArray: function ( vectors ) {\n\n\t\tvar array = this.array, offset = 0;\n\n\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\n\n\t\t\tvar vector = vectors[ i ];\n\n\t\t\tif ( vector === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );\n\t\t\t\tvector = new Vector2();\n\n\t\t\t}\n\n\t\t\tarray[ offset ++ ] = vector.x;\n\t\t\tarray[ offset ++ ] = vector.y;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcopyVector3sArray: function ( vectors ) {\n\n\t\tvar array = this.array, offset = 0;\n\n\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\n\n\t\t\tvar vector = vectors[ i ];\n\n\t\t\tif ( vector === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );\n\t\t\t\tvector = new Vector3();\n\n\t\t\t}\n\n\t\t\tarray[ offset ++ ] = vector.x;\n\t\t\tarray[ offset ++ ] = vector.y;\n\t\t\tarray[ offset ++ ] = vector.z;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcopyVector4sArray: function ( vectors ) {\n\n\t\tvar array = this.array, offset = 0;\n\n\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\n\n\t\t\tvar vector = vectors[ i ];\n\n\t\t\tif ( vector === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );\n\t\t\t\tvector = new Vector4();\n\n\t\t\t}\n\n\t\t\tarray[ offset ++ ] = vector.x;\n\t\t\tarray[ offset ++ ] = vector.y;\n\t\t\tarray[ offset ++ ] = vector.z;\n\t\t\tarray[ offset ++ ] = vector.w;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tapplyMatrix3: function ( m ) {\n\n\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\n\n\t\t\t_vector.x = this.getX( i );\n\t\t\t_vector.y = this.getY( i );\n\t\t\t_vector.z = this.getZ( i );\n\n\t\t\t_vector.applyMatrix3( m );\n\n\t\t\tthis.setXYZ( i, _vector.x, _vector.y, _vector.z );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tapplyMatrix4: function ( m ) {\n\n\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\n\n\t\t\t_vector.x = this.getX( i );\n\t\t\t_vector.y = this.getY( i );\n\t\t\t_vector.z = this.getZ( i );\n\n\t\t\t_vector.applyMatrix4( m );\n\n\t\t\tthis.setXYZ( i, _vector.x, _vector.y, _vector.z );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tapplyNormalMatrix: function ( m ) {\n\n\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\n\n\t\t\t_vector.x = this.getX( i );\n\t\t\t_vector.y = this.getY( i );\n\t\t\t_vector.z = this.getZ( i );\n\n\t\t\t_vector.applyNormalMatrix( m );\n\n\t\t\tthis.setXYZ( i, _vector.x, _vector.y, _vector.z );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\ttransformDirection: function ( m ) {\n\n\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\n\n\t\t\t_vector.x = this.getX( i );\n\t\t\t_vector.y = this.getY( i );\n\t\t\t_vector.z = this.getZ( i );\n\n\t\t\t_vector.transformDirection( m );\n\n\t\t\tthis.setXYZ( i, _vector.x, _vector.y, _vector.z );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tset: function ( value, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis.array.set( value, offset );\n\n\t\treturn this;\n\n\t},\n\n\tgetX: function ( index ) {\n\n\t\treturn this.array[ index * this.itemSize ];\n\n\t},\n\n\tsetX: function ( index, x ) {\n\n\t\tthis.array[ index * this.itemSize ] = x;\n\n\t\treturn this;\n\n\t},\n\n\tgetY: function ( index ) {\n\n\t\treturn this.array[ index * this.itemSize + 1 ];\n\n\t},\n\n\tsetY: function ( index, y ) {\n\n\t\tthis.array[ index * this.itemSize + 1 ] = y;\n\n\t\treturn this;\n\n\t},\n\n\tgetZ: function ( index ) {\n\n\t\treturn this.array[ index * this.itemSize + 2 ];\n\n\t},\n\n\tsetZ: function ( index, z ) {\n\n\t\tthis.array[ index * this.itemSize + 2 ] = z;\n\n\t\treturn this;\n\n\t},\n\n\tgetW: function ( index ) {\n\n\t\treturn this.array[ index * this.itemSize + 3 ];\n\n\t},\n\n\tsetW: function ( index, w ) {\n\n\t\tthis.array[ index * this.itemSize + 3 ] = w;\n\n\t\treturn this;\n\n\t},\n\n\tsetXY: function ( index, x, y ) {\n\n\t\tindex *= this.itemSize;\n\n\t\tthis.array[ index + 0 ] = x;\n\t\tthis.array[ index + 1 ] = y;\n\n\t\treturn this;\n\n\t},\n\n\tsetXYZ: function ( index, x, y, z ) {\n\n\t\tindex *= this.itemSize;\n\n\t\tthis.array[ index + 0 ] = x;\n\t\tthis.array[ index + 1 ] = y;\n\t\tthis.array[ index + 2 ] = z;\n\n\t\treturn this;\n\n\t},\n\n\tsetXYZW: function ( index, x, y, z, w ) {\n\n\t\tindex *= this.itemSize;\n\n\t\tthis.array[ index + 0 ] = x;\n\t\tthis.array[ index + 1 ] = y;\n\t\tthis.array[ index + 2 ] = z;\n\t\tthis.array[ index + 3 ] = w;\n\n\t\treturn this;\n\n\t},\n\n\tonUpload: function ( callback ) {\n\n\t\tthis.onUploadCallback = callback;\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.array, this.itemSize ).copy( this );\n\n\t},\n\n\ttoJSON: function () {\n\n\t\treturn {\n\t\t\titemSize: this.itemSize,\n\t\t\ttype: this.array.constructor.name,\n\t\t\tarray: Array.prototype.slice.call( this.array ),\n\t\t\tnormalized: this.normalized\n\t\t};\n\n\t}\n\n} );\n\n//\n\nfunction Int8BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );\n\n}\n\nInt8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nInt8BufferAttribute.prototype.constructor = Int8BufferAttribute;\n\n\nfunction Uint8BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );\n\n}\n\nUint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nUint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;\n\n\nfunction Uint8ClampedBufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );\n\n}\n\nUint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nUint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;\n\n\nfunction Int16BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );\n\n}\n\nInt16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nInt16BufferAttribute.prototype.constructor = Int16BufferAttribute;\n\n\nfunction Uint16BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );\n\n}\n\nUint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nUint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;\n\n\nfunction Int32BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );\n\n}\n\nInt32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nInt32BufferAttribute.prototype.constructor = Int32BufferAttribute;\n\n\nfunction Uint32BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );\n\n}\n\nUint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nUint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;\n\n\nfunction Float32BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );\n\n}\n\nFloat32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nFloat32BufferAttribute.prototype.constructor = Float32BufferAttribute;\n\n\nfunction Float64BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );\n\n}\n\nFloat64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nFloat64BufferAttribute.prototype.constructor = Float64BufferAttribute;\n\n//\n\nexport {\n\tFloat64BufferAttribute,\n\tFloat32BufferAttribute,\n\tUint32BufferAttribute,\n\tInt32BufferAttribute,\n\tUint16BufferAttribute,\n\tInt16BufferAttribute,\n\tUint8ClampedBufferAttribute,\n\tUint8BufferAttribute,\n\tInt8BufferAttribute,\n\tBufferAttribute\n};\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { Vector2 } from '../math/Vector2.js';\n\nfunction DirectGeometry() {\n\n\tthis.vertices = [];\n\tthis.normals = [];\n\tthis.colors = [];\n\tthis.uvs = [];\n\tthis.uvs2 = [];\n\n\tthis.groups = [];\n\n\tthis.morphTargets = {};\n\n\tthis.skinWeights = [];\n\tthis.skinIndices = [];\n\n\t// this.lineDistances = [];\n\n\tthis.boundingBox = null;\n\tthis.boundingSphere = null;\n\n\t// update flags\n\n\tthis.verticesNeedUpdate = false;\n\tthis.normalsNeedUpdate = false;\n\tthis.colorsNeedUpdate = false;\n\tthis.uvsNeedUpdate = false;\n\tthis.groupsNeedUpdate = false;\n\n}\n\nObject.assign( DirectGeometry.prototype, {\n\n\tcomputeGroups: function ( geometry ) {\n\n\t\tvar group;\n\t\tvar groups = [];\n\t\tvar materialIndex = undefined;\n\n\t\tvar faces = geometry.faces;\n\n\t\tfor ( var i = 0; i < faces.length; i ++ ) {\n\n\t\t\tvar face = faces[ i ];\n\n\t\t\t// materials\n\n\t\t\tif ( face.materialIndex !== materialIndex ) {\n\n\t\t\t\tmaterialIndex = face.materialIndex;\n\n\t\t\t\tif ( group !== undefined ) {\n\n\t\t\t\t\tgroup.count = ( i * 3 ) - group.start;\n\t\t\t\t\tgroups.push( group );\n\n\t\t\t\t}\n\n\t\t\t\tgroup = {\n\t\t\t\t\tstart: i * 3,\n\t\t\t\t\tmaterialIndex: materialIndex\n\t\t\t\t};\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( group !== undefined ) {\n\n\t\t\tgroup.count = ( i * 3 ) - group.start;\n\t\t\tgroups.push( group );\n\n\t\t}\n\n\t\tthis.groups = groups;\n\n\t},\n\n\tfromGeometry: function ( geometry ) {\n\n\t\tvar faces = geometry.faces;\n\t\tvar vertices = geometry.vertices;\n\t\tvar faceVertexUvs = geometry.faceVertexUvs;\n\n\t\tvar hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;\n\t\tvar hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;\n\n\t\t// morphs\n\n\t\tvar morphTargets = geometry.morphTargets;\n\t\tvar morphTargetsLength = morphTargets.length;\n\n\t\tvar morphTargetsPosition;\n\n\t\tif ( morphTargetsLength > 0 ) {\n\n\t\t\tmorphTargetsPosition = [];\n\n\t\t\tfor ( var i = 0; i < morphTargetsLength; i ++ ) {\n\n\t\t\t\tmorphTargetsPosition[ i ] = {\n\t\t\t\t\tname: morphTargets[ i ].name,\n\t\t\t\t \tdata: []\n\t\t\t\t};\n\n\t\t\t}\n\n\t\t\tthis.morphTargets.position = morphTargetsPosition;\n\n\t\t}\n\n\t\tvar morphNormals = geometry.morphNormals;\n\t\tvar morphNormalsLength = morphNormals.length;\n\n\t\tvar morphTargetsNormal;\n\n\t\tif ( morphNormalsLength > 0 ) {\n\n\t\t\tmorphTargetsNormal = [];\n\n\t\t\tfor ( var i = 0; i < morphNormalsLength; i ++ ) {\n\n\t\t\t\tmorphTargetsNormal[ i ] = {\n\t\t\t\t\tname: morphNormals[ i ].name,\n\t\t\t\t \tdata: []\n\t\t\t\t};\n\n\t\t\t}\n\n\t\t\tthis.morphTargets.normal = morphTargetsNormal;\n\n\t\t}\n\n\t\t// skins\n\n\t\tvar skinIndices = geometry.skinIndices;\n\t\tvar skinWeights = geometry.skinWeights;\n\n\t\tvar hasSkinIndices = skinIndices.length === vertices.length;\n\t\tvar hasSkinWeights = skinWeights.length === vertices.length;\n\n\t\t//\n\n\t\tif ( vertices.length > 0 && faces.length === 0 ) {\n\n\t\t\tconsole.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );\n\n\t\t}\n\n\t\tfor ( var i = 0; i < faces.length; i ++ ) {\n\n\t\t\tvar face = faces[ i ];\n\n\t\t\tthis.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );\n\n\t\t\tvar vertexNormals = face.vertexNormals;\n\n\t\t\tif ( vertexNormals.length === 3 ) {\n\n\t\t\t\tthis.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );\n\n\t\t\t} else {\n\n\t\t\t\tvar normal = face.normal;\n\n\t\t\t\tthis.normals.push( normal, normal, normal );\n\n\t\t\t}\n\n\t\t\tvar vertexColors = face.vertexColors;\n\n\t\t\tif ( vertexColors.length === 3 ) {\n\n\t\t\t\tthis.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );\n\n\t\t\t} else {\n\n\t\t\t\tvar color = face.color;\n\n\t\t\t\tthis.colors.push( color, color, color );\n\n\t\t\t}\n\n\t\t\tif ( hasFaceVertexUv === true ) {\n\n\t\t\t\tvar vertexUvs = faceVertexUvs[ 0 ][ i ];\n\n\t\t\t\tif ( vertexUvs !== undefined ) {\n\n\t\t\t\t\tthis.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );\n\n\t\t\t\t\tthis.uvs.push( new Vector2(), new Vector2(), new Vector2() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( hasFaceVertexUv2 === true ) {\n\n\t\t\t\tvar vertexUvs = faceVertexUvs[ 1 ][ i ];\n\n\t\t\t\tif ( vertexUvs !== undefined ) {\n\n\t\t\t\t\tthis.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );\n\n\t\t\t\t\tthis.uvs2.push( new Vector2(), new Vector2(), new Vector2() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// morphs\n\n\t\t\tfor ( var j = 0; j < morphTargetsLength; j ++ ) {\n\n\t\t\t\tvar morphTarget = morphTargets[ j ].vertices;\n\n\t\t\t\tmorphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );\n\n\t\t\t}\n\n\t\t\tfor ( var j = 0; j < morphNormalsLength; j ++ ) {\n\n\t\t\t\tvar morphNormal = morphNormals[ j ].vertexNormals[ i ];\n\n\t\t\t\tmorphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c );\n\n\t\t\t}\n\n\t\t\t// skins\n\n\t\t\tif ( hasSkinIndices ) {\n\n\t\t\t\tthis.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );\n\n\t\t\t}\n\n\t\t\tif ( hasSkinWeights ) {\n\n\t\t\t\tthis.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis.computeGroups( geometry );\n\n\t\tthis.verticesNeedUpdate = geometry.verticesNeedUpdate;\n\t\tthis.normalsNeedUpdate = geometry.normalsNeedUpdate;\n\t\tthis.colorsNeedUpdate = geometry.colorsNeedUpdate;\n\t\tthis.uvsNeedUpdate = geometry.uvsNeedUpdate;\n\t\tthis.groupsNeedUpdate = geometry.groupsNeedUpdate;\n\n\t\tif ( geometry.boundingSphere !== null ) {\n\n\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\n\n\t\t}\n\n\t\tif ( geometry.boundingBox !== null ) {\n\n\t\t\tthis.boundingBox = geometry.boundingBox.clone();\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { DirectGeometry };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction arrayMin( array ) {\n\n\tif ( array.length === 0 ) return Infinity;\n\n\tlet min = array[ 0 ];\n\n\tfor ( let i = 1, l = array.length; i < l; ++ i ) {\n\n\t\tif ( array[ i ] < min ) min = array[ i ];\n\n\t}\n\n\treturn min;\n\n}\n\nfunction arrayMax( array ) {\n\n\tif ( array.length === 0 ) return - Infinity;\n\n\tlet max = array[ 0 ];\n\n\tfor ( let i = 1, l = array.length; i < l; ++ i ) {\n\n\t\tif ( array[ i ] > max ) max = array[ i ];\n\n\t}\n\n\treturn max;\n\n}\n\nexport { arrayMin, arrayMax };\n","import { Vector3 } from '../math/Vector3.js';\nimport { Box3 } from '../math/Box3.js';\nimport { EventDispatcher } from './EventDispatcher.js';\nimport { BufferAttribute, Float32BufferAttribute, Uint16BufferAttribute, Uint32BufferAttribute } from './BufferAttribute.js';\nimport { Sphere } from '../math/Sphere.js';\nimport { DirectGeometry } from './DirectGeometry.js';\nimport { Object3D } from './Object3D.js';\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { Matrix3 } from '../math/Matrix3.js';\nimport { MathUtils } from '../math/MathUtils.js';\nimport { arrayMax } from '../utils.js';\n\n/**\n * @author alteredq / http://alteredqualia.com/\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar _bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id\n\nvar _m1 = new Matrix4();\nvar _obj = new Object3D();\nvar _offset = new Vector3();\nvar _box = new Box3();\nvar _boxMorphTargets = new Box3();\nvar _vector = new Vector3();\n\nfunction BufferGeometry() {\n\n\tObject.defineProperty( this, 'id', { value: _bufferGeometryId += 2 } );\n\n\tthis.uuid = MathUtils.generateUUID();\n\n\tthis.name = '';\n\tthis.type = 'BufferGeometry';\n\n\tthis.index = null;\n\tthis.attributes = {};\n\n\tthis.morphAttributes = {};\n\tthis.morphTargetsRelative = false;\n\n\tthis.groups = [];\n\n\tthis.boundingBox = null;\n\tthis.boundingSphere = null;\n\n\tthis.drawRange = { start: 0, count: Infinity };\n\n\tthis.userData = {};\n\n}\n\nBufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: BufferGeometry,\n\n\tisBufferGeometry: true,\n\n\tgetIndex: function () {\n\n\t\treturn this.index;\n\n\t},\n\n\tsetIndex: function ( index ) {\n\n\t\tif ( Array.isArray( index ) ) {\n\n\t\t\tthis.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );\n\n\t\t} else {\n\n\t\t\tthis.index = index;\n\n\t\t}\n\n\t},\n\n\tgetAttribute: function ( name ) {\n\n\t\treturn this.attributes[ name ];\n\n\t},\n\n\tsetAttribute: function ( name, attribute ) {\n\n\t\tthis.attributes[ name ] = attribute;\n\n\t\treturn this;\n\n\t},\n\n\tdeleteAttribute: function ( name ) {\n\n\t\tdelete this.attributes[ name ];\n\n\t\treturn this;\n\n\t},\n\n\taddGroup: function ( start, count, materialIndex ) {\n\n\t\tthis.groups.push( {\n\n\t\t\tstart: start,\n\t\t\tcount: count,\n\t\t\tmaterialIndex: materialIndex !== undefined ? materialIndex : 0\n\n\t\t} );\n\n\t},\n\n\tclearGroups: function () {\n\n\t\tthis.groups = [];\n\n\t},\n\n\tsetDrawRange: function ( start, count ) {\n\n\t\tthis.drawRange.start = start;\n\t\tthis.drawRange.count = count;\n\n\t},\n\n\tapplyMatrix4: function ( matrix ) {\n\n\t\tvar position = this.attributes.position;\n\n\t\tif ( position !== undefined ) {\n\n\t\t\tposition.applyMatrix4( matrix );\n\n\t\t\tposition.needsUpdate = true;\n\n\t\t}\n\n\t\tvar normal = this.attributes.normal;\n\n\t\tif ( normal !== undefined ) {\n\n\t\t\tvar normalMatrix = new Matrix3().getNormalMatrix( matrix );\n\n\t\t\tnormal.applyNormalMatrix( normalMatrix );\n\n\t\t\tnormal.needsUpdate = true;\n\n\t\t}\n\n\t\tvar tangent = this.attributes.tangent;\n\n\t\tif ( tangent !== undefined ) {\n\n\t\t\ttangent.transformDirection( matrix );\n\n\t\t\ttangent.needsUpdate = true;\n\n\t\t}\n\n\t\tif ( this.boundingBox !== null ) {\n\n\t\t\tthis.computeBoundingBox();\n\n\t\t}\n\n\t\tif ( this.boundingSphere !== null ) {\n\n\t\t\tthis.computeBoundingSphere();\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\trotateX: function ( angle ) {\n\n\t\t// rotate geometry around world x-axis\n\n\t\t_m1.makeRotationX( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateY: function ( angle ) {\n\n\t\t// rotate geometry around world y-axis\n\n\t\t_m1.makeRotationY( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateZ: function ( angle ) {\n\n\t\t// rotate geometry around world z-axis\n\n\t\t_m1.makeRotationZ( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( x, y, z ) {\n\n\t\t// translate geometry\n\n\t\t_m1.makeTranslation( x, y, z );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\tscale: function ( x, y, z ) {\n\n\t\t// scale geometry\n\n\t\t_m1.makeScale( x, y, z );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\tlookAt: function ( vector ) {\n\n\t\t_obj.lookAt( vector );\n\n\t\t_obj.updateMatrix();\n\n\t\tthis.applyMatrix4( _obj.matrix );\n\n\t\treturn this;\n\n\t},\n\n\tcenter: function () {\n\n\t\tthis.computeBoundingBox();\n\n\t\tthis.boundingBox.getCenter( _offset ).negate();\n\n\t\tthis.translate( _offset.x, _offset.y, _offset.z );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromObject: function ( object ) {\n\n\t\t// console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );\n\n\t\tvar geometry = object.geometry;\n\n\t\tif ( object.isPoints || object.isLine ) {\n\n\t\t\tvar positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );\n\t\t\tvar colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );\n\n\t\t\tthis.setAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );\n\t\t\tthis.setAttribute( 'color', colors.copyColorsArray( geometry.colors ) );\n\n\t\t\tif ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {\n\n\t\t\t\tvar lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );\n\n\t\t\t\tthis.setAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );\n\n\t\t\t}\n\n\t\t\tif ( geometry.boundingSphere !== null ) {\n\n\t\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\n\n\t\t\t}\n\n\t\t\tif ( geometry.boundingBox !== null ) {\n\n\t\t\t\tthis.boundingBox = geometry.boundingBox.clone();\n\n\t\t\t}\n\n\t\t} else if ( object.isMesh ) {\n\n\t\t\tif ( geometry && geometry.isGeometry ) {\n\n\t\t\t\tthis.fromGeometry( geometry );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetFromPoints: function ( points ) {\n\n\t\tvar position = [];\n\n\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\n\n\t\t\tvar point = points[ i ];\n\t\t\tposition.push( point.x, point.y, point.z || 0 );\n\n\t\t}\n\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );\n\n\t\treturn this;\n\n\t},\n\n\tupdateFromObject: function ( object ) {\n\n\t\tvar geometry = object.geometry;\n\n\t\tif ( object.isMesh ) {\n\n\t\t\tvar direct = geometry.__directGeometry;\n\n\t\t\tif ( geometry.elementsNeedUpdate === true ) {\n\n\t\t\t\tdirect = undefined;\n\t\t\t\tgeometry.elementsNeedUpdate = false;\n\n\t\t\t}\n\n\t\t\tif ( direct === undefined ) {\n\n\t\t\t\treturn this.fromGeometry( geometry );\n\n\t\t\t}\n\n\t\t\tdirect.verticesNeedUpdate = geometry.verticesNeedUpdate;\n\t\t\tdirect.normalsNeedUpdate = geometry.normalsNeedUpdate;\n\t\t\tdirect.colorsNeedUpdate = geometry.colorsNeedUpdate;\n\t\t\tdirect.uvsNeedUpdate = geometry.uvsNeedUpdate;\n\t\t\tdirect.groupsNeedUpdate = geometry.groupsNeedUpdate;\n\n\t\t\tgeometry.verticesNeedUpdate = false;\n\t\t\tgeometry.normalsNeedUpdate = false;\n\t\t\tgeometry.colorsNeedUpdate = false;\n\t\t\tgeometry.uvsNeedUpdate = false;\n\t\t\tgeometry.groupsNeedUpdate = false;\n\n\t\t\tgeometry = direct;\n\n\t\t}\n\n\t\tvar attribute;\n\n\t\tif ( geometry.verticesNeedUpdate === true ) {\n\n\t\t\tattribute = this.attributes.position;\n\n\t\t\tif ( attribute !== undefined ) {\n\n\t\t\t\tattribute.copyVector3sArray( geometry.vertices );\n\t\t\t\tattribute.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tgeometry.verticesNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( geometry.normalsNeedUpdate === true ) {\n\n\t\t\tattribute = this.attributes.normal;\n\n\t\t\tif ( attribute !== undefined ) {\n\n\t\t\t\tattribute.copyVector3sArray( geometry.normals );\n\t\t\t\tattribute.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tgeometry.normalsNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( geometry.colorsNeedUpdate === true ) {\n\n\t\t\tattribute = this.attributes.color;\n\n\t\t\tif ( attribute !== undefined ) {\n\n\t\t\t\tattribute.copyColorsArray( geometry.colors );\n\t\t\t\tattribute.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tgeometry.colorsNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( geometry.uvsNeedUpdate ) {\n\n\t\t\tattribute = this.attributes.uv;\n\n\t\t\tif ( attribute !== undefined ) {\n\n\t\t\t\tattribute.copyVector2sArray( geometry.uvs );\n\t\t\t\tattribute.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tgeometry.uvsNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( geometry.lineDistancesNeedUpdate ) {\n\n\t\t\tattribute = this.attributes.lineDistance;\n\n\t\t\tif ( attribute !== undefined ) {\n\n\t\t\t\tattribute.copyArray( geometry.lineDistances );\n\t\t\t\tattribute.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tgeometry.lineDistancesNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( geometry.groupsNeedUpdate ) {\n\n\t\t\tgeometry.computeGroups( object.geometry );\n\t\t\tthis.groups = geometry.groups;\n\n\t\t\tgeometry.groupsNeedUpdate = false;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tfromGeometry: function ( geometry ) {\n\n\t\tgeometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );\n\n\t\treturn this.fromDirectGeometry( geometry.__directGeometry );\n\n\t},\n\n\tfromDirectGeometry: function ( geometry ) {\n\n\t\tvar positions = new Float32Array( geometry.vertices.length * 3 );\n\t\tthis.setAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );\n\n\t\tif ( geometry.normals.length > 0 ) {\n\n\t\t\tvar normals = new Float32Array( geometry.normals.length * 3 );\n\t\t\tthis.setAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );\n\n\t\t}\n\n\t\tif ( geometry.colors.length > 0 ) {\n\n\t\t\tvar colors = new Float32Array( geometry.colors.length * 3 );\n\t\t\tthis.setAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );\n\n\t\t}\n\n\t\tif ( geometry.uvs.length > 0 ) {\n\n\t\t\tvar uvs = new Float32Array( geometry.uvs.length * 2 );\n\t\t\tthis.setAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );\n\n\t\t}\n\n\t\tif ( geometry.uvs2.length > 0 ) {\n\n\t\t\tvar uvs2 = new Float32Array( geometry.uvs2.length * 2 );\n\t\t\tthis.setAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );\n\n\t\t}\n\n\t\t// groups\n\n\t\tthis.groups = geometry.groups;\n\n\t\t// morphs\n\n\t\tfor ( var name in geometry.morphTargets ) {\n\n\t\t\tvar array = [];\n\t\t\tvar morphTargets = geometry.morphTargets[ name ];\n\n\t\t\tfor ( var i = 0, l = morphTargets.length; i < l; i ++ ) {\n\n\t\t\t\tvar morphTarget = morphTargets[ i ];\n\n\t\t\t\tvar attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 );\n\t\t\t\tattribute.name = morphTarget.name;\n\n\t\t\t\tarray.push( attribute.copyVector3sArray( morphTarget.data ) );\n\n\t\t\t}\n\n\t\t\tthis.morphAttributes[ name ] = array;\n\n\t\t}\n\n\t\t// skinning\n\n\t\tif ( geometry.skinIndices.length > 0 ) {\n\n\t\t\tvar skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );\n\t\t\tthis.setAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );\n\n\t\t}\n\n\t\tif ( geometry.skinWeights.length > 0 ) {\n\n\t\t\tvar skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );\n\t\t\tthis.setAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );\n\n\t\t}\n\n\t\t//\n\n\t\tif ( geometry.boundingSphere !== null ) {\n\n\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\n\n\t\t}\n\n\t\tif ( geometry.boundingBox !== null ) {\n\n\t\t\tthis.boundingBox = geometry.boundingBox.clone();\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcomputeBoundingBox: function () {\n\n\t\tif ( this.boundingBox === null ) {\n\n\t\t\tthis.boundingBox = new Box3();\n\n\t\t}\n\n\t\tvar position = this.attributes.position;\n\t\tvar morphAttributesPosition = this.morphAttributes.position;\n\n\t\tif ( position !== undefined ) {\n\n\t\t\tthis.boundingBox.setFromBufferAttribute( position );\n\n\t\t\t// process morph attributes if present\n\n\t\t\tif ( morphAttributesPosition ) {\n\n\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\n\n\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\n\t\t\t\t\t_box.setFromBufferAttribute( morphAttribute );\n\n\t\t\t\t\tif ( this.morphTargetsRelative ) {\n\n\t\t\t\t\t\t_vector.addVectors( this.boundingBox.min, _box.min );\n\t\t\t\t\t\tthis.boundingBox.expandByPoint( _vector );\n\n\t\t\t\t\t\t_vector.addVectors( this.boundingBox.max, _box.max );\n\t\t\t\t\t\tthis.boundingBox.expandByPoint( _vector );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tthis.boundingBox.expandByPoint( _box.min );\n\t\t\t\t\t\tthis.boundingBox.expandByPoint( _box.max );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tthis.boundingBox.makeEmpty();\n\n\t\t}\n\n\t\tif ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The \"position\" attribute is likely to have NaN values.', this );\n\n\t\t}\n\n\t},\n\n\tcomputeBoundingSphere: function () {\n\n\t\tif ( this.boundingSphere === null ) {\n\n\t\t\tthis.boundingSphere = new Sphere();\n\n\t\t}\n\n\t\tvar position = this.attributes.position;\n\t\tvar morphAttributesPosition = this.morphAttributes.position;\n\n\t\tif ( position ) {\n\n\t\t\t// first, find the center of the bounding sphere\n\n\t\t\tvar center = this.boundingSphere.center;\n\n\t\t\t_box.setFromBufferAttribute( position );\n\n\t\t\t// process morph attributes if present\n\n\t\t\tif ( morphAttributesPosition ) {\n\n\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\n\n\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\n\t\t\t\t\t_boxMorphTargets.setFromBufferAttribute( morphAttribute );\n\n\t\t\t\t\tif ( this.morphTargetsRelative ) {\n\n\t\t\t\t\t\t_vector.addVectors( _box.min, _boxMorphTargets.min );\n\t\t\t\t\t\t_box.expandByPoint( _vector );\n\n\t\t\t\t\t\t_vector.addVectors( _box.max, _boxMorphTargets.max );\n\t\t\t\t\t\t_box.expandByPoint( _vector );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t_box.expandByPoint( _boxMorphTargets.min );\n\t\t\t\t\t\t_box.expandByPoint( _boxMorphTargets.max );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t_box.getCenter( center );\n\n\t\t\t// second, try to find a boundingSphere with a radius smaller than the\n\t\t\t// boundingSphere of the boundingBox: sqrt(3) smaller in the best case\n\n\t\t\tvar maxRadiusSq = 0;\n\n\t\t\tfor ( var i = 0, il = position.count; i < il; i ++ ) {\n\n\t\t\t\t_vector.fromBufferAttribute( position, i );\n\n\t\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) );\n\n\t\t\t}\n\n\t\t\t// process morph attributes if present\n\n\t\t\tif ( morphAttributesPosition ) {\n\n\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\n\n\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\n\t\t\t\t\tvar morphTargetsRelative = this.morphTargetsRelative;\n\n\t\t\t\t\tfor ( var j = 0, jl = morphAttribute.count; j < jl; j ++ ) {\n\n\t\t\t\t\t\t_vector.fromBufferAttribute( morphAttribute, j );\n\n\t\t\t\t\t\tif ( morphTargetsRelative ) {\n\n\t\t\t\t\t\t\t_offset.fromBufferAttribute( position, j );\n\t\t\t\t\t\t\t_vector.add( _offset );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.boundingSphere.radius = Math.sqrt( maxRadiusSq );\n\n\t\t\tif ( isNaN( this.boundingSphere.radius ) ) {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The \"position\" attribute is likely to have NaN values.', this );\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\tcomputeFaceNormals: function () {\n\n\t\t// backwards compatibility\n\n\t},\n\n\tcomputeVertexNormals: function () {\n\n\t\tvar index = this.index;\n\t\tvar attributes = this.attributes;\n\n\t\tif ( attributes.position ) {\n\n\t\t\tvar positions = attributes.position.array;\n\n\t\t\tif ( attributes.normal === undefined ) {\n\n\t\t\t\tthis.setAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );\n\n\t\t\t} else {\n\n\t\t\t\t// reset existing normals to zero\n\n\t\t\t\tvar array = attributes.normal.array;\n\n\t\t\t\tfor ( var i = 0, il = array.length; i < il; i ++ ) {\n\n\t\t\t\t\tarray[ i ] = 0;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar normals = attributes.normal.array;\n\n\t\t\tvar vA, vB, vC;\n\t\t\tvar pA = new Vector3(), pB = new Vector3(), pC = new Vector3();\n\t\t\tvar cb = new Vector3(), ab = new Vector3();\n\n\t\t\t// indexed elements\n\n\t\t\tif ( index ) {\n\n\t\t\t\tvar indices = index.array;\n\n\t\t\t\tfor ( var i = 0, il = index.count; i < il; i += 3 ) {\n\n\t\t\t\t\tvA = indices[ i + 0 ] * 3;\n\t\t\t\t\tvB = indices[ i + 1 ] * 3;\n\t\t\t\t\tvC = indices[ i + 2 ] * 3;\n\n\t\t\t\t\tpA.fromArray( positions, vA );\n\t\t\t\t\tpB.fromArray( positions, vB );\n\t\t\t\t\tpC.fromArray( positions, vC );\n\n\t\t\t\t\tcb.subVectors( pC, pB );\n\t\t\t\t\tab.subVectors( pA, pB );\n\t\t\t\t\tcb.cross( ab );\n\n\t\t\t\t\tnormals[ vA ] += cb.x;\n\t\t\t\t\tnormals[ vA + 1 ] += cb.y;\n\t\t\t\t\tnormals[ vA + 2 ] += cb.z;\n\n\t\t\t\t\tnormals[ vB ] += cb.x;\n\t\t\t\t\tnormals[ vB + 1 ] += cb.y;\n\t\t\t\t\tnormals[ vB + 2 ] += cb.z;\n\n\t\t\t\t\tnormals[ vC ] += cb.x;\n\t\t\t\t\tnormals[ vC + 1 ] += cb.y;\n\t\t\t\t\tnormals[ vC + 2 ] += cb.z;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t// non-indexed elements (unconnected triangle soup)\n\n\t\t\t\tfor ( var i = 0, il = positions.length; i < il; i += 9 ) {\n\n\t\t\t\t\tpA.fromArray( positions, i );\n\t\t\t\t\tpB.fromArray( positions, i + 3 );\n\t\t\t\t\tpC.fromArray( positions, i + 6 );\n\n\t\t\t\t\tcb.subVectors( pC, pB );\n\t\t\t\t\tab.subVectors( pA, pB );\n\t\t\t\t\tcb.cross( ab );\n\n\t\t\t\t\tnormals[ i ] = cb.x;\n\t\t\t\t\tnormals[ i + 1 ] = cb.y;\n\t\t\t\t\tnormals[ i + 2 ] = cb.z;\n\n\t\t\t\t\tnormals[ i + 3 ] = cb.x;\n\t\t\t\t\tnormals[ i + 4 ] = cb.y;\n\t\t\t\t\tnormals[ i + 5 ] = cb.z;\n\n\t\t\t\t\tnormals[ i + 6 ] = cb.x;\n\t\t\t\t\tnormals[ i + 7 ] = cb.y;\n\t\t\t\t\tnormals[ i + 8 ] = cb.z;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.normalizeNormals();\n\n\t\t\tattributes.normal.needsUpdate = true;\n\n\t\t}\n\n\t},\n\n\tmerge: function ( geometry, offset ) {\n\n\t\tif ( ! ( geometry && geometry.isBufferGeometry ) ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( offset === undefined ) {\n\n\t\t\toffset = 0;\n\n\t\t\tconsole.warn(\n\t\t\t\t'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '\n\t\t\t\t+ 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'\n\t\t\t);\n\n\t\t}\n\n\t\tvar attributes = this.attributes;\n\n\t\tfor ( var key in attributes ) {\n\n\t\t\tif ( geometry.attributes[ key ] === undefined ) continue;\n\n\t\t\tvar attribute1 = attributes[ key ];\n\t\t\tvar attributeArray1 = attribute1.array;\n\n\t\t\tvar attribute2 = geometry.attributes[ key ];\n\t\t\tvar attributeArray2 = attribute2.array;\n\n\t\t\tvar attributeOffset = attribute2.itemSize * offset;\n\t\t\tvar length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );\n\n\t\t\tfor ( var i = 0, j = attributeOffset; i < length; i ++, j ++ ) {\n\n\t\t\t\tattributeArray1[ j ] = attributeArray2[ i ];\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tnormalizeNormals: function () {\n\n\t\tvar normals = this.attributes.normal;\n\n\t\tfor ( var i = 0, il = normals.count; i < il; i ++ ) {\n\n\t\t\t_vector.x = normals.getX( i );\n\t\t\t_vector.y = normals.getY( i );\n\t\t\t_vector.z = normals.getZ( i );\n\n\t\t\t_vector.normalize();\n\n\t\t\tnormals.setXYZ( i, _vector.x, _vector.y, _vector.z );\n\n\t\t}\n\n\t},\n\n\ttoNonIndexed: function () {\n\n\t\tfunction convertBufferAttribute( attribute, indices ) {\n\n\t\t\tvar array = attribute.array;\n\t\t\tvar itemSize = attribute.itemSize;\n\t\t\tvar normalized = attribute.normalized;\n\n\t\t\tvar array2 = new array.constructor( indices.length * itemSize );\n\n\t\t\tvar index = 0, index2 = 0;\n\n\t\t\tfor ( var i = 0, l = indices.length; i < l; i ++ ) {\n\n\t\t\t\tindex = indices[ i ] * itemSize;\n\n\t\t\t\tfor ( var j = 0; j < itemSize; j ++ ) {\n\n\t\t\t\t\tarray2[ index2 ++ ] = array[ index ++ ];\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn new BufferAttribute( array2, itemSize, normalized );\n\n\t\t}\n\n\t\t//\n\n\t\tif ( this.index === null ) {\n\n\t\t\tconsole.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );\n\t\t\treturn this;\n\n\t\t}\n\n\t\tvar geometry2 = new BufferGeometry();\n\n\t\tvar indices = this.index.array;\n\t\tvar attributes = this.attributes;\n\n\t\t// attributes\n\n\t\tfor ( var name in attributes ) {\n\n\t\t\tvar attribute = attributes[ name ];\n\n\t\t\tvar newAttribute = convertBufferAttribute( attribute, indices );\n\n\t\t\tgeometry2.setAttribute( name, newAttribute );\n\n\t\t}\n\n\t\t// morph attributes\n\n\t\tvar morphAttributes = this.morphAttributes;\n\n\t\tfor ( name in morphAttributes ) {\n\n\t\t\tvar morphArray = [];\n\t\t\tvar morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes\n\n\t\t\tfor ( var i = 0, il = morphAttribute.length; i < il; i ++ ) {\n\n\t\t\t\tvar attribute = morphAttribute[ i ];\n\n\t\t\t\tvar newAttribute = convertBufferAttribute( attribute, indices );\n\n\t\t\t\tmorphArray.push( newAttribute );\n\n\t\t\t}\n\n\t\t\tgeometry2.morphAttributes[ name ] = morphArray;\n\n\t\t}\n\n\t\tgeometry2.morphTargetsRelative = this.morphTargetsRelative;\n\n\t\t// groups\n\n\t\tvar groups = this.groups;\n\n\t\tfor ( var i = 0, l = groups.length; i < l; i ++ ) {\n\n\t\t\tvar group = groups[ i ];\n\t\t\tgeometry2.addGroup( group.start, group.count, group.materialIndex );\n\n\t\t}\n\n\t\treturn geometry2;\n\n\t},\n\n\ttoJSON: function () {\n\n\t\tvar data = {\n\t\t\tmetadata: {\n\t\t\t\tversion: 4.5,\n\t\t\t\ttype: 'BufferGeometry',\n\t\t\t\tgenerator: 'BufferGeometry.toJSON'\n\t\t\t}\n\t\t};\n\n\t\t// standard BufferGeometry serialization\n\n\t\tdata.uuid = this.uuid;\n\t\tdata.type = this.type;\n\t\tif ( this.name !== '' ) data.name = this.name;\n\t\tif ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;\n\n\t\tif ( this.parameters !== undefined ) {\n\n\t\t\tvar parameters = this.parameters;\n\n\t\t\tfor ( var key in parameters ) {\n\n\t\t\t\tif ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tdata.data = { attributes: {} };\n\n\t\tvar index = this.index;\n\n\t\tif ( index !== null ) {\n\n\t\t\tdata.data.index = {\n\t\t\t\ttype: index.array.constructor.name,\n\t\t\t\tarray: Array.prototype.slice.call( index.array )\n\t\t\t};\n\n\t\t}\n\n\t\tvar attributes = this.attributes;\n\n\t\tfor ( var key in attributes ) {\n\n\t\t\tvar attribute = attributes[ key ];\n\n\t\t\tvar attributeData = attribute.toJSON();\n\n\t\t\tif ( attribute.name !== '' ) attributeData.name = attribute.name;\n\n\t\t\tdata.data.attributes[ key ] = attributeData;\n\n\t\t}\n\n\t\tvar morphAttributes = {};\n\t\tvar hasMorphAttributes = false;\n\n\t\tfor ( var key in this.morphAttributes ) {\n\n\t\t\tvar attributeArray = this.morphAttributes[ key ];\n\n\t\t\tvar array = [];\n\n\t\t\tfor ( var i = 0, il = attributeArray.length; i < il; i ++ ) {\n\n\t\t\t\tvar attribute = attributeArray[ i ];\n\n\t\t\t\tvar attributeData = attribute.toJSON();\n\n\t\t\t\tif ( attribute.name !== '' ) attributeData.name = attribute.name;\n\n\t\t\t\tarray.push( attributeData );\n\n\t\t\t}\n\n\t\t\tif ( array.length > 0 ) {\n\n\t\t\t\tmorphAttributes[ key ] = array;\n\n\t\t\t\thasMorphAttributes = true;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( hasMorphAttributes ) {\n\n\t\t\tdata.data.morphAttributes = morphAttributes;\n\t\t\tdata.data.morphTargetsRelative = this.morphTargetsRelative;\n\n\t\t}\n\n\t\tvar groups = this.groups;\n\n\t\tif ( groups.length > 0 ) {\n\n\t\t\tdata.data.groups = JSON.parse( JSON.stringify( groups ) );\n\n\t\t}\n\n\t\tvar boundingSphere = this.boundingSphere;\n\n\t\tif ( boundingSphere !== null ) {\n\n\t\t\tdata.data.boundingSphere = {\n\t\t\t\tcenter: boundingSphere.center.toArray(),\n\t\t\t\tradius: boundingSphere.radius\n\t\t\t};\n\n\t\t}\n\n\t\treturn data;\n\n\t},\n\n\tclone: function () {\n\n\t\t/*\n\t\t // Handle primitives\n\n\t\t var parameters = this.parameters;\n\n\t\t if ( parameters !== undefined ) {\n\n\t\t var values = [];\n\n\t\t for ( var key in parameters ) {\n\n\t\t values.push( parameters[ key ] );\n\n\t\t }\n\n\t\t var geometry = Object.create( this.constructor.prototype );\n\t\t this.constructor.apply( geometry, values );\n\t\t return geometry;\n\n\t\t }\n\n\t\t return new this.constructor().copy( this );\n\t\t */\n\n\t\treturn new BufferGeometry().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tvar name, i, l;\n\n\t\t// reset\n\n\t\tthis.index = null;\n\t\tthis.attributes = {};\n\t\tthis.morphAttributes = {};\n\t\tthis.groups = [];\n\t\tthis.boundingBox = null;\n\t\tthis.boundingSphere = null;\n\n\t\t// name\n\n\t\tthis.name = source.name;\n\n\t\t// index\n\n\t\tvar index = source.index;\n\n\t\tif ( index !== null ) {\n\n\t\t\tthis.setIndex( index.clone() );\n\n\t\t}\n\n\t\t// attributes\n\n\t\tvar attributes = source.attributes;\n\n\t\tfor ( name in attributes ) {\n\n\t\t\tvar attribute = attributes[ name ];\n\t\t\tthis.setAttribute( name, attribute.clone() );\n\n\t\t}\n\n\t\t// morph attributes\n\n\t\tvar morphAttributes = source.morphAttributes;\n\n\t\tfor ( name in morphAttributes ) {\n\n\t\t\tvar array = [];\n\t\t\tvar morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes\n\n\t\t\tfor ( i = 0, l = morphAttribute.length; i < l; i ++ ) {\n\n\t\t\t\tarray.push( morphAttribute[ i ].clone() );\n\n\t\t\t}\n\n\t\t\tthis.morphAttributes[ name ] = array;\n\n\t\t}\n\n\t\tthis.morphTargetsRelative = source.morphTargetsRelative;\n\n\t\t// groups\n\n\t\tvar groups = source.groups;\n\n\t\tfor ( i = 0, l = groups.length; i < l; i ++ ) {\n\n\t\t\tvar group = groups[ i ];\n\t\t\tthis.addGroup( group.start, group.count, group.materialIndex );\n\n\t\t}\n\n\t\t// bounding box\n\n\t\tvar boundingBox = source.boundingBox;\n\n\t\tif ( boundingBox !== null ) {\n\n\t\t\tthis.boundingBox = boundingBox.clone();\n\n\t\t}\n\n\t\t// bounding sphere\n\n\t\tvar boundingSphere = source.boundingSphere;\n\n\t\tif ( boundingSphere !== null ) {\n\n\t\t\tthis.boundingSphere = boundingSphere.clone();\n\n\t\t}\n\n\t\t// draw range\n\n\t\tthis.drawRange.start = source.drawRange.start;\n\t\tthis.drawRange.count = source.drawRange.count;\n\n\t\t// user data\n\n\t\tthis.userData = source.userData;\n\n\t\treturn this;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t}\n\n} );\n\n\nexport { BufferGeometry };\n","import { Vector3 } from '../math/Vector3.js';\nimport { Vector2 } from '../math/Vector2.js';\nimport { Sphere } from '../math/Sphere.js';\nimport { Ray } from '../math/Ray.js';\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { Object3D } from '../core/Object3D.js';\nimport { Triangle } from '../math/Triangle.js';\nimport { Face3 } from '../core/Face3.js';\nimport { DoubleSide, BackSide } from '../constants.js';\nimport { MeshBasicMaterial } from '../materials/MeshBasicMaterial.js';\nimport { BufferGeometry } from '../core/BufferGeometry.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author mikael emtinger / http://gomo.se/\n * @author jonobr1 / http://jonobr1.com/\n */\n\nvar _inverseMatrix = new Matrix4();\nvar _ray = new Ray();\nvar _sphere = new Sphere();\n\nvar _vA = new Vector3();\nvar _vB = new Vector3();\nvar _vC = new Vector3();\n\nvar _tempA = new Vector3();\nvar _tempB = new Vector3();\nvar _tempC = new Vector3();\n\nvar _morphA = new Vector3();\nvar _morphB = new Vector3();\nvar _morphC = new Vector3();\n\nvar _uvA = new Vector2();\nvar _uvB = new Vector2();\nvar _uvC = new Vector2();\n\nvar _intersectionPoint = new Vector3();\nvar _intersectionPointWorld = new Vector3();\n\nfunction Mesh( geometry, material ) {\n\n\tObject3D.call( this );\n\n\tthis.type = 'Mesh';\n\n\tthis.geometry = geometry !== undefined ? geometry : new BufferGeometry();\n\tthis.material = material !== undefined ? material : new MeshBasicMaterial();\n\n\tthis.updateMorphTargets();\n\n}\n\nMesh.prototype = Object.assign( Object.create( Object3D.prototype ), {\n\n\tconstructor: Mesh,\n\n\tisMesh: true,\n\n\tcopy: function ( source ) {\n\n\t\tObject3D.prototype.copy.call( this, source );\n\n\t\tif ( source.morphTargetInfluences !== undefined ) {\n\n\t\t\tthis.morphTargetInfluences = source.morphTargetInfluences.slice();\n\n\t\t}\n\n\t\tif ( source.morphTargetDictionary !== undefined ) {\n\n\t\t\tthis.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tupdateMorphTargets: function () {\n\n\t\tvar geometry = this.geometry;\n\t\tvar m, ml, name;\n\n\t\tif ( geometry.isBufferGeometry ) {\n\n\t\t\tvar morphAttributes = geometry.morphAttributes;\n\t\t\tvar keys = Object.keys( morphAttributes );\n\n\t\t\tif ( keys.length > 0 ) {\n\n\t\t\t\tvar morphAttribute = morphAttributes[ keys[ 0 ] ];\n\n\t\t\t\tif ( morphAttribute !== undefined ) {\n\n\t\t\t\t\tthis.morphTargetInfluences = [];\n\t\t\t\t\tthis.morphTargetDictionary = {};\n\n\t\t\t\t\tfor ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {\n\n\t\t\t\t\t\tname = morphAttribute[ m ].name || String( m );\n\n\t\t\t\t\t\tthis.morphTargetInfluences.push( 0 );\n\t\t\t\t\t\tthis.morphTargetDictionary[ name ] = m;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tvar morphTargets = geometry.morphTargets;\n\n\t\t\tif ( morphTargets !== undefined && morphTargets.length > 0 ) {\n\n\t\t\t\tconsole.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\traycast: function ( raycaster, intersects ) {\n\n\t\tvar geometry = this.geometry;\n\t\tvar material = this.material;\n\t\tvar matrixWorld = this.matrixWorld;\n\n\t\tif ( material === undefined ) return;\n\n\t\t// Checking boundingSphere distance to ray\n\n\t\tif ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();\n\n\t\t_sphere.copy( geometry.boundingSphere );\n\t\t_sphere.applyMatrix4( matrixWorld );\n\n\t\tif ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;\n\n\t\t//\n\n\t\t_inverseMatrix.getInverse( matrixWorld );\n\t\t_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );\n\n\t\t// Check boundingBox before continuing\n\n\t\tif ( geometry.boundingBox !== null ) {\n\n\t\t\tif ( _ray.intersectsBox( geometry.boundingBox ) === false ) return;\n\n\t\t}\n\n\t\tvar intersection;\n\n\t\tif ( geometry.isBufferGeometry ) {\n\n\t\t\tvar a, b, c;\n\t\t\tvar index = geometry.index;\n\t\t\tvar position = geometry.attributes.position;\n\t\t\tvar morphPosition = geometry.morphAttributes.position;\n\t\t\tvar morphTargetsRelative = geometry.morphTargetsRelative;\n\t\t\tvar uv = geometry.attributes.uv;\n\t\t\tvar uv2 = geometry.attributes.uv2;\n\t\t\tvar groups = geometry.groups;\n\t\t\tvar drawRange = geometry.drawRange;\n\t\t\tvar i, j, il, jl;\n\t\t\tvar group, groupMaterial;\n\t\t\tvar start, end;\n\n\t\t\tif ( index !== null ) {\n\n\t\t\t\t// indexed buffer geometry\n\n\t\t\t\tif ( Array.isArray( material ) ) {\n\n\t\t\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\n\n\t\t\t\t\t\tgroup = groups[ i ];\n\t\t\t\t\t\tgroupMaterial = material[ group.materialIndex ];\n\n\t\t\t\t\t\tstart = Math.max( group.start, drawRange.start );\n\t\t\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\n\n\t\t\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\n\n\t\t\t\t\t\t\ta = index.getX( j );\n\t\t\t\t\t\t\tb = index.getX( j + 1 );\n\t\t\t\t\t\t\tc = index.getX( j + 2 );\n\n\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\n\n\t\t\t\t\t\t\tif ( intersection ) {\n\n\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics\n\t\t\t\t\t\t\t\tintersection.face.materialIndex = group.materialIndex;\n\t\t\t\t\t\t\t\tintersects.push( intersection );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tstart = Math.max( 0, drawRange.start );\n\t\t\t\t\tend = Math.min( index.count, ( drawRange.start + drawRange.count ) );\n\n\t\t\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\n\n\t\t\t\t\t\ta = index.getX( i );\n\t\t\t\t\t\tb = index.getX( i + 1 );\n\t\t\t\t\t\tc = index.getX( i + 2 );\n\n\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\n\n\t\t\t\t\t\tif ( intersection ) {\n\n\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics\n\t\t\t\t\t\t\tintersects.push( intersection );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( position !== undefined ) {\n\n\t\t\t\t// non-indexed buffer geometry\n\n\t\t\t\tif ( Array.isArray( material ) ) {\n\n\t\t\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\n\n\t\t\t\t\t\tgroup = groups[ i ];\n\t\t\t\t\t\tgroupMaterial = material[ group.materialIndex ];\n\n\t\t\t\t\t\tstart = Math.max( group.start, drawRange.start );\n\t\t\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\n\n\t\t\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\n\n\t\t\t\t\t\t\ta = j;\n\t\t\t\t\t\t\tb = j + 1;\n\t\t\t\t\t\t\tc = j + 2;\n\n\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\n\n\t\t\t\t\t\t\tif ( intersection ) {\n\n\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics\n\t\t\t\t\t\t\t\tintersection.face.materialIndex = group.materialIndex;\n\t\t\t\t\t\t\t\tintersects.push( intersection );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tstart = Math.max( 0, drawRange.start );\n\t\t\t\t\tend = Math.min( position.count, ( drawRange.start + drawRange.count ) );\n\n\t\t\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\n\n\t\t\t\t\t\ta = i;\n\t\t\t\t\t\tb = i + 1;\n\t\t\t\t\t\tc = i + 2;\n\n\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\n\n\t\t\t\t\t\tif ( intersection ) {\n\n\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics\n\t\t\t\t\t\t\tintersects.push( intersection );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else if ( geometry.isGeometry ) {\n\n\t\t\tvar fvA, fvB, fvC;\n\t\t\tvar isMultiMaterial = Array.isArray( material );\n\n\t\t\tvar vertices = geometry.vertices;\n\t\t\tvar faces = geometry.faces;\n\t\t\tvar uvs;\n\n\t\t\tvar faceVertexUvs = geometry.faceVertexUvs[ 0 ];\n\t\t\tif ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;\n\n\t\t\tfor ( var f = 0, fl = faces.length; f < fl; f ++ ) {\n\n\t\t\t\tvar face = faces[ f ];\n\t\t\t\tvar faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;\n\n\t\t\t\tif ( faceMaterial === undefined ) continue;\n\n\t\t\t\tfvA = vertices[ face.a ];\n\t\t\t\tfvB = vertices[ face.b ];\n\t\t\t\tfvC = vertices[ face.c ];\n\n\t\t\t\tintersection = checkIntersection( this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint );\n\n\t\t\t\tif ( intersection ) {\n\n\t\t\t\t\tif ( uvs && uvs[ f ] ) {\n\n\t\t\t\t\t\tvar uvs_f = uvs[ f ];\n\t\t\t\t\t\t_uvA.copy( uvs_f[ 0 ] );\n\t\t\t\t\t\t_uvB.copy( uvs_f[ 1 ] );\n\t\t\t\t\t\t_uvC.copy( uvs_f[ 2 ] );\n\n\t\t\t\t\t\tintersection.uv = Triangle.getUV( _intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2() );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tintersection.face = face;\n\t\t\t\t\tintersection.faceIndex = f;\n\t\t\t\t\tintersects.push( intersection );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.geometry, this.material ).copy( this );\n\n\t}\n\n} );\n\nfunction checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {\n\n\tvar intersect;\n\n\tif ( material.side === BackSide ) {\n\n\t\tintersect = ray.intersectTriangle( pC, pB, pA, true, point );\n\n\t} else {\n\n\t\tintersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );\n\n\t}\n\n\tif ( intersect === null ) return null;\n\n\t_intersectionPointWorld.copy( point );\n\t_intersectionPointWorld.applyMatrix4( object.matrixWorld );\n\n\tvar distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );\n\n\tif ( distance < raycaster.near || distance > raycaster.far ) return null;\n\n\treturn {\n\t\tdistance: distance,\n\t\tpoint: _intersectionPointWorld.clone(),\n\t\tobject: object\n\t};\n\n}\n\nfunction checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c ) {\n\n\t_vA.fromBufferAttribute( position, a );\n\t_vB.fromBufferAttribute( position, b );\n\t_vC.fromBufferAttribute( position, c );\n\n\tvar morphInfluences = object.morphTargetInfluences;\n\n\tif ( material.morphTargets && morphPosition && morphInfluences ) {\n\n\t\t_morphA.set( 0, 0, 0 );\n\t\t_morphB.set( 0, 0, 0 );\n\t\t_morphC.set( 0, 0, 0 );\n\n\t\tfor ( var i = 0, il = morphPosition.length; i < il; i ++ ) {\n\n\t\t\tvar influence = morphInfluences[ i ];\n\t\t\tvar morphAttribute = morphPosition[ i ];\n\n\t\t\tif ( influence === 0 ) continue;\n\n\t\t\t_tempA.fromBufferAttribute( morphAttribute, a );\n\t\t\t_tempB.fromBufferAttribute( morphAttribute, b );\n\t\t\t_tempC.fromBufferAttribute( morphAttribute, c );\n\n\t\t\tif ( morphTargetsRelative ) {\n\n\t\t\t\t_morphA.addScaledVector( _tempA, influence );\n\t\t\t\t_morphB.addScaledVector( _tempB, influence );\n\t\t\t\t_morphC.addScaledVector( _tempC, influence );\n\n\t\t\t} else {\n\n\t\t\t\t_morphA.addScaledVector( _tempA.sub( _vA ), influence );\n\t\t\t\t_morphB.addScaledVector( _tempB.sub( _vB ), influence );\n\t\t\t\t_morphC.addScaledVector( _tempC.sub( _vC ), influence );\n\n\t\t\t}\n\n\t\t}\n\n\t\t_vA.add( _morphA );\n\t\t_vB.add( _morphB );\n\t\t_vC.add( _morphC );\n\n\t}\n\n\tif ( object.isSkinnedMesh ) {\n\n\t\tobject.boneTransform( a, _vA );\n\t\tobject.boneTransform( b, _vB );\n\t\tobject.boneTransform( c, _vC );\n\n\t}\n\n\tvar intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );\n\n\tif ( intersection ) {\n\n\t\tif ( uv ) {\n\n\t\t\t_uvA.fromBufferAttribute( uv, a );\n\t\t\t_uvB.fromBufferAttribute( uv, b );\n\t\t\t_uvC.fromBufferAttribute( uv, c );\n\n\t\t\tintersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );\n\n\t\t}\n\n\t\tif ( uv2 ) {\n\n\t\t\t_uvA.fromBufferAttribute( uv2, a );\n\t\t\t_uvB.fromBufferAttribute( uv2, b );\n\t\t\t_uvC.fromBufferAttribute( uv2, c );\n\n\t\t\tintersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );\n\n\t\t}\n\n\t\tvar face = new Face3( a, b, c );\n\t\tTriangle.getNormal( _vA, _vB, _vC, face.normal );\n\n\t\tintersection.face = face;\n\n\t}\n\n\treturn intersection;\n\n}\n\nexport { Mesh };\n","import { EventDispatcher } from './EventDispatcher.js';\nimport { Face3 } from './Face3.js';\nimport { Matrix3 } from '../math/Matrix3.js';\nimport { Sphere } from '../math/Sphere.js';\nimport { Box3 } from '../math/Box3.js';\nimport { Vector3 } from '../math/Vector3.js';\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { Vector2 } from '../math/Vector2.js';\nimport { Color } from '../math/Color.js';\nimport { Object3D } from './Object3D.js';\nimport { MathUtils } from '../math/MathUtils.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author kile / http://kile.stravaganza.org/\n * @author alteredq / http://alteredqualia.com/\n * @author mikael emtinger / http://gomo.se/\n * @author zz85 / http://www.lab4games.net/zz85/blog\n * @author bhouston / http://clara.io\n */\n\nvar _geometryId = 0; // Geometry uses even numbers as Id\nvar _m1 = new Matrix4();\nvar _obj = new Object3D();\nvar _offset = new Vector3();\n\nfunction Geometry() {\n\n\tObject.defineProperty( this, 'id', { value: _geometryId += 2 } );\n\n\tthis.uuid = MathUtils.generateUUID();\n\n\tthis.name = '';\n\tthis.type = 'Geometry';\n\n\tthis.vertices = [];\n\tthis.colors = [];\n\tthis.faces = [];\n\tthis.faceVertexUvs = [[]];\n\n\tthis.morphTargets = [];\n\tthis.morphNormals = [];\n\n\tthis.skinWeights = [];\n\tthis.skinIndices = [];\n\n\tthis.lineDistances = [];\n\n\tthis.boundingBox = null;\n\tthis.boundingSphere = null;\n\n\t// update flags\n\n\tthis.elementsNeedUpdate = false;\n\tthis.verticesNeedUpdate = false;\n\tthis.uvsNeedUpdate = false;\n\tthis.normalsNeedUpdate = false;\n\tthis.colorsNeedUpdate = false;\n\tthis.lineDistancesNeedUpdate = false;\n\tthis.groupsNeedUpdate = false;\n\n}\n\nGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: Geometry,\n\n\tisGeometry: true,\n\n\tapplyMatrix4: function ( matrix ) {\n\n\t\tvar normalMatrix = new Matrix3().getNormalMatrix( matrix );\n\n\t\tfor ( var i = 0, il = this.vertices.length; i < il; i ++ ) {\n\n\t\t\tvar vertex = this.vertices[ i ];\n\t\t\tvertex.applyMatrix4( matrix );\n\n\t\t}\n\n\t\tfor ( var i = 0, il = this.faces.length; i < il; i ++ ) {\n\n\t\t\tvar face = this.faces[ i ];\n\t\t\tface.normal.applyMatrix3( normalMatrix ).normalize();\n\n\t\t\tfor ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {\n\n\t\t\t\tface.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.boundingBox !== null ) {\n\n\t\t\tthis.computeBoundingBox();\n\n\t\t}\n\n\t\tif ( this.boundingSphere !== null ) {\n\n\t\t\tthis.computeBoundingSphere();\n\n\t\t}\n\n\t\tthis.verticesNeedUpdate = true;\n\t\tthis.normalsNeedUpdate = true;\n\n\t\treturn this;\n\n\t},\n\n\trotateX: function ( angle ) {\n\n\t\t// rotate geometry around world x-axis\n\n\t\t_m1.makeRotationX( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateY: function ( angle ) {\n\n\t\t// rotate geometry around world y-axis\n\n\t\t_m1.makeRotationY( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateZ: function ( angle ) {\n\n\t\t// rotate geometry around world z-axis\n\n\t\t_m1.makeRotationZ( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( x, y, z ) {\n\n\t\t// translate geometry\n\n\t\t_m1.makeTranslation( x, y, z );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\tscale: function ( x, y, z ) {\n\n\t\t// scale geometry\n\n\t\t_m1.makeScale( x, y, z );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\tlookAt: function ( vector ) {\n\n\t\t_obj.lookAt( vector );\n\n\t\t_obj.updateMatrix();\n\n\t\tthis.applyMatrix4( _obj.matrix );\n\n\t\treturn this;\n\n\t},\n\n\tfromBufferGeometry: function ( geometry ) {\n\n\t\tvar scope = this;\n\n\t\tvar indices = geometry.index !== null ? geometry.index.array : undefined;\n\t\tvar attributes = geometry.attributes;\n\n\t\tif ( attributes.position === undefined ) {\n\n\t\t\tconsole.error( 'THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.' );\n\t\t\treturn this;\n\n\t\t}\n\n\t\tvar positions = attributes.position.array;\n\t\tvar normals = attributes.normal !== undefined ? attributes.normal.array : undefined;\n\t\tvar colors = attributes.color !== undefined ? attributes.color.array : undefined;\n\t\tvar uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;\n\t\tvar uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;\n\n\t\tif ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];\n\n\t\tfor ( var i = 0; i < positions.length; i += 3 ) {\n\n\t\t\tscope.vertices.push( new Vector3().fromArray( positions, i ) );\n\n\t\t\tif ( colors !== undefined ) {\n\n\t\t\t\tscope.colors.push( new Color().fromArray( colors, i ) );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction addFace( a, b, c, materialIndex ) {\n\n\t\t\tvar vertexColors = ( colors === undefined ) ? [] : [\n\t\t\t\tscope.colors[ a ].clone(),\n\t\t\t\tscope.colors[ b ].clone(),\n\t\t\t\tscope.colors[ c ].clone() ];\n\n\t\t\tvar vertexNormals = ( normals === undefined ) ? [] : [\n\t\t\t\tnew Vector3().fromArray( normals, a * 3 ),\n\t\t\t\tnew Vector3().fromArray( normals, b * 3 ),\n\t\t\t\tnew Vector3().fromArray( normals, c * 3 )\n\t\t\t];\n\n\t\t\tvar face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );\n\n\t\t\tscope.faces.push( face );\n\n\t\t\tif ( uvs !== undefined ) {\n\n\t\t\t\tscope.faceVertexUvs[ 0 ].push( [\n\t\t\t\t\tnew Vector2().fromArray( uvs, a * 2 ),\n\t\t\t\t\tnew Vector2().fromArray( uvs, b * 2 ),\n\t\t\t\t\tnew Vector2().fromArray( uvs, c * 2 )\n\t\t\t\t] );\n\n\t\t\t}\n\n\t\t\tif ( uvs2 !== undefined ) {\n\n\t\t\t\tscope.faceVertexUvs[ 1 ].push( [\n\t\t\t\t\tnew Vector2().fromArray( uvs2, a * 2 ),\n\t\t\t\t\tnew Vector2().fromArray( uvs2, b * 2 ),\n\t\t\t\t\tnew Vector2().fromArray( uvs2, c * 2 )\n\t\t\t\t] );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar groups = geometry.groups;\n\n\t\tif ( groups.length > 0 ) {\n\n\t\t\tfor ( var i = 0; i < groups.length; i ++ ) {\n\n\t\t\t\tvar group = groups[ i ];\n\n\t\t\t\tvar start = group.start;\n\t\t\t\tvar count = group.count;\n\n\t\t\t\tfor ( var j = start, jl = start + count; j < jl; j += 3 ) {\n\n\t\t\t\t\tif ( indices !== undefined ) {\n\n\t\t\t\t\t\taddFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\taddFace( j, j + 1, j + 2, group.materialIndex );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif ( indices !== undefined ) {\n\n\t\t\t\tfor ( var i = 0; i < indices.length; i += 3 ) {\n\n\t\t\t\t\taddFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tfor ( var i = 0; i < positions.length / 3; i += 3 ) {\n\n\t\t\t\t\taddFace( i, i + 1, i + 2 );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis.computeFaceNormals();\n\n\t\tif ( geometry.boundingBox !== null ) {\n\n\t\t\tthis.boundingBox = geometry.boundingBox.clone();\n\n\t\t}\n\n\t\tif ( geometry.boundingSphere !== null ) {\n\n\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcenter: function () {\n\n\t\tthis.computeBoundingBox();\n\n\t\tthis.boundingBox.getCenter( _offset ).negate();\n\n\t\tthis.translate( _offset.x, _offset.y, _offset.z );\n\n\t\treturn this;\n\n\t},\n\n\tnormalize: function () {\n\n\t\tthis.computeBoundingSphere();\n\n\t\tvar center = this.boundingSphere.center;\n\t\tvar radius = this.boundingSphere.radius;\n\n\t\tvar s = radius === 0 ? 1 : 1.0 / radius;\n\n\t\tvar matrix = new Matrix4();\n\t\tmatrix.set(\n\t\t\ts, 0, 0, - s * center.x,\n\t\t\t0, s, 0, - s * center.y,\n\t\t\t0, 0, s, - s * center.z,\n\t\t\t0, 0, 0, 1\n\t\t);\n\n\t\tthis.applyMatrix4( matrix );\n\n\t\treturn this;\n\n\t},\n\n\tcomputeFaceNormals: function () {\n\n\t\tvar cb = new Vector3(), ab = new Vector3();\n\n\t\tfor ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\tvar face = this.faces[ f ];\n\n\t\t\tvar vA = this.vertices[ face.a ];\n\t\t\tvar vB = this.vertices[ face.b ];\n\t\t\tvar vC = this.vertices[ face.c ];\n\n\t\t\tcb.subVectors( vC, vB );\n\t\t\tab.subVectors( vA, vB );\n\t\t\tcb.cross( ab );\n\n\t\t\tcb.normalize();\n\n\t\t\tface.normal.copy( cb );\n\n\t\t}\n\n\t},\n\n\tcomputeVertexNormals: function ( areaWeighted ) {\n\n\t\tif ( areaWeighted === undefined ) areaWeighted = true;\n\n\t\tvar v, vl, f, fl, face, vertices;\n\n\t\tvertices = new Array( this.vertices.length );\n\n\t\tfor ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {\n\n\t\t\tvertices[ v ] = new Vector3();\n\n\t\t}\n\n\t\tif ( areaWeighted ) {\n\n\t\t\t// vertex normals weighted by triangle areas\n\t\t\t// http://www.iquilezles.org/www/articles/normals/normals.htm\n\n\t\t\tvar vA, vB, vC;\n\t\t\tvar cb = new Vector3(), ab = new Vector3();\n\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\t\tface = this.faces[ f ];\n\n\t\t\t\tvA = this.vertices[ face.a ];\n\t\t\t\tvB = this.vertices[ face.b ];\n\t\t\t\tvC = this.vertices[ face.c ];\n\n\t\t\t\tcb.subVectors( vC, vB );\n\t\t\t\tab.subVectors( vA, vB );\n\t\t\t\tcb.cross( ab );\n\n\t\t\t\tvertices[ face.a ].add( cb );\n\t\t\t\tvertices[ face.b ].add( cb );\n\t\t\t\tvertices[ face.c ].add( cb );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tthis.computeFaceNormals();\n\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\t\tface = this.faces[ f ];\n\n\t\t\t\tvertices[ face.a ].add( face.normal );\n\t\t\t\tvertices[ face.b ].add( face.normal );\n\t\t\t\tvertices[ face.c ].add( face.normal );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfor ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {\n\n\t\t\tvertices[ v ].normalize();\n\n\t\t}\n\n\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\tface = this.faces[ f ];\n\n\t\t\tvar vertexNormals = face.vertexNormals;\n\n\t\t\tif ( vertexNormals.length === 3 ) {\n\n\t\t\t\tvertexNormals[ 0 ].copy( vertices[ face.a ] );\n\t\t\t\tvertexNormals[ 1 ].copy( vertices[ face.b ] );\n\t\t\t\tvertexNormals[ 2 ].copy( vertices[ face.c ] );\n\n\t\t\t} else {\n\n\t\t\t\tvertexNormals[ 0 ] = vertices[ face.a ].clone();\n\t\t\t\tvertexNormals[ 1 ] = vertices[ face.b ].clone();\n\t\t\t\tvertexNormals[ 2 ] = vertices[ face.c ].clone();\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.faces.length > 0 ) {\n\n\t\t\tthis.normalsNeedUpdate = true;\n\n\t\t}\n\n\t},\n\n\tcomputeFlatVertexNormals: function () {\n\n\t\tvar f, fl, face;\n\n\t\tthis.computeFaceNormals();\n\n\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\tface = this.faces[ f ];\n\n\t\t\tvar vertexNormals = face.vertexNormals;\n\n\t\t\tif ( vertexNormals.length === 3 ) {\n\n\t\t\t\tvertexNormals[ 0 ].copy( face.normal );\n\t\t\t\tvertexNormals[ 1 ].copy( face.normal );\n\t\t\t\tvertexNormals[ 2 ].copy( face.normal );\n\n\t\t\t} else {\n\n\t\t\t\tvertexNormals[ 0 ] = face.normal.clone();\n\t\t\t\tvertexNormals[ 1 ] = face.normal.clone();\n\t\t\t\tvertexNormals[ 2 ] = face.normal.clone();\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.faces.length > 0 ) {\n\n\t\t\tthis.normalsNeedUpdate = true;\n\n\t\t}\n\n\t},\n\n\tcomputeMorphNormals: function () {\n\n\t\tvar i, il, f, fl, face;\n\n\t\t// save original normals\n\t\t// - create temp variables on first access\n\t\t// otherwise just copy (for faster repeated calls)\n\n\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\tface = this.faces[ f ];\n\n\t\t\tif ( ! face.__originalFaceNormal ) {\n\n\t\t\t\tface.__originalFaceNormal = face.normal.clone();\n\n\t\t\t} else {\n\n\t\t\t\tface.__originalFaceNormal.copy( face.normal );\n\n\t\t\t}\n\n\t\t\tif ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];\n\n\t\t\tfor ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {\n\n\t\t\t\tif ( ! face.__originalVertexNormals[ i ] ) {\n\n\t\t\t\t\tface.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();\n\n\t\t\t\t} else {\n\n\t\t\t\t\tface.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// use temp geometry to compute face and vertex normals for each morph\n\n\t\tvar tmpGeo = new Geometry();\n\t\ttmpGeo.faces = this.faces;\n\n\t\tfor ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {\n\n\t\t\t// create on first access\n\n\t\t\tif ( ! this.morphNormals[ i ] ) {\n\n\t\t\t\tthis.morphNormals[ i ] = {};\n\t\t\t\tthis.morphNormals[ i ].faceNormals = [];\n\t\t\t\tthis.morphNormals[ i ].vertexNormals = [];\n\n\t\t\t\tvar dstNormalsFace = this.morphNormals[ i ].faceNormals;\n\t\t\t\tvar dstNormalsVertex = this.morphNormals[ i ].vertexNormals;\n\n\t\t\t\tvar faceNormal, vertexNormals;\n\n\t\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\t\t\tfaceNormal = new Vector3();\n\t\t\t\t\tvertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };\n\n\t\t\t\t\tdstNormalsFace.push( faceNormal );\n\t\t\t\t\tdstNormalsVertex.push( vertexNormals );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar morphNormals = this.morphNormals[ i ];\n\n\t\t\t// set vertices to morph target\n\n\t\t\ttmpGeo.vertices = this.morphTargets[ i ].vertices;\n\n\t\t\t// compute morph normals\n\n\t\t\ttmpGeo.computeFaceNormals();\n\t\t\ttmpGeo.computeVertexNormals();\n\n\t\t\t// store morph normals\n\n\t\t\tvar faceNormal, vertexNormals;\n\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\t\tface = this.faces[ f ];\n\n\t\t\t\tfaceNormal = morphNormals.faceNormals[ f ];\n\t\t\t\tvertexNormals = morphNormals.vertexNormals[ f ];\n\n\t\t\t\tfaceNormal.copy( face.normal );\n\n\t\t\t\tvertexNormals.a.copy( face.vertexNormals[ 0 ] );\n\t\t\t\tvertexNormals.b.copy( face.vertexNormals[ 1 ] );\n\t\t\t\tvertexNormals.c.copy( face.vertexNormals[ 2 ] );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// restore original normals\n\n\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\tface = this.faces[ f ];\n\n\t\t\tface.normal = face.__originalFaceNormal;\n\t\t\tface.vertexNormals = face.__originalVertexNormals;\n\n\t\t}\n\n\t},\n\n\tcomputeBoundingBox: function () {\n\n\t\tif ( this.boundingBox === null ) {\n\n\t\t\tthis.boundingBox = new Box3();\n\n\t\t}\n\n\t\tthis.boundingBox.setFromPoints( this.vertices );\n\n\t},\n\n\tcomputeBoundingSphere: function () {\n\n\t\tif ( this.boundingSphere === null ) {\n\n\t\t\tthis.boundingSphere = new Sphere();\n\n\t\t}\n\n\t\tthis.boundingSphere.setFromPoints( this.vertices );\n\n\t},\n\n\tmerge: function ( geometry, matrix, materialIndexOffset ) {\n\n\t\tif ( ! ( geometry && geometry.isGeometry ) ) {\n\n\t\t\tconsole.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );\n\t\t\treturn;\n\n\t\t}\n\n\t\tvar normalMatrix,\n\t\t\tvertexOffset = this.vertices.length,\n\t\t\tvertices1 = this.vertices,\n\t\t\tvertices2 = geometry.vertices,\n\t\t\tfaces1 = this.faces,\n\t\t\tfaces2 = geometry.faces,\n\t\t\tcolors1 = this.colors,\n\t\t\tcolors2 = geometry.colors;\n\n\t\tif ( materialIndexOffset === undefined ) materialIndexOffset = 0;\n\n\t\tif ( matrix !== undefined ) {\n\n\t\t\tnormalMatrix = new Matrix3().getNormalMatrix( matrix );\n\n\t\t}\n\n\t\t// vertices\n\n\t\tfor ( var i = 0, il = vertices2.length; i < il; i ++ ) {\n\n\t\t\tvar vertex = vertices2[ i ];\n\n\t\t\tvar vertexCopy = vertex.clone();\n\n\t\t\tif ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );\n\n\t\t\tvertices1.push( vertexCopy );\n\n\t\t}\n\n\t\t// colors\n\n\t\tfor ( var i = 0, il = colors2.length; i < il; i ++ ) {\n\n\t\t\tcolors1.push( colors2[ i ].clone() );\n\n\t\t}\n\n\t\t// faces\n\n\t\tfor ( i = 0, il = faces2.length; i < il; i ++ ) {\n\n\t\t\tvar face = faces2[ i ], faceCopy, normal, color,\n\t\t\t\tfaceVertexNormals = face.vertexNormals,\n\t\t\t\tfaceVertexColors = face.vertexColors;\n\n\t\t\tfaceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );\n\t\t\tfaceCopy.normal.copy( face.normal );\n\n\t\t\tif ( normalMatrix !== undefined ) {\n\n\t\t\t\tfaceCopy.normal.applyMatrix3( normalMatrix ).normalize();\n\n\t\t\t}\n\n\t\t\tfor ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {\n\n\t\t\t\tnormal = faceVertexNormals[ j ].clone();\n\n\t\t\t\tif ( normalMatrix !== undefined ) {\n\n\t\t\t\t\tnormal.applyMatrix3( normalMatrix ).normalize();\n\n\t\t\t\t}\n\n\t\t\t\tfaceCopy.vertexNormals.push( normal );\n\n\t\t\t}\n\n\t\t\tfaceCopy.color.copy( face.color );\n\n\t\t\tfor ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {\n\n\t\t\t\tcolor = faceVertexColors[ j ];\n\t\t\t\tfaceCopy.vertexColors.push( color.clone() );\n\n\t\t\t}\n\n\t\t\tfaceCopy.materialIndex = face.materialIndex + materialIndexOffset;\n\n\t\t\tfaces1.push( faceCopy );\n\n\t\t}\n\n\t\t// uvs\n\n\t\tfor ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {\n\n\t\t\tvar faceVertexUvs2 = geometry.faceVertexUvs[ i ];\n\n\t\t\tif ( this.faceVertexUvs[ i ] === undefined ) this.faceVertexUvs[ i ] = [];\n\n\t\t\tfor ( var j = 0, jl = faceVertexUvs2.length; j < jl; j ++ ) {\n\n\t\t\t\tvar uvs2 = faceVertexUvs2[ j ], uvsCopy = [];\n\n\t\t\t\tfor ( var k = 0, kl = uvs2.length; k < kl; k ++ ) {\n\n\t\t\t\t\tuvsCopy.push( uvs2[ k ].clone() );\n\n\t\t\t\t}\n\n\t\t\t\tthis.faceVertexUvs[ i ].push( uvsCopy );\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\tmergeMesh: function ( mesh ) {\n\n\t\tif ( ! ( mesh && mesh.isMesh ) ) {\n\n\t\t\tconsole.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( mesh.matrixAutoUpdate ) mesh.updateMatrix();\n\n\t\tthis.merge( mesh.geometry, mesh.matrix );\n\n\t},\n\n\t/*\n\t * Checks for duplicate vertices with hashmap.\n\t * Duplicated vertices are removed\n\t * and faces' vertices are updated.\n\t */\n\n\tmergeVertices: function () {\n\n\t\tvar verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)\n\t\tvar unique = [], changes = [];\n\n\t\tvar v, key;\n\t\tvar precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001\n\t\tvar precision = Math.pow( 10, precisionPoints );\n\t\tvar i, il, face;\n\t\tvar indices, j, jl;\n\n\t\tfor ( i = 0, il = this.vertices.length; i < il; i ++ ) {\n\n\t\t\tv = this.vertices[ i ];\n\t\t\tkey = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );\n\n\t\t\tif ( verticesMap[ key ] === undefined ) {\n\n\t\t\t\tverticesMap[ key ] = i;\n\t\t\t\tunique.push( this.vertices[ i ] );\n\t\t\t\tchanges[ i ] = unique.length - 1;\n\n\t\t\t} else {\n\n\t\t\t\t//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);\n\t\t\t\tchanges[ i ] = changes[ verticesMap[ key ] ];\n\n\t\t\t}\n\n\t\t}\n\n\n\t\t// if faces are completely degenerate after merging vertices, we\n\t\t// have to remove them from the geometry.\n\t\tvar faceIndicesToRemove = [];\n\n\t\tfor ( i = 0, il = this.faces.length; i < il; i ++ ) {\n\n\t\t\tface = this.faces[ i ];\n\n\t\t\tface.a = changes[ face.a ];\n\t\t\tface.b = changes[ face.b ];\n\t\t\tface.c = changes[ face.c ];\n\n\t\t\tindices = [ face.a, face.b, face.c ];\n\n\t\t\t// if any duplicate vertices are found in a Face3\n\t\t\t// we have to remove the face as nothing can be saved\n\t\t\tfor ( var n = 0; n < 3; n ++ ) {\n\n\t\t\t\tif ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {\n\n\t\t\t\t\tfaceIndicesToRemove.push( i );\n\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfor ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {\n\n\t\t\tvar idx = faceIndicesToRemove[ i ];\n\n\t\t\tthis.faces.splice( idx, 1 );\n\n\t\t\tfor ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {\n\n\t\t\t\tthis.faceVertexUvs[ j ].splice( idx, 1 );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Use unique set of vertices\n\n\t\tvar diff = this.vertices.length - unique.length;\n\t\tthis.vertices = unique;\n\t\treturn diff;\n\n\t},\n\n\tsetFromPoints: function ( points ) {\n\n\t\tthis.vertices = [];\n\n\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\n\n\t\t\tvar point = points[ i ];\n\t\t\tthis.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsortFacesByMaterialIndex: function () {\n\n\t\tvar faces = this.faces;\n\t\tvar length = faces.length;\n\n\t\t// tag faces\n\n\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\tfaces[ i ]._id = i;\n\n\t\t}\n\n\t\t// sort faces\n\n\t\tfunction materialIndexSort( a, b ) {\n\n\t\t\treturn a.materialIndex - b.materialIndex;\n\n\t\t}\n\n\t\tfaces.sort( materialIndexSort );\n\n\t\t// sort uvs\n\n\t\tvar uvs1 = this.faceVertexUvs[ 0 ];\n\t\tvar uvs2 = this.faceVertexUvs[ 1 ];\n\n\t\tvar newUvs1, newUvs2;\n\n\t\tif ( uvs1 && uvs1.length === length ) newUvs1 = [];\n\t\tif ( uvs2 && uvs2.length === length ) newUvs2 = [];\n\n\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\tvar id = faces[ i ]._id;\n\n\t\t\tif ( newUvs1 ) newUvs1.push( uvs1[ id ] );\n\t\t\tif ( newUvs2 ) newUvs2.push( uvs2[ id ] );\n\n\t\t}\n\n\t\tif ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;\n\t\tif ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;\n\n\t},\n\n\ttoJSON: function () {\n\n\t\tvar data = {\n\t\t\tmetadata: {\n\t\t\t\tversion: 4.5,\n\t\t\t\ttype: 'Geometry',\n\t\t\t\tgenerator: 'Geometry.toJSON'\n\t\t\t}\n\t\t};\n\n\t\t// standard Geometry serialization\n\n\t\tdata.uuid = this.uuid;\n\t\tdata.type = this.type;\n\t\tif ( this.name !== '' ) data.name = this.name;\n\n\t\tif ( this.parameters !== undefined ) {\n\n\t\t\tvar parameters = this.parameters;\n\n\t\t\tfor ( var key in parameters ) {\n\n\t\t\t\tif ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tvar vertices = [];\n\n\t\tfor ( var i = 0; i < this.vertices.length; i ++ ) {\n\n\t\t\tvar vertex = this.vertices[ i ];\n\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\n\n\t\t}\n\n\t\tvar faces = [];\n\t\tvar normals = [];\n\t\tvar normalsHash = {};\n\t\tvar colors = [];\n\t\tvar colorsHash = {};\n\t\tvar uvs = [];\n\t\tvar uvsHash = {};\n\n\t\tfor ( var i = 0; i < this.faces.length; i ++ ) {\n\n\t\t\tvar face = this.faces[ i ];\n\n\t\t\tvar hasMaterial = true;\n\t\t\tvar hasFaceUv = false; // deprecated\n\t\t\tvar hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;\n\t\t\tvar hasFaceNormal = face.normal.length() > 0;\n\t\t\tvar hasFaceVertexNormal = face.vertexNormals.length > 0;\n\t\t\tvar hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;\n\t\t\tvar hasFaceVertexColor = face.vertexColors.length > 0;\n\n\t\t\tvar faceType = 0;\n\n\t\t\tfaceType = setBit( faceType, 0, 0 ); // isQuad\n\t\t\tfaceType = setBit( faceType, 1, hasMaterial );\n\t\t\tfaceType = setBit( faceType, 2, hasFaceUv );\n\t\t\tfaceType = setBit( faceType, 3, hasFaceVertexUv );\n\t\t\tfaceType = setBit( faceType, 4, hasFaceNormal );\n\t\t\tfaceType = setBit( faceType, 5, hasFaceVertexNormal );\n\t\t\tfaceType = setBit( faceType, 6, hasFaceColor );\n\t\t\tfaceType = setBit( faceType, 7, hasFaceVertexColor );\n\n\t\t\tfaces.push( faceType );\n\t\t\tfaces.push( face.a, face.b, face.c );\n\t\t\tfaces.push( face.materialIndex );\n\n\t\t\tif ( hasFaceVertexUv ) {\n\n\t\t\t\tvar faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];\n\n\t\t\t\tfaces.push(\n\t\t\t\t\tgetUvIndex( faceVertexUvs[ 0 ] ),\n\t\t\t\t\tgetUvIndex( faceVertexUvs[ 1 ] ),\n\t\t\t\t\tgetUvIndex( faceVertexUvs[ 2 ] )\n\t\t\t\t);\n\n\t\t\t}\n\n\t\t\tif ( hasFaceNormal ) {\n\n\t\t\t\tfaces.push( getNormalIndex( face.normal ) );\n\n\t\t\t}\n\n\t\t\tif ( hasFaceVertexNormal ) {\n\n\t\t\t\tvar vertexNormals = face.vertexNormals;\n\n\t\t\t\tfaces.push(\n\t\t\t\t\tgetNormalIndex( vertexNormals[ 0 ] ),\n\t\t\t\t\tgetNormalIndex( vertexNormals[ 1 ] ),\n\t\t\t\t\tgetNormalIndex( vertexNormals[ 2 ] )\n\t\t\t\t);\n\n\t\t\t}\n\n\t\t\tif ( hasFaceColor ) {\n\n\t\t\t\tfaces.push( getColorIndex( face.color ) );\n\n\t\t\t}\n\n\t\t\tif ( hasFaceVertexColor ) {\n\n\t\t\t\tvar vertexColors = face.vertexColors;\n\n\t\t\t\tfaces.push(\n\t\t\t\t\tgetColorIndex( vertexColors[ 0 ] ),\n\t\t\t\t\tgetColorIndex( vertexColors[ 1 ] ),\n\t\t\t\t\tgetColorIndex( vertexColors[ 2 ] )\n\t\t\t\t);\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction setBit( value, position, enabled ) {\n\n\t\t\treturn enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );\n\n\t\t}\n\n\t\tfunction getNormalIndex( normal ) {\n\n\t\t\tvar hash = normal.x.toString() + normal.y.toString() + normal.z.toString();\n\n\t\t\tif ( normalsHash[ hash ] !== undefined ) {\n\n\t\t\t\treturn normalsHash[ hash ];\n\n\t\t\t}\n\n\t\t\tnormalsHash[ hash ] = normals.length / 3;\n\t\t\tnormals.push( normal.x, normal.y, normal.z );\n\n\t\t\treturn normalsHash[ hash ];\n\n\t\t}\n\n\t\tfunction getColorIndex( color ) {\n\n\t\t\tvar hash = color.r.toString() + color.g.toString() + color.b.toString();\n\n\t\t\tif ( colorsHash[ hash ] !== undefined ) {\n\n\t\t\t\treturn colorsHash[ hash ];\n\n\t\t\t}\n\n\t\t\tcolorsHash[ hash ] = colors.length;\n\t\t\tcolors.push( color.getHex() );\n\n\t\t\treturn colorsHash[ hash ];\n\n\t\t}\n\n\t\tfunction getUvIndex( uv ) {\n\n\t\t\tvar hash = uv.x.toString() + uv.y.toString();\n\n\t\t\tif ( uvsHash[ hash ] !== undefined ) {\n\n\t\t\t\treturn uvsHash[ hash ];\n\n\t\t\t}\n\n\t\t\tuvsHash[ hash ] = uvs.length / 2;\n\t\t\tuvs.push( uv.x, uv.y );\n\n\t\t\treturn uvsHash[ hash ];\n\n\t\t}\n\n\t\tdata.data = {};\n\n\t\tdata.data.vertices = vertices;\n\t\tdata.data.normals = normals;\n\t\tif ( colors.length > 0 ) data.data.colors = colors;\n\t\tif ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility\n\t\tdata.data.faces = faces;\n\n\t\treturn data;\n\n\t},\n\n\tclone: function () {\n\n\t\t/*\n\t\t // Handle primitives\n\n\t\t var parameters = this.parameters;\n\n\t\t if ( parameters !== undefined ) {\n\n\t\t var values = [];\n\n\t\t for ( var key in parameters ) {\n\n\t\t values.push( parameters[ key ] );\n\n\t\t }\n\n\t\t var geometry = Object.create( this.constructor.prototype );\n\t\t this.constructor.apply( geometry, values );\n\t\t return geometry;\n\n\t\t }\n\n\t\t return new this.constructor().copy( this );\n\t\t */\n\n\t\treturn new Geometry().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tvar i, il, j, jl, k, kl;\n\n\t\t// reset\n\n\t\tthis.vertices = [];\n\t\tthis.colors = [];\n\t\tthis.faces = [];\n\t\tthis.faceVertexUvs = [[]];\n\t\tthis.morphTargets = [];\n\t\tthis.morphNormals = [];\n\t\tthis.skinWeights = [];\n\t\tthis.skinIndices = [];\n\t\tthis.lineDistances = [];\n\t\tthis.boundingBox = null;\n\t\tthis.boundingSphere = null;\n\n\t\t// name\n\n\t\tthis.name = source.name;\n\n\t\t// vertices\n\n\t\tvar vertices = source.vertices;\n\n\t\tfor ( i = 0, il = vertices.length; i < il; i ++ ) {\n\n\t\t\tthis.vertices.push( vertices[ i ].clone() );\n\n\t\t}\n\n\t\t// colors\n\n\t\tvar colors = source.colors;\n\n\t\tfor ( i = 0, il = colors.length; i < il; i ++ ) {\n\n\t\t\tthis.colors.push( colors[ i ].clone() );\n\n\t\t}\n\n\t\t// faces\n\n\t\tvar faces = source.faces;\n\n\t\tfor ( i = 0, il = faces.length; i < il; i ++ ) {\n\n\t\t\tthis.faces.push( faces[ i ].clone() );\n\n\t\t}\n\n\t\t// face vertex uvs\n\n\t\tfor ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {\n\n\t\t\tvar faceVertexUvs = source.faceVertexUvs[ i ];\n\n\t\t\tif ( this.faceVertexUvs[ i ] === undefined ) {\n\n\t\t\t\tthis.faceVertexUvs[ i ] = [];\n\n\t\t\t}\n\n\t\t\tfor ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {\n\n\t\t\t\tvar uvs = faceVertexUvs[ j ], uvsCopy = [];\n\n\t\t\t\tfor ( k = 0, kl = uvs.length; k < kl; k ++ ) {\n\n\t\t\t\t\tvar uv = uvs[ k ];\n\n\t\t\t\t\tuvsCopy.push( uv.clone() );\n\n\t\t\t\t}\n\n\t\t\t\tthis.faceVertexUvs[ i ].push( uvsCopy );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// morph targets\n\n\t\tvar morphTargets = source.morphTargets;\n\n\t\tfor ( i = 0, il = morphTargets.length; i < il; i ++ ) {\n\n\t\t\tvar morphTarget = {};\n\t\t\tmorphTarget.name = morphTargets[ i ].name;\n\n\t\t\t// vertices\n\n\t\t\tif ( morphTargets[ i ].vertices !== undefined ) {\n\n\t\t\t\tmorphTarget.vertices = [];\n\n\t\t\t\tfor ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {\n\n\t\t\t\t\tmorphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// normals\n\n\t\t\tif ( morphTargets[ i ].normals !== undefined ) {\n\n\t\t\t\tmorphTarget.normals = [];\n\n\t\t\t\tfor ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {\n\n\t\t\t\t\tmorphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.morphTargets.push( morphTarget );\n\n\t\t}\n\n\t\t// morph normals\n\n\t\tvar morphNormals = source.morphNormals;\n\n\t\tfor ( i = 0, il = morphNormals.length; i < il; i ++ ) {\n\n\t\t\tvar morphNormal = {};\n\n\t\t\t// vertex normals\n\n\t\t\tif ( morphNormals[ i ].vertexNormals !== undefined ) {\n\n\t\t\t\tmorphNormal.vertexNormals = [];\n\n\t\t\t\tfor ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {\n\n\t\t\t\t\tvar srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];\n\t\t\t\t\tvar destVertexNormal = {};\n\n\t\t\t\t\tdestVertexNormal.a = srcVertexNormal.a.clone();\n\t\t\t\t\tdestVertexNormal.b = srcVertexNormal.b.clone();\n\t\t\t\t\tdestVertexNormal.c = srcVertexNormal.c.clone();\n\n\t\t\t\t\tmorphNormal.vertexNormals.push( destVertexNormal );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// face normals\n\n\t\t\tif ( morphNormals[ i ].faceNormals !== undefined ) {\n\n\t\t\t\tmorphNormal.faceNormals = [];\n\n\t\t\t\tfor ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {\n\n\t\t\t\t\tmorphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.morphNormals.push( morphNormal );\n\n\t\t}\n\n\t\t// skin weights\n\n\t\tvar skinWeights = source.skinWeights;\n\n\t\tfor ( i = 0, il = skinWeights.length; i < il; i ++ ) {\n\n\t\t\tthis.skinWeights.push( skinWeights[ i ].clone() );\n\n\t\t}\n\n\t\t// skin indices\n\n\t\tvar skinIndices = source.skinIndices;\n\n\t\tfor ( i = 0, il = skinIndices.length; i < il; i ++ ) {\n\n\t\t\tthis.skinIndices.push( skinIndices[ i ].clone() );\n\n\t\t}\n\n\t\t// line distances\n\n\t\tvar lineDistances = source.lineDistances;\n\n\t\tfor ( i = 0, il = lineDistances.length; i < il; i ++ ) {\n\n\t\t\tthis.lineDistances.push( lineDistances[ i ] );\n\n\t\t}\n\n\t\t// bounding box\n\n\t\tvar boundingBox = source.boundingBox;\n\n\t\tif ( boundingBox !== null ) {\n\n\t\t\tthis.boundingBox = boundingBox.clone();\n\n\t\t}\n\n\t\t// bounding sphere\n\n\t\tvar boundingSphere = source.boundingSphere;\n\n\t\tif ( boundingSphere !== null ) {\n\n\t\t\tthis.boundingSphere = boundingSphere.clone();\n\n\t\t}\n\n\t\t// update flags\n\n\t\tthis.elementsNeedUpdate = source.elementsNeedUpdate;\n\t\tthis.verticesNeedUpdate = source.verticesNeedUpdate;\n\t\tthis.uvsNeedUpdate = source.uvsNeedUpdate;\n\t\tthis.normalsNeedUpdate = source.normalsNeedUpdate;\n\t\tthis.colorsNeedUpdate = source.colorsNeedUpdate;\n\t\tthis.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;\n\t\tthis.groupsNeedUpdate = source.groupsNeedUpdate;\n\n\t\treturn this;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t}\n\n} );\n\n\nexport { Geometry };\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author Mugen87 / https://github.com/Mugen87\n */\n\nimport { Geometry } from '../core/Geometry.js';\nimport { BufferGeometry } from '../core/BufferGeometry.js';\nimport { Float32BufferAttribute } from '../core/BufferAttribute.js';\nimport { Vector3 } from '../math/Vector3.js';\n\n// BoxGeometry\n\nclass BoxGeometry extends Geometry {\n\n\tconstructor( width, height, depth, widthSegments, heightSegments, depthSegments ) {\n\n\t\tsuper();\n\n\t\tthis.type = 'BoxGeometry';\n\n\t\tthis.parameters = {\n\t\t\twidth: width,\n\t\t\theight: height,\n\t\t\tdepth: depth,\n\t\t\twidthSegments: widthSegments,\n\t\t\theightSegments: heightSegments,\n\t\t\tdepthSegments: depthSegments\n\t\t};\n\n\t\tthis.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );\n\t\tthis.mergeVertices();\n\n\t}\n\n}\n\n// BoxBufferGeometry\n\nclass BoxBufferGeometry extends BufferGeometry {\n\n\tconstructor( width, height, depth, widthSegments, heightSegments, depthSegments ) {\n\n\t\tsuper();\n\n\t\tthis.type = 'BoxBufferGeometry';\n\n\t\tthis.parameters = {\n\t\t\twidth: width,\n\t\t\theight: height,\n\t\t\tdepth: depth,\n\t\t\twidthSegments: widthSegments,\n\t\t\theightSegments: heightSegments,\n\t\t\tdepthSegments: depthSegments\n\t\t};\n\n\t\tconst scope = this;\n\n\t\twidth = width || 1;\n\t\theight = height || 1;\n\t\tdepth = depth || 1;\n\n\t\t// segments\n\n\t\twidthSegments = Math.floor( widthSegments ) || 1;\n\t\theightSegments = Math.floor( heightSegments ) || 1;\n\t\tdepthSegments = Math.floor( depthSegments ) || 1;\n\n\t\t// buffers\n\n\t\tconst indices = [];\n\t\tconst vertices = [];\n\t\tconst normals = [];\n\t\tconst uvs = [];\n\n\t\t// helper variables\n\n\t\tlet numberOfVertices = 0;\n\t\tlet groupStart = 0;\n\n\t\t// build each side of the box geometry\n\n\t\tbuildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px\n\t\tbuildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx\n\t\tbuildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py\n\t\tbuildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny\n\t\tbuildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz\n\t\tbuildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz\n\n\t\t// build geometry\n\n\t\tthis.setIndex( indices );\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\n\n\t\tfunction buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {\n\n\t\t\tconst segmentWidth = width / gridX;\n\t\t\tconst segmentHeight = height / gridY;\n\n\t\t\tconst widthHalf = width / 2;\n\t\t\tconst heightHalf = height / 2;\n\t\t\tconst depthHalf = depth / 2;\n\n\t\t\tconst gridX1 = gridX + 1;\n\t\t\tconst gridY1 = gridY + 1;\n\n\t\t\tlet vertexCounter = 0;\n\t\t\tlet groupCount = 0;\n\n\t\t\tconst vector = new Vector3();\n\n\t\t\t// generate vertices, normals and uvs\n\n\t\t\tfor ( let iy = 0; iy < gridY1; iy ++ ) {\n\n\t\t\t\tconst y = iy * segmentHeight - heightHalf;\n\n\t\t\t\tfor ( let ix = 0; ix < gridX1; ix ++ ) {\n\n\t\t\t\t\tconst x = ix * segmentWidth - widthHalf;\n\n\t\t\t\t\t// set values to correct vector component\n\n\t\t\t\t\tvector[ u ] = x * udir;\n\t\t\t\t\tvector[ v ] = y * vdir;\n\t\t\t\t\tvector[ w ] = depthHalf;\n\n\t\t\t\t\t// now apply vector to vertex buffer\n\n\t\t\t\t\tvertices.push( vector.x, vector.y, vector.z );\n\n\t\t\t\t\t// set values to correct vector component\n\n\t\t\t\t\tvector[ u ] = 0;\n\t\t\t\t\tvector[ v ] = 0;\n\t\t\t\t\tvector[ w ] = depth > 0 ? 1 : - 1;\n\n\t\t\t\t\t// now apply vector to normal buffer\n\n\t\t\t\t\tnormals.push( vector.x, vector.y, vector.z );\n\n\t\t\t\t\t// uvs\n\n\t\t\t\t\tuvs.push( ix / gridX );\n\t\t\t\t\tuvs.push( 1 - ( iy / gridY ) );\n\n\t\t\t\t\t// counters\n\n\t\t\t\t\tvertexCounter += 1;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// indices\n\n\t\t\t// 1. you need three indices to draw a single face\n\t\t\t// 2. a single segment consists of two faces\n\t\t\t// 3. so we need to generate six (2*3) indices per segment\n\n\t\t\tfor ( let iy = 0; iy < gridY; iy ++ ) {\n\n\t\t\t\tfor ( let ix = 0; ix < gridX; ix ++ ) {\n\n\t\t\t\t\tconst a = numberOfVertices + ix + gridX1 * iy;\n\t\t\t\t\tconst b = numberOfVertices + ix + gridX1 * ( iy + 1 );\n\t\t\t\t\tconst c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );\n\t\t\t\t\tconst d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;\n\n\t\t\t\t\t// faces\n\n\t\t\t\t\tindices.push( a, b, d );\n\t\t\t\t\tindices.push( b, c, d );\n\n\t\t\t\t\t// increase counter\n\n\t\t\t\t\tgroupCount += 6;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// add a group to the geometry. this will ensure multi material support\n\n\t\t\tscope.addGroup( groupStart, groupCount, materialIndex );\n\n\t\t\t// calculate new start value for groups\n\n\t\t\tgroupStart += groupCount;\n\n\t\t\t// update total number of vertices\n\n\t\t\tnumberOfVertices += vertexCounter;\n\n\t\t}\n\n\t}\n\n}\n\nexport { BoxGeometry, BoxBufferGeometry };\n","/**\n * Uniform Utilities\n */\n\nexport function cloneUniforms( src ) {\n\n\tvar dst = {};\n\n\tfor ( var u in src ) {\n\n\t\tdst[ u ] = {};\n\n\t\tfor ( var p in src[ u ] ) {\n\n\t\t\tvar property = src[ u ][ p ];\n\n\t\t\tif ( property && ( property.isColor ||\n\t\t\t\tproperty.isMatrix3 || property.isMatrix4 ||\n\t\t\t\tproperty.isVector2 || property.isVector3 || property.isVector4 ||\n\t\t\t\tproperty.isTexture ) ) {\n\n\t\t\t\tdst[ u ][ p ] = property.clone();\n\n\t\t\t} else if ( Array.isArray( property ) ) {\n\n\t\t\t\tdst[ u ][ p ] = property.slice();\n\n\t\t\t} else {\n\n\t\t\t\tdst[ u ][ p ] = property;\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\treturn dst;\n\n}\n\nexport function mergeUniforms( uniforms ) {\n\n\tvar merged = {};\n\n\tfor ( var u = 0; u < uniforms.length; u ++ ) {\n\n\t\tvar tmp = cloneUniforms( uniforms[ u ] );\n\n\t\tfor ( var p in tmp ) {\n\n\t\t\tmerged[ p ] = tmp[ p ];\n\n\t\t}\n\n\t}\n\n\treturn merged;\n\n}\n\n// Legacy\n\nvar UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };\n\nexport { UniformsUtils };\n","/**\n * @author alteredq / http://alteredqualia.com/\n *\n * parameters = {\n * defines: { \"label\" : \"value\" },\n * uniforms: { \"parameter1\": { value: 1.0 }, \"parameter2\": { value2: 2 } },\n *\n * fragmentShader: ,\n * vertexShader: ,\n *\n * wireframe: ,\n * wireframeLinewidth: ,\n *\n * lights: ,\n *\n * skinning: ,\n * morphTargets: ,\n * morphNormals: \n * }\n */\n\nimport { Material } from './Material.js';\nimport { cloneUniforms } from '../renderers/shaders/UniformsUtils.js';\n\nimport default_vertex from '../renderers/shaders/ShaderChunk/default_vertex.glsl.js';\nimport default_fragment from '../renderers/shaders/ShaderChunk/default_fragment.glsl.js';\n\nfunction ShaderMaterial( parameters ) {\n\n\tMaterial.call( this );\n\n\tthis.type = 'ShaderMaterial';\n\n\tthis.defines = {};\n\tthis.uniforms = {};\n\n\tthis.vertexShader = default_vertex;\n\tthis.fragmentShader = default_fragment;\n\n\tthis.linewidth = 1;\n\n\tthis.wireframe = false;\n\tthis.wireframeLinewidth = 1;\n\n\tthis.fog = false; // set to use scene fog\n\tthis.lights = false; // set to use scene lights\n\tthis.clipping = false; // set to use user-defined clipping planes\n\n\tthis.skinning = false; // set to use skinning attribute streams\n\tthis.morphTargets = false; // set to use morph targets\n\tthis.morphNormals = false; // set to use morph normals\n\n\tthis.extensions = {\n\t\tderivatives: false, // set to use derivatives\n\t\tfragDepth: false, // set to use fragment depth values\n\t\tdrawBuffers: false, // set to use draw buffers\n\t\tshaderTextureLOD: false // set to use shader texture LOD\n\t};\n\n\t// When rendered geometry doesn't include these attributes but the material does,\n\t// use these default values in WebGL. This avoids errors when buffer data is missing.\n\tthis.defaultAttributeValues = {\n\t\t'color': [ 1, 1, 1 ],\n\t\t'uv': [ 0, 0 ],\n\t\t'uv2': [ 0, 0 ]\n\t};\n\n\tthis.index0AttributeName = undefined;\n\tthis.uniformsNeedUpdate = false;\n\n\tif ( parameters !== undefined ) {\n\n\t\tif ( parameters.attributes !== undefined ) {\n\n\t\t\tconsole.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );\n\n\t\t}\n\n\t\tthis.setValues( parameters );\n\n\t}\n\n}\n\nShaderMaterial.prototype = Object.create( Material.prototype );\nShaderMaterial.prototype.constructor = ShaderMaterial;\n\nShaderMaterial.prototype.isShaderMaterial = true;\n\nShaderMaterial.prototype.copy = function ( source ) {\n\n\tMaterial.prototype.copy.call( this, source );\n\n\tthis.fragmentShader = source.fragmentShader;\n\tthis.vertexShader = source.vertexShader;\n\n\tthis.uniforms = cloneUniforms( source.uniforms );\n\n\tthis.defines = Object.assign( {}, source.defines );\n\n\tthis.wireframe = source.wireframe;\n\tthis.wireframeLinewidth = source.wireframeLinewidth;\n\n\tthis.lights = source.lights;\n\tthis.clipping = source.clipping;\n\n\tthis.skinning = source.skinning;\n\n\tthis.morphTargets = source.morphTargets;\n\tthis.morphNormals = source.morphNormals;\n\n\tthis.extensions = Object.assign( {}, source.extensions );\n\n\treturn this;\n\n};\n\nShaderMaterial.prototype.toJSON = function ( meta ) {\n\n\tvar data = Material.prototype.toJSON.call( this, meta );\n\n\tdata.uniforms = {};\n\n\tfor ( var name in this.uniforms ) {\n\n\t\tvar uniform = this.uniforms[ name ];\n\t\tvar value = uniform.value;\n\n\t\tif ( value && value.isTexture ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 't',\n\t\t\t\tvalue: value.toJSON( meta ).uuid\n\t\t\t};\n\n\t\t} else if ( value && value.isColor ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'c',\n\t\t\t\tvalue: value.getHex()\n\t\t\t};\n\n\t\t} else if ( value && value.isVector2 ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'v2',\n\t\t\t\tvalue: value.toArray()\n\t\t\t};\n\n\t\t} else if ( value && value.isVector3 ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'v3',\n\t\t\t\tvalue: value.toArray()\n\t\t\t};\n\n\t\t} else if ( value && value.isVector4 ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'v4',\n\t\t\t\tvalue: value.toArray()\n\t\t\t};\n\n\t\t} else if ( value && value.isMatrix3 ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'm3',\n\t\t\t\tvalue: value.toArray()\n\t\t\t};\n\n\t\t} else if ( value && value.isMatrix4 ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'm4',\n\t\t\t\tvalue: value.toArray()\n\t\t\t};\n\n\t\t} else {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\tvalue: value\n\t\t\t};\n\n\t\t\t// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far\n\n\t\t}\n\n\t}\n\n\tif ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;\n\n\tdata.vertexShader = this.vertexShader;\n\tdata.fragmentShader = this.fragmentShader;\n\n\tvar extensions = {};\n\n\tfor ( var key in this.extensions ) {\n\n\t\tif ( this.extensions[ key ] === true ) extensions[ key ] = true;\n\n\t}\n\n\tif ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;\n\n\treturn data;\n\n};\n\n\nexport { ShaderMaterial };\n","export default /* glsl */`\nvoid main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}\n`;\n","export default /* glsl */`\nvoid main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}\n`;\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author mikael emtinger / http://gomo.se/\n * @author WestLangley / http://github.com/WestLangley\n*/\n\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { Object3D } from '../core/Object3D.js';\nimport { Vector3 } from '../math/Vector3.js';\n\nfunction Camera() {\n\n\tObject3D.call( this );\n\n\tthis.type = 'Camera';\n\n\tthis.matrixWorldInverse = new Matrix4();\n\n\tthis.projectionMatrix = new Matrix4();\n\tthis.projectionMatrixInverse = new Matrix4();\n\n}\n\nCamera.prototype = Object.assign( Object.create( Object3D.prototype ), {\n\n\tconstructor: Camera,\n\n\tisCamera: true,\n\n\tcopy: function ( source, recursive ) {\n\n\t\tObject3D.prototype.copy.call( this, source, recursive );\n\n\t\tthis.matrixWorldInverse.copy( source.matrixWorldInverse );\n\n\t\tthis.projectionMatrix.copy( source.projectionMatrix );\n\t\tthis.projectionMatrixInverse.copy( source.projectionMatrixInverse );\n\n\t\treturn this;\n\n\t},\n\n\tgetWorldDirection: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Camera: .getWorldDirection() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tthis.updateMatrixWorld( true );\n\n\t\tvar e = this.matrixWorld.elements;\n\n\t\treturn target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();\n\n\t},\n\n\tupdateMatrixWorld: function ( force ) {\n\n\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\n\n\t\tthis.matrixWorldInverse.getInverse( this.matrixWorld );\n\n\t},\n\n\tupdateWorldMatrix: function ( updateParents, updateChildren ) {\n\n\t\tObject3D.prototype.updateWorldMatrix.call( this, updateParents, updateChildren );\n\n\t\tthis.matrixWorldInverse.getInverse( this.matrixWorld );\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t}\n\n} );\n\nexport { Camera };\n","import { Camera } from './Camera.js';\nimport { Object3D } from '../core/Object3D.js';\nimport { MathUtils } from '../math/MathUtils.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author greggman / http://games.greggman.com/\n * @author zz85 / http://www.lab4games.net/zz85/blog\n * @author tschw\n */\n\nfunction PerspectiveCamera( fov, aspect, near, far ) {\n\n\tCamera.call( this );\n\n\tthis.type = 'PerspectiveCamera';\n\n\tthis.fov = fov !== undefined ? fov : 50;\n\tthis.zoom = 1;\n\n\tthis.near = near !== undefined ? near : 0.1;\n\tthis.far = far !== undefined ? far : 2000;\n\tthis.focus = 10;\n\n\tthis.aspect = aspect !== undefined ? aspect : 1;\n\tthis.view = null;\n\n\tthis.filmGauge = 35;\t// width of the film (default in millimeters)\n\tthis.filmOffset = 0;\t// horizontal film offset (same unit as gauge)\n\n\tthis.updateProjectionMatrix();\n\n}\n\nPerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {\n\n\tconstructor: PerspectiveCamera,\n\n\tisPerspectiveCamera: true,\n\n\tcopy: function ( source, recursive ) {\n\n\t\tCamera.prototype.copy.call( this, source, recursive );\n\n\t\tthis.fov = source.fov;\n\t\tthis.zoom = source.zoom;\n\n\t\tthis.near = source.near;\n\t\tthis.far = source.far;\n\t\tthis.focus = source.focus;\n\n\t\tthis.aspect = source.aspect;\n\t\tthis.view = source.view === null ? null : Object.assign( {}, source.view );\n\n\t\tthis.filmGauge = source.filmGauge;\n\t\tthis.filmOffset = source.filmOffset;\n\n\t\treturn this;\n\n\t},\n\n\t/**\n\t * Sets the FOV by focal length in respect to the current .filmGauge.\n\t *\n\t * The default film gauge is 35, so that the focal length can be specified for\n\t * a 35mm (full frame) camera.\n\t *\n\t * Values for focal length and film gauge must have the same unit.\n\t */\n\tsetFocalLength: function ( focalLength ) {\n\n\t\t// see http://www.bobatkins.com/photography/technical/field_of_view.html\n\t\tvar vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;\n\n\t\tthis.fov = MathUtils.RAD2DEG * 2 * Math.atan( vExtentSlope );\n\t\tthis.updateProjectionMatrix();\n\n\t},\n\n\t/**\n\t * Calculates the focal length from the current .fov and .filmGauge.\n\t */\n\tgetFocalLength: function () {\n\n\t\tvar vExtentSlope = Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov );\n\n\t\treturn 0.5 * this.getFilmHeight() / vExtentSlope;\n\n\t},\n\n\tgetEffectiveFOV: function () {\n\n\t\treturn MathUtils.RAD2DEG * 2 * Math.atan(\n\t\t\tMath.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom );\n\n\t},\n\n\tgetFilmWidth: function () {\n\n\t\t// film not completely covered in portrait format (aspect < 1)\n\t\treturn this.filmGauge * Math.min( this.aspect, 1 );\n\n\t},\n\n\tgetFilmHeight: function () {\n\n\t\t// film not completely covered in landscape format (aspect > 1)\n\t\treturn this.filmGauge / Math.max( this.aspect, 1 );\n\n\t},\n\n\t/**\n\t * Sets an offset in a larger frustum. This is useful for multi-window or\n\t * multi-monitor/multi-machine setups.\n\t *\n\t * For example, if you have 3x2 monitors and each monitor is 1920x1080 and\n\t * the monitors are in grid like this\n\t *\n\t * +---+---+---+\n\t * | A | B | C |\n\t * +---+---+---+\n\t * | D | E | F |\n\t * +---+---+---+\n\t *\n\t * then for each monitor you would call it like this\n\t *\n\t * var w = 1920;\n\t * var h = 1080;\n\t * var fullWidth = w * 3;\n\t * var fullHeight = h * 2;\n\t *\n\t * --A--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );\n\t * --B--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );\n\t * --C--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );\n\t * --D--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );\n\t * --E--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );\n\t * --F--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );\n\t *\n\t * Note there is no reason monitors have to be the same size or in a grid.\n\t */\n\tsetViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {\n\n\t\tthis.aspect = fullWidth / fullHeight;\n\n\t\tif ( this.view === null ) {\n\n\t\t\tthis.view = {\n\t\t\t\tenabled: true,\n\t\t\t\tfullWidth: 1,\n\t\t\t\tfullHeight: 1,\n\t\t\t\toffsetX: 0,\n\t\t\t\toffsetY: 0,\n\t\t\t\twidth: 1,\n\t\t\t\theight: 1\n\t\t\t};\n\n\t\t}\n\n\t\tthis.view.enabled = true;\n\t\tthis.view.fullWidth = fullWidth;\n\t\tthis.view.fullHeight = fullHeight;\n\t\tthis.view.offsetX = x;\n\t\tthis.view.offsetY = y;\n\t\tthis.view.width = width;\n\t\tthis.view.height = height;\n\n\t\tthis.updateProjectionMatrix();\n\n\t},\n\n\tclearViewOffset: function () {\n\n\t\tif ( this.view !== null ) {\n\n\t\t\tthis.view.enabled = false;\n\n\t\t}\n\n\t\tthis.updateProjectionMatrix();\n\n\t},\n\n\tupdateProjectionMatrix: function () {\n\n\t\tvar near = this.near,\n\t\t\ttop = near * Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom,\n\t\t\theight = 2 * top,\n\t\t\twidth = this.aspect * height,\n\t\t\tleft = - 0.5 * width,\n\t\t\tview = this.view;\n\n\t\tif ( this.view !== null && this.view.enabled ) {\n\n\t\t\tvar fullWidth = view.fullWidth,\n\t\t\t\tfullHeight = view.fullHeight;\n\n\t\t\tleft += view.offsetX * width / fullWidth;\n\t\t\ttop -= view.offsetY * height / fullHeight;\n\t\t\twidth *= view.width / fullWidth;\n\t\t\theight *= view.height / fullHeight;\n\n\t\t}\n\n\t\tvar skew = this.filmOffset;\n\t\tif ( skew !== 0 ) left += near * skew / this.getFilmWidth();\n\n\t\tthis.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );\n\n\t\tthis.projectionMatrixInverse.getInverse( this.projectionMatrix );\n\n\t},\n\n\ttoJSON: function ( meta ) {\n\n\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\n\n\t\tdata.object.fov = this.fov;\n\t\tdata.object.zoom = this.zoom;\n\n\t\tdata.object.near = this.near;\n\t\tdata.object.far = this.far;\n\t\tdata.object.focus = this.focus;\n\n\t\tdata.object.aspect = this.aspect;\n\n\t\tif ( this.view !== null ) data.object.view = Object.assign( {}, this.view );\n\n\t\tdata.object.filmGauge = this.filmGauge;\n\t\tdata.object.filmOffset = this.filmOffset;\n\n\t\treturn data;\n\n\t}\n\n} );\n\n\nexport { PerspectiveCamera };\n","/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nimport { Texture } from './Texture.js';\nimport { NearestFilter } from '../constants.js';\n\nfunction DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {\n\n\tTexture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );\n\n\tthis.image = { data: data || null, width: width || 1, height: height || 1 };\n\n\tthis.magFilter = magFilter !== undefined ? magFilter : NearestFilter;\n\tthis.minFilter = minFilter !== undefined ? minFilter : NearestFilter;\n\n\tthis.generateMipmaps = false;\n\tthis.flipY = false;\n\tthis.unpackAlignment = 1;\n\n\tthis.needsUpdate = true;\n\n}\n\nDataTexture.prototype = Object.create( Texture.prototype );\nDataTexture.prototype.constructor = DataTexture;\n\nDataTexture.prototype.isDataTexture = true;\n\n\nexport { DataTexture };\n","import { Vector3 } from './Vector3.js';\nimport { Sphere } from './Sphere.js';\nimport { Plane } from './Plane.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author bhouston / http://clara.io\n */\n\nvar _sphere = new Sphere();\nvar _vector = new Vector3();\n\nfunction Frustum( p0, p1, p2, p3, p4, p5 ) {\n\n\tthis.planes = [\n\n\t\t( p0 !== undefined ) ? p0 : new Plane(),\n\t\t( p1 !== undefined ) ? p1 : new Plane(),\n\t\t( p2 !== undefined ) ? p2 : new Plane(),\n\t\t( p3 !== undefined ) ? p3 : new Plane(),\n\t\t( p4 !== undefined ) ? p4 : new Plane(),\n\t\t( p5 !== undefined ) ? p5 : new Plane()\n\n\t];\n\n}\n\nObject.assign( Frustum.prototype, {\n\n\tset: function ( p0, p1, p2, p3, p4, p5 ) {\n\n\t\tvar planes = this.planes;\n\n\t\tplanes[ 0 ].copy( p0 );\n\t\tplanes[ 1 ].copy( p1 );\n\t\tplanes[ 2 ].copy( p2 );\n\t\tplanes[ 3 ].copy( p3 );\n\t\tplanes[ 4 ].copy( p4 );\n\t\tplanes[ 5 ].copy( p5 );\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( frustum ) {\n\n\t\tvar planes = this.planes;\n\n\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\tplanes[ i ].copy( frustum.planes[ i ] );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetFromProjectionMatrix: function ( m ) {\n\n\t\tvar planes = this.planes;\n\t\tvar me = m.elements;\n\t\tvar me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];\n\t\tvar me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];\n\t\tvar me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];\n\t\tvar me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];\n\n\t\tplanes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();\n\t\tplanes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();\n\t\tplanes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();\n\t\tplanes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();\n\t\tplanes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();\n\t\tplanes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();\n\n\t\treturn this;\n\n\t},\n\n\tintersectsObject: function ( object ) {\n\n\t\tvar geometry = object.geometry;\n\n\t\tif ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();\n\n\t\t_sphere.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );\n\n\t\treturn this.intersectsSphere( _sphere );\n\n\t},\n\n\tintersectsSprite: function ( sprite ) {\n\n\t\t_sphere.center.set( 0, 0, 0 );\n\t\t_sphere.radius = 0.7071067811865476;\n\t\t_sphere.applyMatrix4( sprite.matrixWorld );\n\n\t\treturn this.intersectsSphere( _sphere );\n\n\t},\n\n\tintersectsSphere: function ( sphere ) {\n\n\t\tvar planes = this.planes;\n\t\tvar center = sphere.center;\n\t\tvar negRadius = - sphere.radius;\n\n\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\tvar distance = planes[ i ].distanceToPoint( center );\n\n\t\t\tif ( distance < negRadius ) {\n\n\t\t\t\treturn false;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn true;\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\tvar planes = this.planes;\n\n\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\tvar plane = planes[ i ];\n\n\t\t\t// corner at max distance\n\n\t\t\t_vector.x = plane.normal.x > 0 ? box.max.x : box.min.x;\n\t\t\t_vector.y = plane.normal.y > 0 ? box.max.y : box.min.y;\n\t\t\t_vector.z = plane.normal.z > 0 ? box.max.z : box.min.z;\n\n\t\t\tif ( plane.distanceToPoint( _vector ) < 0 ) {\n\n\t\t\t\treturn false;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn true;\n\n\t},\n\n\tcontainsPoint: function ( point ) {\n\n\t\tvar planes = this.planes;\n\n\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\tif ( planes[ i ].distanceToPoint( point ) < 0 ) {\n\n\t\t\t\treturn false;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn true;\n\n\t}\n\n} );\n\n\nexport { Frustum };\n","import { Color } from '../../math/Color.js';\nimport { Vector2 } from '../../math/Vector2.js';\nimport { Matrix3 } from '../../math/Matrix3.js';\n\n/**\n * Uniforms library for shared webgl shaders\n */\n\nvar UniformsLib = {\n\n\tcommon: {\n\n\t\tdiffuse: { value: new Color( 0xeeeeee ) },\n\t\topacity: { value: 1.0 },\n\n\t\tmap: { value: null },\n\t\tuvTransform: { value: new Matrix3() },\n\t\tuv2Transform: { value: new Matrix3() },\n\n\t\talphaMap: { value: null },\n\n\t},\n\n\tspecularmap: {\n\n\t\tspecularMap: { value: null },\n\n\t},\n\n\tenvmap: {\n\n\t\tenvMap: { value: null },\n\t\tflipEnvMap: { value: - 1 },\n\t\treflectivity: { value: 1.0 },\n\t\trefractionRatio: { value: 0.98 },\n\t\tmaxMipLevel: { value: 0 }\n\n\t},\n\n\taomap: {\n\n\t\taoMap: { value: null },\n\t\taoMapIntensity: { value: 1 }\n\n\t},\n\n\tlightmap: {\n\n\t\tlightMap: { value: null },\n\t\tlightMapIntensity: { value: 1 }\n\n\t},\n\n\temissivemap: {\n\n\t\temissiveMap: { value: null }\n\n\t},\n\n\tbumpmap: {\n\n\t\tbumpMap: { value: null },\n\t\tbumpScale: { value: 1 }\n\n\t},\n\n\tnormalmap: {\n\n\t\tnormalMap: { value: null },\n\t\tnormalScale: { value: new Vector2( 1, 1 ) }\n\n\t},\n\n\tdisplacementmap: {\n\n\t\tdisplacementMap: { value: null },\n\t\tdisplacementScale: { value: 1 },\n\t\tdisplacementBias: { value: 0 }\n\n\t},\n\n\troughnessmap: {\n\n\t\troughnessMap: { value: null }\n\n\t},\n\n\tmetalnessmap: {\n\n\t\tmetalnessMap: { value: null }\n\n\t},\n\n\tgradientmap: {\n\n\t\tgradientMap: { value: null }\n\n\t},\n\n\tfog: {\n\n\t\tfogDensity: { value: 0.00025 },\n\t\tfogNear: { value: 1 },\n\t\tfogFar: { value: 2000 },\n\t\tfogColor: { value: new Color( 0xffffff ) }\n\n\t},\n\n\tlights: {\n\n\t\tambientLightColor: { value: [] },\n\n\t\tlightProbe: { value: [] },\n\n\t\tdirectionalLights: { value: [], properties: {\n\t\t\tdirection: {},\n\t\t\tcolor: {}\n\t\t} },\n\n\t\tdirectionalLightShadows: { value: [], properties: {\n\t\t\tshadowBias: {},\n\t\t\tshadowRadius: {},\n\t\t\tshadowMapSize: {}\n\t\t} },\n\n\t\tdirectionalShadowMap: { value: [] },\n\t\tdirectionalShadowMatrix: { value: [] },\n\n\t\tspotLights: { value: [], properties: {\n\t\t\tcolor: {},\n\t\t\tposition: {},\n\t\t\tdirection: {},\n\t\t\tdistance: {},\n\t\t\tconeCos: {},\n\t\t\tpenumbraCos: {},\n\t\t\tdecay: {}\n\t\t} },\n\n\t\tspotLightShadows: { value: [], properties: {\n\t\t\tshadowBias: {},\n\t\t\tshadowRadius: {},\n\t\t\tshadowMapSize: {}\n\t\t} },\n\n\t\tspotShadowMap: { value: [] },\n\t\tspotShadowMatrix: { value: [] },\n\n\t\tpointLights: { value: [], properties: {\n\t\t\tcolor: {},\n\t\t\tposition: {},\n\t\t\tdecay: {},\n\t\t\tdistance: {}\n\t\t} },\n\n\t\tpointLightShadows: { value: [], properties: {\n\t\t\tshadowBias: {},\n\t\t\tshadowRadius: {},\n\t\t\tshadowMapSize: {},\n\t\t\tshadowCameraNear: {},\n\t\t\tshadowCameraFar: {}\n\t\t} },\n\n\t\tpointShadowMap: { value: [] },\n\t\tpointShadowMatrix: { value: [] },\n\n\t\themisphereLights: { value: [], properties: {\n\t\t\tdirection: {},\n\t\t\tskyColor: {},\n\t\t\tgroundColor: {}\n\t\t} },\n\n\t\t// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src\n\t\trectAreaLights: { value: [], properties: {\n\t\t\tcolor: {},\n\t\t\tposition: {},\n\t\t\twidth: {},\n\t\t\theight: {}\n\t\t} }\n\n\t},\n\n\tpoints: {\n\n\t\tdiffuse: { value: new Color( 0xeeeeee ) },\n\t\topacity: { value: 1.0 },\n\t\tsize: { value: 1.0 },\n\t\tscale: { value: 1.0 },\n\t\tmap: { value: null },\n\t\talphaMap: { value: null },\n\t\tuvTransform: { value: new Matrix3() }\n\n\t},\n\n\tsprite: {\n\n\t\tdiffuse: { value: new Color( 0xeeeeee ) },\n\t\topacity: { value: 1.0 },\n\t\tcenter: { value: new Vector2( 0.5, 0.5 ) },\n\t\trotation: { value: 0.0 },\n\t\tmap: { value: null },\n\t\talphaMap: { value: null },\n\t\tuvTransform: { value: new Matrix3() }\n\n\t}\n\n};\n\nexport { UniformsLib };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLAnimation() {\n\n\tvar context = null;\n\tvar isAnimating = false;\n\tvar animationLoop = null;\n\n\tfunction onAnimationFrame( time, frame ) {\n\n\t\tif ( isAnimating === false ) return;\n\n\t\tanimationLoop( time, frame );\n\n\t\tcontext.requestAnimationFrame( onAnimationFrame );\n\n\t}\n\n\treturn {\n\n\t\tstart: function () {\n\n\t\t\tif ( isAnimating === true ) return;\n\t\t\tif ( animationLoop === null ) return;\n\n\t\t\tcontext.requestAnimationFrame( onAnimationFrame );\n\n\t\t\tisAnimating = true;\n\n\t\t},\n\n\t\tstop: function () {\n\n\t\t\tisAnimating = false;\n\n\t\t},\n\n\t\tsetAnimationLoop: function ( callback ) {\n\n\t\t\tanimationLoop = callback;\n\n\t\t},\n\n\t\tsetContext: function ( value ) {\n\n\t\t\tcontext = value;\n\n\t\t}\n\n\t};\n\n}\n\nexport { WebGLAnimation };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLAttributes( gl, capabilities ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\n\tvar buffers = new WeakMap();\n\n\tfunction createBuffer( attribute, bufferType ) {\n\n\t\tvar array = attribute.array;\n\t\tvar usage = attribute.usage;\n\n\t\tvar buffer = gl.createBuffer();\n\n\t\tgl.bindBuffer( bufferType, buffer );\n\t\tgl.bufferData( bufferType, array, usage );\n\n\t\tattribute.onUploadCallback();\n\n\t\tvar type = gl.FLOAT;\n\n\t\tif ( array instanceof Float32Array ) {\n\n\t\t\ttype = gl.FLOAT;\n\n\t\t} else if ( array instanceof Float64Array ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );\n\n\t\t} else if ( array instanceof Uint16Array ) {\n\n\t\t\ttype = gl.UNSIGNED_SHORT;\n\n\t\t} else if ( array instanceof Int16Array ) {\n\n\t\t\ttype = gl.SHORT;\n\n\t\t} else if ( array instanceof Uint32Array ) {\n\n\t\t\ttype = gl.UNSIGNED_INT;\n\n\t\t} else if ( array instanceof Int32Array ) {\n\n\t\t\ttype = gl.INT;\n\n\t\t} else if ( array instanceof Int8Array ) {\n\n\t\t\ttype = gl.BYTE;\n\n\t\t} else if ( array instanceof Uint8Array ) {\n\n\t\t\ttype = gl.UNSIGNED_BYTE;\n\n\t\t}\n\n\t\treturn {\n\t\t\tbuffer: buffer,\n\t\t\ttype: type,\n\t\t\tbytesPerElement: array.BYTES_PER_ELEMENT,\n\t\t\tversion: attribute.version\n\t\t};\n\n\t}\n\n\tfunction updateBuffer( buffer, attribute, bufferType ) {\n\n\t\tvar array = attribute.array;\n\t\tvar updateRange = attribute.updateRange;\n\n\t\tgl.bindBuffer( bufferType, buffer );\n\n\t\tif ( updateRange.count === - 1 ) {\n\n\t\t\t// Not using update ranges\n\n\t\t\tgl.bufferSubData( bufferType, 0, array );\n\n\t\t} else {\n\n\t\t\tif ( isWebGL2 ) {\n\n\t\t\t\tgl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,\n\t\t\t\t\tarray, updateRange.offset, updateRange.count );\n\n\t\t\t} else {\n\n\t\t\t\tgl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,\n\t\t\t\t\tarray.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );\n\n\t\t\t}\n\n\t\t\tupdateRange.count = - 1; // reset range\n\n\t\t}\n\n\t}\n\n\t//\n\n\tfunction get( attribute ) {\n\n\t\tif ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;\n\n\t\treturn buffers.get( attribute );\n\n\t}\n\n\tfunction remove( attribute ) {\n\n\t\tif ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;\n\n\t\tvar data = buffers.get( attribute );\n\n\t\tif ( data ) {\n\n\t\t\tgl.deleteBuffer( data.buffer );\n\n\t\t\tbuffers.delete( attribute );\n\n\t\t}\n\n\t}\n\n\tfunction update( attribute, bufferType ) {\n\n\t\tif ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;\n\n\t\tvar data = buffers.get( attribute );\n\n\t\tif ( data === undefined ) {\n\n\t\t\tbuffers.set( attribute, createBuffer( attribute, bufferType ) );\n\n\t\t} else if ( data.version < attribute.version ) {\n\n\t\t\tupdateBuffer( data.buffer, attribute, bufferType );\n\n\t\t\tdata.version = attribute.version;\n\n\t\t}\n\n\t}\n\n\treturn {\n\n\t\tget: get,\n\t\tremove: remove,\n\t\tupdate: update\n\n\t};\n\n}\n\n\nexport { WebGLAttributes };\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author Mugen87 / https://github.com/Mugen87\n */\n\nimport { Geometry } from '../core/Geometry.js';\nimport { BufferGeometry } from '../core/BufferGeometry.js';\nimport { Float32BufferAttribute } from '../core/BufferAttribute.js';\n\n// PlaneGeometry\n\nfunction PlaneGeometry( width, height, widthSegments, heightSegments ) {\n\n\tGeometry.call( this );\n\n\tthis.type = 'PlaneGeometry';\n\n\tthis.parameters = {\n\t\twidth: width,\n\t\theight: height,\n\t\twidthSegments: widthSegments,\n\t\theightSegments: heightSegments\n\t};\n\n\tthis.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );\n\tthis.mergeVertices();\n\n}\n\nPlaneGeometry.prototype = Object.create( Geometry.prototype );\nPlaneGeometry.prototype.constructor = PlaneGeometry;\n\n// PlaneBufferGeometry\n\nfunction PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {\n\n\tBufferGeometry.call( this );\n\n\tthis.type = 'PlaneBufferGeometry';\n\n\tthis.parameters = {\n\t\twidth: width,\n\t\theight: height,\n\t\twidthSegments: widthSegments,\n\t\theightSegments: heightSegments\n\t};\n\n\twidth = width || 1;\n\theight = height || 1;\n\n\tvar width_half = width / 2;\n\tvar height_half = height / 2;\n\n\tvar gridX = Math.floor( widthSegments ) || 1;\n\tvar gridY = Math.floor( heightSegments ) || 1;\n\n\tvar gridX1 = gridX + 1;\n\tvar gridY1 = gridY + 1;\n\n\tvar segment_width = width / gridX;\n\tvar segment_height = height / gridY;\n\n\tvar ix, iy;\n\n\t// buffers\n\n\tvar indices = [];\n\tvar vertices = [];\n\tvar normals = [];\n\tvar uvs = [];\n\n\t// generate vertices, normals and uvs\n\n\tfor ( iy = 0; iy < gridY1; iy ++ ) {\n\n\t\tvar y = iy * segment_height - height_half;\n\n\t\tfor ( ix = 0; ix < gridX1; ix ++ ) {\n\n\t\t\tvar x = ix * segment_width - width_half;\n\n\t\t\tvertices.push( x, - y, 0 );\n\n\t\t\tnormals.push( 0, 0, 1 );\n\n\t\t\tuvs.push( ix / gridX );\n\t\t\tuvs.push( 1 - ( iy / gridY ) );\n\n\t\t}\n\n\t}\n\n\t// indices\n\n\tfor ( iy = 0; iy < gridY; iy ++ ) {\n\n\t\tfor ( ix = 0; ix < gridX; ix ++ ) {\n\n\t\t\tvar a = ix + gridX1 * iy;\n\t\t\tvar b = ix + gridX1 * ( iy + 1 );\n\t\t\tvar c = ( ix + 1 ) + gridX1 * ( iy + 1 );\n\t\t\tvar d = ( ix + 1 ) + gridX1 * iy;\n\n\t\t\t// faces\n\n\t\t\tindices.push( a, b, d );\n\t\t\tindices.push( b, c, d );\n\n\t\t}\n\n\t}\n\n\t// build geometry\n\n\tthis.setIndex( indices );\n\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\n\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\n\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\n\n}\n\nPlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\nPlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;\n\n\nexport { PlaneGeometry, PlaneBufferGeometry };\n","export default /* glsl */`\n#ifdef USE_ALPHAMAP\n\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ALPHAMAP\n\n\tuniform sampler2D alphaMap;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef ALPHATEST\n\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_AOMAP\n\n\t// reads channel R, compatible with a combined OcclusionRoughnessMetallic (RGB) texture\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_AOMAP\n\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n\n#endif\n`;\n","export default /* glsl */`\nvec3 transformed = vec3( position );\n`;\n","export default /* glsl */`\nvec3 objectNormal = vec3( normal );\n\n#ifdef USE_TANGENT\n\n\tvec3 objectTangent = vec3( tangent.xyz );\n\n#endif\n`;\n","export default /* glsl */`\n\n// Analytical approximation of the DFG LUT, one half of the\n// split-sum approximation used in indirect specular lighting.\n// via 'environmentBRDF' from \"Physically Based Shading on Mobile\"\n// https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile\nvec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\n\tvec4 r = roughness * c0 + c1;\n\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\n\treturn vec2( -1.04, 1.04 ) * a004 + r.zw;\n\n}\n\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\n\t// based upon Frostbite 3 Moving to Physically-based Rendering\n\t// page 32, equation 26: E[window1]\n\t// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\n\t// this is intended to be used on spot and point lights who are represented as luminous intensity\n\t// but who must be converted to luminous irradiance for surface lighting calculation\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\n\tif( cutoffDistance > 0.0 ) {\n\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\n\t}\n\n\treturn distanceFalloff;\n\n#else\n\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\n\t}\n\n\treturn 1.0;\n\n#endif\n\n}\n\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\n\treturn RECIPROCAL_PI * diffuseColor;\n\n} // validated\n\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\n\t// Original approximation by Christophe Schlick '94\n\t// float fresnel = pow( 1.0 - dotLH, 5.0 );\n\n\t// Optimized variant (presented by Epic at SIGGRAPH '13)\n\t// https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n\n} // validated\n\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\n\n\t// See F_Schlick\n\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\n\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\n\n\treturn Fr * fresnel + F0;\n\n}\n\n\n// Microfacet Models for Refraction through Rough Surfaces - equation (34)\n// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html\n// alpha is \"roughness squared\" in Disney’s reparameterization\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\n\t// geometry term (normalized) = G(l)⋅G(v) / 4(n⋅l)(n⋅v)\n\t// also see #12151\n\n\tfloat a2 = pow2( alpha );\n\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\n\treturn 1.0 / ( gl * gv );\n\n} // validated\n\n// Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2\n// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\n\tfloat a2 = pow2( alpha );\n\n\t// dotNL and dotNV are explicitly swapped. This is not a mistake.\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\n\treturn 0.5 / max( gv + gl, EPSILON );\n\n}\n\n// Microfacet Models for Refraction through Rough Surfaces - equation (33)\n// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html\n// alpha is \"roughness squared\" in Disney’s reparameterization\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\n\tfloat a2 = pow2( alpha );\n\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1\n\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n\n}\n\n// GGX Distribution, Schlick Fresnel, GGX-Smith Visibility\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\n\tfloat alpha = pow2( roughness ); // UE4's roughness\n\n\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\n\n\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\n\tfloat D = D_GGX( alpha, dotNH );\n\n\treturn F * ( G * D );\n\n} // validated\n\n// Rect Area Light\n\n// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines\n// by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt\n// code: https://github.com/selfshadow/ltc_code/\n\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\n\tfloat dotNV = saturate( dot( N, V ) );\n\n\t// texture parameterized by sqrt( GGX alpha ) and sqrt( 1 - cos( theta ) )\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\n\treturn uv;\n\n}\n\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\n\t// Real-Time Area Lighting: a Journey from Research to Production (p.102)\n\t// An approximation of the form factor of a horizon-clipped rectangle.\n\n\tfloat l = length( f );\n\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n\n}\n\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\n\tfloat x = dot( v1, v2 );\n\n\tfloat y = abs( x );\n\n\t// rational polynomial approximation to theta / sin( theta ) / 2PI\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\n\treturn cross( v1, v2 ) * theta_sintheta;\n\n}\n\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\n\t// bail if point is on back side of plane of light\n\t// assumes ccw winding order of light vertices\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\n\t// construct orthonormal basis around N\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 ); // negated from paper; possibly due to a different handedness of world coordinate system\n\n\t// compute transform\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\n\t// transform rect\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\n\t// project rect onto sphere\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\n\t// calculate vector form factor\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\n\t// adjust for horizon clipping\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\n/*\n\t// alternate method of adjusting for horizon clipping (see referece)\n\t// refactoring required\n\tfloat len = length( vectorFormFactor );\n\tfloat z = vectorFormFactor.z / len;\n\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\n\t// tabulated horizon-clipped sphere, apparently...\n\tvec2 uv = vec2( z * 0.5 + 0.5, len );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\n\tfloat scale = texture2D( ltc_2, uv ).w;\n\n\tfloat result = len * scale;\n*/\n\n\treturn vec3( result );\n\n}\n\n// End Rect Area Light\n\n// ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\n\treturn specularColor * brdf.x + brdf.y;\n\n} // validated\n\n// Fdez-Agüera's \"Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting\"\n// Approximates multiscattering in order to preserve energy.\n// http://www.jcgt.org/published/0008/01/03/\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\n\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619; // 1/21\n\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n\n}\n\nfloat G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ ) {\n\n\t// geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v)\n\treturn 0.25;\n\n}\n\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n\n}\n\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\n\t//float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\t//float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\n\tfloat G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );\n\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\n\treturn F * ( G * D );\n\n} // validated\n\n// source: http://simonstechblog.blogspot.ca/2011/12/microfacet-brdf.html\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\n\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n\n#if defined( USE_SHEEN )\n\n// https://github.com/google/filament/blob/master/shaders/src/brdf.fs#L94\nfloat D_Charlie(float roughness, float NoH) {\n\t// Estevez and Kulla 2017, \"Production Friendly Microfacet Sheen BRDF\"\n\tfloat invAlpha = 1.0 / roughness;\n\tfloat cos2h = NoH * NoH;\n\tfloat sin2h = max(1.0 - cos2h, 0.0078125); // 2^(-14/2), so sin2h^2 > 0 in fp16\n\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\n}\n\n// https://github.com/google/filament/blob/master/shaders/src/brdf.fs#L136\nfloat V_Neubelt(float NoV, float NoL) {\n\t// Neubelt and Pettineo 2013, \"Crafting a Next-gen Material Pipeline for The Order: 1886\"\n\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\n}\n\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n\n\tvec3 N = geometry.normal;\n\tvec3 V = geometry.viewDir;\n\n\tvec3 H = normalize( V + L );\n\tfloat dotNH = saturate( dot( N, H ) );\n\n\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\n\n}\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_BUMPMAP\n\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\n\t// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen\n\t// http://api.unrealengine.com/attachments/Engine/Rendering/LightingAndShadows/BumpMappingWithoutTangentSpace/mm_sfgrad_bump.pdf\n\n\t// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)\n\n\tvec2 dHdxy_fwd() {\n\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\n\t\treturn vec2( dBx, dBy );\n\n\t}\n\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\n\t\t// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988\n\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\t\t// normalized\n\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\n\t}\n\n#endif\n`;\n","export default /* glsl */`\n#if NUM_CLIPPING_PLANES > 0\n\n\tvec4 plane;\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\n\t\tbool clipped = true;\n\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\n\t\t}\n\t\t#pragma unroll_loop_end\n\n\t\tif ( clipped ) discard;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#if NUM_CLIPPING_PLANES > 0\n\n\tvarying vec3 vClipPosition;\n\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n\n#endif\n`;\n","export default /* glsl */`\n#if NUM_CLIPPING_PLANES > 0\n\n\tvarying vec3 vClipPosition;\n\n#endif\n`;\n","export default /* glsl */`\n#if NUM_CLIPPING_PLANES > 0\n\n\tvClipPosition = - mvPosition.xyz;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_COLOR\n\n\tdiffuseColor.rgb *= vColor;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_COLOR\n\n\tvarying vec3 vColor;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_COLOR\n\n\tvarying vec3 vColor;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_COLOR\n\n\tvColor.xyz = color.xyz;\n\n#endif\n`;\n","export default /* glsl */`\n#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n\n#ifndef saturate\n// may have defined saturate() already\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement(a) ( 1.0 - saturate( a ) )\n\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\n// expects values in the range of [0,1]x[0,1], returns values in the [0,1] range.\n// do not collapse into a single function per: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\n\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\n\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\n\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\n\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n}\n\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t// dir can be either a direction vector or a normal vector\n\t// upper-left 3x3 of matrix is assumed to be orthogonal\n\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n\n}\n\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\n\treturn - distance * planeNormal + point;\n\n}\n\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n\n}\n\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n\n}\n\nmat3 transposeMat3( const in mat3 m ) {\n\n\tmat3 tmp;\n\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\n\treturn tmp;\n\n}\n\n// https://en.wikipedia.org/wiki/Relative_luminance\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\n\treturn dot( weights, color.rgb );\n\n}\n\nbool isPerspectiveMatrix( mat4 m ) {\n\n return m[ 2 ][ 3 ] == - 1.0;\n\n}\n\nvec2 equirectUv( in vec3 dir ) {\n\n\t// dir is assumed to be unit length\n\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\n\treturn vec2( u, v );\n\n}\n`;\n","export default /* glsl */`\n#ifdef ENVMAP_TYPE_CUBE_UV\n\n#define cubeUV_maxMipLevel 8.0\n#define cubeUV_minMipLevel 4.0\n#define cubeUV_maxTileSize 256.0\n#define cubeUV_minTileSize 16.0\n\n// These shader functions convert between the UV coordinates of a single face of\n// a cubemap, the 0-5 integer index of a cube face, and the direction vector for\n// sampling a textureCube (not generally normalized).\n\nfloat getFace(vec3 direction) {\n vec3 absDirection = abs(direction);\n float face = -1.0;\n if (absDirection.x > absDirection.z) {\n if (absDirection.x > absDirection.y)\n face = direction.x > 0.0 ? 0.0 : 3.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n } else {\n if (absDirection.z > absDirection.y)\n face = direction.z > 0.0 ? 2.0 : 5.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n }\n return face;\n}\n\n// RH coordinate system; PMREM face-indexing convention\nvec2 getUV(vec3 direction, float face) {\n vec2 uv;\n if (face == 0.0) {\n uv = vec2(direction.z, direction.y) / abs(direction.x); // pos x\n } else if (face == 1.0) {\n uv = vec2(-direction.x, -direction.z) / abs(direction.y); // pos y\n } else if (face == 2.0) {\n uv = vec2(-direction.x, direction.y) / abs(direction.z); // pos z\n } else if (face == 3.0) {\n uv = vec2(-direction.z, direction.y) / abs(direction.x); // neg x\n } else if (face == 4.0) {\n uv = vec2(-direction.x, direction.z) / abs(direction.y); // neg y\n } else {\n uv = vec2(direction.x, direction.y) / abs(direction.z); // neg z\n }\n return 0.5 * (uv + 1.0);\n}\n\nvec3 bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {\n float face = getFace(direction);\n float filterInt = max(cubeUV_minMipLevel - mipInt, 0.0);\n mipInt = max(mipInt, cubeUV_minMipLevel);\n float faceSize = exp2(mipInt);\n\n float texelSize = 1.0 / (3.0 * cubeUV_maxTileSize);\n\n vec2 uv = getUV(direction, face) * (faceSize - 1.0);\n vec2 f = fract(uv);\n uv += 0.5 - f;\n if (face > 2.0) {\n uv.y += faceSize;\n face -= 3.0;\n }\n uv.x += face * faceSize;\n if(mipInt < cubeUV_maxMipLevel){\n uv.y += 2.0 * cubeUV_maxTileSize;\n }\n uv.y += filterInt * 2.0 * cubeUV_minTileSize;\n uv.x += 3.0 * max(0.0, cubeUV_maxTileSize - 2.0 * faceSize);\n uv *= texelSize;\n\n vec3 tl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.x += texelSize;\n vec3 tr = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.y += texelSize;\n vec3 br = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.x -= texelSize;\n vec3 bl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n vec3 tm = mix(tl, tr, f.x);\n vec3 bm = mix(bl, br, f.x);\n return mix(tm, bm, f.y);\n}\n\n// These defines must match with PMREMGenerator\n\n#define r0 1.0\n#define v0 0.339\n#define m0 -2.0\n#define r1 0.8\n#define v1 0.276\n#define m1 -1.0\n#define r4 0.4\n#define v4 0.046\n#define m4 2.0\n#define r5 0.305\n#define v5 0.016\n#define m5 3.0\n#define r6 0.21\n#define v6 0.0038\n#define m6 4.0\n\nfloat roughnessToMip(float roughness) {\n float mip = 0.0;\n if (roughness >= r1) {\n mip = (r0 - roughness) * (m1 - m0) / (r0 - r1) + m0;\n } else if (roughness >= r4) {\n mip = (r1 - roughness) * (m4 - m1) / (r1 - r4) + m1;\n } else if (roughness >= r5) {\n mip = (r4 - roughness) * (m5 - m4) / (r4 - r5) + m4;\n } else if (roughness >= r6) {\n mip = (r5 - roughness) * (m6 - m5) / (r5 - r6) + m5;\n } else {\n mip = -2.0 * log2(1.16 * roughness);// 1.16 = 1.79^0.25\n }\n return mip;\n}\n\nvec4 textureCubeUV(sampler2D envMap, vec3 sampleDir, float roughness) {\n float mip = clamp(roughnessToMip(roughness), m0, cubeUV_maxMipLevel);\n float mipF = fract(mip);\n float mipInt = floor(mip);\n\n vec3 color0 = bilinearCubeUV(envMap, sampleDir, mipInt);\n if (mipF == 0.0) {\n return vec4(color0, 1.0);\n } else {\n vec3 color1 = bilinearCubeUV(envMap, sampleDir, mipInt + 1.0);\n return vec4(mix(color0, color1, mipF), 1.0);\n }\n}\n#endif\n`;\n","export default /* glsl */`\nvec3 transformedNormal = objectNormal;\n\n#ifdef USE_INSTANCING\n\n\t// this is in lieu of a per-instance normal-matrix\n\t// shear transforms in the instance matrix are not supported\n\n\tmat3 m = mat3( instanceMatrix );\n\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\n\ttransformedNormal = m * transformedNormal;\n\n#endif\n\ntransformedNormal = normalMatrix * transformedNormal;\n\n#ifdef FLIP_SIDED\n\n\ttransformedNormal = - transformedNormal;\n\n#endif\n\n#ifdef USE_TANGENT\n\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\n\t#ifdef FLIP_SIDED\n\n\t\ttransformedTangent = - transformedTangent;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_DISPLACEMENTMAP\n\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_DISPLACEMENTMAP\n\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_EMISSIVEMAP\n\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_EMISSIVEMAP\n\n\tuniform sampler2D emissiveMap;\n\n#endif\n`;\n","export default /* glsl */`\ngl_FragColor = linearToOutputTexel( gl_FragColor );\n`;\n","export default /* glsl */`\n// For a discussion of what this is, please read this: http://lousodrome.net/blog/light/2013/05/26/gamma-correct-and-hdr-rendering-in-a-32-bits-buffer/\n\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\n\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\n\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\n\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\n\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\n\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\n\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n// return vec4( value.brg, ( 3.0 + 128.0 ) / 256.0 );\n}\n\n// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\n\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\n\n// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\n\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\t// NOTE: The implementation with min causes the shader to not compile on\n\t// a common Alcatel A502DL in Chrome 78/Android 8.1. Some research suggests \n\t// that the chipset is Mediatek MT6739 w/ IMG PowerVR GE8100 GPU.\n\t// D = min( floor( D ) / 255.0, 1.0 );\n\tD = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\n\n// LogLuv reference: http://graphicrants.blogspot.ca/2009/04/rgbm-color-encoding.html\n\n// M matrix, for encoding\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}\n\n// Inverse M matrix, for decoding\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\n}\n`;\n","export default /* glsl */`\n#ifdef USE_ENVMAP\n\n\t#ifdef ENV_WORLDPOS\n\n\t\tvec3 cameraToFrag;\n\t\t\n\t\tif ( isOrthographic ) {\n\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\n\t\t} else {\n\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\n\t\t}\n\n\t\t// Transforming Normal Vectors with the Inverse Transformation\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\n\t\t#else\n\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\n\t\t#endif\n\n\t#else\n\n\t\tvec3 reflectVec = vReflect;\n\n\t#endif\n\n\t#ifdef ENVMAP_TYPE_CUBE\n\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\n\t\treflectVec = normalize( reflectVec );\n\n\t\tvec2 sampleUV = equirectUv( reflectVec );\n\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\n\t\treflectVec = normalize( reflectVec );\n\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\n\t#else\n\n\t\tvec4 envColor = vec4( 0.0 );\n\n\t#endif\n\n\t#ifndef ENVMAP_TYPE_CUBE_UV\n\n\t\tenvColor = envMapTexelToLinear( envColor );\n\n\t#endif\n\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ENVMAP\n\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ENVMAP\n\n\tuniform float reflectivity;\n\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\n\t\t#define ENV_WORLDPOS\n\n\t#endif\n\n\t#ifdef ENV_WORLDPOS\n\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ENVMAP\n\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n\n\t\t#define ENV_WORLDPOS\n\n\t#endif\n\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\n\t#else\n\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_ENVMAP )\n\n\t#ifdef ENVMAP_MODE_REFRACTION\n\t\tuniform float refractionRatio;\n\t#endif\n\n\tvec3 getLightProbeIndirectIrradiance( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in int maxMIPLevel ) {\n\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\n\t\t\t// TODO: replace with properly filtered cubemaps and access the irradiance LOD level, be it the last LOD level\n\t\t\t// of a specular cubemap, or just the default level of a specially created irradiance cubemap.\n\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\n\t\t\t#else\n\n\t\t\t\t// force the bias high to get the last LOD level as it is the most blurred.\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\n\t\t\t#endif\n\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\n\t\t#else\n\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\n\t\t#endif\n\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\n\t}\n\n\t// Trowbridge-Reitz distribution to Mip level, following the logic of http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html\n\tfloat getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {\n\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\n\t\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\n\n\t\t// clamp to allowable LOD ranges.\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\n\t}\n\n\tvec3 getLightProbeIndirectRadiance( /*const in SpecularLightProbe specularLightProbe,*/ const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\n\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\n\t\t vec3 reflectVec = reflect( -viewDir, normal );\n\n\t\t // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.\n\t\t reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\n\t\t#else\n\n\t\t vec3 reflectVec = refract( -viewDir, normal, refractionRatio );\n\n\t\t#endif\n\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );\n\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\n\t\t\t#else\n\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\n\t\t\t#endif\n\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\n\t\t\tvec2 sampleUV = equirectUv( reflectVec );\n\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\n\t\t\t#else\n\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\n\t\t\t#endif\n\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\n\t\t\t#else\n\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\n\t\t\t#endif\n\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\n\t\t#endif\n\n\t\treturn envMapColor.rgb * envMapIntensity;\n\n\t}\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ENVMAP\n\n\t#ifdef ENV_WORLDPOS\n\n\t\tvWorldPosition = worldPosition.xyz;\n\n\t#else\n\n\t\tvec3 cameraToVertex;\n\n\t\tif ( isOrthographic ) { \n\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\n\t\t} else {\n\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\n\t\t}\n\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\n\t\t#else\n\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\n\t\t#endif\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_FOG\n\n\tfogDepth = -mvPosition.z;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_FOG\n\n\tvarying float fogDepth;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_FOG\n\n\t#ifdef FOG_EXP2\n\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\n\n\t#else\n\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\n\t#endif\n\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_FOG\n\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\n\t#ifdef FOG_EXP2\n\n\t\tuniform float fogDensity;\n\n\t#else\n\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n\n#ifdef USE_GRADIENTMAP\n\n\tuniform sampler2D gradientMap;\n\n#endif\n\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\n\t// dotNL will be from -1.0 to 1.0\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\n\t#ifdef USE_GRADIENTMAP\n\n\t\treturn texture2D( gradientMap, coord ).rgb;\n\n\t#else\n\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\n\t#endif\n\n}\n\n`;\n","export default /* glsl */`\n#ifdef USE_LIGHTMAP\n\n\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity; // factor of PI should not be present; included here to prevent breakage\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_LIGHTMAP\n\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n\n#endif\n`;\n","export default /* glsl */`\nvec3 diffuse = vec3( 1.0 );\n\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\n\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\n\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\n\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\n\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry );\n\n#ifdef DOUBLE_SIDED\n\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\n\n#endif\n\n#if NUM_POINT_LIGHTS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\n\t\t#endif\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if NUM_SPOT_LIGHTS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n/*\n#if NUM_RECT_AREA_LIGHTS > 0\n\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\n\t\t// TODO (abelnation): implement\n\n\t}\n\n#endif\n*/\n\n#if NUM_DIR_LIGHTS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\n\t\t#endif\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if NUM_HEMI_LIGHTS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\n\t\t#endif\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n`;\n","export default /* glsl */`\nuniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\n\n// get the irradiance (radiance convolved with cosine lobe) at the point 'normal' on the unit sphere\n// source: https://graphics.stanford.edu/papers/envmap/envmap.pdf\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\n\t// normal is assumed to have unit length\n\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\n\t// band 0\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\n\t// band 1\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\n\t// band 2\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\n\treturn result;\n\n}\n\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\n\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\n\treturn irradiance;\n\n}\n\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\n\tvec3 irradiance = ambientLightColor;\n\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\tirradiance *= PI;\n\n\t#endif\n\n\treturn irradiance;\n\n}\n\n#if NUM_DIR_LIGHTS > 0\n\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\n\t#endif\n\n\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\n\t}\n\n#endif\n\n\n#if NUM_POINT_LIGHTS > 0\n\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t// directLight is an out parameter as having it as a return value caused compiler errors on some devices\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\n\t\tfloat lightDistance = length( lVector );\n\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\n\t}\n\n#endif\n\n\n#if NUM_SPOT_LIGHTS > 0\n\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t// directLight is an out parameter as having it as a return value caused compiler errors on some devices\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\n\t\tif ( angleCos > spotLight.coneCos ) {\n\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\n\t\t} else {\n\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\n\t\t}\n\t}\n\n#endif\n\n\n#if NUM_RECT_AREA_LIGHTS > 0\n\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\n\t// Pre-computed values of LinearTransformedCosine approximation of BRDF\n\t// BRDF approximation Texture is 64x64\n\tuniform sampler2D ltc_1; // RGBA Float\n\tuniform sampler2D ltc_2; // RGBA Float\n\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n\n#endif\n\n\n#if NUM_HEMI_LIGHTS > 0\n\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\t\tirradiance *= PI;\n\n\t\t#endif\n\n\t\treturn irradiance;\n\n\t}\n\n#endif\n`;\n","export default /* glsl */`\nToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n`;\n","export default /* glsl */`\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n\nstruct ToonMaterial {\n\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n\n};\n\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\tirradiance *= PI; // punctual light\n\n\t#endif\n\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n\n}\n\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\n}\n\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n\n#define Material_LightProbeLOD( material )\t(0)\n`;\n","export default /* glsl */`\nBlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n`;\n","export default /* glsl */`\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n\nstruct BlinnPhongMaterial {\n\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n\n};\n\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\tirradiance *= PI; // punctual light\n\n\t#endif\n\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n\n}\n\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\n}\n\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n\n#define Material_LightProbeLOD( material )\t(0)\n`;\n","export default /* glsl */`\nPhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\n\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\n\nmaterial.specularRoughness = max( roughnessFactor, 0.0525 );// 0.0525 corresponds to the base mip of a 256 cubemap.\nmaterial.specularRoughness += geometryRoughness;\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\n\n#ifdef REFLECTIVITY\n\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\n#else\n\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n\n#endif\n\n#ifdef CLEARCOAT\n\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\n\t#ifdef USE_CLEARCOATMAP\n\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\n\t#endif\n\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\n\t#endif\n\n\tmaterial.clearcoat = saturate( material.clearcoat ); // Burley clearcoat model\n\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n\n#endif\n\n#ifdef USE_SHEEN\n\n\tmaterial.sheenColor = sheen;\n\n#endif\n`;\n","export default /* glsl */`\nstruct PhysicalMaterial {\n\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\n#ifdef CLEARCOAT\n\tfloat clearcoat;\n\tfloat clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tvec3 sheenColor;\n#endif\n\n};\n\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\n\n// Clear coat directional hemishperical reflectance (this approximation should be improved)\nfloat clearcoatDHRApprox( const in float roughness, const in float dotNL ) {\n\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n\n}\n\n#if NUM_RECT_AREA_LIGHTS > 0\n\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight; // counterclockwise; light shines in local neg z direction\n\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\n\t\t// LTC Fresnel Approximation by Stephen Hill\n\t\t// http://blog.selfshadow.com/publications/s2016-advances/s2016_ltc_fresnel.pdf\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\n\t}\n\n#endif\n\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\n\tvec3 irradiance = dotNL * directLight.color;\n\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\tirradiance *= PI; // punctual light\n\n\t#endif\n\n\t#ifdef CLEARCOAT\n\n\t\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\n\t\tvec3 ccIrradiance = ccDotNL * directLight.color;\n\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\t\tccIrradiance *= PI; // punctual light\n\n\t\t#endif\n\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\n\t\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\n\t#else\n\n\t\tfloat clearcoatDHR = 0.0;\n\n\t#endif\n\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\n\t\t\tmaterial.specularRoughness,\n\t\t\tdirectLight.direction,\n\t\t\tgeometry,\n\t\t\tmaterial.sheenColor\n\t\t);\n\t#else\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\n\t#endif\n\n\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\n}\n\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\n\t#ifdef CLEARCOAT\n\n\t\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\n\t\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\n\t\tfloat ccDotNL = ccDotNV;\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\n\t#else\n\n\t\tfloat clearcoatDHR = 0.0;\n\n\t#endif\n\n\tfloat clearcoatInv = 1.0 - clearcoatDHR;\n\n\t// Both indirect specular and indirect diffuse light accumulate here\n\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\n\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\n\treflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n\n}\n\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n\n// ref: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n\n}\n`;\n","export default /* glsl */`\n/**\n * This is a template that can be used to light a material, it uses pluggable\n * RenderEquations (RE)for specific lighting scenarios.\n *\n * Instructions for use:\n * - Ensure that both RE_Direct, RE_IndirectDiffuse and RE_IndirectSpecular are defined\n * - If you have defined an RE_IndirectSpecular, you need to also provide a Material_LightProbeLOD. <---- ???\n * - Create a material parameter that is to be passed as the third parameter to your lighting functions.\n *\n * TODO:\n * - Add area light support.\n * - Add sphere light support.\n * - Add diffuse light probe (irradiance cubemap) support.\n */\n\nGeometricContext geometry;\n\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n\n#ifdef CLEARCOAT\n\n\tgeometry.clearcoatNormal = clearcoatNormal;\n\n#endif\n\nIncidentLight directLight;\n\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\n\t\tpointLight = pointLights[ i ];\n\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\n\t\tspotLight = spotLights[ i ];\n\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\n\t\tdirectionalLight = directionalLights[ i ];\n\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\n\tRectAreaLight rectAreaLight;\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if defined( RE_IndirectDiffuse )\n\n\tvec3 iblIrradiance = vec3( 0.0 );\n\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\n\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\n\t\t}\n\t\t#pragma unroll_loop_end\n\n\t#endif\n\n#endif\n\n#if defined( RE_IndirectSpecular )\n\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( RE_IndirectDiffuse )\n\n\t#ifdef USE_LIGHTMAP\n\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\t\tlightMapIrradiance *= PI; // factor of PI should not be present; included here to prevent breakage\n\n\t\t#endif\n\n\t\tirradiance += lightMapIrradiance;\n\n\t#endif\n\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\n\t\tiblIrradiance += getLightProbeIndirectIrradiance( /*lightProbe,*/ geometry, maxMipLevel );\n\n\t#endif\n\n#endif\n\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\n\tradiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\n\n\t#ifdef CLEARCOAT\n\n\t\tclearcoatRadiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( RE_IndirectDiffuse )\n\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n\n#endif\n\n#if defined( RE_IndirectSpecular )\n\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\n\t// Doing a strict comparison with == 1.0 can cause noise artifacts\n\t// on some platforms. See issue #17623.\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_LOGDEPTHBUF\n\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\n\t#else\n\n\t\tuniform float logDepthBufFC;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_LOGDEPTHBUF\n\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\n\t#else\n\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\n\t\t\tgl_Position.z *= gl_Position.w;\n\n\t\t}\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_MAP\n\n\tvec4 texelColor = texture2D( map, vUv );\n\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_MAP\n\n\tuniform sampler2D map;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\n#endif\n\n#ifdef USE_MAP\n\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n\n#endif\n\n#ifdef USE_ALPHAMAP\n\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\n\tuniform mat3 uvTransform;\n\n#endif\n\n#ifdef USE_MAP\n\n\tuniform sampler2D map;\n\n#endif\n\n#ifdef USE_ALPHAMAP\n\n\tuniform sampler2D alphaMap;\n\n#endif\n`;\n","export default /* glsl */`\nfloat metalnessFactor = metalness;\n\n#ifdef USE_METALNESSMAP\n\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\n\t// reads channel B, compatible with a combined OcclusionRoughnessMetallic (RGB) texture\n\tmetalnessFactor *= texelMetalness.b;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_METALNESSMAP\n\n\tuniform sampler2D metalnessMap;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_MORPHNORMALS\n\n\t// morphTargetBaseInfluence is set based on BufferGeometry.morphTargetsRelative value:\n\t// When morphTargetsRelative is false, this is set to 1 - sum(influences); this results in normal = sum((target - base) * influence)\n\t// When morphTargetsRelative is true, this is set to 1; as a result, all morph targets are simply added to the base after weighting\n\tobjectNormal *= morphTargetBaseInfluence;\n\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_MORPHTARGETS\n\n\tuniform float morphTargetBaseInfluence;\n\n\t#ifndef USE_MORPHNORMALS\n\n\tuniform float morphTargetInfluences[ 8 ];\n\n\t#else\n\n\tuniform float morphTargetInfluences[ 4 ];\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_MORPHTARGETS\n\n\t// morphTargetBaseInfluence is set based on BufferGeometry.morphTargetsRelative value:\n\t// When morphTargetsRelative is false, this is set to 1 - sum(influences); this results in position = sum((target - base) * influence)\n\t// When morphTargetsRelative is true, this is set to 1; as a result, all morph targets are simply added to the base after weighting\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\n\t#ifndef USE_MORPHNORMALS\n\n\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef FLAT_SHADED\n\n\t// Workaround for Adreno/Nexus5 not able able to do dFdx( vViewPosition ) ...\n\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n\n#else\n\n\tvec3 normal = normalize( vNormal );\n\n\t#ifdef DOUBLE_SIDED\n\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n\t#endif\n\n\t#ifdef USE_TANGENT\n\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n\t\t#endif\n\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\n\t\t#endif\n\n\t#endif\n\n#endif\n\n// non perturbed normal for clearcoat among others\n\nvec3 geometryNormal = normal;\n\n`;\n","export default /* glsl */`\n\n#ifdef OBJECTSPACE_NORMALMAP\n\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0; // overrides both flatShading and attribute normals\n\n\t#ifdef FLIP_SIDED\n\n\t\tnormal = - normal;\n\n\t#endif\n\n\t#ifdef DOUBLE_SIDED\n\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n\t#endif\n\n\tnormal = normalize( normalMatrix * normal );\n\n#elif defined( TANGENTSPACE_NORMALMAP )\n\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\n\t#ifdef USE_TANGENT\n\n\t\tnormal = normalize( vTBN * mapN );\n\n\t#else\n\n\t\tnormal = perturbNormal2Arb( -vViewPosition, normal, mapN );\n\n\t#endif\n\n#elif defined( USE_BUMPMAP )\n\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_NORMALMAP\n\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\n#endif\n\n#ifdef OBJECTSPACE_NORMALMAP\n\n\tuniform mat3 normalMatrix;\n\n#endif\n\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\n\t// Per-Pixel Tangent Space Normal Mapping\n\t// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html\n\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {\n\n\t\t// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988\n\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s ); // we do not care about the magnitude\n\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\n\t\tmat3 tsn = mat3( S, T, N );\n\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n\t\treturn normalize( tsn * mapN );\n\n\t}\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef CLEARCOAT\n\n\tvec3 clearcoatNormal = geometryNormal;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_CLEARCOAT_NORMALMAP\n\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\n\t#ifdef USE_TANGENT\n\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\n\t#else\n\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN );\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n\n#ifdef USE_CLEARCOATMAP\n\n\tuniform sampler2D clearcoatMap;\n\n#endif\n\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\n\tuniform sampler2D clearcoatRoughnessMap;\n\n#endif\n\n#ifdef USE_CLEARCOAT_NORMALMAP\n\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n\n#endif\n`;\n","export default /* glsl */`\nvec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\n\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\n\nconst float PackUpscale = 256. / 255.; // fraction -> 0..1 (including 1)\nconst float UnpackDownscale = 255. / 256.; // 0..1 -> fraction (excluding 1)\n\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\n\nconst float ShiftRight8 = 1. / 256.;\n\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8; // tidy overflow\n\treturn r * PackUpscale;\n}\n\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\n\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ));\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w);\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\n\n// NOTE: viewZ/eyeZ is < 0 when in front of the camera per OpenGL conventions\n\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\n\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n`;\n","export default /* glsl */`\n#ifdef PREMULTIPLIED_ALPHA\n\n\t// Get get normal blending with premultipled, use with CustomBlending, OneFactor, OneMinusSrcAlphaFactor, AddEquation.\n\tgl_FragColor.rgb *= gl_FragColor.a;\n\n#endif\n`;\n","export default /* glsl */`\nvec4 mvPosition = vec4( transformed, 1.0 );\n\n#ifdef USE_INSTANCING\n\n\tmvPosition = instanceMatrix * mvPosition;\n\n#endif\n\nmvPosition = modelViewMatrix * mvPosition;\n\ngl_Position = projectionMatrix * mvPosition;\n`;\n","export default /* glsl */`\n#ifdef DITHERING\n\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef DITHERING\n\n\t// based on https://www.shadertoy.com/view/MslGR8\n\tvec3 dithering( vec3 color ) {\n\t\t//Calculate grid position\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\n\t\t//Shift the individual colors differently, thus making it even harder to see the dithering pattern\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\n\t\t//modify shift acording to grid position.\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\n\t\t//shift the color by dither_shift\n\t\treturn color + dither_shift_RGB;\n\t}\n\n#endif\n`;\n","export default /* glsl */`\nfloat roughnessFactor = roughness;\n\n#ifdef USE_ROUGHNESSMAP\n\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\n\t// reads channel G, compatible with a combined OcclusionRoughnessMetallic (RGB) texture\n\troughnessFactor *= texelRoughness.g;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ROUGHNESSMAP\n\n\tuniform sampler2D roughnessMap;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SHADOWMAP\n\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t/*\n\t#if NUM_RECT_AREA_LIGHTS > 0\n\n\t\t// TODO (abelnation): create uniforms for area light shadows\n\n\t#endif\n\t*/\n\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\n\t}\n\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\n\t}\n\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\n\t\tfloat occlusion = 1.0;\n\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\n\t\tfloat hard_shadow = step( compare , distribution.x ); // Hard Shadow\n\n\t\tif (hard_shadow != 1.0 ) {\n\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance ); // Chebeyshevs inequality\n\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); // 0.3 reduces light bleed\n\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\n\t\t}\n\t\treturn occlusion;\n\n\t}\n\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\n\t\tfloat shadow = 1.0;\n\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\n\t\t// if ( something && something ) breaks ATI OpenGL shader compiler\n\t\t// if ( all( something, something ) ) using this instead\n\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\n\t\tbool frustumTest = all( frustumTestVec );\n\n\t\tif ( frustumTest ) {\n\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\n\t\t#else // no percentage-closer filtering:\n\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\n\t\t#endif\n\n\t\t}\n\n\t\treturn shadow;\n\n\t}\n\n\t// cubeToUV() maps a 3D direction vector suitable for cube texture mapping to a 2D\n\t// vector suitable for 2D texture mapping. This code uses the following layout for the\n\t// 2D texture:\n\t//\n\t// xzXZ\n\t// y Y\n\t//\n\t// Y - Positive y direction\n\t// y - Negative y direction\n\t// X - Positive x direction\n\t// x - Negative x direction\n\t// Z - Positive z direction\n\t// z - Negative z direction\n\t//\n\t// Source and test bed:\n\t// https://gist.github.com/tschw/da10c43c467ce8afd0c4\n\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\n\t\t// Number of texels to avoid at the edge of each square\n\n\t\tvec3 absV = abs( v );\n\n\t\t// Intersect unit cube\n\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\n\t\t// Apply scale to avoid seams\n\n\t\t// two texels less per square (one texel will do for NEAREST)\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\n\t\t// Unwrap\n\n\t\t// space: -1 ... 1 range for each square\n\t\t//\n\t\t// #X##\t\tdim := ( 4 , 2 )\n\t\t// # #\t\tcenter := ( 1 , 1 )\n\n\t\tvec2 planar = v.xy;\n\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\n\t\tif ( absV.z >= almostOne ) {\n\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\n\t\t} else if ( absV.x >= almostOne ) {\n\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\n\t\t} else if ( absV.y >= almostOne ) {\n\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\n\t\t}\n\n\t\t// Transform to UV space\n\n\t\t// scale := 0.5 / dim\n\t\t// translate := ( center + 0.5 ) / dim\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\n\t}\n\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\n\t\t// for point lights, the uniform @vShadowCoord is re-purposed to hold\n\t\t// the vector from the light to the world-space position of the fragment.\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\n\t\t// dp = normalized distance from light to fragment position\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); // need to clamp?\n\t\tdp += shadowBias;\n\n\t\t// bd3D = base direction 3D\n\t\tvec3 bd3D = normalize( lightToPosition );\n\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\n\t\t#else // no percentage-closer filtering\n\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\n\t\t#endif\n\n\t}\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SHADOWMAP\n\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t/*\n\t#if NUM_RECT_AREA_LIGHTS > 0\n\n\t\t// TODO (abelnation): uniforms for area light shadows\n\n\t#endif\n\t*/\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SHADOWMAP\n\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t/*\n\t#if NUM_RECT_AREA_LIGHTS > 0\n\n\t\t// TODO (abelnation): update vAreaShadowCoord with area light info\n\n\t#endif\n\t*/\n\n#endif\n`;\n","export default /* glsl */`\nfloat getShadowMask() {\n\n\tfloat shadow = 1.0;\n\n\t#ifdef USE_SHADOWMAP\n\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\n\tDirectionalLightShadow directionalLight;\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\n\tSpotLightShadow spotLight;\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\n\tPointLightShadow pointLight;\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t/*\n\t#if NUM_RECT_AREA_LIGHTS > 0\n\n\t\t// TODO (abelnation): update shadow for Area light\n\n\t#endif\n\t*/\n\n\t#endif\n\n\treturn shadow;\n\n}\n`;\n","export default /* glsl */`\n#ifdef USE_SKINNING\n\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SKINNING\n\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\n\t#ifdef BONE_TEXTURE\n\n\t\tuniform highp sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\n\t\tmat4 getBoneMatrix( const in float i ) {\n\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\n\t\t\ty = dy * ( y + 0.5 );\n\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\n\t\t\treturn bone;\n\n\t\t}\n\n\t#else\n\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\n\t\tmat4 getBoneMatrix( const in float i ) {\n\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\n\t\t}\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SKINNING\n\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SKINNING\n\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\n\t#ifdef USE_TANGENT\n\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\nfloat specularStrength;\n\n#ifdef USE_SPECULARMAP\n\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n\n#else\n\n\tspecularStrength = 1.0;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SPECULARMAP\n\n\tuniform sampler2D specularMap;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( TONE_MAPPING )\n\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n\n#endif\n`;\n","export default /* glsl */`\n#ifndef saturate\n// may have defined saturate() already\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\n\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\n\n// exposure only\nvec3 LinearToneMapping( vec3 color ) {\n\n\treturn toneMappingExposure * color;\n\n}\n\n// source: https://www.cs.utah.edu/~reinhard/cdrom/\nvec3 ReinhardToneMapping( vec3 color ) {\n\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n\n}\n\n// source: http://filmicgames.com/archives/75\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\n\t// John Hable's filmic operator from Uncharted 2 video game\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n\n}\n\n// source: http://filmicgames.com/archives/75\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\n\t// optimized filmic operator by Jim Hejl and Richard Burgess-Dawson\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n\n}\n\n// source: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\n\tcolor *= toneMappingExposure;\n\treturn saturate( ( color * ( 2.51 * color + 0.03 ) ) / ( color * ( 2.43 * color + 0.59 ) + 0.14 ) );\n\n}\n`;\n","export default /* glsl */`\n#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\n\tvarying vec2 vUv;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_UV\n\n\t#ifdef UVS_VERTEX_ONLY\n\n\t\tvec2 vUv;\n\n\t#else\n\n\t\tvarying vec2 vUv;\n\n\t#endif\n\n\tuniform mat3 uvTransform;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_UV\n\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\n\tvarying vec2 vUv2;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\n\tuniform mat3 uv2Transform;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\n\t#ifdef USE_INSTANCING\n\n\t\tworldPosition = instanceMatrix * worldPosition;\n\n\t#endif\n\n\tworldPosition = modelMatrix * worldPosition;\n\n#endif\n`;\n","export default /* glsl */`\nuniform sampler2D t2D;\n\nvarying vec2 vUv;\n\nvoid main() {\n\n\tvec4 texColor = texture2D( t2D, vUv );\n\n\tgl_FragColor = mapTexelToLinear( texColor );\n\n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nvarying vec2 vUv;\nuniform mat3 uvTransform;\n\nvoid main() {\n\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n\n}\n`;\n","export default /* glsl */`\n\n#include \nuniform float opacity;\n\nvarying vec3 vWorldDirection;\n\n#include \n\nvoid main() {\n\n\tvec3 vReflect = vWorldDirection;\n\t#include \n\n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nvarying vec3 vWorldDirection;\n\n#include \n\nvoid main() {\n\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t#include \n\t#include \n\n\tgl_Position.z = gl_Position.w; // set z to camera.far\n\n}\n`;\n","export default /* glsl */`\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\n\t#include \n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n`;\n","export default /* glsl */`\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\n// This is used for computing an equivalent of gl_FragCoord.z that is as high precision as possible.\n// Some platforms compute gl_FragCoord at a lower precision which makes the manually computed value better for\n// depth-based postprocessing effects. Reproduced on iPad with A10 processor / iPadOS 13.3.1.\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include \n\n\t#include \n\n\t#ifdef USE_DISPLACEMENTMAP\n\n\t\t#include \n\t\t#include \n\t\t#include \n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvHighPrecisionZW = gl_Position.zw;\n\n}\n`;\n","export default /* glsl */`\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main () {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#include \n\t#include \n\t#include \n\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist ); // clamp to [ 0, 1 ]\n\n\tgl_FragColor = packDepthToRGBA( dist );\n\n}\n`;\n","export default /* glsl */`\n#define DISTANCE\n\nvarying vec3 vWorldPosition;\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\t#include \n\n\t#ifdef USE_DISPLACEMENTMAP\n\n\t\t#include \n\t\t#include \n\t\t#include \n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvWorldPosition = worldPosition.xyz;\n\n}\n`;\n","export default /* glsl */`\nuniform sampler2D tEquirect;\n\nvarying vec3 vWorldDirection;\n\n#include \n\nvoid main() {\n\n\tvec3 direction = normalize( vWorldDirection );\n\n\tvec2 sampleUV = equirectUv( direction );\n\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\n\tgl_FragColor = mapTexelToLinear( texColor );\n\n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nvarying vec3 vWorldDirection;\n\n#include \n\nvoid main() {\n\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform vec3 diffuse;\nuniform float opacity;\n\nuniform float dashSize;\nuniform float totalSize;\n\nvarying float vLineDistance;\n\n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\n\t\tdiscard;\n\n\t}\n\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include \n\t#include \n\n\toutgoingLight = diffuseColor.rgb; // simple shader\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform vec3 diffuse;\nuniform float opacity;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\n\t// accumulation (baked indirect lighting only)\n\t#ifdef USE_LIGHTMAP\n\t\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\n\t#else\n\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\n\t#endif\n\n\t// modulation\n\t#include \n\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\n\t#include \n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#ifdef USE_ENVMAP\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// accumulation\n\n\t#ifdef DOUBLE_SIDED\n\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\n\t#else\n\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\n\t#endif\n\n\t#include \n\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\n\t#ifdef DOUBLE_SIDED\n\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\n\t#else\n\n\t\treflectedLight.directDiffuse = vLightFront;\n\n\t#endif\n\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\n\t// modulation\n\n\t#include \n\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\n\t#include \n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n`;\n","export default /* glsl */`\n#define LAMBERT\n\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n`;\n","export default /* glsl */`\n#define MATCAP\n\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n\n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5; // 0.495 to remove artifacts caused by undersized matcap disks\n\n\t#ifdef USE_MATCAP\n\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\n\t#else\n\n\t\tvec4 matcapColor = vec4( 1.0 );\n\n\t#endif\n\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define MATCAP\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n\n\t\tvNormal = normalize( transformedNormal );\n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\n\tvViewPosition = - mvPosition.xyz;\n\n}\n`;\n","export default /* glsl */`\n#define TOON\n\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// accumulation\n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// modulation\n\t#include \n\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define TOON\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n\n\tvNormal = normalize( transformedNormal );\n\n#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvViewPosition = - mvPosition.xyz;\n\n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define PHONG\n\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// accumulation\n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// modulation\n\t#include \n\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\n\t#include \n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define PHONG\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n\n\tvNormal = normalize( transformedNormal );\n\n#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvViewPosition = - mvPosition.xyz;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define STANDARD\n\n#ifdef PHYSICAL\n\t#define REFLECTIVITY\n\t#define CLEARCOAT\n\t#define TRANSPARENCY\n#endif\n\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n\n#ifdef TRANSPARENCY\n\tuniform float transparency;\n#endif\n\n#ifdef REFLECTIVITY\n\tuniform float reflectivity;\n#endif\n\n#ifdef CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n\n#ifdef USE_SHEEN\n\tuniform vec3 sheen;\n#endif\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n\t#ifdef USE_TANGENT\n\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\n\t#endif\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// accumulation\n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// modulation\n\t#include \n\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\n\t// this is a stub for the transparency model\n\t#ifdef TRANSPARENCY\n\t\tdiffuseColor.a *= saturate( 1. - transparency + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) );\n\t#endif\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define STANDARD\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n\t#ifdef USE_TANGENT\n\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\n\t#endif\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n\n\tvNormal = normalize( transformedNormal );\n\n\t#ifdef USE_TANGENT\n\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\n\t#endif\n\n#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvViewPosition = - mvPosition.xyz;\n\n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define NORMAL\n\nuniform float opacity;\n\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\n\tvarying vec3 vViewPosition;\n\n#endif\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n\t#ifdef USE_TANGENT\n\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\n\t#endif\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\n}\n`;\n","export default /* glsl */`\n#define NORMAL\n\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\n\tvarying vec3 vViewPosition;\n\n#endif\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n\t#ifdef USE_TANGENT\n\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\n\t#endif\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n\n\tvNormal = normalize( transformedNormal );\n\n\t#ifdef USE_TANGENT\n\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\n\t#endif\n\n#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\n\tvViewPosition = - mvPosition.xyz;\n\n#endif\n\n}\n`;\n","export default /* glsl */`\nuniform vec3 diffuse;\nuniform float opacity;\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\toutgoingLight = diffuseColor.rgb;\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform float size;\nuniform float scale;\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\tgl_PointSize = size;\n\n\t#ifdef USE_SIZEATTENUATION\n\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform vec3 color;\nuniform float opacity;\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform vec3 diffuse;\nuniform float opacity;\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\toutgoingLight = diffuseColor.rgb;\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform float rotation;\nuniform vec2 center;\n\n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\n\t#ifndef USE_SIZEATTENUATION\n\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\n\t#endif\n\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\n\tmvPosition.xy += rotatedPosition;\n\n\tgl_Position = projectionMatrix * mvPosition;\n\n\t#include \n\t#include \n\t#include \n\n}\n`;\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { BackSide, FrontSide, CubeUVReflectionMapping } from '../../constants.js';\nimport { BoxBufferGeometry } from '../../geometries/BoxGeometry.js';\nimport { PlaneBufferGeometry } from '../../geometries/PlaneGeometry.js';\nimport { ShaderMaterial } from '../../materials/ShaderMaterial.js';\nimport { Color } from '../../math/Color.js';\nimport { Mesh } from '../../objects/Mesh.js';\nimport { ShaderLib } from '../shaders/ShaderLib.js';\nimport { cloneUniforms } from '../shaders/UniformsUtils.js';\n\nfunction WebGLBackground( renderer, state, objects, premultipliedAlpha ) {\n\n\tvar clearColor = new Color( 0x000000 );\n\tvar clearAlpha = 0;\n\n\tvar planeMesh;\n\tvar boxMesh;\n\n\tvar currentBackground = null;\n\tvar currentBackgroundVersion = 0;\n\tvar currentTonemapping = null;\n\n\tfunction render( renderList, scene, camera, forceClear ) {\n\n\t\tvar background = scene.background;\n\n\t\t// Ignore background in AR\n\t\t// TODO: Reconsider this.\n\n\t\tvar xr = renderer.xr;\n\t\tvar session = xr.getSession && xr.getSession();\n\n\t\tif ( session && session.environmentBlendMode === 'additive' ) {\n\n\t\t\tbackground = null;\n\n\t\t}\n\n\t\tif ( background === null ) {\n\n\t\t\tsetClear( clearColor, clearAlpha );\n\n\t\t} else if ( background && background.isColor ) {\n\n\t\t\tsetClear( background, 1 );\n\t\t\tforceClear = true;\n\n\t\t}\n\n\t\tif ( renderer.autoClear || forceClear ) {\n\n\t\t\trenderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );\n\n\t\t}\n\n\t\tif ( background && ( background.isCubeTexture || background.isWebGLCubeRenderTarget || background.mapping === CubeUVReflectionMapping ) ) {\n\n\t\t\tif ( boxMesh === undefined ) {\n\n\t\t\t\tboxMesh = new Mesh(\n\t\t\t\t\tnew BoxBufferGeometry( 1, 1, 1 ),\n\t\t\t\t\tnew ShaderMaterial( {\n\t\t\t\t\t\ttype: 'BackgroundCubeMaterial',\n\t\t\t\t\t\tuniforms: cloneUniforms( ShaderLib.cube.uniforms ),\n\t\t\t\t\t\tvertexShader: ShaderLib.cube.vertexShader,\n\t\t\t\t\t\tfragmentShader: ShaderLib.cube.fragmentShader,\n\t\t\t\t\t\tside: BackSide,\n\t\t\t\t\t\tdepthTest: false,\n\t\t\t\t\t\tdepthWrite: false,\n\t\t\t\t\t\tfog: false\n\t\t\t\t\t} )\n\t\t\t\t);\n\n\t\t\t\tboxMesh.geometry.deleteAttribute( 'normal' );\n\t\t\t\tboxMesh.geometry.deleteAttribute( 'uv' );\n\n\t\t\t\tboxMesh.onBeforeRender = function ( renderer, scene, camera ) {\n\n\t\t\t\t\tthis.matrixWorld.copyPosition( camera.matrixWorld );\n\n\t\t\t\t};\n\n\t\t\t\t// enable code injection for non-built-in material\n\t\t\t\tObject.defineProperty( boxMesh.material, 'envMap', {\n\n\t\t\t\t\tget: function () {\n\n\t\t\t\t\t\treturn this.uniforms.envMap.value;\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t\tobjects.update( boxMesh );\n\n\t\t\t}\n\n\t\t\tvar texture = background.isWebGLCubeRenderTarget ? background.texture : background;\n\n\t\t\tboxMesh.material.uniforms.envMap.value = texture;\n\t\t\tboxMesh.material.uniforms.flipEnvMap.value = texture.isCubeTexture ? - 1 : 1;\n\n\t\t\tif ( currentBackground !== background ||\n\t\t\t\tcurrentBackgroundVersion !== texture.version ||\n\t\t\t\tcurrentTonemapping !== renderer.toneMapping ) {\n\n\t\t\t\tboxMesh.material.needsUpdate = true;\n\n\t\t\t\tcurrentBackground = background;\n\t\t\t\tcurrentBackgroundVersion = texture.version;\n\t\t\t\tcurrentTonemapping = renderer.toneMapping;\n\n\t\t\t}\n\n\t\t\t// push to the pre-sorted opaque render list\n\t\t\trenderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );\n\n\t\t} else if ( background && background.isTexture ) {\n\n\t\t\tif ( planeMesh === undefined ) {\n\n\t\t\t\tplaneMesh = new Mesh(\n\t\t\t\t\tnew PlaneBufferGeometry( 2, 2 ),\n\t\t\t\t\tnew ShaderMaterial( {\n\t\t\t\t\t\ttype: 'BackgroundMaterial',\n\t\t\t\t\t\tuniforms: cloneUniforms( ShaderLib.background.uniforms ),\n\t\t\t\t\t\tvertexShader: ShaderLib.background.vertexShader,\n\t\t\t\t\t\tfragmentShader: ShaderLib.background.fragmentShader,\n\t\t\t\t\t\tside: FrontSide,\n\t\t\t\t\t\tdepthTest: false,\n\t\t\t\t\t\tdepthWrite: false,\n\t\t\t\t\t\tfog: false\n\t\t\t\t\t} )\n\t\t\t\t);\n\n\t\t\t\tplaneMesh.geometry.deleteAttribute( 'normal' );\n\n\t\t\t\t// enable code injection for non-built-in material\n\t\t\t\tObject.defineProperty( planeMesh.material, 'map', {\n\n\t\t\t\t\tget: function () {\n\n\t\t\t\t\t\treturn this.uniforms.t2D.value;\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t\tobjects.update( planeMesh );\n\n\t\t\t}\n\n\t\t\tplaneMesh.material.uniforms.t2D.value = background;\n\n\t\t\tif ( background.matrixAutoUpdate === true ) {\n\n\t\t\t\tbackground.updateMatrix();\n\n\t\t\t}\n\n\t\t\tplaneMesh.material.uniforms.uvTransform.value.copy( background.matrix );\n\n\t\t\tif ( currentBackground !== background ||\n\t\t\t\tcurrentBackgroundVersion !== background.version ||\n\t\t\t\tcurrentTonemapping !== renderer.toneMapping ) {\n\n\t\t\t\tplaneMesh.material.needsUpdate = true;\n\n\t\t\t\tcurrentBackground = background;\n\t\t\t\tcurrentBackgroundVersion = background.version;\n\t\t\t\tcurrentTonemapping = renderer.toneMapping;\n\n\t\t\t}\n\n\n\t\t\t// push to the pre-sorted opaque render list\n\t\t\trenderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );\n\n\t\t}\n\n\t}\n\n\tfunction setClear( color, alpha ) {\n\n\t\tstate.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );\n\n\t}\n\n\treturn {\n\n\t\tgetClearColor: function () {\n\n\t\t\treturn clearColor;\n\n\t\t},\n\t\tsetClearColor: function ( color, alpha ) {\n\n\t\t\tclearColor.set( color );\n\t\t\tclearAlpha = alpha !== undefined ? alpha : 1;\n\t\t\tsetClear( clearColor, clearAlpha );\n\n\t\t},\n\t\tgetClearAlpha: function () {\n\n\t\t\treturn clearAlpha;\n\n\t\t},\n\t\tsetClearAlpha: function ( alpha ) {\n\n\t\t\tclearAlpha = alpha;\n\t\t\tsetClear( clearColor, clearAlpha );\n\n\t\t},\n\t\trender: render\n\n\t};\n\n}\n\n\nexport { WebGLBackground };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLBufferRenderer( gl, extensions, info, capabilities ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\n\tvar mode;\n\n\tfunction setMode( value ) {\n\n\t\tmode = value;\n\n\t}\n\n\tfunction render( start, count ) {\n\n\t\tgl.drawArrays( mode, start, count );\n\n\t\tinfo.update( count, mode );\n\n\t}\n\n\tfunction renderInstances( geometry, start, count, primcount ) {\n\n\t\tif ( primcount === 0 ) return;\n\n\t\tvar extension, methodName;\n\n\t\tif ( isWebGL2 ) {\n\n\t\t\textension = gl;\n\t\t\tmethodName = 'drawArraysInstanced';\n\n\t\t} else {\n\n\t\t\textension = extensions.get( 'ANGLE_instanced_arrays' );\n\t\t\tmethodName = 'drawArraysInstancedANGLE';\n\n\t\t\tif ( extension === null ) {\n\n\t\t\t\tconsole.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t}\n\n\t\textension[ methodName ]( mode, start, count, primcount );\n\n\t\tinfo.update( count, mode, primcount );\n\n\t}\n\n\t//\n\n\tthis.setMode = setMode;\n\tthis.render = render;\n\tthis.renderInstances = renderInstances;\n\n}\n\n\nexport { WebGLBufferRenderer };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLCapabilities( gl, extensions, parameters ) {\n\n\tvar maxAnisotropy;\n\n\tfunction getMaxAnisotropy() {\n\n\t\tif ( maxAnisotropy !== undefined ) return maxAnisotropy;\n\n\t\tvar extension = extensions.get( 'EXT_texture_filter_anisotropic' );\n\n\t\tif ( extension !== null ) {\n\n\t\t\tmaxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );\n\n\t\t} else {\n\n\t\t\tmaxAnisotropy = 0;\n\n\t\t}\n\n\t\treturn maxAnisotropy;\n\n\t}\n\n\tfunction getMaxPrecision( precision ) {\n\n\t\tif ( precision === 'highp' ) {\n\n\t\t\tif ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&\n\t\t\t\tgl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {\n\n\t\t\t\treturn 'highp';\n\n\t\t\t}\n\n\t\t\tprecision = 'mediump';\n\n\t\t}\n\n\t\tif ( precision === 'mediump' ) {\n\n\t\t\tif ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&\n\t\t\t\tgl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {\n\n\t\t\t\treturn 'mediump';\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn 'lowp';\n\n\t}\n\n\t/* eslint-disable no-undef */\n\tvar isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext ) ||\n\t\t( typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext );\n\t/* eslint-enable no-undef */\n\n\tvar precision = parameters.precision !== undefined ? parameters.precision : 'highp';\n\tvar maxPrecision = getMaxPrecision( precision );\n\n\tif ( maxPrecision !== precision ) {\n\n\t\tconsole.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );\n\t\tprecision = maxPrecision;\n\n\t}\n\n\tvar logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;\n\n\tvar maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );\n\tvar maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );\n\tvar maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );\n\tvar maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );\n\n\tvar maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );\n\tvar maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );\n\tvar maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );\n\tvar maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );\n\n\tvar vertexTextures = maxVertexTextures > 0;\n\tvar floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );\n\tvar floatVertexTextures = vertexTextures && floatFragmentTextures;\n\n\tvar maxSamples = isWebGL2 ? gl.getParameter( gl.MAX_SAMPLES ) : 0;\n\n\treturn {\n\n\t\tisWebGL2: isWebGL2,\n\n\t\tgetMaxAnisotropy: getMaxAnisotropy,\n\t\tgetMaxPrecision: getMaxPrecision,\n\n\t\tprecision: precision,\n\t\tlogarithmicDepthBuffer: logarithmicDepthBuffer,\n\n\t\tmaxTextures: maxTextures,\n\t\tmaxVertexTextures: maxVertexTextures,\n\t\tmaxTextureSize: maxTextureSize,\n\t\tmaxCubemapSize: maxCubemapSize,\n\n\t\tmaxAttributes: maxAttributes,\n\t\tmaxVertexUniforms: maxVertexUniforms,\n\t\tmaxVaryings: maxVaryings,\n\t\tmaxFragmentUniforms: maxFragmentUniforms,\n\n\t\tvertexTextures: vertexTextures,\n\t\tfloatFragmentTextures: floatFragmentTextures,\n\t\tfloatVertexTextures: floatVertexTextures,\n\n\t\tmaxSamples: maxSamples\n\n\t};\n\n}\n\n\nexport { WebGLCapabilities };\n","/**\n * @author tschw\n */\n\nimport { Matrix3 } from '../../math/Matrix3.js';\nimport { Plane } from '../../math/Plane.js';\n\nfunction WebGLClipping() {\n\n\tvar scope = this,\n\n\t\tglobalState = null,\n\t\tnumGlobalPlanes = 0,\n\t\tlocalClippingEnabled = false,\n\t\trenderingShadows = false,\n\n\t\tplane = new Plane(),\n\t\tviewNormalMatrix = new Matrix3(),\n\n\t\tuniform = { value: null, needsUpdate: false };\n\n\tthis.uniform = uniform;\n\tthis.numPlanes = 0;\n\tthis.numIntersection = 0;\n\n\tthis.init = function ( planes, enableLocalClipping, camera ) {\n\n\t\tvar enabled =\n\t\t\tplanes.length !== 0 ||\n\t\t\tenableLocalClipping ||\n\t\t\t// enable state of previous frame - the clipping code has to\n\t\t\t// run another frame in order to reset the state:\n\t\t\tnumGlobalPlanes !== 0 ||\n\t\t\tlocalClippingEnabled;\n\n\t\tlocalClippingEnabled = enableLocalClipping;\n\n\t\tglobalState = projectPlanes( planes, camera, 0 );\n\t\tnumGlobalPlanes = planes.length;\n\n\t\treturn enabled;\n\n\t};\n\n\tthis.beginShadows = function () {\n\n\t\trenderingShadows = true;\n\t\tprojectPlanes( null );\n\n\t};\n\n\tthis.endShadows = function () {\n\n\t\trenderingShadows = false;\n\t\tresetGlobalState();\n\n\t};\n\n\tthis.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) {\n\n\t\tif ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {\n\n\t\t\t// there's no local clipping\n\n\t\t\tif ( renderingShadows ) {\n\n\t\t\t\t// there's no global clipping\n\n\t\t\t\tprojectPlanes( null );\n\n\t\t\t} else {\n\n\t\t\t\tresetGlobalState();\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tvar nGlobal = renderingShadows ? 0 : numGlobalPlanes,\n\t\t\t\tlGlobal = nGlobal * 4,\n\n\t\t\t\tdstArray = cache.clippingState || null;\n\n\t\t\tuniform.value = dstArray; // ensure unique state\n\n\t\t\tdstArray = projectPlanes( planes, camera, lGlobal, fromCache );\n\n\t\t\tfor ( var i = 0; i !== lGlobal; ++ i ) {\n\n\t\t\t\tdstArray[ i ] = globalState[ i ];\n\n\t\t\t}\n\n\t\t\tcache.clippingState = dstArray;\n\t\t\tthis.numIntersection = clipIntersection ? this.numPlanes : 0;\n\t\t\tthis.numPlanes += nGlobal;\n\n\t\t}\n\n\n\t};\n\n\tfunction resetGlobalState() {\n\n\t\tif ( uniform.value !== globalState ) {\n\n\t\t\tuniform.value = globalState;\n\t\t\tuniform.needsUpdate = numGlobalPlanes > 0;\n\n\t\t}\n\n\t\tscope.numPlanes = numGlobalPlanes;\n\t\tscope.numIntersection = 0;\n\n\t}\n\n\tfunction projectPlanes( planes, camera, dstOffset, skipTransform ) {\n\n\t\tvar nPlanes = planes !== null ? planes.length : 0,\n\t\t\tdstArray = null;\n\n\t\tif ( nPlanes !== 0 ) {\n\n\t\t\tdstArray = uniform.value;\n\n\t\t\tif ( skipTransform !== true || dstArray === null ) {\n\n\t\t\t\tvar flatSize = dstOffset + nPlanes * 4,\n\t\t\t\t\tviewMatrix = camera.matrixWorldInverse;\n\n\t\t\t\tviewNormalMatrix.getNormalMatrix( viewMatrix );\n\n\t\t\t\tif ( dstArray === null || dstArray.length < flatSize ) {\n\n\t\t\t\t\tdstArray = new Float32Array( flatSize );\n\n\t\t\t\t}\n\n\t\t\t\tfor ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {\n\n\t\t\t\t\tplane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );\n\n\t\t\t\t\tplane.normal.toArray( dstArray, i4 );\n\t\t\t\t\tdstArray[ i4 + 3 ] = plane.constant;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tuniform.value = dstArray;\n\t\t\tuniform.needsUpdate = true;\n\n\t\t}\n\n\t\tscope.numPlanes = nPlanes;\n\t\tscope.numIntersection = 0;\n\n\t\treturn dstArray;\n\n\t}\n\n}\n\n\nexport { WebGLClipping };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLExtensions( gl ) {\n\n\tvar extensions = {};\n\n\treturn {\n\n\t\tget: function ( name ) {\n\n\t\t\tif ( extensions[ name ] !== undefined ) {\n\n\t\t\t\treturn extensions[ name ];\n\n\t\t\t}\n\n\t\t\tvar extension;\n\n\t\t\tswitch ( name ) {\n\n\t\t\t\tcase 'WEBGL_depth_texture':\n\t\t\t\t\textension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'EXT_texture_filter_anisotropic':\n\t\t\t\t\textension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'WEBGL_compressed_texture_s3tc':\n\t\t\t\t\textension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'WEBGL_compressed_texture_pvrtc':\n\t\t\t\t\textension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\textension = gl.getExtension( name );\n\n\t\t\t}\n\n\t\t\tif ( extension === null ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );\n\n\t\t\t}\n\n\t\t\textensions[ name ] = extension;\n\n\t\t\treturn extension;\n\n\t\t}\n\n\t};\n\n}\n\n\nexport { WebGLExtensions };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute.js';\nimport { BufferGeometry } from '../../core/BufferGeometry.js';\nimport { arrayMax } from '../../utils.js';\n\nfunction WebGLGeometries( gl, attributes, info ) {\n\n\tvar geometries = new WeakMap();\n\tvar wireframeAttributes = new WeakMap();\n\n\tfunction onGeometryDispose( event ) {\n\n\t\tvar geometry = event.target;\n\t\tvar buffergeometry = geometries.get( geometry );\n\n\t\tif ( buffergeometry.index !== null ) {\n\n\t\t\tattributes.remove( buffergeometry.index );\n\n\t\t}\n\n\t\tfor ( var name in buffergeometry.attributes ) {\n\n\t\t\tattributes.remove( buffergeometry.attributes[ name ] );\n\n\t\t}\n\n\t\tgeometry.removeEventListener( 'dispose', onGeometryDispose );\n\n\t\tgeometries.delete( geometry );\n\n\t\tvar attribute = wireframeAttributes.get( buffergeometry );\n\n\t\tif ( attribute ) {\n\n\t\t\tattributes.remove( attribute );\n\t\t\twireframeAttributes.delete( buffergeometry );\n\n\t\t}\n\n\t\t//\n\n\t\tinfo.memory.geometries --;\n\n\t}\n\n\tfunction get( object, geometry ) {\n\n\t\tvar buffergeometry = geometries.get( geometry );\n\n\t\tif ( buffergeometry ) return buffergeometry;\n\n\t\tgeometry.addEventListener( 'dispose', onGeometryDispose );\n\n\t\tif ( geometry.isBufferGeometry ) {\n\n\t\t\tbuffergeometry = geometry;\n\n\t\t} else if ( geometry.isGeometry ) {\n\n\t\t\tif ( geometry._bufferGeometry === undefined ) {\n\n\t\t\t\tgeometry._bufferGeometry = new BufferGeometry().setFromObject( object );\n\n\t\t\t}\n\n\t\t\tbuffergeometry = geometry._bufferGeometry;\n\n\t\t}\n\n\t\tgeometries.set( geometry, buffergeometry );\n\n\t\tinfo.memory.geometries ++;\n\n\t\treturn buffergeometry;\n\n\t}\n\n\tfunction update( geometry ) {\n\n\t\tvar index = geometry.index;\n\t\tvar geometryAttributes = geometry.attributes;\n\n\t\tif ( index !== null ) {\n\n\t\t\tattributes.update( index, gl.ELEMENT_ARRAY_BUFFER );\n\n\t\t}\n\n\t\tfor ( var name in geometryAttributes ) {\n\n\t\t\tattributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );\n\n\t\t}\n\n\t\t// morph targets\n\n\t\tvar morphAttributes = geometry.morphAttributes;\n\n\t\tfor ( var name in morphAttributes ) {\n\n\t\t\tvar array = morphAttributes[ name ];\n\n\t\t\tfor ( var i = 0, l = array.length; i < l; i ++ ) {\n\n\t\t\t\tattributes.update( array[ i ], gl.ARRAY_BUFFER );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tfunction updateWireframeAttribute( geometry ) {\n\n\t\tvar indices = [];\n\n\t\tvar geometryIndex = geometry.index;\n\t\tvar geometryPosition = geometry.attributes.position;\n\t\tvar version = 0;\n\n\t\tif ( geometryIndex !== null ) {\n\n\t\t\tvar array = geometryIndex.array;\n\t\t\tversion = geometryIndex.version;\n\n\t\t\tfor ( var i = 0, l = array.length; i < l; i += 3 ) {\n\n\t\t\t\tvar a = array[ i + 0 ];\n\t\t\t\tvar b = array[ i + 1 ];\n\t\t\t\tvar c = array[ i + 2 ];\n\n\t\t\t\tindices.push( a, b, b, c, c, a );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tvar array = geometryPosition.array;\n\t\t\tversion = geometryPosition.version;\n\n\t\t\tfor ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {\n\n\t\t\t\tvar a = i + 0;\n\t\t\t\tvar b = i + 1;\n\t\t\t\tvar c = i + 2;\n\n\t\t\t\tindices.push( a, b, b, c, c, a );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );\n\t\tattribute.version = version;\n\n\t\tattributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER );\n\n\t\t//\n\n\t\tvar previousAttribute = wireframeAttributes.get( geometry );\n\n\t\tif ( previousAttribute ) attributes.remove( previousAttribute );\n\n\t\t//\n\n\t\twireframeAttributes.set( geometry, attribute );\n\n\t}\n\n\tfunction getWireframeAttribute( geometry ) {\n\n\t\tvar currentAttribute = wireframeAttributes.get( geometry );\n\n\t\tif ( currentAttribute ) {\n\n\t\t\tvar geometryIndex = geometry.index;\n\n\t\t\tif ( geometryIndex !== null ) {\n\n\t\t\t\t// if the attribute is obsolete, create a new one\n\n\t\t\t\tif ( currentAttribute.version < geometryIndex.version ) {\n\n\t\t\t\t\tupdateWireframeAttribute( geometry );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tupdateWireframeAttribute( geometry );\n\n\t\t}\n\n\t\treturn wireframeAttributes.get( geometry );\n\n\t}\n\n\treturn {\n\n\t\tget: get,\n\t\tupdate: update,\n\n\t\tgetWireframeAttribute: getWireframeAttribute\n\n\t};\n\n}\n\n\nexport { WebGLGeometries };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\n\tvar mode;\n\n\tfunction setMode( value ) {\n\n\t\tmode = value;\n\n\t}\n\n\tvar type, bytesPerElement;\n\n\tfunction setIndex( value ) {\n\n\t\ttype = value.type;\n\t\tbytesPerElement = value.bytesPerElement;\n\n\t}\n\n\tfunction render( start, count ) {\n\n\t\tgl.drawElements( mode, count, type, start * bytesPerElement );\n\n\t\tinfo.update( count, mode );\n\n\t}\n\n\tfunction renderInstances( geometry, start, count, primcount ) {\n\n\t\tif ( primcount === 0 ) return;\n\n\t\tvar extension, methodName;\n\n\t\tif ( isWebGL2 ) {\n\n\t\t\textension = gl;\n\t\t\tmethodName = 'drawElementsInstanced';\n\n\t\t} else {\n\n\t\t\textension = extensions.get( 'ANGLE_instanced_arrays' );\n\t\t\tmethodName = 'drawElementsInstancedANGLE';\n\n\t\t\tif ( extension === null ) {\n\n\t\t\t\tconsole.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t}\n\n\t\textension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );\n\n\t\tinfo.update( count, mode, primcount );\n\n\t}\n\n\t//\n\n\tthis.setMode = setMode;\n\tthis.setIndex = setIndex;\n\tthis.render = render;\n\tthis.renderInstances = renderInstances;\n\n}\n\n\nexport { WebGLIndexedBufferRenderer };\n","/**\n * @author Mugen87 / https://github.com/Mugen87\n */\n\nfunction WebGLInfo( gl ) {\n\n\tvar memory = {\n\t\tgeometries: 0,\n\t\ttextures: 0\n\t};\n\n\tvar render = {\n\t\tframe: 0,\n\t\tcalls: 0,\n\t\ttriangles: 0,\n\t\tpoints: 0,\n\t\tlines: 0\n\t};\n\n\tfunction update( count, mode, instanceCount ) {\n\n\t\tinstanceCount = instanceCount || 1;\n\n\t\trender.calls ++;\n\n\t\tswitch ( mode ) {\n\n\t\t\tcase gl.TRIANGLES:\n\t\t\t\trender.triangles += instanceCount * ( count / 3 );\n\t\t\t\tbreak;\n\n\t\t\tcase gl.LINES:\n\t\t\t\trender.lines += instanceCount * ( count / 2 );\n\t\t\t\tbreak;\n\n\t\t\tcase gl.LINE_STRIP:\n\t\t\t\trender.lines += instanceCount * ( count - 1 );\n\t\t\t\tbreak;\n\n\t\t\tcase gl.LINE_LOOP:\n\t\t\t\trender.lines += instanceCount * count;\n\t\t\t\tbreak;\n\n\t\t\tcase gl.POINTS:\n\t\t\t\trender.points += instanceCount * count;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tconsole.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\tfunction reset() {\n\n\t\trender.frame ++;\n\t\trender.calls = 0;\n\t\trender.triangles = 0;\n\t\trender.points = 0;\n\t\trender.lines = 0;\n\n\t}\n\n\treturn {\n\t\tmemory: memory,\n\t\trender: render,\n\t\tprograms: null,\n\t\tautoReset: true,\n\t\treset: reset,\n\t\tupdate: update\n\t};\n\n}\n\n\nexport { WebGLInfo };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction absNumericalSort( a, b ) {\n\n\treturn Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );\n\n}\n\nfunction WebGLMorphtargets( gl ) {\n\n\tvar influencesList = {};\n\tvar morphInfluences = new Float32Array( 8 );\n\n\tfunction update( object, geometry, material, program ) {\n\n\t\tvar objectInfluences = object.morphTargetInfluences;\n\n\t\t// When object doesn't have morph target influences defined, we treat it as a 0-length array\n\t\t// This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences\n\n\t\tvar length = objectInfluences === undefined ? 0 : objectInfluences.length;\n\n\t\tvar influences = influencesList[ geometry.id ];\n\n\t\tif ( influences === undefined ) {\n\n\t\t\t// initialise list\n\n\t\t\tinfluences = [];\n\n\t\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\t\tinfluences[ i ] = [ i, 0 ];\n\n\t\t\t}\n\n\t\t\tinfluencesList[ geometry.id ] = influences;\n\n\t\t}\n\n\t\tvar morphTargets = material.morphTargets && geometry.morphAttributes.position;\n\t\tvar morphNormals = material.morphNormals && geometry.morphAttributes.normal;\n\n\t\t// Remove current morphAttributes\n\n\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\tvar influence = influences[ i ];\n\n\t\t\tif ( influence[ 1 ] !== 0 ) {\n\n\t\t\t\tif ( morphTargets ) geometry.deleteAttribute( 'morphTarget' + i );\n\t\t\t\tif ( morphNormals ) geometry.deleteAttribute( 'morphNormal' + i );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Collect influences\n\n\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\tvar influence = influences[ i ];\n\n\t\t\tinfluence[ 0 ] = i;\n\t\t\tinfluence[ 1 ] = objectInfluences[ i ];\n\n\t\t}\n\n\t\tinfluences.sort( absNumericalSort );\n\n\t\t// Add morphAttributes\n\n\t\tvar morphInfluencesSum = 0;\n\n\t\tfor ( var i = 0; i < 8; i ++ ) {\n\n\t\t\tvar influence = influences[ i ];\n\n\t\t\tif ( influence ) {\n\n\t\t\t\tvar index = influence[ 0 ];\n\t\t\t\tvar value = influence[ 1 ];\n\n\t\t\t\tif ( value ) {\n\n\t\t\t\t\tif ( morphTargets ) geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );\n\t\t\t\t\tif ( morphNormals ) geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );\n\n\t\t\t\t\tmorphInfluences[ i ] = value;\n\t\t\t\t\tmorphInfluencesSum += value;\n\t\t\t\t\tcontinue;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tmorphInfluences[ i ] = 0;\n\n\t\t}\n\n\t\t// GLSL shader uses formula baseinfluence * base + sum(target * influence)\n\t\t// This allows us to switch between absolute morphs and relative morphs without changing shader code\n\t\t// When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)\n\t\tvar morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;\n\n\t\tprogram.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );\n\t\tprogram.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );\n\n\t}\n\n\treturn {\n\n\t\tupdate: update\n\n\t};\n\n}\n\n\nexport { WebGLMorphtargets };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLObjects( gl, geometries, attributes, info ) {\n\n\tvar updateMap = new WeakMap();\n\n\tfunction update( object ) {\n\n\t\tvar frame = info.render.frame;\n\n\t\tvar geometry = object.geometry;\n\t\tvar buffergeometry = geometries.get( object, geometry );\n\n\t\t// Update once per frame\n\n\t\tif ( updateMap.get( buffergeometry ) !== frame ) {\n\n\t\t\tif ( geometry.isGeometry ) {\n\n\t\t\t\tbuffergeometry.updateFromObject( object );\n\n\t\t\t}\n\n\t\t\tgeometries.update( buffergeometry );\n\n\t\t\tupdateMap.set( buffergeometry, frame );\n\n\t\t}\n\n\t\tif ( object.isInstancedMesh ) {\n\n\t\t\tattributes.update( object.instanceMatrix, gl.ARRAY_BUFFER );\n\n\t\t}\n\n\t\treturn buffergeometry;\n\n\t}\n\n\tfunction dispose() {\n\n\t\tupdateMap = new WeakMap();\n\n\t}\n\n\treturn {\n\n\t\tupdate: update,\n\t\tdispose: dispose\n\n\t};\n\n}\n\n\nexport { WebGLObjects };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { Texture } from './Texture.js';\nimport { CubeReflectionMapping, RGBFormat } from '../constants.js';\n\nfunction CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {\n\n\timages = images !== undefined ? images : [];\n\tmapping = mapping !== undefined ? mapping : CubeReflectionMapping;\n\tformat = format !== undefined ? format : RGBFormat;\n\n\tTexture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );\n\n\tthis.flipY = false;\n\n}\n\nCubeTexture.prototype = Object.create( Texture.prototype );\nCubeTexture.prototype.constructor = CubeTexture;\n\nCubeTexture.prototype.isCubeTexture = true;\n\nObject.defineProperty( CubeTexture.prototype, 'images', {\n\n\tget: function () {\n\n\t\treturn this.image;\n\n\t},\n\n\tset: function ( value ) {\n\n\t\tthis.image = value;\n\n\t}\n\n} );\n\n\nexport { CubeTexture };\n","/**\n * @author Takahiro https://github.com/takahirox\n */\n\nimport { Texture } from './Texture.js';\nimport { ClampToEdgeWrapping, NearestFilter } from '../constants.js';\n\nfunction DataTexture2DArray( data, width, height, depth ) {\n\n\tTexture.call( this, null );\n\n\tthis.image = { data: data || null, width: width || 1, height: height || 1, depth: depth || 1 };\n\n\tthis.magFilter = NearestFilter;\n\tthis.minFilter = NearestFilter;\n\n\tthis.wrapR = ClampToEdgeWrapping;\n\n\tthis.generateMipmaps = false;\n\tthis.flipY = false;\n\n\tthis.needsUpdate = true;\n\n}\n\nDataTexture2DArray.prototype = Object.create( Texture.prototype );\nDataTexture2DArray.prototype.constructor = DataTexture2DArray;\nDataTexture2DArray.prototype.isDataTexture2DArray = true;\n\nexport { DataTexture2DArray };\n","/**\n * @author Artur Trzesiok\n */\n\nimport { Texture } from './Texture.js';\nimport { ClampToEdgeWrapping, NearestFilter } from '../constants.js';\n\nfunction DataTexture3D( data, width, height, depth ) {\n\n\t// We're going to add .setXXX() methods for setting properties later.\n\t// Users can still set in DataTexture3D directly.\n\t//\n\t//\tvar texture = new THREE.DataTexture3D( data, width, height, depth );\n\t// \ttexture.anisotropy = 16;\n\t//\n\t// See #14839\n\n\tTexture.call( this, null );\n\n\tthis.image = { data: data || null, width: width || 1, height: height || 1, depth: depth || 1 };\n\n\tthis.magFilter = NearestFilter;\n\tthis.minFilter = NearestFilter;\n\n\tthis.wrapR = ClampToEdgeWrapping;\n\n\tthis.generateMipmaps = false;\n\tthis.flipY = false;\n\n\tthis.needsUpdate = true;\n\n\n}\n\nDataTexture3D.prototype = Object.create( Texture.prototype );\nDataTexture3D.prototype.constructor = DataTexture3D;\nDataTexture3D.prototype.isDataTexture3D = true;\n\nexport { DataTexture3D };\n","import { ShaderChunk } from './ShaderChunk.js';\nimport { mergeUniforms } from './UniformsUtils.js';\nimport { Vector2 } from '../../math/Vector2.js';\nimport { Vector3 } from '../../math/Vector3.js';\nimport { UniformsLib } from './UniformsLib.js';\nimport { Color } from '../../math/Color.js';\nimport { Matrix3 } from '../../math/Matrix3.js';\n\n/**\n * @author alteredq / http://alteredqualia.com/\n * @author mrdoob / http://mrdoob.com/\n * @author mikael emtinger / http://gomo.se/\n */\n\nvar ShaderLib = {\n\n\tbasic: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.specularmap,\n\t\t\tUniformsLib.envmap,\n\t\t\tUniformsLib.aomap,\n\t\t\tUniformsLib.lightmap,\n\t\t\tUniformsLib.fog\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshbasic_vert,\n\t\tfragmentShader: ShaderChunk.meshbasic_frag\n\n\t},\n\n\tlambert: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.specularmap,\n\t\t\tUniformsLib.envmap,\n\t\t\tUniformsLib.aomap,\n\t\t\tUniformsLib.lightmap,\n\t\t\tUniformsLib.emissivemap,\n\t\t\tUniformsLib.fog,\n\t\t\tUniformsLib.lights,\n\t\t\t{\n\t\t\t\temissive: { value: new Color( 0x000000 ) }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshlambert_vert,\n\t\tfragmentShader: ShaderChunk.meshlambert_frag\n\n\t},\n\n\tphong: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.specularmap,\n\t\t\tUniformsLib.envmap,\n\t\t\tUniformsLib.aomap,\n\t\t\tUniformsLib.lightmap,\n\t\t\tUniformsLib.emissivemap,\n\t\t\tUniformsLib.bumpmap,\n\t\t\tUniformsLib.normalmap,\n\t\t\tUniformsLib.displacementmap,\n\t\t\tUniformsLib.fog,\n\t\t\tUniformsLib.lights,\n\t\t\t{\n\t\t\t\temissive: { value: new Color( 0x000000 ) },\n\t\t\t\tspecular: { value: new Color( 0x111111 ) },\n\t\t\t\tshininess: { value: 30 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshphong_vert,\n\t\tfragmentShader: ShaderChunk.meshphong_frag\n\n\t},\n\n\tstandard: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.envmap,\n\t\t\tUniformsLib.aomap,\n\t\t\tUniformsLib.lightmap,\n\t\t\tUniformsLib.emissivemap,\n\t\t\tUniformsLib.bumpmap,\n\t\t\tUniformsLib.normalmap,\n\t\t\tUniformsLib.displacementmap,\n\t\t\tUniformsLib.roughnessmap,\n\t\t\tUniformsLib.metalnessmap,\n\t\t\tUniformsLib.fog,\n\t\t\tUniformsLib.lights,\n\t\t\t{\n\t\t\t\temissive: { value: new Color( 0x000000 ) },\n\t\t\t\troughness: { value: 1.0 },\n\t\t\t\tmetalness: { value: 0.0 },\n\t\t\t\tenvMapIntensity: { value: 1 } // temporary\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshphysical_vert,\n\t\tfragmentShader: ShaderChunk.meshphysical_frag\n\n\t},\n\n\ttoon: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.specularmap,\n\t\t\tUniformsLib.aomap,\n\t\t\tUniformsLib.lightmap,\n\t\t\tUniformsLib.emissivemap,\n\t\t\tUniformsLib.bumpmap,\n\t\t\tUniformsLib.normalmap,\n\t\t\tUniformsLib.displacementmap,\n\t\t\tUniformsLib.gradientmap,\n\t\t\tUniformsLib.fog,\n\t\t\tUniformsLib.lights,\n\t\t\t{\n\t\t\t\temissive: { value: new Color( 0x000000 ) },\n\t\t\t\tspecular: { value: new Color( 0x111111 ) },\n\t\t\t\tshininess: { value: 30 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshtoon_vert,\n\t\tfragmentShader: ShaderChunk.meshtoon_frag\n\n\t},\n\n\tmatcap: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.bumpmap,\n\t\t\tUniformsLib.normalmap,\n\t\t\tUniformsLib.displacementmap,\n\t\t\tUniformsLib.fog,\n\t\t\t{\n\t\t\t\tmatcap: { value: null }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshmatcap_vert,\n\t\tfragmentShader: ShaderChunk.meshmatcap_frag\n\n\t},\n\n\tpoints: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.points,\n\t\t\tUniformsLib.fog\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.points_vert,\n\t\tfragmentShader: ShaderChunk.points_frag\n\n\t},\n\n\tdashed: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.fog,\n\t\t\t{\n\t\t\t\tscale: { value: 1 },\n\t\t\t\tdashSize: { value: 1 },\n\t\t\t\ttotalSize: { value: 2 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.linedashed_vert,\n\t\tfragmentShader: ShaderChunk.linedashed_frag\n\n\t},\n\n\tdepth: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.displacementmap\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.depth_vert,\n\t\tfragmentShader: ShaderChunk.depth_frag\n\n\t},\n\n\tnormal: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.bumpmap,\n\t\t\tUniformsLib.normalmap,\n\t\t\tUniformsLib.displacementmap,\n\t\t\t{\n\t\t\t\topacity: { value: 1.0 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.normal_vert,\n\t\tfragmentShader: ShaderChunk.normal_frag\n\n\t},\n\n\tsprite: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.sprite,\n\t\t\tUniformsLib.fog\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.sprite_vert,\n\t\tfragmentShader: ShaderChunk.sprite_frag\n\n\t},\n\n\tbackground: {\n\n\t\tuniforms: {\n\t\t\tuvTransform: { value: new Matrix3() },\n\t\t\tt2D: { value: null },\n\t\t},\n\n\t\tvertexShader: ShaderChunk.background_vert,\n\t\tfragmentShader: ShaderChunk.background_frag\n\n\t},\n\t/* -------------------------------------------------------------------------\n\t//\tCube map shader\n\t ------------------------------------------------------------------------- */\n\n\tcube: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.envmap,\n\t\t\t{\n\t\t\t\topacity: { value: 1.0 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.cube_vert,\n\t\tfragmentShader: ShaderChunk.cube_frag\n\n\t},\n\n\tequirect: {\n\n\t\tuniforms: {\n\t\t\ttEquirect: { value: null },\n\t\t},\n\n\t\tvertexShader: ShaderChunk.equirect_vert,\n\t\tfragmentShader: ShaderChunk.equirect_frag\n\n\t},\n\n\tdistanceRGBA: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.displacementmap,\n\t\t\t{\n\t\t\t\treferencePosition: { value: new Vector3() },\n\t\t\t\tnearDistance: { value: 1 },\n\t\t\t\tfarDistance: { value: 1000 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.distanceRGBA_vert,\n\t\tfragmentShader: ShaderChunk.distanceRGBA_frag\n\n\t},\n\n\tshadow: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.lights,\n\t\t\tUniformsLib.fog,\n\t\t\t{\n\t\t\t\tcolor: { value: new Color( 0x00000 ) },\n\t\t\t\topacity: { value: 1.0 }\n\t\t\t},\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.shadow_vert,\n\t\tfragmentShader: ShaderChunk.shadow_frag\n\n\t}\n\n};\n\nShaderLib.physical = {\n\n\tuniforms: mergeUniforms( [\n\t\tShaderLib.standard.uniforms,\n\t\t{\n\t\t\tclearcoat: { value: 0 },\n\t\t\tclearcoatMap: { value: null },\n\t\t\tclearcoatRoughness: { value: 0 },\n\t\t\tclearcoatRoughnessMap: { value: null },\n\t\t\tclearcoatNormalScale: { value: new Vector2( 1, 1 ) },\n\t\t\tclearcoatNormalMap: { value: null },\n\t\t\tsheen: { value: new Color( 0x000000 ) },\n\t\t\ttransparency: { value: 0 },\n\t\t}\n\t] ),\n\n\tvertexShader: ShaderChunk.meshphysical_vert,\n\tfragmentShader: ShaderChunk.meshphysical_frag\n\n};\n\n\nexport { ShaderLib };\n","/**\n * @author tschw\n * @author Mugen87 / https://github.com/Mugen87\n * @author mrdoob / http://mrdoob.com/\n *\n * Uniforms of a program.\n * Those form a tree structure with a special top-level container for the root,\n * which you get by calling 'new WebGLUniforms( gl, program )'.\n *\n *\n * Properties of inner nodes including the top-level container:\n *\n * .seq - array of nested uniforms\n * .map - nested uniforms by name\n *\n *\n * Methods of all nodes except the top-level container:\n *\n * .setValue( gl, value, [textures] )\n *\n * \t\tuploads a uniform value(s)\n * \tthe 'textures' parameter is needed for sampler uniforms\n *\n *\n * Static methods of the top-level container (textures factorizations):\n *\n * .upload( gl, seq, values, textures )\n *\n * \t\tsets uniforms in 'seq' to 'values[id].value'\n *\n * .seqWithValue( seq, values ) : filteredSeq\n *\n * \t\tfilters 'seq' entries with corresponding entry in values\n *\n *\n * Methods of the top-level container (textures factorizations):\n *\n * .setValue( gl, name, value, textures )\n *\n * \t\tsets uniform with name 'name' to 'value'\n *\n * .setOptional( gl, obj, prop )\n *\n * \t\tlike .set for an optional property of the object\n *\n */\n\nimport { CubeTexture } from '../../textures/CubeTexture.js';\nimport { Texture } from '../../textures/Texture.js';\nimport { DataTexture2DArray } from '../../textures/DataTexture2DArray.js';\nimport { DataTexture3D } from '../../textures/DataTexture3D.js';\n\nvar emptyTexture = new Texture();\nvar emptyTexture2dArray = new DataTexture2DArray();\nvar emptyTexture3d = new DataTexture3D();\nvar emptyCubeTexture = new CubeTexture();\n\n// --- Utilities ---\n\n// Array Caches (provide typed arrays for temporary by size)\n\nvar arrayCacheF32 = [];\nvar arrayCacheI32 = [];\n\n// Float32Array caches used for uploading Matrix uniforms\n\nvar mat4array = new Float32Array( 16 );\nvar mat3array = new Float32Array( 9 );\nvar mat2array = new Float32Array( 4 );\n\n// Flattening for arrays of vectors and matrices\n\nfunction flatten( array, nBlocks, blockSize ) {\n\n\tvar firstElem = array[ 0 ];\n\n\tif ( firstElem <= 0 || firstElem > 0 ) return array;\n\t// unoptimized: ! isNaN( firstElem )\n\t// see http://jacksondunstan.com/articles/983\n\n\tvar n = nBlocks * blockSize,\n\t\tr = arrayCacheF32[ n ];\n\n\tif ( r === undefined ) {\n\n\t\tr = new Float32Array( n );\n\t\tarrayCacheF32[ n ] = r;\n\n\t}\n\n\tif ( nBlocks !== 0 ) {\n\n\t\tfirstElem.toArray( r, 0 );\n\n\t\tfor ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {\n\n\t\t\toffset += blockSize;\n\t\t\tarray[ i ].toArray( r, offset );\n\n\t\t}\n\n\t}\n\n\treturn r;\n\n}\n\nfunction arraysEqual( a, b ) {\n\n\tif ( a.length !== b.length ) return false;\n\n\tfor ( var i = 0, l = a.length; i < l; i ++ ) {\n\n\t\tif ( a[ i ] !== b[ i ] ) return false;\n\n\t}\n\n\treturn true;\n\n}\n\nfunction copyArray( a, b ) {\n\n\tfor ( var i = 0, l = b.length; i < l; i ++ ) {\n\n\t\ta[ i ] = b[ i ];\n\n\t}\n\n}\n\n// Texture unit allocation\n\nfunction allocTexUnits( textures, n ) {\n\n\tvar r = arrayCacheI32[ n ];\n\n\tif ( r === undefined ) {\n\n\t\tr = new Int32Array( n );\n\t\tarrayCacheI32[ n ] = r;\n\n\t}\n\n\tfor ( var i = 0; i !== n; ++ i )\n\t\tr[ i ] = textures.allocateTextureUnit();\n\n\treturn r;\n\n}\n\n// --- Setters ---\n\n// Note: Defining these methods externally, because they come in a bunch\n// and this way their names minify.\n\n// Single scalar\n\nfunction setValueV1f( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( cache[ 0 ] === v ) return;\n\n\tgl.uniform1f( this.addr, v );\n\n\tcache[ 0 ] = v;\n\n}\n\n// Single float vector (from flat array or THREE.VectorN)\n\nfunction setValueV2f( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( v.x !== undefined ) {\n\n\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {\n\n\t\t\tgl.uniform2f( this.addr, v.x, v.y );\n\n\t\t\tcache[ 0 ] = v.x;\n\t\t\tcache[ 1 ] = v.y;\n\n\t\t}\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniform2fv( this.addr, v );\n\n\t\tcopyArray( cache, v );\n\n\t}\n\n}\n\nfunction setValueV3f( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( v.x !== undefined ) {\n\n\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {\n\n\t\t\tgl.uniform3f( this.addr, v.x, v.y, v.z );\n\n\t\t\tcache[ 0 ] = v.x;\n\t\t\tcache[ 1 ] = v.y;\n\t\t\tcache[ 2 ] = v.z;\n\n\t\t}\n\n\t} else if ( v.r !== undefined ) {\n\n\t\tif ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {\n\n\t\t\tgl.uniform3f( this.addr, v.r, v.g, v.b );\n\n\t\t\tcache[ 0 ] = v.r;\n\t\t\tcache[ 1 ] = v.g;\n\t\t\tcache[ 2 ] = v.b;\n\n\t\t}\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniform3fv( this.addr, v );\n\n\t\tcopyArray( cache, v );\n\n\t}\n\n}\n\nfunction setValueV4f( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( v.x !== undefined ) {\n\n\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {\n\n\t\t\tgl.uniform4f( this.addr, v.x, v.y, v.z, v.w );\n\n\t\t\tcache[ 0 ] = v.x;\n\t\t\tcache[ 1 ] = v.y;\n\t\t\tcache[ 2 ] = v.z;\n\t\t\tcache[ 3 ] = v.w;\n\n\t\t}\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniform4fv( this.addr, v );\n\n\t\tcopyArray( cache, v );\n\n\t}\n\n}\n\n// Single matrix (from flat array or MatrixN)\n\nfunction setValueM2( gl, v ) {\n\n\tvar cache = this.cache;\n\tvar elements = v.elements;\n\n\tif ( elements === undefined ) {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniformMatrix2fv( this.addr, false, v );\n\n\t\tcopyArray( cache, v );\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, elements ) ) return;\n\n\t\tmat2array.set( elements );\n\n\t\tgl.uniformMatrix2fv( this.addr, false, mat2array );\n\n\t\tcopyArray( cache, elements );\n\n\t}\n\n}\n\nfunction setValueM3( gl, v ) {\n\n\tvar cache = this.cache;\n\tvar elements = v.elements;\n\n\tif ( elements === undefined ) {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniformMatrix3fv( this.addr, false, v );\n\n\t\tcopyArray( cache, v );\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, elements ) ) return;\n\n\t\tmat3array.set( elements );\n\n\t\tgl.uniformMatrix3fv( this.addr, false, mat3array );\n\n\t\tcopyArray( cache, elements );\n\n\t}\n\n}\n\nfunction setValueM4( gl, v ) {\n\n\tvar cache = this.cache;\n\tvar elements = v.elements;\n\n\tif ( elements === undefined ) {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniformMatrix4fv( this.addr, false, v );\n\n\t\tcopyArray( cache, v );\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, elements ) ) return;\n\n\t\tmat4array.set( elements );\n\n\t\tgl.uniformMatrix4fv( this.addr, false, mat4array );\n\n\t\tcopyArray( cache, elements );\n\n\t}\n\n}\n\n// Single texture (2D / Cube)\n\nfunction setValueT1( gl, v, textures ) {\n\n\tvar cache = this.cache;\n\tvar unit = textures.allocateTextureUnit();\n\n\tif ( cache[ 0 ] !== unit ) {\n\n\t\tgl.uniform1i( this.addr, unit );\n\t\tcache[ 0 ] = unit;\n\n\t}\n\n\ttextures.safeSetTexture2D( v || emptyTexture, unit );\n\n}\n\nfunction setValueT2DArray1( gl, v, textures ) {\n\n\tvar cache = this.cache;\n\tvar unit = textures.allocateTextureUnit();\n\n\tif ( cache[ 0 ] !== unit ) {\n\n\t\tgl.uniform1i( this.addr, unit );\n\t\tcache[ 0 ] = unit;\n\n\t}\n\n\ttextures.setTexture2DArray( v || emptyTexture2dArray, unit );\n\n}\n\nfunction setValueT3D1( gl, v, textures ) {\n\n\tvar cache = this.cache;\n\tvar unit = textures.allocateTextureUnit();\n\n\tif ( cache[ 0 ] !== unit ) {\n\n\t\tgl.uniform1i( this.addr, unit );\n\t\tcache[ 0 ] = unit;\n\n\t}\n\n\ttextures.setTexture3D( v || emptyTexture3d, unit );\n\n}\n\nfunction setValueT6( gl, v, textures ) {\n\n\tvar cache = this.cache;\n\tvar unit = textures.allocateTextureUnit();\n\n\tif ( cache[ 0 ] !== unit ) {\n\n\t\tgl.uniform1i( this.addr, unit );\n\t\tcache[ 0 ] = unit;\n\n\t}\n\n\ttextures.safeSetTextureCube( v || emptyCubeTexture, unit );\n\n}\n\n// Integer / Boolean vectors or arrays thereof (always flat arrays)\n\nfunction setValueV1i( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( cache[ 0 ] === v ) return;\n\n\tgl.uniform1i( this.addr, v );\n\n\tcache[ 0 ] = v;\n\n}\n\nfunction setValueV2i( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( arraysEqual( cache, v ) ) return;\n\n\tgl.uniform2iv( this.addr, v );\n\n\tcopyArray( cache, v );\n\n}\n\nfunction setValueV3i( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( arraysEqual( cache, v ) ) return;\n\n\tgl.uniform3iv( this.addr, v );\n\n\tcopyArray( cache, v );\n\n}\n\nfunction setValueV4i( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( arraysEqual( cache, v ) ) return;\n\n\tgl.uniform4iv( this.addr, v );\n\n\tcopyArray( cache, v );\n\n}\n\n// uint\n\nfunction setValueV1ui( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( cache[ 0 ] === v ) return;\n\n\tgl.uniform1ui( this.addr, v );\n\n\tcache[ 0 ] = v;\n\n}\n\n// Helper to pick the right setter for the singular case\n\nfunction getSingularSetter( type ) {\n\n\tswitch ( type ) {\n\n\t\tcase 0x1406: return setValueV1f; // FLOAT\n\t\tcase 0x8b50: return setValueV2f; // _VEC2\n\t\tcase 0x8b51: return setValueV3f; // _VEC3\n\t\tcase 0x8b52: return setValueV4f; // _VEC4\n\n\t\tcase 0x8b5a: return setValueM2; // _MAT2\n\t\tcase 0x8b5b: return setValueM3; // _MAT3\n\t\tcase 0x8b5c: return setValueM4; // _MAT4\n\n\t\tcase 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL\n\t\tcase 0x8b53: case 0x8b57: return setValueV2i; // _VEC2\n\t\tcase 0x8b54: case 0x8b58: return setValueV3i; // _VEC3\n\t\tcase 0x8b55: case 0x8b59: return setValueV4i; // _VEC4\n\n\t\tcase 0x1405: return setValueV1ui; // UINT\n\n\t\tcase 0x8b5e: // SAMPLER_2D\n\t\tcase 0x8d66: // SAMPLER_EXTERNAL_OES\n\t\tcase 0x8dca: // INT_SAMPLER_2D\n\t\tcase 0x8dd2: // UNSIGNED_INT_SAMPLER_2D\n\t\tcase 0x8b62: // SAMPLER_2D_SHADOW\n\t\t\treturn setValueT1;\n\n\t\tcase 0x8b5f: // SAMPLER_3D\n\t\tcase 0x8dcb: // INT_SAMPLER_3D\n\t\tcase 0x8dd3: // UNSIGNED_INT_SAMPLER_3D\n\t\t\treturn setValueT3D1;\n\n\t\tcase 0x8b60: // SAMPLER_CUBE\n\t\tcase 0x8dcc: // INT_SAMPLER_CUBE\n\t\tcase 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE\n\t\tcase 0x8dc5: // SAMPLER_CUBE_SHADOW\n\t\t\treturn setValueT6;\n\n\t\tcase 0x8dc1: // SAMPLER_2D_ARRAY\n\t\tcase 0x8dcf: // INT_SAMPLER_2D_ARRAY\n\t\tcase 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY\n\t\tcase 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW\n\t\t\treturn setValueT2DArray1;\n\n\t}\n\n}\n\n// Array of scalars\nfunction setValueV1fArray( gl, v ) {\n\n\tgl.uniform1fv( this.addr, v );\n\n}\n\n// Integer / Boolean vectors or arrays thereof (always flat arrays)\nfunction setValueV1iArray( gl, v ) {\n\n\tgl.uniform1iv( this.addr, v );\n\n}\n\nfunction setValueV2iArray( gl, v ) {\n\n\tgl.uniform2iv( this.addr, v );\n\n}\n\nfunction setValueV3iArray( gl, v ) {\n\n\tgl.uniform3iv( this.addr, v );\n\n}\n\nfunction setValueV4iArray( gl, v ) {\n\n\tgl.uniform4iv( this.addr, v );\n\n}\n\n\n// Array of vectors (flat or from THREE classes)\n\nfunction setValueV2fArray( gl, v ) {\n\n\tvar data = flatten( v, this.size, 2 );\n\n\tgl.uniform2fv( this.addr, data );\n\n}\n\nfunction setValueV3fArray( gl, v ) {\n\n\tvar data = flatten( v, this.size, 3 );\n\n\tgl.uniform3fv( this.addr, data );\n\n}\n\nfunction setValueV4fArray( gl, v ) {\n\n\tvar data = flatten( v, this.size, 4 );\n\n\tgl.uniform4fv( this.addr, data );\n\n}\n\n// Array of matrices (flat or from THREE clases)\n\nfunction setValueM2Array( gl, v ) {\n\n\tvar data = flatten( v, this.size, 4 );\n\n\tgl.uniformMatrix2fv( this.addr, false, data );\n\n}\n\nfunction setValueM3Array( gl, v ) {\n\n\tvar data = flatten( v, this.size, 9 );\n\n\tgl.uniformMatrix3fv( this.addr, false, data );\n\n}\n\nfunction setValueM4Array( gl, v ) {\n\n\tvar data = flatten( v, this.size, 16 );\n\n\tgl.uniformMatrix4fv( this.addr, false, data );\n\n}\n\n// Array of textures (2D / Cube)\n\nfunction setValueT1Array( gl, v, textures ) {\n\n\tvar n = v.length;\n\n\tvar units = allocTexUnits( textures, n );\n\n\tgl.uniform1iv( this.addr, units );\n\n\tfor ( var i = 0; i !== n; ++ i ) {\n\n\t\ttextures.safeSetTexture2D( v[ i ] || emptyTexture, units[ i ] );\n\n\t}\n\n}\n\nfunction setValueT6Array( gl, v, textures ) {\n\n\tvar n = v.length;\n\n\tvar units = allocTexUnits( textures, n );\n\n\tgl.uniform1iv( this.addr, units );\n\n\tfor ( var i = 0; i !== n; ++ i ) {\n\n\t\ttextures.safeSetTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );\n\n\t}\n\n}\n\n// Helper to pick the right setter for a pure (bottom-level) array\n\nfunction getPureArraySetter( type ) {\n\n\tswitch ( type ) {\n\n\t\tcase 0x1406: return setValueV1fArray; // FLOAT\n\t\tcase 0x8b50: return setValueV2fArray; // _VEC2\n\t\tcase 0x8b51: return setValueV3fArray; // _VEC3\n\t\tcase 0x8b52: return setValueV4fArray; // _VEC4\n\n\t\tcase 0x8b5a: return setValueM2Array; // _MAT2\n\t\tcase 0x8b5b: return setValueM3Array; // _MAT3\n\t\tcase 0x8b5c: return setValueM4Array; // _MAT4\n\n\t\tcase 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL\n\t\tcase 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2\n\t\tcase 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3\n\t\tcase 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4\n\n\t\tcase 0x8b5e: // SAMPLER_2D\n\t\tcase 0x8d66: // SAMPLER_EXTERNAL_OES\n\t\tcase 0x8dca: // INT_SAMPLER_2D\n\t\tcase 0x8dd2: // UNSIGNED_INT_SAMPLER_2D\n\t\tcase 0x8b62: // SAMPLER_2D_SHADOW\n\t\t\treturn setValueT1Array;\n\n\t\tcase 0x8b60: // SAMPLER_CUBE\n\t\tcase 0x8dcc: // INT_SAMPLER_CUBE\n\t\tcase 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE\n\t\tcase 0x8dc5: // SAMPLER_CUBE_SHADOW\n\t\t\treturn setValueT6Array;\n\n\t}\n\n}\n\n// --- Uniform Classes ---\n\nfunction SingleUniform( id, activeInfo, addr ) {\n\n\tthis.id = id;\n\tthis.addr = addr;\n\tthis.cache = [];\n\tthis.setValue = getSingularSetter( activeInfo.type );\n\n\t// this.path = activeInfo.name; // DEBUG\n\n}\n\nfunction PureArrayUniform( id, activeInfo, addr ) {\n\n\tthis.id = id;\n\tthis.addr = addr;\n\tthis.cache = [];\n\tthis.size = activeInfo.size;\n\tthis.setValue = getPureArraySetter( activeInfo.type );\n\n\t// this.path = activeInfo.name; // DEBUG\n\n}\n\nPureArrayUniform.prototype.updateCache = function ( data ) {\n\n\tvar cache = this.cache;\n\n\tif ( data instanceof Float32Array && cache.length !== data.length ) {\n\n\t\tthis.cache = new Float32Array( data.length );\n\n\t}\n\n\tcopyArray( cache, data );\n\n};\n\nfunction StructuredUniform( id ) {\n\n\tthis.id = id;\n\n\tthis.seq = [];\n\tthis.map = {};\n\n}\n\nStructuredUniform.prototype.setValue = function ( gl, value, textures ) {\n\n\tvar seq = this.seq;\n\n\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\n\n\t\tvar u = seq[ i ];\n\t\tu.setValue( gl, value[ u.id ], textures );\n\n\t}\n\n};\n\n// --- Top-level ---\n\n// Parser - builds up the property tree from the path strings\n\nvar RePathPart = /([\\w\\d_]+)(\\])?(\\[|\\.)?/g;\n\n// extracts\n// \t- the identifier (member name or array index)\n// - followed by an optional right bracket (found when array index)\n// - followed by an optional left bracket or dot (type of subscript)\n//\n// Note: These portions can be read in a non-overlapping fashion and\n// allow straightforward parsing of the hierarchy that WebGL encodes\n// in the uniform names.\n\nfunction addUniform( container, uniformObject ) {\n\n\tcontainer.seq.push( uniformObject );\n\tcontainer.map[ uniformObject.id ] = uniformObject;\n\n}\n\nfunction parseUniform( activeInfo, addr, container ) {\n\n\tvar path = activeInfo.name,\n\t\tpathLength = path.length;\n\n\t// reset RegExp object, because of the early exit of a previous run\n\tRePathPart.lastIndex = 0;\n\n\twhile ( true ) {\n\n\t\tvar match = RePathPart.exec( path ),\n\t\t\tmatchEnd = RePathPart.lastIndex,\n\n\t\t\tid = match[ 1 ],\n\t\t\tidIsIndex = match[ 2 ] === ']',\n\t\t\tsubscript = match[ 3 ];\n\n\t\tif ( idIsIndex ) id = id | 0; // convert to integer\n\n\t\tif ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {\n\n\t\t\t// bare name or \"pure\" bottom-level array \"[0]\" suffix\n\n\t\t\taddUniform( container, subscript === undefined ?\n\t\t\t\tnew SingleUniform( id, activeInfo, addr ) :\n\t\t\t\tnew PureArrayUniform( id, activeInfo, addr ) );\n\n\t\t\tbreak;\n\n\t\t} else {\n\n\t\t\t// step into inner node / create it in case it doesn't exist\n\n\t\t\tvar map = container.map, next = map[ id ];\n\n\t\t\tif ( next === undefined ) {\n\n\t\t\t\tnext = new StructuredUniform( id );\n\t\t\t\taddUniform( container, next );\n\n\t\t\t}\n\n\t\t\tcontainer = next;\n\n\t\t}\n\n\t}\n\n}\n\n// Root Container\n\nfunction WebGLUniforms( gl, program ) {\n\n\tthis.seq = [];\n\tthis.map = {};\n\n\tvar n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );\n\n\tfor ( var i = 0; i < n; ++ i ) {\n\n\t\tvar info = gl.getActiveUniform( program, i ),\n\t\t\taddr = gl.getUniformLocation( program, info.name );\n\n\t\tparseUniform( info, addr, this );\n\n\t}\n\n}\n\nWebGLUniforms.prototype.setValue = function ( gl, name, value, textures ) {\n\n\tvar u = this.map[ name ];\n\n\tif ( u !== undefined ) u.setValue( gl, value, textures );\n\n};\n\nWebGLUniforms.prototype.setOptional = function ( gl, object, name ) {\n\n\tvar v = object[ name ];\n\n\tif ( v !== undefined ) this.setValue( gl, name, v );\n\n};\n\n\n// Static interface\n\nWebGLUniforms.upload = function ( gl, seq, values, textures ) {\n\n\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\n\n\t\tvar u = seq[ i ],\n\t\t\tv = values[ u.id ];\n\n\t\tif ( v.needsUpdate !== false ) {\n\n\t\t\t// note: always updating when .needsUpdate is undefined\n\t\t\tu.setValue( gl, v.value, textures );\n\n\t\t}\n\n\t}\n\n};\n\nWebGLUniforms.seqWithValue = function ( seq, values ) {\n\n\tvar r = [];\n\n\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\n\n\t\tvar u = seq[ i ];\n\t\tif ( u.id in values ) r.push( u );\n\n\t}\n\n\treturn r;\n\n};\n\nexport { WebGLUniforms };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLShader( gl, type, string ) {\n\n\tvar shader = gl.createShader( type );\n\n\tgl.shaderSource( shader, string );\n\tgl.compileShader( shader );\n\n\treturn shader;\n\n}\n\nexport { WebGLShader };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { WebGLUniforms } from './WebGLUniforms.js';\nimport { WebGLShader } from './WebGLShader.js';\nimport { ShaderChunk } from '../shaders/ShaderChunk.js';\nimport { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, EquirectangularRefractionMapping, CubeRefractionMapping, SphericalReflectionMapping, EquirectangularReflectionMapping, CubeUVRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, VSMShadowMap, ACESFilmicToneMapping, CineonToneMapping, Uncharted2ToneMapping, ReinhardToneMapping, LinearToneMapping, GammaEncoding, RGBDEncoding, RGBM16Encoding, RGBM7Encoding, RGBEEncoding, sRGBEncoding, LinearEncoding, LogLuvEncoding } from '../../constants.js';\n\nvar programIdCount = 0;\n\nfunction addLineNumbers( string ) {\n\n\tvar lines = string.split( '\\n' );\n\n\tfor ( var i = 0; i < lines.length; i ++ ) {\n\n\t\tlines[ i ] = ( i + 1 ) + ': ' + lines[ i ];\n\n\t}\n\n\treturn lines.join( '\\n' );\n\n}\n\nfunction getEncodingComponents( encoding ) {\n\n\tswitch ( encoding ) {\n\n\t\tcase LinearEncoding:\n\t\t\treturn [ 'Linear', '( value )' ];\n\t\tcase sRGBEncoding:\n\t\t\treturn [ 'sRGB', '( value )' ];\n\t\tcase RGBEEncoding:\n\t\t\treturn [ 'RGBE', '( value )' ];\n\t\tcase RGBM7Encoding:\n\t\t\treturn [ 'RGBM', '( value, 7.0 )' ];\n\t\tcase RGBM16Encoding:\n\t\t\treturn [ 'RGBM', '( value, 16.0 )' ];\n\t\tcase RGBDEncoding:\n\t\t\treturn [ 'RGBD', '( value, 256.0 )' ];\n\t\tcase GammaEncoding:\n\t\t\treturn [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];\n\t\tcase LogLuvEncoding:\n\t\t\treturn [ 'LogLuv', '( value )' ];\n\t\tdefault:\n\t\t\tthrow new Error( 'unsupported encoding: ' + encoding );\n\n\t}\n\n}\n\nfunction getShaderErrors( gl, shader, type ) {\n\n\tvar status = gl.getShaderParameter( shader, gl.COMPILE_STATUS );\n\tvar log = gl.getShaderInfoLog( shader ).trim();\n\n\tif ( status && log === '' ) return '';\n\n\t// --enable-privileged-webgl-extension\n\t// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );\n\n\tvar source = gl.getShaderSource( shader );\n\n\treturn 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\\n' + log + addLineNumbers( source );\n\n}\n\nfunction getTexelDecodingFunction( functionName, encoding ) {\n\n\tvar components = getEncodingComponents( encoding );\n\treturn 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';\n\n}\n\nfunction getTexelEncodingFunction( functionName, encoding ) {\n\n\tvar components = getEncodingComponents( encoding );\n\treturn 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';\n\n}\n\nfunction getToneMappingFunction( functionName, toneMapping ) {\n\n\tvar toneMappingName;\n\n\tswitch ( toneMapping ) {\n\n\t\tcase LinearToneMapping:\n\t\t\ttoneMappingName = 'Linear';\n\t\t\tbreak;\n\n\t\tcase ReinhardToneMapping:\n\t\t\ttoneMappingName = 'Reinhard';\n\t\t\tbreak;\n\n\t\tcase Uncharted2ToneMapping:\n\t\t\ttoneMappingName = 'Uncharted2';\n\t\t\tbreak;\n\n\t\tcase CineonToneMapping:\n\t\t\ttoneMappingName = 'OptimizedCineon';\n\t\t\tbreak;\n\n\t\tcase ACESFilmicToneMapping:\n\t\t\ttoneMappingName = 'ACESFilmic';\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tthrow new Error( 'unsupported toneMapping: ' + toneMapping );\n\n\t}\n\n\treturn 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';\n\n}\n\nfunction generateExtensions( parameters ) {\n\n\tvar chunks = [\n\t\t( parameters.extensionDerivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '',\n\t\t( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',\n\t\t( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '',\n\t\t( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''\n\t];\n\n\treturn chunks.filter( filterEmptyLine ).join( '\\n' );\n\n}\n\nfunction generateDefines( defines ) {\n\n\tvar chunks = [];\n\n\tfor ( var name in defines ) {\n\n\t\tvar value = defines[ name ];\n\n\t\tif ( value === false ) continue;\n\n\t\tchunks.push( '#define ' + name + ' ' + value );\n\n\t}\n\n\treturn chunks.join( '\\n' );\n\n}\n\nfunction fetchAttributeLocations( gl, program ) {\n\n\tvar attributes = {};\n\n\tvar n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );\n\n\tfor ( var i = 0; i < n; i ++ ) {\n\n\t\tvar info = gl.getActiveAttrib( program, i );\n\t\tvar name = info.name;\n\n\t\t// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );\n\n\t\tattributes[ name ] = gl.getAttribLocation( program, name );\n\n\t}\n\n\treturn attributes;\n\n}\n\nfunction filterEmptyLine( string ) {\n\n\treturn string !== '';\n\n}\n\nfunction replaceLightNums( string, parameters ) {\n\n\treturn string\n\t\t.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )\n\t\t.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )\n\t\t.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )\n\t\t.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )\n\t\t.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )\n\t\t.replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )\n\t\t.replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )\n\t\t.replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );\n\n}\n\nfunction replaceClippingPlaneNums( string, parameters ) {\n\n\treturn string\n\t\t.replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )\n\t\t.replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );\n\n}\n\n// Resolve Includes\n\nvar includePattern = /^[ \\t]*#include +<([\\w\\d./]+)>/gm;\n\nfunction resolveIncludes( string ) {\n\n\treturn string.replace( includePattern, includeReplacer );\n\n}\n\nfunction includeReplacer( match, include ) {\n\n\tvar string = ShaderChunk[ include ];\n\n\tif ( string === undefined ) {\n\n\t\tthrow new Error( 'Can not resolve #include <' + include + '>' );\n\n\t}\n\n\treturn resolveIncludes( string );\n\n}\n\n// Unroll Loops\n\nvar deprecatedUnrollLoopPattern = /#pragma unroll_loop[\\s]+?for \\( int i \\= (\\d+)\\; i < (\\d+)\\; i \\+\\+ \\) \\{([\\s\\S]+?)(?=\\})\\}/g;\nvar unrollLoopPattern = /#pragma unroll_loop_start[\\s]+?for \\( int i \\= (\\d+)\\; i < (\\d+)\\; i \\+\\+ \\) \\{([\\s\\S]+?)(?=\\})\\}[\\s]+?#pragma unroll_loop_end/g;\n\nfunction unrollLoops( string ) {\n\n\treturn string\n\t\t.replace( unrollLoopPattern, loopReplacer )\n\t\t.replace( deprecatedUnrollLoopPattern, deprecatedLoopReplacer );\n\n}\n\nfunction deprecatedLoopReplacer( match, start, end, snippet ) {\n\n\tconsole.warn( 'WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.' );\n\treturn loopReplacer( match, start, end, snippet );\n\n}\n\nfunction loopReplacer( match, start, end, snippet ) {\n\n\tvar string = '';\n\n\tfor ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {\n\n\t\tstring += snippet\n\t\t\t.replace( /\\[ i \\]/g, '[ ' + i + ' ]' )\n\t\t\t.replace( /UNROLLED_LOOP_INDEX/g, i );\n\n\t}\n\n\treturn string;\n\n}\n\n//\n\nfunction generatePrecision( parameters ) {\n\n\tvar precisionstring = \"precision \" + parameters.precision + \" float;\\nprecision \" + parameters.precision + \" int;\";\n\n\tif ( parameters.precision === \"highp\" ) {\n\n\t\tprecisionstring += \"\\n#define HIGH_PRECISION\";\n\n\t} else if ( parameters.precision === \"mediump\" ) {\n\n\t\tprecisionstring += \"\\n#define MEDIUM_PRECISION\";\n\n\t} else if ( parameters.precision === \"lowp\" ) {\n\n\t\tprecisionstring += \"\\n#define LOW_PRECISION\";\n\n\t}\n\n\treturn precisionstring;\n\n}\n\nfunction generateShadowMapTypeDefine( parameters ) {\n\n\tvar shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';\n\n\tif ( parameters.shadowMapType === PCFShadowMap ) {\n\n\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';\n\n\t} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {\n\n\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';\n\n\t} else if ( parameters.shadowMapType === VSMShadowMap ) {\n\n\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';\n\n\t}\n\n\treturn shadowMapTypeDefine;\n\n}\n\nfunction generateEnvMapTypeDefine( parameters ) {\n\n\tvar envMapTypeDefine = 'ENVMAP_TYPE_CUBE';\n\n\tif ( parameters.envMap ) {\n\n\t\tswitch ( parameters.envMapMode ) {\n\n\t\t\tcase CubeReflectionMapping:\n\t\t\tcase CubeRefractionMapping:\n\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_CUBE';\n\t\t\t\tbreak;\n\n\t\t\tcase CubeUVReflectionMapping:\n\t\t\tcase CubeUVRefractionMapping:\n\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';\n\t\t\t\tbreak;\n\n\t\t\tcase EquirectangularReflectionMapping:\n\t\t\tcase EquirectangularRefractionMapping:\n\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';\n\t\t\t\tbreak;\n\n\t\t\tcase SphericalReflectionMapping:\n\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_SPHERE';\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\treturn envMapTypeDefine;\n\n}\n\nfunction generateEnvMapModeDefine( parameters ) {\n\n\tvar envMapModeDefine = 'ENVMAP_MODE_REFLECTION';\n\n\tif ( parameters.envMap ) {\n\n\t\tswitch ( parameters.envMapMode ) {\n\n\t\t\tcase CubeRefractionMapping:\n\t\t\tcase EquirectangularRefractionMapping:\n\t\t\t\tenvMapModeDefine = 'ENVMAP_MODE_REFRACTION';\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\treturn envMapModeDefine;\n\n}\n\nfunction generateEnvMapBlendingDefine( parameters ) {\n\n\tvar envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';\n\n\tif ( parameters.envMap ) {\n\n\t\tswitch ( parameters.combine ) {\n\n\t\t\tcase MultiplyOperation:\n\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';\n\t\t\t\tbreak;\n\n\t\t\tcase MixOperation:\n\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_MIX';\n\t\t\t\tbreak;\n\n\t\t\tcase AddOperation:\n\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_ADD';\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\treturn envMapBlendingDefine;\n\n}\n\nfunction WebGLProgram( renderer, cacheKey, parameters ) {\n\n\tvar gl = renderer.getContext();\n\n\tvar defines = parameters.defines;\n\n\tvar vertexShader = parameters.vertexShader;\n\tvar fragmentShader = parameters.fragmentShader;\n\tvar shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );\n\tvar envMapTypeDefine = generateEnvMapTypeDefine( parameters );\n\tvar envMapModeDefine = generateEnvMapModeDefine( parameters );\n\tvar envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );\n\n\n\tvar gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;\n\n\tvar customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters );\n\n\tvar customDefines = generateDefines( defines );\n\n\tvar program = gl.createProgram();\n\n\tvar prefixVertex, prefixFragment;\n\n\tif ( parameters.isRawShaderMaterial ) {\n\n\t\tprefixVertex = [\n\n\t\t\tcustomDefines\n\n\t\t].filter( filterEmptyLine ).join( '\\n' );\n\n\t\tif ( prefixVertex.length > 0 ) {\n\n\t\t\tprefixVertex += '\\n';\n\n\t\t}\n\n\t\tprefixFragment = [\n\n\t\t\tcustomExtensions,\n\t\t\tcustomDefines\n\n\t\t].filter( filterEmptyLine ).join( '\\n' );\n\n\t\tif ( prefixFragment.length > 0 ) {\n\n\t\t\tprefixFragment += '\\n';\n\n\t\t}\n\n\t} else {\n\n\t\tprefixVertex = [\n\n\t\t\tgeneratePrecision( parameters ),\n\n\t\t\t'#define SHADER_NAME ' + parameters.shaderName,\n\n\t\t\tcustomDefines,\n\n\t\t\tparameters.instancing ? '#define USE_INSTANCING' : '',\n\t\t\tparameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',\n\n\t\t\t'#define GAMMA_FACTOR ' + gammaFactorDefine,\n\n\t\t\t'#define MAX_BONES ' + parameters.maxBones,\n\t\t\t( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',\n\t\t\t( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',\n\n\t\t\tparameters.map ? '#define USE_MAP' : '',\n\t\t\tparameters.envMap ? '#define USE_ENVMAP' : '',\n\t\t\tparameters.envMap ? '#define ' + envMapModeDefine : '',\n\t\t\tparameters.lightMap ? '#define USE_LIGHTMAP' : '',\n\t\t\tparameters.aoMap ? '#define USE_AOMAP' : '',\n\t\t\tparameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',\n\t\t\tparameters.bumpMap ? '#define USE_BUMPMAP' : '',\n\t\t\tparameters.normalMap ? '#define USE_NORMALMAP' : '',\n\t\t\t( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',\n\t\t\t( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',\n\n\t\t\tparameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',\n\t\t\tparameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',\n\t\t\tparameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',\n\t\t\tparameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',\n\t\t\tparameters.specularMap ? '#define USE_SPECULARMAP' : '',\n\t\t\tparameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',\n\t\t\tparameters.metalnessMap ? '#define USE_METALNESSMAP' : '',\n\t\t\tparameters.alphaMap ? '#define USE_ALPHAMAP' : '',\n\n\t\t\tparameters.vertexTangents ? '#define USE_TANGENT' : '',\n\t\t\tparameters.vertexColors ? '#define USE_COLOR' : '',\n\t\t\tparameters.vertexUvs ? '#define USE_UV' : '',\n\t\t\tparameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',\n\n\t\t\tparameters.flatShading ? '#define FLAT_SHADED' : '',\n\n\t\t\tparameters.skinning ? '#define USE_SKINNING' : '',\n\t\t\tparameters.useVertexTexture ? '#define BONE_TEXTURE' : '',\n\n\t\t\tparameters.morphTargets ? '#define USE_MORPHTARGETS' : '',\n\t\t\tparameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',\n\t\t\tparameters.doubleSided ? '#define DOUBLE_SIDED' : '',\n\t\t\tparameters.flipSided ? '#define FLIP_SIDED' : '',\n\n\t\t\tparameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',\n\t\t\tparameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',\n\n\t\t\tparameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',\n\n\t\t\tparameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',\n\t\t\t( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',\n\n\t\t\t'uniform mat4 modelMatrix;',\n\t\t\t'uniform mat4 modelViewMatrix;',\n\t\t\t'uniform mat4 projectionMatrix;',\n\t\t\t'uniform mat4 viewMatrix;',\n\t\t\t'uniform mat3 normalMatrix;',\n\t\t\t'uniform vec3 cameraPosition;',\n\t\t\t'uniform bool isOrthographic;',\n\n\t\t\t'#ifdef USE_INSTANCING',\n\n\t\t\t' attribute mat4 instanceMatrix;',\n\n\t\t\t'#endif',\n\n\t\t\t'attribute vec3 position;',\n\t\t\t'attribute vec3 normal;',\n\t\t\t'attribute vec2 uv;',\n\n\t\t\t'#ifdef USE_TANGENT',\n\n\t\t\t'\tattribute vec4 tangent;',\n\n\t\t\t'#endif',\n\n\t\t\t'#ifdef USE_COLOR',\n\n\t\t\t'\tattribute vec3 color;',\n\n\t\t\t'#endif',\n\n\t\t\t'#ifdef USE_MORPHTARGETS',\n\n\t\t\t'\tattribute vec3 morphTarget0;',\n\t\t\t'\tattribute vec3 morphTarget1;',\n\t\t\t'\tattribute vec3 morphTarget2;',\n\t\t\t'\tattribute vec3 morphTarget3;',\n\n\t\t\t'\t#ifdef USE_MORPHNORMALS',\n\n\t\t\t'\t\tattribute vec3 morphNormal0;',\n\t\t\t'\t\tattribute vec3 morphNormal1;',\n\t\t\t'\t\tattribute vec3 morphNormal2;',\n\t\t\t'\t\tattribute vec3 morphNormal3;',\n\n\t\t\t'\t#else',\n\n\t\t\t'\t\tattribute vec3 morphTarget4;',\n\t\t\t'\t\tattribute vec3 morphTarget5;',\n\t\t\t'\t\tattribute vec3 morphTarget6;',\n\t\t\t'\t\tattribute vec3 morphTarget7;',\n\n\t\t\t'\t#endif',\n\n\t\t\t'#endif',\n\n\t\t\t'#ifdef USE_SKINNING',\n\n\t\t\t'\tattribute vec4 skinIndex;',\n\t\t\t'\tattribute vec4 skinWeight;',\n\n\t\t\t'#endif',\n\n\t\t\t'\\n'\n\n\t\t].filter( filterEmptyLine ).join( '\\n' );\n\n\t\tprefixFragment = [\n\n\t\t\tcustomExtensions,\n\n\t\t\tgeneratePrecision( parameters ),\n\n\t\t\t'#define SHADER_NAME ' + parameters.shaderName,\n\n\t\t\tcustomDefines,\n\n\t\t\tparameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer\n\n\t\t\t'#define GAMMA_FACTOR ' + gammaFactorDefine,\n\n\t\t\t( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',\n\t\t\t( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',\n\n\t\t\tparameters.map ? '#define USE_MAP' : '',\n\t\t\tparameters.matcap ? '#define USE_MATCAP' : '',\n\t\t\tparameters.envMap ? '#define USE_ENVMAP' : '',\n\t\t\tparameters.envMap ? '#define ' + envMapTypeDefine : '',\n\t\t\tparameters.envMap ? '#define ' + envMapModeDefine : '',\n\t\t\tparameters.envMap ? '#define ' + envMapBlendingDefine : '',\n\t\t\tparameters.lightMap ? '#define USE_LIGHTMAP' : '',\n\t\t\tparameters.aoMap ? '#define USE_AOMAP' : '',\n\t\t\tparameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',\n\t\t\tparameters.bumpMap ? '#define USE_BUMPMAP' : '',\n\t\t\tparameters.normalMap ? '#define USE_NORMALMAP' : '',\n\t\t\t( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',\n\t\t\t( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',\n\t\t\tparameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',\n\t\t\tparameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',\n\t\t\tparameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',\n\t\t\tparameters.specularMap ? '#define USE_SPECULARMAP' : '',\n\t\t\tparameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',\n\t\t\tparameters.metalnessMap ? '#define USE_METALNESSMAP' : '',\n\t\t\tparameters.alphaMap ? '#define USE_ALPHAMAP' : '',\n\n\t\t\tparameters.sheen ? '#define USE_SHEEN' : '',\n\n\t\t\tparameters.vertexTangents ? '#define USE_TANGENT' : '',\n\t\t\tparameters.vertexColors ? '#define USE_COLOR' : '',\n\t\t\tparameters.vertexUvs ? '#define USE_UV' : '',\n\t\t\tparameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',\n\n\t\t\tparameters.gradientMap ? '#define USE_GRADIENTMAP' : '',\n\n\t\t\tparameters.flatShading ? '#define FLAT_SHADED' : '',\n\n\t\t\tparameters.doubleSided ? '#define DOUBLE_SIDED' : '',\n\t\t\tparameters.flipSided ? '#define FLIP_SIDED' : '',\n\n\t\t\tparameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',\n\t\t\tparameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',\n\n\t\t\tparameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',\n\n\t\t\tparameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',\n\n\t\t\tparameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',\n\t\t\t( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',\n\n\t\t\t( ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ) ? '#define TEXTURE_LOD_EXT' : '',\n\n\t\t\t'uniform mat4 viewMatrix;',\n\t\t\t'uniform vec3 cameraPosition;',\n\t\t\t'uniform bool isOrthographic;',\n\n\t\t\t( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',\n\t\t\t( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below\n\t\t\t( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',\n\n\t\t\tparameters.dithering ? '#define DITHERING' : '',\n\n\t\t\t( parameters.outputEncoding || parameters.mapEncoding || parameters.matcapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding || parameters.lightMapEncoding ) ?\n\t\t\t\tShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below\n\t\t\tparameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',\n\t\t\tparameters.matcapEncoding ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',\n\t\t\tparameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',\n\t\t\tparameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',\n\t\t\tparameters.lightMapEncoding ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '',\n\t\t\tparameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',\n\n\t\t\tparameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',\n\n\t\t\t'\\n'\n\n\t\t].filter( filterEmptyLine ).join( '\\n' );\n\n\t}\n\n\tvertexShader = resolveIncludes( vertexShader );\n\tvertexShader = replaceLightNums( vertexShader, parameters );\n\tvertexShader = replaceClippingPlaneNums( vertexShader, parameters );\n\n\tfragmentShader = resolveIncludes( fragmentShader );\n\tfragmentShader = replaceLightNums( fragmentShader, parameters );\n\tfragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );\n\n\tvertexShader = unrollLoops( vertexShader );\n\tfragmentShader = unrollLoops( fragmentShader );\n\n\tif ( parameters.isWebGL2 && ! parameters.isRawShaderMaterial ) {\n\n\t\tvar isGLSL3ShaderMaterial = false;\n\n\t\tvar versionRegex = /^\\s*#version\\s+300\\s+es\\s*\\n/;\n\n\t\tif ( parameters.isShaderMaterial &&\n\t\t\tvertexShader.match( versionRegex ) !== null &&\n\t\t\tfragmentShader.match( versionRegex ) !== null ) {\n\n\t\t\tisGLSL3ShaderMaterial = true;\n\n\t\t\tvertexShader = vertexShader.replace( versionRegex, '' );\n\t\t\tfragmentShader = fragmentShader.replace( versionRegex, '' );\n\n\t\t}\n\n\t\t// GLSL 3.0 conversion\n\n\t\tprefixVertex = [\n\t\t\t'#version 300 es\\n',\n\t\t\t'#define attribute in',\n\t\t\t'#define varying out',\n\t\t\t'#define texture2D texture'\n\t\t].join( '\\n' ) + '\\n' + prefixVertex;\n\n\t\tprefixFragment = [\n\t\t\t'#version 300 es\\n',\n\t\t\t'#define varying in',\n\t\t\tisGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',\n\t\t\tisGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',\n\t\t\t'#define gl_FragDepthEXT gl_FragDepth',\n\t\t\t'#define texture2D texture',\n\t\t\t'#define textureCube texture',\n\t\t\t'#define texture2DProj textureProj',\n\t\t\t'#define texture2DLodEXT textureLod',\n\t\t\t'#define texture2DProjLodEXT textureProjLod',\n\t\t\t'#define textureCubeLodEXT textureLod',\n\t\t\t'#define texture2DGradEXT textureGrad',\n\t\t\t'#define texture2DProjGradEXT textureProjGrad',\n\t\t\t'#define textureCubeGradEXT textureGrad'\n\t\t].join( '\\n' ) + '\\n' + prefixFragment;\n\n\t}\n\n\tvar vertexGlsl = prefixVertex + vertexShader;\n\tvar fragmentGlsl = prefixFragment + fragmentShader;\n\n\t// console.log( '*VERTEX*', vertexGlsl );\n\t// console.log( '*FRAGMENT*', fragmentGlsl );\n\n\tvar glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );\n\tvar glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );\n\n\tgl.attachShader( program, glVertexShader );\n\tgl.attachShader( program, glFragmentShader );\n\n\t// Force a particular attribute to index 0.\n\n\tif ( parameters.index0AttributeName !== undefined ) {\n\n\t\tgl.bindAttribLocation( program, 0, parameters.index0AttributeName );\n\n\t} else if ( parameters.morphTargets === true ) {\n\n\t\t// programs with morphTargets displace position out of attribute 0\n\t\tgl.bindAttribLocation( program, 0, 'position' );\n\n\t}\n\n\tgl.linkProgram( program );\n\n\t// check for link errors\n\tif ( renderer.debug.checkShaderErrors ) {\n\n\t\tvar programLog = gl.getProgramInfoLog( program ).trim();\n\t\tvar vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();\n\t\tvar fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();\n\n\t\tvar runnable = true;\n\t\tvar haveDiagnostics = true;\n\n\t\tif ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {\n\n\t\t\trunnable = false;\n\n\t\t\tvar vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );\n\t\t\tvar fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );\n\n\t\t\tconsole.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors );\n\n\t\t} else if ( programLog !== '' ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );\n\n\t\t} else if ( vertexLog === '' || fragmentLog === '' ) {\n\n\t\t\thaveDiagnostics = false;\n\n\t\t}\n\n\t\tif ( haveDiagnostics ) {\n\n\t\t\tthis.diagnostics = {\n\n\t\t\t\trunnable: runnable,\n\n\t\t\t\tprogramLog: programLog,\n\n\t\t\t\tvertexShader: {\n\n\t\t\t\t\tlog: vertexLog,\n\t\t\t\t\tprefix: prefixVertex\n\n\t\t\t\t},\n\n\t\t\t\tfragmentShader: {\n\n\t\t\t\t\tlog: fragmentLog,\n\t\t\t\t\tprefix: prefixFragment\n\n\t\t\t\t}\n\n\t\t\t};\n\n\t\t}\n\n\t}\n\n\t// Clean up\n\n\t// Crashes in iOS9 and iOS10. #18402\n\t// gl.detachShader( program, glVertexShader );\n\t// gl.detachShader( program, glFragmentShader );\n\n\tgl.deleteShader( glVertexShader );\n\tgl.deleteShader( glFragmentShader );\n\n\t// set up caching for uniform locations\n\n\tvar cachedUniforms;\n\n\tthis.getUniforms = function () {\n\n\t\tif ( cachedUniforms === undefined ) {\n\n\t\t\tcachedUniforms = new WebGLUniforms( gl, program );\n\n\t\t}\n\n\t\treturn cachedUniforms;\n\n\t};\n\n\t// set up caching for attribute locations\n\n\tvar cachedAttributes;\n\n\tthis.getAttributes = function () {\n\n\t\tif ( cachedAttributes === undefined ) {\n\n\t\t\tcachedAttributes = fetchAttributeLocations( gl, program );\n\n\t\t}\n\n\t\treturn cachedAttributes;\n\n\t};\n\n\t// free resource\n\n\tthis.destroy = function () {\n\n\t\tgl.deleteProgram( program );\n\t\tthis.program = undefined;\n\n\t};\n\n\t//\n\n\tthis.name = parameters.shaderName;\n\tthis.id = programIdCount ++;\n\tthis.cacheKey = cacheKey;\n\tthis.usedTimes = 1;\n\tthis.program = program;\n\tthis.vertexShader = glVertexShader;\n\tthis.fragmentShader = glFragmentShader;\n\n\treturn this;\n\n}\n\nexport { WebGLProgram };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { BackSide, DoubleSide, CubeUVRefractionMapping, CubeUVReflectionMapping, LinearEncoding, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping } from '../../constants.js';\nimport { WebGLProgram } from './WebGLProgram.js';\nimport { ShaderLib } from '../shaders/ShaderLib.js';\nimport { UniformsUtils } from '../shaders/UniformsUtils.js';\n\nfunction WebGLPrograms( renderer, extensions, capabilities ) {\n\n\tvar programs = [];\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\tvar logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;\n\tvar floatVertexTextures = capabilities.floatVertexTextures;\n\tvar precision = capabilities.precision;\n\tvar maxVertexUniforms = capabilities.maxVertexUniforms;\n\tvar vertexTextures = capabilities.vertexTextures;\n\n\tvar shaderIDs = {\n\t\tMeshDepthMaterial: 'depth',\n\t\tMeshDistanceMaterial: 'distanceRGBA',\n\t\tMeshNormalMaterial: 'normal',\n\t\tMeshBasicMaterial: 'basic',\n\t\tMeshLambertMaterial: 'lambert',\n\t\tMeshPhongMaterial: 'phong',\n\t\tMeshToonMaterial: 'toon',\n\t\tMeshStandardMaterial: 'physical',\n\t\tMeshPhysicalMaterial: 'physical',\n\t\tMeshMatcapMaterial: 'matcap',\n\t\tLineBasicMaterial: 'basic',\n\t\tLineDashedMaterial: 'dashed',\n\t\tPointsMaterial: 'points',\n\t\tShadowMaterial: 'shadow',\n\t\tSpriteMaterial: 'sprite'\n\t};\n\n\tvar parameterNames = [\n\t\t\"precision\", \"isWebGL2\", \"supportsVertexTextures\", \"outputEncoding\", \"instancing\",\n\t\t\"map\", \"mapEncoding\", \"matcap\", \"matcapEncoding\", \"envMap\", \"envMapMode\", \"envMapEncoding\", \"envMapCubeUV\",\n\t\t\"lightMap\", \"lightMapEncoding\", \"aoMap\", \"emissiveMap\", \"emissiveMapEncoding\", \"bumpMap\", \"normalMap\", \"objectSpaceNormalMap\", \"tangentSpaceNormalMap\", \"clearcoatMap\", \"clearcoatRoughnessMap\", \"clearcoatNormalMap\", \"displacementMap\", \"specularMap\",\n\t\t\"roughnessMap\", \"metalnessMap\", \"gradientMap\",\n\t\t\"alphaMap\", \"combine\", \"vertexColors\", \"vertexTangents\", \"vertexUvs\", \"uvsVertexOnly\", \"fog\", \"useFog\", \"fogExp2\",\n\t\t\"flatShading\", \"sizeAttenuation\", \"logarithmicDepthBuffer\", \"skinning\",\n\t\t\"maxBones\", \"useVertexTexture\", \"morphTargets\", \"morphNormals\",\n\t\t\"maxMorphTargets\", \"maxMorphNormals\", \"premultipliedAlpha\",\n\t\t\"numDirLights\", \"numPointLights\", \"numSpotLights\", \"numHemiLights\", \"numRectAreaLights\",\n\t\t\"numDirLightShadows\", \"numPointLightShadows\", \"numSpotLightShadows\",\n\t\t\"shadowMapEnabled\", \"shadowMapType\", \"toneMapping\", 'physicallyCorrectLights',\n\t\t\"alphaTest\", \"doubleSided\", \"flipSided\", \"numClippingPlanes\", \"numClipIntersection\", \"depthPacking\", \"dithering\",\n\t\t\"sheen\"\n\t];\n\n\tfunction getShaderObject( material, shaderID ) {\n\n\t\tvar shaderobject;\n\n\t\tif ( shaderID ) {\n\n\t\t\tvar shader = ShaderLib[ shaderID ];\n\n\t\t\tshaderobject = {\n\t\t\t\tname: material.type,\n\t\t\t\tuniforms: UniformsUtils.clone( shader.uniforms ),\n\t\t\t\tvertexShader: shader.vertexShader,\n\t\t\t\tfragmentShader: shader.fragmentShader\n\t\t\t};\n\n\t\t} else {\n\n\t\t\tshaderobject = {\n\t\t\t\tname: material.type,\n\t\t\t\tuniforms: material.uniforms,\n\t\t\t\tvertexShader: material.vertexShader,\n\t\t\t\tfragmentShader: material.fragmentShader\n\t\t\t};\n\n\t\t}\n\n\t\treturn shaderobject;\n\n\t}\n\n\tfunction allocateBones( object ) {\n\n\t\tvar skeleton = object.skeleton;\n\t\tvar bones = skeleton.bones;\n\n\t\tif ( floatVertexTextures ) {\n\n\t\t\treturn 1024;\n\n\t\t} else {\n\n\t\t\t// default for when object is not specified\n\t\t\t// ( for example when prebuilding shader to be used with multiple objects )\n\t\t\t//\n\t\t\t// - leave some extra space for other uniforms\n\t\t\t// - limit here is ANGLE's 254 max uniform vectors\n\t\t\t// (up to 54 should be safe)\n\n\t\t\tvar nVertexUniforms = maxVertexUniforms;\n\t\t\tvar nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );\n\n\t\t\tvar maxBones = Math.min( nVertexMatrices, bones.length );\n\n\t\t\tif ( maxBones < bones.length ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );\n\t\t\t\treturn 0;\n\n\t\t\t}\n\n\t\t\treturn maxBones;\n\n\t\t}\n\n\t}\n\n\tfunction getTextureEncodingFromMap( map ) {\n\n\t\tvar encoding;\n\n\t\tif ( ! map ) {\n\n\t\t\tencoding = LinearEncoding;\n\n\t\t} else if ( map.isTexture ) {\n\n\t\t\tencoding = map.encoding;\n\n\t\t} else if ( map.isWebGLRenderTarget ) {\n\n\t\t\tconsole.warn( \"THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead.\" );\n\t\t\tencoding = map.texture.encoding;\n\n\t\t}\n\n\t\treturn encoding;\n\n\t}\n\n\tthis.getParameters = function ( material, lights, shadows, scene, nClipPlanes, nClipIntersection, object ) {\n\n\t\tvar fog = scene.fog;\n\t\tvar environment = material.isMeshStandardMaterial ? scene.environment : null;\n\n\t\tvar envMap = material.envMap || environment;\n\n\t\tvar shaderID = shaderIDs[ material.type ];\n\n\t\t// heuristics to create shader parameters according to lights in the scene\n\t\t// (not to blow over maxLights budget)\n\n\t\tvar maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;\n\n\t\tif ( material.precision !== null ) {\n\n\t\t\tprecision = capabilities.getMaxPrecision( material.precision );\n\n\t\t\tif ( precision !== material.precision ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar shaderobject = getShaderObject( material, shaderID );\n\t\tmaterial.onBeforeCompile( shaderobject, renderer );\n\n\t\tvar currentRenderTarget = renderer.getRenderTarget();\n\n\t\tvar parameters = {\n\n\t\t\tisWebGL2: isWebGL2,\n\n\t\t\tshaderID: shaderID,\n\t\t\tshaderName: shaderobject.name,\n\n\t\t\tuniforms: shaderobject.uniforms,\n\t\t\tvertexShader: shaderobject.vertexShader,\n\t\t\tfragmentShader: shaderobject.fragmentShader,\n\t\t\tdefines: material.defines,\n\n\t\t\tisRawShaderMaterial: material.isRawShaderMaterial,\n\t\t\tisShaderMaterial: material.isShaderMaterial,\n\n\t\t\tprecision: precision,\n\n\t\t\tinstancing: object.isInstancedMesh === true,\n\n\t\t\tsupportsVertexTextures: vertexTextures,\n\t\t\toutputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,\n\t\t\tmap: !! material.map,\n\t\t\tmapEncoding: getTextureEncodingFromMap( material.map ),\n\t\t\tmatcap: !! material.matcap,\n\t\t\tmatcapEncoding: getTextureEncodingFromMap( material.matcap ),\n\t\t\tenvMap: !! envMap,\n\t\t\tenvMapMode: envMap && envMap.mapping,\n\t\t\tenvMapEncoding: getTextureEncodingFromMap( envMap ),\n\t\t\tenvMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ),\n\t\t\tlightMap: !! material.lightMap,\n\t\t\tlightMapEncoding: getTextureEncodingFromMap( material.lightMap ),\n\t\t\taoMap: !! material.aoMap,\n\t\t\temissiveMap: !! material.emissiveMap,\n\t\t\temissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),\n\t\t\tbumpMap: !! material.bumpMap,\n\t\t\tnormalMap: !! material.normalMap,\n\t\t\tobjectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,\n\t\t\ttangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,\n\t\t\tclearcoatMap: !! material.clearcoatMap,\n\t\t\tclearcoatRoughnessMap: !! material.clearcoatRoughnessMap,\n\t\t\tclearcoatNormalMap: !! material.clearcoatNormalMap,\n\t\t\tdisplacementMap: !! material.displacementMap,\n\t\t\troughnessMap: !! material.roughnessMap,\n\t\t\tmetalnessMap: !! material.metalnessMap,\n\t\t\tspecularMap: !! material.specularMap,\n\t\t\talphaMap: !! material.alphaMap,\n\n\t\t\tgradientMap: !! material.gradientMap,\n\n\t\t\tsheen: !! material.sheen,\n\n\t\t\tcombine: material.combine,\n\n\t\t\tvertexTangents: ( material.normalMap && material.vertexTangents ),\n\t\t\tvertexColors: material.vertexColors,\n\t\t\tvertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap,\n\t\t\tuvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap ) && !! material.displacementMap,\n\n\t\t\tfog: !! fog,\n\t\t\tuseFog: material.fog,\n\t\t\tfogExp2: ( fog && fog.isFogExp2 ),\n\n\t\t\tflatShading: material.flatShading,\n\n\t\t\tsizeAttenuation: material.sizeAttenuation,\n\t\t\tlogarithmicDepthBuffer: logarithmicDepthBuffer,\n\n\t\t\tskinning: material.skinning && maxBones > 0,\n\t\t\tmaxBones: maxBones,\n\t\t\tuseVertexTexture: floatVertexTextures,\n\n\t\t\tmorphTargets: material.morphTargets,\n\t\t\tmorphNormals: material.morphNormals,\n\t\t\tmaxMorphTargets: renderer.maxMorphTargets,\n\t\t\tmaxMorphNormals: renderer.maxMorphNormals,\n\n\t\t\tnumDirLights: lights.directional.length,\n\t\t\tnumPointLights: lights.point.length,\n\t\t\tnumSpotLights: lights.spot.length,\n\t\t\tnumRectAreaLights: lights.rectArea.length,\n\t\t\tnumHemiLights: lights.hemi.length,\n\n\t\t\tnumDirLightShadows: lights.directionalShadowMap.length,\n\t\t\tnumPointLightShadows: lights.pointShadowMap.length,\n\t\t\tnumSpotLightShadows: lights.spotShadowMap.length,\n\n\t\t\tnumClippingPlanes: nClipPlanes,\n\t\t\tnumClipIntersection: nClipIntersection,\n\n\t\t\tdithering: material.dithering,\n\n\t\t\tshadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,\n\t\t\tshadowMapType: renderer.shadowMap.type,\n\n\t\t\ttoneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,\n\t\t\tphysicallyCorrectLights: renderer.physicallyCorrectLights,\n\n\t\t\tpremultipliedAlpha: material.premultipliedAlpha,\n\n\t\t\talphaTest: material.alphaTest,\n\t\t\tdoubleSided: material.side === DoubleSide,\n\t\t\tflipSided: material.side === BackSide,\n\n\t\t\tdepthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,\n\n\t\t\tindex0AttributeName: material.index0AttributeName,\n\n\t\t\textensionDerivatives: material.extensions && material.extensions.derivatives,\n\t\t\textensionFragDepth: material.extensions && material.extensions.fragDepth,\n\t\t\textensionDrawBuffers: material.extensions && material.extensions.drawBuffers,\n\t\t\textensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,\n\n\t\t\trendererExtensionFragDepth: isWebGL2 || extensions.get( 'EXT_frag_depth' ) !== null,\n\t\t\trendererExtensionDrawBuffers: isWebGL2 || extensions.get( 'WEBGL_draw_buffers' ) !== null,\n\t\t\trendererExtensionShaderTextureLod: isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) !== null,\n\n\t\t\tonBeforeCompile: material.onBeforeCompile\n\n\t\t};\n\n\t\treturn parameters;\n\n\t};\n\n\tthis.getProgramCacheKey = function ( parameters ) {\n\n\t\tvar array = [];\n\n\t\tif ( parameters.shaderID ) {\n\n\t\t\tarray.push( parameters.shaderID );\n\n\t\t} else {\n\n\t\t\tarray.push( parameters.fragmentShader );\n\t\t\tarray.push( parameters.vertexShader );\n\n\t\t}\n\n\t\tif ( parameters.defines !== undefined ) {\n\n\t\t\tfor ( var name in parameters.defines ) {\n\n\t\t\t\tarray.push( name );\n\t\t\t\tarray.push( parameters.defines[ name ] );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( parameters.isRawShaderMaterial === undefined ) {\n\n\t\t\tfor ( var i = 0; i < parameterNames.length; i ++ ) {\n\n\t\t\t\tarray.push( parameters[ parameterNames[ i ] ] );\n\n\t\t\t}\n\n\t\t\tarray.push( renderer.outputEncoding );\n\t\t\tarray.push( renderer.gammaFactor );\n\n\t\t}\n\n\t\tarray.push( parameters.onBeforeCompile.toString() );\n\n\t\treturn array.join();\n\n\t};\n\n\tthis.acquireProgram = function ( parameters, cacheKey ) {\n\n\t\tvar program;\n\n\t\t// Check if code has been already compiled\n\t\tfor ( var p = 0, pl = programs.length; p < pl; p ++ ) {\n\n\t\t\tvar preexistingProgram = programs[ p ];\n\n\t\t\tif ( preexistingProgram.cacheKey === cacheKey ) {\n\n\t\t\t\tprogram = preexistingProgram;\n\t\t\t\t++ program.usedTimes;\n\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( program === undefined ) {\n\n\t\t\tprogram = new WebGLProgram( renderer, cacheKey, parameters );\n\t\t\tprograms.push( program );\n\n\t\t}\n\n\t\treturn program;\n\n\t};\n\n\tthis.releaseProgram = function ( program ) {\n\n\t\tif ( -- program.usedTimes === 0 ) {\n\n\t\t\t// Remove from unordered set\n\t\t\tvar i = programs.indexOf( program );\n\t\t\tprograms[ i ] = programs[ programs.length - 1 ];\n\t\t\tprograms.pop();\n\n\t\t\t// Free WebGL resources\n\t\t\tprogram.destroy();\n\n\t\t}\n\n\t};\n\n\t// Exposed for resource monitoring & error feedback via renderer.info:\n\tthis.programs = programs;\n\n}\n\n\nexport { WebGLPrograms };\n","/**\n * @author fordacious / fordacious.github.io\n */\n\nfunction WebGLProperties() {\n\n\tvar properties = new WeakMap();\n\n\tfunction get( object ) {\n\n\t\tvar map = properties.get( object );\n\n\t\tif ( map === undefined ) {\n\n\t\t\tmap = {};\n\t\t\tproperties.set( object, map );\n\n\t\t}\n\n\t\treturn map;\n\n\t}\n\n\tfunction remove( object ) {\n\n\t\tproperties.delete( object );\n\n\t}\n\n\tfunction update( object, key, value ) {\n\n\t\tproperties.get( object )[ key ] = value;\n\n\t}\n\n\tfunction dispose() {\n\n\t\tproperties = new WeakMap();\n\n\t}\n\n\treturn {\n\t\tget: get,\n\t\tremove: remove,\n\t\tupdate: update,\n\t\tdispose: dispose\n\t};\n\n}\n\n\nexport { WebGLProperties };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction painterSortStable( a, b ) {\n\n\tif ( a.groupOrder !== b.groupOrder ) {\n\n\t\treturn a.groupOrder - b.groupOrder;\n\n\t} else if ( a.renderOrder !== b.renderOrder ) {\n\n\t\treturn a.renderOrder - b.renderOrder;\n\n\t} else if ( a.program !== b.program ) {\n\n\t\treturn a.program.id - b.program.id;\n\n\t} else if ( a.material.id !== b.material.id ) {\n\n\t\treturn a.material.id - b.material.id;\n\n\t} else if ( a.z !== b.z ) {\n\n\t\treturn a.z - b.z;\n\n\t} else {\n\n\t\treturn a.id - b.id;\n\n\t}\n\n}\n\nfunction reversePainterSortStable( a, b ) {\n\n\tif ( a.groupOrder !== b.groupOrder ) {\n\n\t\treturn a.groupOrder - b.groupOrder;\n\n\t} else if ( a.renderOrder !== b.renderOrder ) {\n\n\t\treturn a.renderOrder - b.renderOrder;\n\n\t} else if ( a.z !== b.z ) {\n\n\t\treturn b.z - a.z;\n\n\t} else {\n\n\t\treturn a.id - b.id;\n\n\t}\n\n}\n\n\nfunction WebGLRenderList() {\n\n\tvar renderItems = [];\n\tvar renderItemsIndex = 0;\n\n\tvar opaque = [];\n\tvar transparent = [];\n\n\tvar defaultProgram = { id: - 1 };\n\n\tfunction init() {\n\n\t\trenderItemsIndex = 0;\n\n\t\topaque.length = 0;\n\t\ttransparent.length = 0;\n\n\t}\n\n\tfunction getNextRenderItem( object, geometry, material, groupOrder, z, group ) {\n\n\t\tvar renderItem = renderItems[ renderItemsIndex ];\n\n\t\tif ( renderItem === undefined ) {\n\n\t\t\trenderItem = {\n\t\t\t\tid: object.id,\n\t\t\t\tobject: object,\n\t\t\t\tgeometry: geometry,\n\t\t\t\tmaterial: material,\n\t\t\t\tprogram: material.program || defaultProgram,\n\t\t\t\tgroupOrder: groupOrder,\n\t\t\t\trenderOrder: object.renderOrder,\n\t\t\t\tz: z,\n\t\t\t\tgroup: group\n\t\t\t};\n\n\t\t\trenderItems[ renderItemsIndex ] = renderItem;\n\n\t\t} else {\n\n\t\t\trenderItem.id = object.id;\n\t\t\trenderItem.object = object;\n\t\t\trenderItem.geometry = geometry;\n\t\t\trenderItem.material = material;\n\t\t\trenderItem.program = material.program || defaultProgram;\n\t\t\trenderItem.groupOrder = groupOrder;\n\t\t\trenderItem.renderOrder = object.renderOrder;\n\t\t\trenderItem.z = z;\n\t\t\trenderItem.group = group;\n\n\t\t}\n\n\t\trenderItemsIndex ++;\n\n\t\treturn renderItem;\n\n\t}\n\n\tfunction push( object, geometry, material, groupOrder, z, group ) {\n\n\t\tvar renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );\n\n\t\t( material.transparent === true ? transparent : opaque ).push( renderItem );\n\n\t}\n\n\tfunction unshift( object, geometry, material, groupOrder, z, group ) {\n\n\t\tvar renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );\n\n\t\t( material.transparent === true ? transparent : opaque ).unshift( renderItem );\n\n\t}\n\n\tfunction sort( customOpaqueSort, customTransparentSort ) {\n\n\t\tif ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );\n\t\tif ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );\n\n\t}\n\n\tfunction finish() {\n\n\t\t// Clear references from inactive renderItems in the list\n\n\t\tfor ( var i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {\n\n\t\t\tvar renderItem = renderItems[ i ];\n\n\t\t\tif ( renderItem.id === null ) break;\n\n\t\t\trenderItem.id = null;\n\t\t\trenderItem.object = null;\n\t\t\trenderItem.geometry = null;\n\t\t\trenderItem.material = null;\n\t\t\trenderItem.program = null;\n\t\t\trenderItem.group = null;\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\topaque: opaque,\n\t\ttransparent: transparent,\n\n\t\tinit: init,\n\t\tpush: push,\n\t\tunshift: unshift,\n\t\tfinish: finish,\n\n\t\tsort: sort\n\t};\n\n}\n\nfunction WebGLRenderLists() {\n\n\tvar lists = new WeakMap();\n\n\tfunction onSceneDispose( event ) {\n\n\t\tvar scene = event.target;\n\n\t\tscene.removeEventListener( 'dispose', onSceneDispose );\n\n\t\tlists.delete( scene );\n\n\t}\n\n\tfunction get( scene, camera ) {\n\n\t\tvar cameras = lists.get( scene );\n\t\tvar list;\n\t\tif ( cameras === undefined ) {\n\n\t\t\tlist = new WebGLRenderList();\n\t\t\tlists.set( scene, new WeakMap() );\n\t\t\tlists.get( scene ).set( camera, list );\n\n\t\t\tscene.addEventListener( 'dispose', onSceneDispose );\n\n\t\t} else {\n\n\t\t\tlist = cameras.get( camera );\n\t\t\tif ( list === undefined ) {\n\n\t\t\t\tlist = new WebGLRenderList();\n\t\t\t\tcameras.set( camera, list );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn list;\n\n\t}\n\n\tfunction dispose() {\n\n\t\tlists = new WeakMap();\n\n\t}\n\n\treturn {\n\t\tget: get,\n\t\tdispose: dispose\n\t};\n\n}\n\n\nexport { WebGLRenderLists };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { Color } from '../../math/Color.js';\nimport { Matrix4 } from '../../math/Matrix4.js';\nimport { Vector2 } from '../../math/Vector2.js';\nimport { Vector3 } from '../../math/Vector3.js';\n\nfunction UniformsCache() {\n\n\tvar lights = {};\n\n\treturn {\n\n\t\tget: function ( light ) {\n\n\t\t\tif ( lights[ light.id ] !== undefined ) {\n\n\t\t\t\treturn lights[ light.id ];\n\n\t\t\t}\n\n\t\t\tvar uniforms;\n\n\t\t\tswitch ( light.type ) {\n\n\t\t\t\tcase 'DirectionalLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tdirection: new Vector3(),\n\t\t\t\t\t\tcolor: new Color()\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'SpotLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tposition: new Vector3(),\n\t\t\t\t\t\tdirection: new Vector3(),\n\t\t\t\t\t\tcolor: new Color(),\n\t\t\t\t\t\tdistance: 0,\n\t\t\t\t\t\tconeCos: 0,\n\t\t\t\t\t\tpenumbraCos: 0,\n\t\t\t\t\t\tdecay: 0\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'PointLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tposition: new Vector3(),\n\t\t\t\t\t\tcolor: new Color(),\n\t\t\t\t\t\tdistance: 0,\n\t\t\t\t\t\tdecay: 0\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'HemisphereLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tdirection: new Vector3(),\n\t\t\t\t\t\tskyColor: new Color(),\n\t\t\t\t\t\tgroundColor: new Color()\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'RectAreaLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tcolor: new Color(),\n\t\t\t\t\t\tposition: new Vector3(),\n\t\t\t\t\t\thalfWidth: new Vector3(),\n\t\t\t\t\t\thalfHeight: new Vector3()\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tlights[ light.id ] = uniforms;\n\n\t\t\treturn uniforms;\n\n\t\t}\n\n\t};\n\n}\n\nfunction ShadowUniformsCache() {\n\n\tvar lights = {};\n\n\treturn {\n\n\t\tget: function ( light ) {\n\n\t\t\tif ( lights[ light.id ] !== undefined ) {\n\n\t\t\t\treturn lights[ light.id ];\n\n\t\t\t}\n\n\t\t\tvar uniforms;\n\n\t\t\tswitch ( light.type ) {\n\n\t\t\t\tcase 'DirectionalLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tshadowBias: 0,\n\t\t\t\t\t\tshadowRadius: 1,\n\t\t\t\t\t\tshadowMapSize: new Vector2()\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'SpotLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tshadowBias: 0,\n\t\t\t\t\t\tshadowRadius: 1,\n\t\t\t\t\t\tshadowMapSize: new Vector2()\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'PointLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tshadowBias: 0,\n\t\t\t\t\t\tshadowRadius: 1,\n\t\t\t\t\t\tshadowMapSize: new Vector2(),\n\t\t\t\t\t\tshadowCameraNear: 1,\n\t\t\t\t\t\tshadowCameraFar: 1000\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\t// TODO (abelnation): set RectAreaLight shadow uniforms\n\n\t\t\t}\n\n\t\t\tlights[ light.id ] = uniforms;\n\n\t\t\treturn uniforms;\n\n\t\t}\n\n\t};\n\n}\n\n\n\nvar nextVersion = 0;\n\nfunction shadowCastingLightsFirst( lightA, lightB ) {\n\n\treturn ( lightB.castShadow ? 1 : 0 ) - ( lightA.castShadow ? 1 : 0 );\n\n}\n\nfunction WebGLLights() {\n\n\tvar cache = new UniformsCache();\n\n\tvar shadowCache = ShadowUniformsCache();\n\n\tvar state = {\n\n\t\tversion: 0,\n\n\t\thash: {\n\t\t\tdirectionalLength: - 1,\n\t\t\tpointLength: - 1,\n\t\t\tspotLength: - 1,\n\t\t\trectAreaLength: - 1,\n\t\t\themiLength: - 1,\n\n\t\t\tnumDirectionalShadows: - 1,\n\t\t\tnumPointShadows: - 1,\n\t\t\tnumSpotShadows: - 1\n\t\t},\n\n\t\tambient: [ 0, 0, 0 ],\n\t\tprobe: [],\n\t\tdirectional: [],\n\t\tdirectionalShadow: [],\n\t\tdirectionalShadowMap: [],\n\t\tdirectionalShadowMatrix: [],\n\t\tspot: [],\n\t\tspotShadow: [],\n\t\tspotShadowMap: [],\n\t\tspotShadowMatrix: [],\n\t\trectArea: [],\n\t\tpoint: [],\n\t\tpointShadow: [],\n\t\tpointShadowMap: [],\n\t\tpointShadowMatrix: [],\n\t\themi: []\n\n\t};\n\n\tfor ( var i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );\n\n\tvar vector3 = new Vector3();\n\tvar matrix4 = new Matrix4();\n\tvar matrix42 = new Matrix4();\n\n\tfunction setup( lights, shadows, camera ) {\n\n\t\tvar r = 0, g = 0, b = 0;\n\n\t\tfor ( var i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );\n\n\t\tvar directionalLength = 0;\n\t\tvar pointLength = 0;\n\t\tvar spotLength = 0;\n\t\tvar rectAreaLength = 0;\n\t\tvar hemiLength = 0;\n\n\t\tvar numDirectionalShadows = 0;\n\t\tvar numPointShadows = 0;\n\t\tvar numSpotShadows = 0;\n\n\t\tvar viewMatrix = camera.matrixWorldInverse;\n\n\t\tlights.sort( shadowCastingLightsFirst );\n\n\t\tfor ( var i = 0, l = lights.length; i < l; i ++ ) {\n\n\t\t\tvar light = lights[ i ];\n\n\t\t\tvar color = light.color;\n\t\t\tvar intensity = light.intensity;\n\t\t\tvar distance = light.distance;\n\n\t\t\tvar shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;\n\n\t\t\tif ( light.isAmbientLight ) {\n\n\t\t\t\tr += color.r * intensity;\n\t\t\t\tg += color.g * intensity;\n\t\t\t\tb += color.b * intensity;\n\n\t\t\t} else if ( light.isLightProbe ) {\n\n\t\t\t\tfor ( var j = 0; j < 9; j ++ ) {\n\n\t\t\t\t\tstate.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );\n\n\t\t\t\t}\n\n\t\t\t} else if ( light.isDirectionalLight ) {\n\n\t\t\t\tvar uniforms = cache.get( light );\n\n\t\t\t\tuniforms.color.copy( light.color ).multiplyScalar( light.intensity );\n\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tvector3.setFromMatrixPosition( light.target.matrixWorld );\n\t\t\t\tuniforms.direction.sub( vector3 );\n\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\n\n\t\t\t\tif ( light.castShadow ) {\n\n\t\t\t\t\tvar shadow = light.shadow;\n\n\t\t\t\t\tvar shadowUniforms = shadowCache.get( light );\n\n\t\t\t\t\tshadowUniforms.shadowBias = shadow.bias;\n\t\t\t\t\tshadowUniforms.shadowRadius = shadow.radius;\n\t\t\t\t\tshadowUniforms.shadowMapSize = shadow.mapSize;\n\n\t\t\t\t\tstate.directionalShadow[ directionalLength ] = shadowUniforms;\n\t\t\t\t\tstate.directionalShadowMap[ directionalLength ] = shadowMap;\n\t\t\t\t\tstate.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;\n\n\t\t\t\t\tnumDirectionalShadows ++;\n\n\t\t\t\t}\n\n\t\t\t\tstate.directional[ directionalLength ] = uniforms;\n\n\t\t\t\tdirectionalLength ++;\n\n\t\t\t} else if ( light.isSpotLight ) {\n\n\t\t\t\tvar uniforms = cache.get( light );\n\n\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\n\n\t\t\t\tuniforms.color.copy( color ).multiplyScalar( intensity );\n\t\t\t\tuniforms.distance = distance;\n\n\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tvector3.setFromMatrixPosition( light.target.matrixWorld );\n\t\t\t\tuniforms.direction.sub( vector3 );\n\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\n\n\t\t\t\tuniforms.coneCos = Math.cos( light.angle );\n\t\t\t\tuniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );\n\t\t\t\tuniforms.decay = light.decay;\n\n\t\t\t\tif ( light.castShadow ) {\n\n\t\t\t\t\tvar shadow = light.shadow;\n\n\t\t\t\t\tvar shadowUniforms = shadowCache.get( light );\n\n\t\t\t\t\tshadowUniforms.shadowBias = shadow.bias;\n\t\t\t\t\tshadowUniforms.shadowRadius = shadow.radius;\n\t\t\t\t\tshadowUniforms.shadowMapSize = shadow.mapSize;\n\n\t\t\t\t\tstate.spotShadow[ spotLength ] = shadowUniforms;\n\t\t\t\t\tstate.spotShadowMap[ spotLength ] = shadowMap;\n\t\t\t\t\tstate.spotShadowMatrix[ spotLength ] = light.shadow.matrix;\n\n\t\t\t\t\tnumSpotShadows ++;\n\n\t\t\t\t}\n\n\t\t\t\tstate.spot[ spotLength ] = uniforms;\n\n\t\t\t\tspotLength ++;\n\n\t\t\t} else if ( light.isRectAreaLight ) {\n\n\t\t\t\tvar uniforms = cache.get( light );\n\n\t\t\t\t// (a) intensity is the total visible light emitted\n\t\t\t\t//uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );\n\n\t\t\t\t// (b) intensity is the brightness of the light\n\t\t\t\tuniforms.color.copy( color ).multiplyScalar( intensity );\n\n\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\n\n\t\t\t\t// extract local rotation of light to derive width/height half vectors\n\t\t\t\tmatrix42.identity();\n\t\t\t\tmatrix4.copy( light.matrixWorld );\n\t\t\t\tmatrix4.premultiply( viewMatrix );\n\t\t\t\tmatrix42.extractRotation( matrix4 );\n\n\t\t\t\tuniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );\n\t\t\t\tuniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );\n\n\t\t\t\tuniforms.halfWidth.applyMatrix4( matrix42 );\n\t\t\t\tuniforms.halfHeight.applyMatrix4( matrix42 );\n\n\t\t\t\t// TODO (abelnation): RectAreaLight distance?\n\t\t\t\t// uniforms.distance = distance;\n\n\t\t\t\tstate.rectArea[ rectAreaLength ] = uniforms;\n\n\t\t\t\trectAreaLength ++;\n\n\t\t\t} else if ( light.isPointLight ) {\n\n\t\t\t\tvar uniforms = cache.get( light );\n\n\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\n\n\t\t\t\tuniforms.color.copy( light.color ).multiplyScalar( light.intensity );\n\t\t\t\tuniforms.distance = light.distance;\n\t\t\t\tuniforms.decay = light.decay;\n\n\t\t\t\tif ( light.castShadow ) {\n\n\t\t\t\t\tvar shadow = light.shadow;\n\n\t\t\t\t\tvar shadowUniforms = shadowCache.get( light );\n\n\t\t\t\t\tshadowUniforms.shadowBias = shadow.bias;\n\t\t\t\t\tshadowUniforms.shadowRadius = shadow.radius;\n\t\t\t\t\tshadowUniforms.shadowMapSize = shadow.mapSize;\n\t\t\t\t\tshadowUniforms.shadowCameraNear = shadow.camera.near;\n\t\t\t\t\tshadowUniforms.shadowCameraFar = shadow.camera.far;\n\n\t\t\t\t\tstate.pointShadow[ pointLength ] = shadowUniforms;\n\t\t\t\t\tstate.pointShadowMap[ pointLength ] = shadowMap;\n\t\t\t\t\tstate.pointShadowMatrix[ pointLength ] = light.shadow.matrix;\n\n\t\t\t\t\tnumPointShadows ++;\n\n\t\t\t\t}\n\n\t\t\t\tstate.point[ pointLength ] = uniforms;\n\n\t\t\t\tpointLength ++;\n\n\t\t\t} else if ( light.isHemisphereLight ) {\n\n\t\t\t\tvar uniforms = cache.get( light );\n\n\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\n\t\t\t\tuniforms.direction.normalize();\n\n\t\t\t\tuniforms.skyColor.copy( light.color ).multiplyScalar( intensity );\n\t\t\t\tuniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );\n\n\t\t\t\tstate.hemi[ hemiLength ] = uniforms;\n\n\t\t\t\themiLength ++;\n\n\t\t\t}\n\n\t\t}\n\n\t\tstate.ambient[ 0 ] = r;\n\t\tstate.ambient[ 1 ] = g;\n\t\tstate.ambient[ 2 ] = b;\n\n\t\tvar hash = state.hash;\n\n\t\tif ( hash.directionalLength !== directionalLength ||\n\t\t\thash.pointLength !== pointLength ||\n\t\t\thash.spotLength !== spotLength ||\n\t\t\thash.rectAreaLength !== rectAreaLength ||\n\t\t\thash.hemiLength !== hemiLength ||\n\t\t\thash.numDirectionalShadows !== numDirectionalShadows ||\n\t\t\thash.numPointShadows !== numPointShadows ||\n\t\t\thash.numSpotShadows !== numSpotShadows ) {\n\n\t\t\tstate.directional.length = directionalLength;\n\t\t\tstate.spot.length = spotLength;\n\t\t\tstate.rectArea.length = rectAreaLength;\n\t\t\tstate.point.length = pointLength;\n\t\t\tstate.hemi.length = hemiLength;\n\n\t\t\tstate.directionalShadow.length = numDirectionalShadows;\n\t\t\tstate.directionalShadowMap.length = numDirectionalShadows;\n\t\t\tstate.pointShadow.length = numPointShadows;\n\t\t\tstate.pointShadowMap.length = numPointShadows;\n\t\t\tstate.spotShadow.length = numSpotShadows;\n\t\t\tstate.spotShadowMap.length = numSpotShadows;\n\t\t\tstate.directionalShadowMatrix.length = numDirectionalShadows;\n\t\t\tstate.pointShadowMatrix.length = numPointShadows;\n\t\t\tstate.spotShadowMatrix.length = numSpotShadows;\n\n\t\t\thash.directionalLength = directionalLength;\n\t\t\thash.pointLength = pointLength;\n\t\t\thash.spotLength = spotLength;\n\t\t\thash.rectAreaLength = rectAreaLength;\n\t\t\thash.hemiLength = hemiLength;\n\n\t\t\thash.numDirectionalShadows = numDirectionalShadows;\n\t\t\thash.numPointShadows = numPointShadows;\n\t\t\thash.numSpotShadows = numSpotShadows;\n\n\t\t\tstate.version = nextVersion ++;\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\tsetup: setup,\n\t\tstate: state\n\t};\n\n}\n\n\nexport { WebGLLights };\n","/**\n * @author Mugen87 / https://github.com/Mugen87\n */\n\nimport { WebGLLights } from './WebGLLights.js';\n\nfunction WebGLRenderState() {\n\n\tvar lights = new WebGLLights();\n\n\tvar lightsArray = [];\n\tvar shadowsArray = [];\n\n\tfunction init() {\n\n\t\tlightsArray.length = 0;\n\t\tshadowsArray.length = 0;\n\n\t}\n\n\tfunction pushLight( light ) {\n\n\t\tlightsArray.push( light );\n\n\t}\n\n\tfunction pushShadow( shadowLight ) {\n\n\t\tshadowsArray.push( shadowLight );\n\n\t}\n\n\tfunction setupLights( camera ) {\n\n\t\tlights.setup( lightsArray, shadowsArray, camera );\n\n\t}\n\n\tvar state = {\n\t\tlightsArray: lightsArray,\n\t\tshadowsArray: shadowsArray,\n\n\t\tlights: lights\n\t};\n\n\treturn {\n\t\tinit: init,\n\t\tstate: state,\n\t\tsetupLights: setupLights,\n\n\t\tpushLight: pushLight,\n\t\tpushShadow: pushShadow\n\t};\n\n}\n\nfunction WebGLRenderStates() {\n\n\tvar renderStates = new WeakMap();\n\n\tfunction onSceneDispose( event ) {\n\n\t\tvar scene = event.target;\n\n\t\tscene.removeEventListener( 'dispose', onSceneDispose );\n\n\t\trenderStates.delete( scene );\n\n\t}\n\n\tfunction get( scene, camera ) {\n\n\t\tvar renderState;\n\n\t\tif ( renderStates.has( scene ) === false ) {\n\n\t\t\trenderState = new WebGLRenderState();\n\t\t\trenderStates.set( scene, new WeakMap() );\n\t\t\trenderStates.get( scene ).set( camera, renderState );\n\n\t\t\tscene.addEventListener( 'dispose', onSceneDispose );\n\n\t\t} else {\n\n\t\t\tif ( renderStates.get( scene ).has( camera ) === false ) {\n\n\t\t\t\trenderState = new WebGLRenderState();\n\t\t\t\trenderStates.get( scene ).set( camera, renderState );\n\n\t\t\t} else {\n\n\t\t\t\trenderState = renderStates.get( scene ).get( camera );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn renderState;\n\n\t}\n\n\tfunction dispose() {\n\n\t\trenderStates = new WeakMap();\n\n\t}\n\n\treturn {\n\t\tget: get,\n\t\tdispose: dispose\n\t};\n\n}\n\n\nexport { WebGLRenderStates };\n","import { Material } from './Material.js';\nimport { BasicDepthPacking } from '../constants.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author bhouston / https://clara.io\n * @author WestLangley / http://github.com/WestLangley\n *\n * parameters = {\n *\n * opacity: ,\n *\n * map: new THREE.Texture( ),\n *\n * alphaMap: new THREE.Texture( ),\n *\n * displacementMap: new THREE.Texture( ),\n * displacementScale: ,\n * displacementBias: ,\n *\n * wireframe: ,\n * wireframeLinewidth: \n * }\n */\n\nfunction MeshDepthMaterial( parameters ) {\n\n\tMaterial.call( this );\n\n\tthis.type = 'MeshDepthMaterial';\n\n\tthis.depthPacking = BasicDepthPacking;\n\n\tthis.skinning = false;\n\tthis.morphTargets = false;\n\n\tthis.map = null;\n\n\tthis.alphaMap = null;\n\n\tthis.displacementMap = null;\n\tthis.displacementScale = 1;\n\tthis.displacementBias = 0;\n\n\tthis.wireframe = false;\n\tthis.wireframeLinewidth = 1;\n\n\tthis.fog = false;\n\n\tthis.setValues( parameters );\n\n}\n\nMeshDepthMaterial.prototype = Object.create( Material.prototype );\nMeshDepthMaterial.prototype.constructor = MeshDepthMaterial;\n\nMeshDepthMaterial.prototype.isMeshDepthMaterial = true;\n\nMeshDepthMaterial.prototype.copy = function ( source ) {\n\n\tMaterial.prototype.copy.call( this, source );\n\n\tthis.depthPacking = source.depthPacking;\n\n\tthis.skinning = source.skinning;\n\tthis.morphTargets = source.morphTargets;\n\n\tthis.map = source.map;\n\n\tthis.alphaMap = source.alphaMap;\n\n\tthis.displacementMap = source.displacementMap;\n\tthis.displacementScale = source.displacementScale;\n\tthis.displacementBias = source.displacementBias;\n\n\tthis.wireframe = source.wireframe;\n\tthis.wireframeLinewidth = source.wireframeLinewidth;\n\n\treturn this;\n\n};\n\n\nexport { MeshDepthMaterial };\n","import { Material } from './Material.js';\nimport { Vector3 } from '../math/Vector3.js';\n\n/**\n * @author WestLangley / http://github.com/WestLangley\n *\n * parameters = {\n *\n * referencePosition: ,\n * nearDistance: ,\n * farDistance: ,\n *\n * skinning: ,\n * morphTargets: ,\n *\n * map: new THREE.Texture( ),\n *\n * alphaMap: new THREE.Texture( ),\n *\n * displacementMap: new THREE.Texture( ),\n * displacementScale: ,\n * displacementBias: \n *\n * }\n */\n\nfunction MeshDistanceMaterial( parameters ) {\n\n\tMaterial.call( this );\n\n\tthis.type = 'MeshDistanceMaterial';\n\n\tthis.referencePosition = new Vector3();\n\tthis.nearDistance = 1;\n\tthis.farDistance = 1000;\n\n\tthis.skinning = false;\n\tthis.morphTargets = false;\n\n\tthis.map = null;\n\n\tthis.alphaMap = null;\n\n\tthis.displacementMap = null;\n\tthis.displacementScale = 1;\n\tthis.displacementBias = 0;\n\n\tthis.fog = false;\n\n\tthis.setValues( parameters );\n\n}\n\nMeshDistanceMaterial.prototype = Object.create( Material.prototype );\nMeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;\n\nMeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;\n\nMeshDistanceMaterial.prototype.copy = function ( source ) {\n\n\tMaterial.prototype.copy.call( this, source );\n\n\tthis.referencePosition.copy( source.referencePosition );\n\tthis.nearDistance = source.nearDistance;\n\tthis.farDistance = source.farDistance;\n\n\tthis.skinning = source.skinning;\n\tthis.morphTargets = source.morphTargets;\n\n\tthis.map = source.map;\n\n\tthis.alphaMap = source.alphaMap;\n\n\tthis.displacementMap = source.displacementMap;\n\tthis.displacementScale = source.displacementScale;\n\tthis.displacementBias = source.displacementBias;\n\n\treturn this;\n\n};\n\n\nexport { MeshDistanceMaterial };\n","/**\n * @author alteredq / http://alteredqualia.com/\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { FrontSide, BackSide, DoubleSide, RGBAFormat, NearestFilter, LinearFilter, PCFShadowMap, VSMShadowMap, RGBADepthPacking, NoBlending } from '../../constants.js';\nimport { WebGLRenderTarget } from '../WebGLRenderTarget.js';\nimport { MeshDepthMaterial } from '../../materials/MeshDepthMaterial.js';\nimport { MeshDistanceMaterial } from '../../materials/MeshDistanceMaterial.js';\nimport { ShaderMaterial } from '../../materials/ShaderMaterial.js';\nimport { BufferAttribute } from '../../core/BufferAttribute.js';\nimport { BufferGeometry } from '../../core/BufferGeometry.js';\nimport { Mesh } from '../../objects/Mesh.js';\nimport { Vector4 } from '../../math/Vector4.js';\nimport { Vector2 } from '../../math/Vector2.js';\nimport { Frustum } from '../../math/Frustum.js';\n\nimport vsm_frag from '../shaders/ShaderLib/vsm_frag.glsl.js';\nimport vsm_vert from '../shaders/ShaderLib/vsm_vert.glsl.js';\n\nfunction WebGLShadowMap( _renderer, _objects, maxTextureSize ) {\n\n\tvar _frustum = new Frustum(),\n\n\t\t_shadowMapSize = new Vector2(),\n\t\t_viewportSize = new Vector2(),\n\n\t\t_viewport = new Vector4(),\n\n\t\t_depthMaterials = [],\n\t\t_distanceMaterials = [],\n\n\t\t_materialCache = {};\n\n\tvar shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };\n\n\tvar shadowMaterialVertical = new ShaderMaterial( {\n\n\t\tdefines: {\n\t\t\tSAMPLE_RATE: 2.0 / 8.0,\n\t\t\tHALF_SAMPLE_RATE: 1.0 / 8.0\n\t\t},\n\n\t\tuniforms: {\n\t\t\tshadow_pass: { value: null },\n\t\t\tresolution: { value: new Vector2() },\n\t\t\tradius: { value: 4.0 }\n\t\t},\n\n\t\tvertexShader: vsm_vert,\n\n\t\tfragmentShader: vsm_frag\n\n\t} );\n\n\tvar shadowMaterialHorizonal = shadowMaterialVertical.clone();\n\tshadowMaterialHorizonal.defines.HORIZONAL_PASS = 1;\n\n\tvar fullScreenTri = new BufferGeometry();\n\tfullScreenTri.setAttribute(\n\t\t\"position\",\n\t\tnew BufferAttribute(\n\t\t\tnew Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),\n\t\t\t3\n\t\t)\n\t);\n\n\tvar fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );\n\n\tvar scope = this;\n\n\tthis.enabled = false;\n\n\tthis.autoUpdate = true;\n\tthis.needsUpdate = false;\n\n\tthis.type = PCFShadowMap;\n\n\tthis.render = function ( lights, scene, camera ) {\n\n\t\tif ( scope.enabled === false ) return;\n\t\tif ( scope.autoUpdate === false && scope.needsUpdate === false ) return;\n\n\t\tif ( lights.length === 0 ) return;\n\n\t\tvar currentRenderTarget = _renderer.getRenderTarget();\n\t\tvar activeCubeFace = _renderer.getActiveCubeFace();\n\t\tvar activeMipmapLevel = _renderer.getActiveMipmapLevel();\n\n\t\tvar _state = _renderer.state;\n\n\t\t// Set GL state for depth map.\n\t\t_state.setBlending( NoBlending );\n\t\t_state.buffers.color.setClear( 1, 1, 1, 1 );\n\t\t_state.buffers.depth.setTest( true );\n\t\t_state.setScissorTest( false );\n\n\t\t// render depth map\n\n\t\tfor ( var i = 0, il = lights.length; i < il; i ++ ) {\n\n\t\t\tvar light = lights[ i ];\n\t\t\tvar shadow = light.shadow;\n\n\t\t\tif ( shadow === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\t_shadowMapSize.copy( shadow.mapSize );\n\n\t\t\tvar shadowFrameExtents = shadow.getFrameExtents();\n\n\t\t\t_shadowMapSize.multiply( shadowFrameExtents );\n\n\t\t\t_viewportSize.copy( shadow.mapSize );\n\n\t\t\tif ( _shadowMapSize.x > maxTextureSize || _shadowMapSize.y > maxTextureSize ) {\n\n\t\t\t\tif ( _shadowMapSize.x > maxTextureSize ) {\n\n\t\t\t\t\t_viewportSize.x = Math.floor( maxTextureSize / shadowFrameExtents.x );\n\t\t\t\t\t_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;\n\t\t\t\t\tshadow.mapSize.x = _viewportSize.x;\n\n\t\t\t\t}\n\n\t\t\t\tif ( _shadowMapSize.y > maxTextureSize ) {\n\n\t\t\t\t\t_viewportSize.y = Math.floor( maxTextureSize / shadowFrameExtents.y );\n\t\t\t\t\t_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;\n\t\t\t\t\tshadow.mapSize.y = _viewportSize.y;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {\n\n\t\t\t\tvar pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };\n\n\t\t\t\tshadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\n\t\t\t\tshadow.map.texture.name = light.name + \".shadowMap\";\n\n\t\t\t\tshadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\n\n\t\t\t\tshadow.camera.updateProjectionMatrix();\n\n\t\t\t}\n\n\t\t\tif ( shadow.map === null ) {\n\n\t\t\t\tvar pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };\n\n\t\t\t\tshadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\n\t\t\t\tshadow.map.texture.name = light.name + \".shadowMap\";\n\n\t\t\t\tshadow.camera.updateProjectionMatrix();\n\n\t\t\t}\n\n\t\t\t_renderer.setRenderTarget( shadow.map );\n\t\t\t_renderer.clear();\n\n\t\t\tvar viewportCount = shadow.getViewportCount();\n\n\t\t\tfor ( var vp = 0; vp < viewportCount; vp ++ ) {\n\n\t\t\t\tvar viewport = shadow.getViewport( vp );\n\n\t\t\t\t_viewport.set(\n\t\t\t\t\t_viewportSize.x * viewport.x,\n\t\t\t\t\t_viewportSize.y * viewport.y,\n\t\t\t\t\t_viewportSize.x * viewport.z,\n\t\t\t\t\t_viewportSize.y * viewport.w\n\t\t\t\t);\n\n\t\t\t\t_state.viewport( _viewport );\n\n\t\t\t\tshadow.updateMatrices( light, vp );\n\n\t\t\t\t_frustum = shadow.getFrustum();\n\n\t\t\t\trenderObject( scene, camera, shadow.camera, light, this.type );\n\n\t\t\t}\n\n\t\t\t// do blur pass for VSM\n\n\t\t\tif ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {\n\n\t\t\t\tVSMPass( shadow, camera );\n\n\t\t\t}\n\n\t\t}\n\n\t\tscope.needsUpdate = false;\n\n\t\t_renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );\n\n\t};\n\n\tfunction VSMPass( shadow, camera ) {\n\n\t\tvar geometry = _objects.update( fullScreenMesh );\n\n\t\t// vertical pass\n\n\t\tshadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;\n\t\tshadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;\n\t\tshadowMaterialVertical.uniforms.radius.value = shadow.radius;\n\t\t_renderer.setRenderTarget( shadow.mapPass );\n\t\t_renderer.clear();\n\t\t_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );\n\n\t\t// horizonal pass\n\n\t\tshadowMaterialHorizonal.uniforms.shadow_pass.value = shadow.mapPass.texture;\n\t\tshadowMaterialHorizonal.uniforms.resolution.value = shadow.mapSize;\n\t\tshadowMaterialHorizonal.uniforms.radius.value = shadow.radius;\n\t\t_renderer.setRenderTarget( shadow.map );\n\t\t_renderer.clear();\n\t\t_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizonal, fullScreenMesh, null );\n\n\t}\n\n\tfunction getDepthMaterialVariant( useMorphing, useSkinning, useInstancing ) {\n\n\t\tvar index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;\n\n\t\tvar material = _depthMaterials[ index ];\n\n\t\tif ( material === undefined ) {\n\n\t\t\tmaterial = new MeshDepthMaterial( {\n\n\t\t\t\tdepthPacking: RGBADepthPacking,\n\n\t\t\t\tmorphTargets: useMorphing,\n\t\t\t\tskinning: useSkinning\n\n\t\t\t} );\n\n\t\t\t_depthMaterials[ index ] = material;\n\n\t\t}\n\n\t\treturn material;\n\n\t}\n\n\tfunction getDistanceMaterialVariant( useMorphing, useSkinning, useInstancing ) {\n\n\t\tvar index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;\n\n\t\tvar material = _distanceMaterials[ index ];\n\n\t\tif ( material === undefined ) {\n\n\t\t\tmaterial = new MeshDistanceMaterial( {\n\n\t\t\t\tmorphTargets: useMorphing,\n\t\t\t\tskinning: useSkinning\n\n\t\t\t} );\n\n\t\t\t_distanceMaterials[ index ] = material;\n\n\t\t}\n\n\t\treturn material;\n\n\t}\n\n\tfunction getDepthMaterial( object, geometry, material, light, shadowCameraNear, shadowCameraFar, type ) {\n\n\t\tvar result = null;\n\n\t\tvar getMaterialVariant = getDepthMaterialVariant;\n\t\tvar customMaterial = object.customDepthMaterial;\n\n\t\tif ( light.isPointLight === true ) {\n\n\t\t\tgetMaterialVariant = getDistanceMaterialVariant;\n\t\t\tcustomMaterial = object.customDistanceMaterial;\n\n\t\t}\n\n\t\tif ( customMaterial === undefined ) {\n\n\t\t\tvar useMorphing = false;\n\n\t\t\tif ( material.morphTargets === true ) {\n\n\t\t\t\tuseMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;\n\n\t\t\t}\n\n\t\t\tvar useSkinning = false;\n\n\t\t\tif ( object.isSkinnedMesh === true ) {\n\n\t\t\t\tif ( material.skinning === true ) {\n\n\t\t\t\t\tuseSkinning = true;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar useInstancing = object.isInstancedMesh === true;\n\n\t\t\tresult = getMaterialVariant( useMorphing, useSkinning, useInstancing );\n\n\t\t} else {\n\n\t\t\tresult = customMaterial;\n\n\t\t}\n\n\t\tif ( _renderer.localClippingEnabled &&\n\t\t\t\tmaterial.clipShadows === true &&\n\t\t\t\tmaterial.clippingPlanes.length !== 0 ) {\n\n\t\t\t// in this case we need a unique material instance reflecting the\n\t\t\t// appropriate state\n\n\t\t\tvar keyA = result.uuid, keyB = material.uuid;\n\n\t\t\tvar materialsForVariant = _materialCache[ keyA ];\n\n\t\t\tif ( materialsForVariant === undefined ) {\n\n\t\t\t\tmaterialsForVariant = {};\n\t\t\t\t_materialCache[ keyA ] = materialsForVariant;\n\n\t\t\t}\n\n\t\t\tvar cachedMaterial = materialsForVariant[ keyB ];\n\n\t\t\tif ( cachedMaterial === undefined ) {\n\n\t\t\t\tcachedMaterial = result.clone();\n\t\t\t\tmaterialsForVariant[ keyB ] = cachedMaterial;\n\n\t\t\t}\n\n\t\t\tresult = cachedMaterial;\n\n\t\t}\n\n\t\tresult.visible = material.visible;\n\t\tresult.wireframe = material.wireframe;\n\n\t\tif ( type === VSMShadowMap ) {\n\n\t\t\tresult.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;\n\n\t\t} else {\n\n\t\t\tresult.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];\n\n\t\t}\n\n\t\tresult.clipShadows = material.clipShadows;\n\t\tresult.clippingPlanes = material.clippingPlanes;\n\t\tresult.clipIntersection = material.clipIntersection;\n\n\t\tresult.wireframeLinewidth = material.wireframeLinewidth;\n\t\tresult.linewidth = material.linewidth;\n\n\t\tif ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {\n\n\t\t\tresult.referencePosition.setFromMatrixPosition( light.matrixWorld );\n\t\t\tresult.nearDistance = shadowCameraNear;\n\t\t\tresult.farDistance = shadowCameraFar;\n\n\t\t}\n\n\t\treturn result;\n\n\t}\n\n\tfunction renderObject( object, camera, shadowCamera, light, type ) {\n\n\t\tif ( object.visible === false ) return;\n\n\t\tvar visible = object.layers.test( camera.layers );\n\n\t\tif ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {\n\n\t\t\tif ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {\n\n\t\t\t\tobject.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );\n\n\t\t\t\tvar geometry = _objects.update( object );\n\t\t\t\tvar material = object.material;\n\n\t\t\t\tif ( Array.isArray( material ) ) {\n\n\t\t\t\t\tvar groups = geometry.groups;\n\n\t\t\t\t\tfor ( var k = 0, kl = groups.length; k < kl; k ++ ) {\n\n\t\t\t\t\t\tvar group = groups[ k ];\n\t\t\t\t\t\tvar groupMaterial = material[ group.materialIndex ];\n\n\t\t\t\t\t\tif ( groupMaterial && groupMaterial.visible ) {\n\n\t\t\t\t\t\t\tvar depthMaterial = getDepthMaterial( object, geometry, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );\n\n\t\t\t\t\t\t\t_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( material.visible ) {\n\n\t\t\t\t\tvar depthMaterial = getDepthMaterial( object, geometry, material, light, shadowCamera.near, shadowCamera.far, type );\n\n\t\t\t\t\t_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar children = object.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\trenderObject( children[ i ], camera, shadowCamera, light, type );\n\n\t\t}\n\n\t}\n\n}\n\n\nexport { WebGLShadowMap };\n","export default /* glsl */`\n\nvoid main() {\n\n\tgl_Position = vec4( position, 1.0 );\n\n}\n\n`;\n","export default /* glsl */`\nuniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n\n#include \n\nvoid main() {\n\n float mean = 0.0;\n float squared_mean = 0.0;\n\n\t// This seems totally useless but it's a crazy work around for a Adreno compiler bug\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\n for ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\n #ifdef HORIZONAL_PASS\n\n vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n mean += distribution.x;\n squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\n #else\n\n float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\n mean += depth;\n squared_mean += depth * depth;\n\n #endif\n\n }\n\n mean = mean * HALF_SAMPLE_RATE;\n squared_mean = squared_mean * HALF_SAMPLE_RATE;\n\n float std_dev = sqrt( squared_mean - mean * mean );\n\n gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n\n}\n`;\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceFront, CullFaceBack, CullFaceNone, DoubleSide, BackSide, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NoBlending, NormalBlending, AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, ZeroFactor, OneFactor, SrcColorFactor, SrcAlphaFactor, SrcAlphaSaturateFactor, DstColorFactor, DstAlphaFactor, OneMinusSrcColorFactor, OneMinusSrcAlphaFactor, OneMinusDstColorFactor, OneMinusDstAlphaFactor } from '../../constants.js';\nimport { Vector4 } from '../../math/Vector4.js';\n\nfunction WebGLState( gl, extensions, capabilities ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\n\tfunction ColorBuffer() {\n\n\t\tvar locked = false;\n\n\t\tvar color = new Vector4();\n\t\tvar currentColorMask = null;\n\t\tvar currentColorClear = new Vector4( 0, 0, 0, 0 );\n\n\t\treturn {\n\n\t\t\tsetMask: function ( colorMask ) {\n\n\t\t\t\tif ( currentColorMask !== colorMask && ! locked ) {\n\n\t\t\t\t\tgl.colorMask( colorMask, colorMask, colorMask, colorMask );\n\t\t\t\t\tcurrentColorMask = colorMask;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetLocked: function ( lock ) {\n\n\t\t\t\tlocked = lock;\n\n\t\t\t},\n\n\t\t\tsetClear: function ( r, g, b, a, premultipliedAlpha ) {\n\n\t\t\t\tif ( premultipliedAlpha === true ) {\n\n\t\t\t\t\tr *= a; g *= a; b *= a;\n\n\t\t\t\t}\n\n\t\t\t\tcolor.set( r, g, b, a );\n\n\t\t\t\tif ( currentColorClear.equals( color ) === false ) {\n\n\t\t\t\t\tgl.clearColor( r, g, b, a );\n\t\t\t\t\tcurrentColorClear.copy( color );\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\treset: function () {\n\n\t\t\t\tlocked = false;\n\n\t\t\t\tcurrentColorMask = null;\n\t\t\t\tcurrentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state\n\n\t\t\t}\n\n\t\t};\n\n\t}\n\n\tfunction DepthBuffer() {\n\n\t\tvar locked = false;\n\n\t\tvar currentDepthMask = null;\n\t\tvar currentDepthFunc = null;\n\t\tvar currentDepthClear = null;\n\n\t\treturn {\n\n\t\t\tsetTest: function ( depthTest ) {\n\n\t\t\t\tif ( depthTest ) {\n\n\t\t\t\t\tenable( gl.DEPTH_TEST );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tdisable( gl.DEPTH_TEST );\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetMask: function ( depthMask ) {\n\n\t\t\t\tif ( currentDepthMask !== depthMask && ! locked ) {\n\n\t\t\t\t\tgl.depthMask( depthMask );\n\t\t\t\t\tcurrentDepthMask = depthMask;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetFunc: function ( depthFunc ) {\n\n\t\t\t\tif ( currentDepthFunc !== depthFunc ) {\n\n\t\t\t\t\tif ( depthFunc ) {\n\n\t\t\t\t\t\tswitch ( depthFunc ) {\n\n\t\t\t\t\t\t\tcase NeverDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.NEVER );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase AlwaysDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.ALWAYS );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase LessDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.LESS );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase LessEqualDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.LEQUAL );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase EqualDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.EQUAL );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase GreaterEqualDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.GEQUAL );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase GreaterDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.GREATER );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase NotEqualDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.NOTEQUAL );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.LEQUAL );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tgl.depthFunc( gl.LEQUAL );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tcurrentDepthFunc = depthFunc;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetLocked: function ( lock ) {\n\n\t\t\t\tlocked = lock;\n\n\t\t\t},\n\n\t\t\tsetClear: function ( depth ) {\n\n\t\t\t\tif ( currentDepthClear !== depth ) {\n\n\t\t\t\t\tgl.clearDepth( depth );\n\t\t\t\t\tcurrentDepthClear = depth;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\treset: function () {\n\n\t\t\t\tlocked = false;\n\n\t\t\t\tcurrentDepthMask = null;\n\t\t\t\tcurrentDepthFunc = null;\n\t\t\t\tcurrentDepthClear = null;\n\n\t\t\t}\n\n\t\t};\n\n\t}\n\n\tfunction StencilBuffer() {\n\n\t\tvar locked = false;\n\n\t\tvar currentStencilMask = null;\n\t\tvar currentStencilFunc = null;\n\t\tvar currentStencilRef = null;\n\t\tvar currentStencilFuncMask = null;\n\t\tvar currentStencilFail = null;\n\t\tvar currentStencilZFail = null;\n\t\tvar currentStencilZPass = null;\n\t\tvar currentStencilClear = null;\n\n\t\treturn {\n\n\t\t\tsetTest: function ( stencilTest ) {\n\n\t\t\t\tif ( ! locked ) {\n\n\t\t\t\t\tif ( stencilTest ) {\n\n\t\t\t\t\t\tenable( gl.STENCIL_TEST );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tdisable( gl.STENCIL_TEST );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetMask: function ( stencilMask ) {\n\n\t\t\t\tif ( currentStencilMask !== stencilMask && ! locked ) {\n\n\t\t\t\t\tgl.stencilMask( stencilMask );\n\t\t\t\t\tcurrentStencilMask = stencilMask;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetFunc: function ( stencilFunc, stencilRef, stencilMask ) {\n\n\t\t\t\tif ( currentStencilFunc !== stencilFunc ||\n\t\t\t\t currentStencilRef \t!== stencilRef \t||\n\t\t\t\t currentStencilFuncMask !== stencilMask ) {\n\n\t\t\t\t\tgl.stencilFunc( stencilFunc, stencilRef, stencilMask );\n\n\t\t\t\t\tcurrentStencilFunc = stencilFunc;\n\t\t\t\t\tcurrentStencilRef = stencilRef;\n\t\t\t\t\tcurrentStencilFuncMask = stencilMask;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetOp: function ( stencilFail, stencilZFail, stencilZPass ) {\n\n\t\t\t\tif ( currentStencilFail\t !== stencilFail \t||\n\t\t\t\t currentStencilZFail !== stencilZFail ||\n\t\t\t\t currentStencilZPass !== stencilZPass ) {\n\n\t\t\t\t\tgl.stencilOp( stencilFail, stencilZFail, stencilZPass );\n\n\t\t\t\t\tcurrentStencilFail = stencilFail;\n\t\t\t\t\tcurrentStencilZFail = stencilZFail;\n\t\t\t\t\tcurrentStencilZPass = stencilZPass;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetLocked: function ( lock ) {\n\n\t\t\t\tlocked = lock;\n\n\t\t\t},\n\n\t\t\tsetClear: function ( stencil ) {\n\n\t\t\t\tif ( currentStencilClear !== stencil ) {\n\n\t\t\t\t\tgl.clearStencil( stencil );\n\t\t\t\t\tcurrentStencilClear = stencil;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\treset: function () {\n\n\t\t\t\tlocked = false;\n\n\t\t\t\tcurrentStencilMask = null;\n\t\t\t\tcurrentStencilFunc = null;\n\t\t\t\tcurrentStencilRef = null;\n\t\t\t\tcurrentStencilFuncMask = null;\n\t\t\t\tcurrentStencilFail = null;\n\t\t\t\tcurrentStencilZFail = null;\n\t\t\t\tcurrentStencilZPass = null;\n\t\t\t\tcurrentStencilClear = null;\n\n\t\t\t}\n\n\t\t};\n\n\t}\n\n\t//\n\n\tvar colorBuffer = new ColorBuffer();\n\tvar depthBuffer = new DepthBuffer();\n\tvar stencilBuffer = new StencilBuffer();\n\n\tvar maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );\n\tvar newAttributes = new Uint8Array( maxVertexAttributes );\n\tvar enabledAttributes = new Uint8Array( maxVertexAttributes );\n\tvar attributeDivisors = new Uint8Array( maxVertexAttributes );\n\n\tvar enabledCapabilities = {};\n\n\tvar currentProgram = null;\n\n\tvar currentBlendingEnabled = null;\n\tvar currentBlending = null;\n\tvar currentBlendEquation = null;\n\tvar currentBlendSrc = null;\n\tvar currentBlendDst = null;\n\tvar currentBlendEquationAlpha = null;\n\tvar currentBlendSrcAlpha = null;\n\tvar currentBlendDstAlpha = null;\n\tvar currentPremultipledAlpha = false;\n\n\tvar currentFlipSided = null;\n\tvar currentCullFace = null;\n\n\tvar currentLineWidth = null;\n\n\tvar currentPolygonOffsetFactor = null;\n\tvar currentPolygonOffsetUnits = null;\n\n\tvar maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS );\n\n\tvar lineWidthAvailable = false;\n\tvar version = 0;\n\tvar glVersion = gl.getParameter( gl.VERSION );\n\n\tif ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {\n\n\t\tversion = parseFloat( /^WebGL\\ ([0-9])/.exec( glVersion )[ 1 ] );\n\t\tlineWidthAvailable = ( version >= 1.0 );\n\n\t} else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {\n\n\t\tversion = parseFloat( /^OpenGL\\ ES\\ ([0-9])/.exec( glVersion )[ 1 ] );\n\t\tlineWidthAvailable = ( version >= 2.0 );\n\n\t}\n\n\tvar currentTextureSlot = null;\n\tvar currentBoundTextures = {};\n\n\tvar currentScissor = new Vector4();\n\tvar currentViewport = new Vector4();\n\n\tfunction createTexture( type, target, count ) {\n\n\t\tvar data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.\n\t\tvar texture = gl.createTexture();\n\n\t\tgl.bindTexture( type, texture );\n\t\tgl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST );\n\t\tgl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST );\n\n\t\tfor ( var i = 0; i < count; i ++ ) {\n\n\t\t\tgl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );\n\n\t\t}\n\n\t\treturn texture;\n\n\t}\n\n\tvar emptyTextures = {};\n\temptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 );\n\temptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 );\n\n\t// init\n\n\tcolorBuffer.setClear( 0, 0, 0, 1 );\n\tdepthBuffer.setClear( 1 );\n\tstencilBuffer.setClear( 0 );\n\n\tenable( gl.DEPTH_TEST );\n\tdepthBuffer.setFunc( LessEqualDepth );\n\n\tsetFlipSided( false );\n\tsetCullFace( CullFaceBack );\n\tenable( gl.CULL_FACE );\n\n\tsetBlending( NoBlending );\n\n\t//\n\n\tfunction initAttributes() {\n\n\t\tfor ( var i = 0, l = newAttributes.length; i < l; i ++ ) {\n\n\t\t\tnewAttributes[ i ] = 0;\n\n\t\t}\n\n\t}\n\n\tfunction enableAttribute( attribute ) {\n\n\t\tenableAttributeAndDivisor( attribute, 0 );\n\n\t}\n\n\tfunction enableAttributeAndDivisor( attribute, meshPerAttribute ) {\n\n\t\tnewAttributes[ attribute ] = 1;\n\n\t\tif ( enabledAttributes[ attribute ] === 0 ) {\n\n\t\t\tgl.enableVertexAttribArray( attribute );\n\t\t\tenabledAttributes[ attribute ] = 1;\n\n\t\t}\n\n\t\tif ( attributeDivisors[ attribute ] !== meshPerAttribute ) {\n\n\t\t\tvar extension = isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );\n\n\t\t\textension[ isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );\n\t\t\tattributeDivisors[ attribute ] = meshPerAttribute;\n\n\t\t}\n\n\t}\n\n\tfunction disableUnusedAttributes() {\n\n\t\tfor ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {\n\n\t\t\tif ( enabledAttributes[ i ] !== newAttributes[ i ] ) {\n\n\t\t\t\tgl.disableVertexAttribArray( i );\n\t\t\t\tenabledAttributes[ i ] = 0;\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tfunction vertexAttribPointer( index, size, type, normalized, stride, offset ) {\n\n\t\tif ( isWebGL2 === true && ( type === gl.INT || type === gl.UNSIGNED_INT ) ) {\n\n\t\t\tgl.vertexAttribIPointer( index, size, type, normalized, stride, offset );\n\n\t\t} else {\n\n\t\t\tgl.vertexAttribPointer( index, size, type, normalized, stride, offset );\n\n\t\t}\n\n\t}\n\n\tfunction enable( id ) {\n\n\t\tif ( enabledCapabilities[ id ] !== true ) {\n\n\t\t\tgl.enable( id );\n\t\t\tenabledCapabilities[ id ] = true;\n\n\t\t}\n\n\t}\n\n\tfunction disable( id ) {\n\n\t\tif ( enabledCapabilities[ id ] !== false ) {\n\n\t\t\tgl.disable( id );\n\t\t\tenabledCapabilities[ id ] = false;\n\n\t\t}\n\n\t}\n\n\tfunction useProgram( program ) {\n\n\t\tif ( currentProgram !== program ) {\n\n\t\t\tgl.useProgram( program );\n\n\t\t\tcurrentProgram = program;\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\tvar equationToGL = {\n\t\t[ AddEquation ]: gl.FUNC_ADD,\n\t\t[ SubtractEquation ]: gl.FUNC_SUBTRACT,\n\t\t[ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT\n\t};\n\n\tif ( isWebGL2 ) {\n\n\t\tequationToGL[ MinEquation ] = gl.MIN;\n\t\tequationToGL[ MaxEquation ] = gl.MAX;\n\n\t} else {\n\n\t\tvar extension = extensions.get( 'EXT_blend_minmax' );\n\n\t\tif ( extension !== null ) {\n\n\t\t\tequationToGL[ MinEquation ] = extension.MIN_EXT;\n\t\t\tequationToGL[ MaxEquation ] = extension.MAX_EXT;\n\n\t\t}\n\n\t}\n\n\tvar factorToGL = {\n\t\t[ ZeroFactor ]: gl.ZERO,\n\t\t[ OneFactor ]: gl.ONE,\n\t\t[ SrcColorFactor ]: gl.SRC_COLOR,\n\t\t[ SrcAlphaFactor ]: gl.SRC_ALPHA,\n\t\t[ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE,\n\t\t[ DstColorFactor ]: gl.DST_COLOR,\n\t\t[ DstAlphaFactor ]: gl.DST_ALPHA,\n\t\t[ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR,\n\t\t[ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA,\n\t\t[ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR,\n\t\t[ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA\n\t};\n\n\tfunction setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {\n\n\t\tif ( blending === NoBlending ) {\n\n\t\t\tif ( currentBlendingEnabled ) {\n\n\t\t\t\tdisable( gl.BLEND );\n\t\t\t\tcurrentBlendingEnabled = false;\n\n\t\t\t}\n\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( ! currentBlendingEnabled ) {\n\n\t\t\tenable( gl.BLEND );\n\t\t\tcurrentBlendingEnabled = true;\n\n\t\t}\n\n\t\tif ( blending !== CustomBlending ) {\n\n\t\t\tif ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {\n\n\t\t\t\tif ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {\n\n\t\t\t\t\tgl.blendEquation( gl.FUNC_ADD );\n\n\t\t\t\t\tcurrentBlendEquation = AddEquation;\n\t\t\t\t\tcurrentBlendEquationAlpha = AddEquation;\n\n\t\t\t\t}\n\n\t\t\t\tif ( premultipliedAlpha ) {\n\n\t\t\t\t\tswitch ( blending ) {\n\n\t\t\t\t\t\tcase NormalBlending:\n\t\t\t\t\t\t\tgl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase AdditiveBlending:\n\t\t\t\t\t\t\tgl.blendFunc( gl.ONE, gl.ONE );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase SubtractiveBlending:\n\t\t\t\t\t\t\tgl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase MultiplyBlending:\n\t\t\t\t\t\t\tgl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tconsole.error( 'THREE.WebGLState: Invalid blending: ', blending );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tswitch ( blending ) {\n\n\t\t\t\t\t\tcase NormalBlending:\n\t\t\t\t\t\t\tgl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase AdditiveBlending:\n\t\t\t\t\t\t\tgl.blendFunc( gl.SRC_ALPHA, gl.ONE );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase SubtractiveBlending:\n\t\t\t\t\t\t\tgl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase MultiplyBlending:\n\t\t\t\t\t\t\tgl.blendFunc( gl.ZERO, gl.SRC_COLOR );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tconsole.error( 'THREE.WebGLState: Invalid blending: ', blending );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tcurrentBlendSrc = null;\n\t\t\t\tcurrentBlendDst = null;\n\t\t\t\tcurrentBlendSrcAlpha = null;\n\t\t\t\tcurrentBlendDstAlpha = null;\n\n\t\t\t\tcurrentBlending = blending;\n\t\t\t\tcurrentPremultipledAlpha = premultipliedAlpha;\n\n\t\t\t}\n\n\t\t\treturn;\n\n\t\t}\n\n\t\t// custom blending\n\n\t\tblendEquationAlpha = blendEquationAlpha || blendEquation;\n\t\tblendSrcAlpha = blendSrcAlpha || blendSrc;\n\t\tblendDstAlpha = blendDstAlpha || blendDst;\n\n\t\tif ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {\n\n\t\t\tgl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );\n\n\t\t\tcurrentBlendEquation = blendEquation;\n\t\t\tcurrentBlendEquationAlpha = blendEquationAlpha;\n\n\t\t}\n\n\t\tif ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {\n\n\t\t\tgl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );\n\n\t\t\tcurrentBlendSrc = blendSrc;\n\t\t\tcurrentBlendDst = blendDst;\n\t\t\tcurrentBlendSrcAlpha = blendSrcAlpha;\n\t\t\tcurrentBlendDstAlpha = blendDstAlpha;\n\n\t\t}\n\n\t\tcurrentBlending = blending;\n\t\tcurrentPremultipledAlpha = null;\n\n\t}\n\n\tfunction setMaterial( material, frontFaceCW ) {\n\n\t\tmaterial.side === DoubleSide\n\t\t\t? disable( gl.CULL_FACE )\n\t\t\t: enable( gl.CULL_FACE );\n\n\t\tvar flipSided = ( material.side === BackSide );\n\t\tif ( frontFaceCW ) flipSided = ! flipSided;\n\n\t\tsetFlipSided( flipSided );\n\n\t\t( material.blending === NormalBlending && material.transparent === false )\n\t\t\t? setBlending( NoBlending )\n\t\t\t: setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );\n\n\t\tdepthBuffer.setFunc( material.depthFunc );\n\t\tdepthBuffer.setTest( material.depthTest );\n\t\tdepthBuffer.setMask( material.depthWrite );\n\t\tcolorBuffer.setMask( material.colorWrite );\n\n\t\tvar stencilWrite = material.stencilWrite;\n\t\tstencilBuffer.setTest( stencilWrite );\n\t\tif ( stencilWrite ) {\n\n\t\t\tstencilBuffer.setMask( material.stencilWriteMask );\n\t\t\tstencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );\n\t\t\tstencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );\n\n\t\t}\n\n\t\tsetPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );\n\n\t}\n\n\t//\n\n\tfunction setFlipSided( flipSided ) {\n\n\t\tif ( currentFlipSided !== flipSided ) {\n\n\t\t\tif ( flipSided ) {\n\n\t\t\t\tgl.frontFace( gl.CW );\n\n\t\t\t} else {\n\n\t\t\t\tgl.frontFace( gl.CCW );\n\n\t\t\t}\n\n\t\t\tcurrentFlipSided = flipSided;\n\n\t\t}\n\n\t}\n\n\tfunction setCullFace( cullFace ) {\n\n\t\tif ( cullFace !== CullFaceNone ) {\n\n\t\t\tenable( gl.CULL_FACE );\n\n\t\t\tif ( cullFace !== currentCullFace ) {\n\n\t\t\t\tif ( cullFace === CullFaceBack ) {\n\n\t\t\t\t\tgl.cullFace( gl.BACK );\n\n\t\t\t\t} else if ( cullFace === CullFaceFront ) {\n\n\t\t\t\t\tgl.cullFace( gl.FRONT );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tgl.cullFace( gl.FRONT_AND_BACK );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tdisable( gl.CULL_FACE );\n\n\t\t}\n\n\t\tcurrentCullFace = cullFace;\n\n\t}\n\n\tfunction setLineWidth( width ) {\n\n\t\tif ( width !== currentLineWidth ) {\n\n\t\t\tif ( lineWidthAvailable ) gl.lineWidth( width );\n\n\t\t\tcurrentLineWidth = width;\n\n\t\t}\n\n\t}\n\n\tfunction setPolygonOffset( polygonOffset, factor, units ) {\n\n\t\tif ( polygonOffset ) {\n\n\t\t\tenable( gl.POLYGON_OFFSET_FILL );\n\n\t\t\tif ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {\n\n\t\t\t\tgl.polygonOffset( factor, units );\n\n\t\t\t\tcurrentPolygonOffsetFactor = factor;\n\t\t\t\tcurrentPolygonOffsetUnits = units;\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tdisable( gl.POLYGON_OFFSET_FILL );\n\n\t\t}\n\n\t}\n\n\tfunction setScissorTest( scissorTest ) {\n\n\t\tif ( scissorTest ) {\n\n\t\t\tenable( gl.SCISSOR_TEST );\n\n\t\t} else {\n\n\t\t\tdisable( gl.SCISSOR_TEST );\n\n\t\t}\n\n\t}\n\n\t// texture\n\n\tfunction activeTexture( webglSlot ) {\n\n\t\tif ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;\n\n\t\tif ( currentTextureSlot !== webglSlot ) {\n\n\t\t\tgl.activeTexture( webglSlot );\n\t\t\tcurrentTextureSlot = webglSlot;\n\n\t\t}\n\n\t}\n\n\tfunction bindTexture( webglType, webglTexture ) {\n\n\t\tif ( currentTextureSlot === null ) {\n\n\t\t\tactiveTexture();\n\n\t\t}\n\n\t\tvar boundTexture = currentBoundTextures[ currentTextureSlot ];\n\n\t\tif ( boundTexture === undefined ) {\n\n\t\t\tboundTexture = { type: undefined, texture: undefined };\n\t\t\tcurrentBoundTextures[ currentTextureSlot ] = boundTexture;\n\n\t\t}\n\n\t\tif ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {\n\n\t\t\tgl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );\n\n\t\t\tboundTexture.type = webglType;\n\t\t\tboundTexture.texture = webglTexture;\n\n\t\t}\n\n\t}\n\n\tfunction unbindTexture() {\n\n\t\tvar boundTexture = currentBoundTextures[ currentTextureSlot ];\n\n\t\tif ( boundTexture !== undefined && boundTexture.type !== undefined ) {\n\n\t\t\tgl.bindTexture( boundTexture.type, null );\n\n\t\t\tboundTexture.type = undefined;\n\t\t\tboundTexture.texture = undefined;\n\n\t\t}\n\n\t}\n\n\tfunction compressedTexImage2D() {\n\n\t\ttry {\n\n\t\t\tgl.compressedTexImage2D.apply( gl, arguments );\n\n\t\t} catch ( error ) {\n\n\t\t\tconsole.error( 'THREE.WebGLState:', error );\n\n\t\t}\n\n\t}\n\n\tfunction texImage2D() {\n\n\t\ttry {\n\n\t\t\tgl.texImage2D.apply( gl, arguments );\n\n\t\t} catch ( error ) {\n\n\t\t\tconsole.error( 'THREE.WebGLState:', error );\n\n\t\t}\n\n\t}\n\n\tfunction texImage3D() {\n\n\t\ttry {\n\n\t\t\tgl.texImage3D.apply( gl, arguments );\n\n\t\t} catch ( error ) {\n\n\t\t\tconsole.error( 'THREE.WebGLState:', error );\n\n\t\t}\n\n\t}\n\n\t//\n\n\tfunction scissor( scissor ) {\n\n\t\tif ( currentScissor.equals( scissor ) === false ) {\n\n\t\t\tgl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );\n\t\t\tcurrentScissor.copy( scissor );\n\n\t\t}\n\n\t}\n\n\tfunction viewport( viewport ) {\n\n\t\tif ( currentViewport.equals( viewport ) === false ) {\n\n\t\t\tgl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );\n\t\t\tcurrentViewport.copy( viewport );\n\n\t\t}\n\n\t}\n\n\t//\n\n\tfunction reset() {\n\n\t\tfor ( var i = 0; i < enabledAttributes.length; i ++ ) {\n\n\t\t\tif ( enabledAttributes[ i ] === 1 ) {\n\n\t\t\t\tgl.disableVertexAttribArray( i );\n\t\t\t\tenabledAttributes[ i ] = 0;\n\n\t\t\t}\n\n\t\t}\n\n\t\tenabledCapabilities = {};\n\n\t\tcurrentTextureSlot = null;\n\t\tcurrentBoundTextures = {};\n\n\t\tcurrentProgram = null;\n\n\t\tcurrentBlending = null;\n\n\t\tcurrentFlipSided = null;\n\t\tcurrentCullFace = null;\n\n\t\tcolorBuffer.reset();\n\t\tdepthBuffer.reset();\n\t\tstencilBuffer.reset();\n\n\t}\n\n\treturn {\n\n\t\tbuffers: {\n\t\t\tcolor: colorBuffer,\n\t\t\tdepth: depthBuffer,\n\t\t\tstencil: stencilBuffer\n\t\t},\n\n\t\tinitAttributes: initAttributes,\n\t\tenableAttribute: enableAttribute,\n\t\tenableAttributeAndDivisor: enableAttributeAndDivisor,\n\t\tdisableUnusedAttributes: disableUnusedAttributes,\n\t\tvertexAttribPointer: vertexAttribPointer,\n\t\tenable: enable,\n\t\tdisable: disable,\n\n\t\tuseProgram: useProgram,\n\n\t\tsetBlending: setBlending,\n\t\tsetMaterial: setMaterial,\n\n\t\tsetFlipSided: setFlipSided,\n\t\tsetCullFace: setCullFace,\n\n\t\tsetLineWidth: setLineWidth,\n\t\tsetPolygonOffset: setPolygonOffset,\n\n\t\tsetScissorTest: setScissorTest,\n\n\t\tactiveTexture: activeTexture,\n\t\tbindTexture: bindTexture,\n\t\tunbindTexture: unbindTexture,\n\t\tcompressedTexImage2D: compressedTexImage2D,\n\t\ttexImage2D: texImage2D,\n\t\ttexImage3D: texImage3D,\n\n\t\tscissor: scissor,\n\t\tviewport: viewport,\n\n\t\treset: reset\n\n\t};\n\n}\n\nexport { WebGLState };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping } from '../../constants.js';\nimport { MathUtils } from '../../math/MathUtils.js';\n\nfunction WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\tvar maxTextures = capabilities.maxTextures;\n\tvar maxCubemapSize = capabilities.maxCubemapSize;\n\tvar maxTextureSize = capabilities.maxTextureSize;\n\tvar maxSamples = capabilities.maxSamples;\n\n\tvar _videoTextures = new WeakMap();\n\tvar _canvas;\n\n\t// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,\n\t// also OffscreenCanvas.getContext(\"webgl\"), but not OffscreenCanvas.getContext(\"2d\")!\n\t// Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).\n\n\tvar useOffscreenCanvas = false;\n\n\ttry {\n\n\t\tuseOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'\n\t\t\t&& ( new OffscreenCanvas( 1, 1 ).getContext( \"2d\" ) ) !== null;\n\n\t} catch ( err ) {\n\n\t\t// Ignore any errors\n\n\t}\n\n\tfunction createCanvas( width, height ) {\n\n\t\t// Use OffscreenCanvas when available. Specially needed in web workers\n\n\t\treturn useOffscreenCanvas ?\n\t\t\tnew OffscreenCanvas( width, height ) :\n\t\t\tdocument.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );\n\n\t}\n\n\tfunction resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {\n\n\t\tvar scale = 1;\n\n\t\t// handle case if texture exceeds max size\n\n\t\tif ( image.width > maxSize || image.height > maxSize ) {\n\n\t\t\tscale = maxSize / Math.max( image.width, image.height );\n\n\t\t}\n\n\t\t// only perform resize if necessary\n\n\t\tif ( scale < 1 || needsPowerOfTwo === true ) {\n\n\t\t\t// only perform resize for certain image types\n\n\t\t\tif ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||\n\t\t\t\t( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||\n\t\t\t\t( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {\n\n\t\t\t\tvar floor = needsPowerOfTwo ? MathUtils.floorPowerOfTwo : Math.floor;\n\n\t\t\t\tvar width = floor( scale * image.width );\n\t\t\t\tvar height = floor( scale * image.height );\n\n\t\t\t\tif ( _canvas === undefined ) _canvas = createCanvas( width, height );\n\n\t\t\t\t// cube textures can't reuse the same canvas\n\n\t\t\t\tvar canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;\n\n\t\t\t\tcanvas.width = width;\n\t\t\t\tcanvas.height = height;\n\n\t\t\t\tvar context = canvas.getContext( '2d' );\n\t\t\t\tcontext.drawImage( image, 0, 0, width, height );\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );\n\n\t\t\t\treturn canvas;\n\n\t\t\t} else {\n\n\t\t\t\tif ( 'data' in image ) {\n\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );\n\n\t\t\t\t}\n\n\t\t\t\treturn image;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn image;\n\n\t}\n\n\tfunction isPowerOfTwo( image ) {\n\n\t\treturn MathUtils.isPowerOfTwo( image.width ) && MathUtils.isPowerOfTwo( image.height );\n\n\t}\n\n\tfunction textureNeedsPowerOfTwo( texture ) {\n\n\t\tif ( isWebGL2 ) return false;\n\n\t\treturn ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||\n\t\t\t( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );\n\n\t}\n\n\tfunction textureNeedsGenerateMipmaps( texture, supportsMips ) {\n\n\t\treturn texture.generateMipmaps && supportsMips &&\n\t\t\ttexture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;\n\n\t}\n\n\tfunction generateMipmap( target, texture, width, height ) {\n\n\t\t_gl.generateMipmap( target );\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\t// Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11\n\t\ttextureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;\n\n\t}\n\n\tfunction getInternalFormat( internalFormatName, glFormat, glType ) {\n\n\t\tif ( isWebGL2 === false ) return glFormat;\n\n\t\tif ( internalFormatName !== null ) {\n\n\t\t\tif ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \\'' + internalFormatName + '\\'' );\n\n\t\t}\n\n\t\tvar internalFormat = glFormat;\n\n\t\tif ( glFormat === _gl.RED ) {\n\n\t\t\tif ( glType === _gl.FLOAT ) internalFormat = _gl.R32F;\n\t\t\tif ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F;\n\t\t\tif ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8;\n\n\t\t}\n\n\t\tif ( glFormat === _gl.RGB ) {\n\n\t\t\tif ( glType === _gl.FLOAT ) internalFormat = _gl.RGB32F;\n\t\t\tif ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGB16F;\n\t\t\tif ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RGB8;\n\n\t\t}\n\n\t\tif ( glFormat === _gl.RGBA ) {\n\n\t\t\tif ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F;\n\t\t\tif ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F;\n\t\t\tif ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RGBA8;\n\n\t\t}\n\n\t\tif ( internalFormat === _gl.R16F || internalFormat === _gl.R32F ||\n\t\t\tinternalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) {\n\n\t\t\textensions.get( 'EXT_color_buffer_float' );\n\n\t\t}\n\n\t\treturn internalFormat;\n\n\t}\n\n\t// Fallback filters for non-power-of-2 textures\n\n\tfunction filterFallback( f ) {\n\n\t\tif ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {\n\n\t\t\treturn _gl.NEAREST;\n\n\t\t}\n\n\t\treturn _gl.LINEAR;\n\n\t}\n\n\t//\n\n\tfunction onTextureDispose( event ) {\n\n\t\tvar texture = event.target;\n\n\t\ttexture.removeEventListener( 'dispose', onTextureDispose );\n\n\t\tdeallocateTexture( texture );\n\n\t\tif ( texture.isVideoTexture ) {\n\n\t\t\t_videoTextures.delete( texture );\n\n\t\t}\n\n\t\tinfo.memory.textures --;\n\n\t}\n\n\tfunction onRenderTargetDispose( event ) {\n\n\t\tvar renderTarget = event.target;\n\n\t\trenderTarget.removeEventListener( 'dispose', onRenderTargetDispose );\n\n\t\tdeallocateRenderTarget( renderTarget );\n\n\t\tinfo.memory.textures --;\n\n\t}\n\n\t//\n\n\tfunction deallocateTexture( texture ) {\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\tif ( textureProperties.__webglInit === undefined ) return;\n\n\t\t_gl.deleteTexture( textureProperties.__webglTexture );\n\n\t\tproperties.remove( texture );\n\n\t}\n\n\tfunction deallocateRenderTarget( renderTarget ) {\n\n\t\tvar renderTargetProperties = properties.get( renderTarget );\n\t\tvar textureProperties = properties.get( renderTarget.texture );\n\n\t\tif ( ! renderTarget ) return;\n\n\t\tif ( textureProperties.__webglTexture !== undefined ) {\n\n\t\t\t_gl.deleteTexture( textureProperties.__webglTexture );\n\n\t\t}\n\n\t\tif ( renderTarget.depthTexture ) {\n\n\t\t\trenderTarget.depthTexture.dispose();\n\n\t\t}\n\n\t\tif ( renderTarget.isWebGLCubeRenderTarget ) {\n\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\t_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );\n\t\t\t\tif ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );\n\t\t\tif ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );\n\t\t\tif ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );\n\t\t\tif ( renderTargetProperties.__webglColorRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer );\n\t\t\tif ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );\n\n\t\t}\n\n\t\tproperties.remove( renderTarget.texture );\n\t\tproperties.remove( renderTarget );\n\n\t}\n\n\t//\n\n\tvar textureUnits = 0;\n\n\tfunction resetTextureUnits() {\n\n\t\ttextureUnits = 0;\n\n\t}\n\n\tfunction allocateTextureUnit() {\n\n\t\tvar textureUnit = textureUnits;\n\n\t\tif ( textureUnit >= maxTextures ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );\n\n\t\t}\n\n\t\ttextureUnits += 1;\n\n\t\treturn textureUnit;\n\n\t}\n\n\t//\n\n\tfunction setTexture2D( texture, slot ) {\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\tif ( texture.isVideoTexture ) updateVideoTexture( texture );\n\n\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\n\n\t\t\tvar image = texture.image;\n\n\t\t\tif ( image === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );\n\n\t\t\t} else if ( image.complete === false ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );\n\n\t\t\t} else {\n\n\t\t\t\tuploadTexture( textureProperties, texture, slot );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t}\n\n\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\tstate.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );\n\n\t}\n\n\tfunction setTexture2DArray( texture, slot ) {\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\n\n\t\t\tuploadTexture( textureProperties, texture, slot );\n\t\t\treturn;\n\n\t\t}\n\n\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\tstate.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture );\n\n\t}\n\n\tfunction setTexture3D( texture, slot ) {\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\n\n\t\t\tuploadTexture( textureProperties, texture, slot );\n\t\t\treturn;\n\n\t\t}\n\n\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\tstate.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture );\n\n\t}\n\n\tfunction setTextureCube( texture, slot ) {\n\n\t\tif ( texture.image.length !== 6 ) return;\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\n\n\t\t\tinitTexture( textureProperties, texture );\n\n\t\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\t\tstate.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );\n\n\t\t\t_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );\n\n\t\t\tvar isCompressed = ( texture && ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ) );\n\t\t\tvar isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );\n\n\t\t\tvar cubeImage = [];\n\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\tif ( ! isCompressed && ! isDataTexture ) {\n\n\t\t\t\t\tcubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tcubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar image = cubeImage[ 0 ],\n\t\t\t\tsupportsMips = isPowerOfTwo( image ) || isWebGL2,\n\t\t\t\tglFormat = utils.convert( texture.format ),\n\t\t\t\tglType = utils.convert( texture.type ),\n\t\t\t\tglInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );\n\n\t\t\tsetTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips );\n\n\t\t\tvar mipmaps;\n\n\t\t\tif ( isCompressed ) {\n\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\t\tmipmaps = cubeImage[ i ].mipmaps;\n\n\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\n\n\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\n\n\t\t\t\t\t\tif ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {\n\n\t\t\t\t\t\t\tif ( glFormat !== null ) {\n\n\t\t\t\t\t\t\t\tstate.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );\n\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\n\n\t\t\t} else {\n\n\t\t\t\tmipmaps = texture.mipmaps;\n\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\t\tif ( isDataTexture ) {\n\n\t\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );\n\n\t\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\n\n\t\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\n\t\t\t\t\t\t\tvar mipmapImage = mipmap.image[ i ].image;\n\n\t\t\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );\n\n\t\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\n\n\t\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\n\n\t\t\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length;\n\n\t\t\t}\n\n\t\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\n\n\t\t\t\t// We assume images for cube map have the same size.\n\t\t\t\tgenerateMipmap( _gl.TEXTURE_CUBE_MAP, texture, image.width, image.height );\n\n\t\t\t}\n\n\t\t\ttextureProperties.__version = texture.version;\n\n\t\t\tif ( texture.onUpdate ) texture.onUpdate( texture );\n\n\t\t} else {\n\n\t\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\t\tstate.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );\n\n\t\t}\n\n\t}\n\n\tfunction setTextureCubeDynamic( texture, slot ) {\n\n\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\tstate.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );\n\n\t}\n\n\tvar wrappingToGL = {\n\t\t[ RepeatWrapping ]: _gl.REPEAT,\n\t\t[ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE,\n\t\t[ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT\n\t};\n\n\tvar filterToGL = {\n\t\t[ NearestFilter ]: _gl.NEAREST,\n\t\t[ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST,\n\t\t[ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR,\n\n\t\t[ LinearFilter ]: _gl.LINEAR,\n\t\t[ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST,\n\t\t[ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR\n\t};\n\n\tfunction setTextureParameters( textureType, texture, supportsMips ) {\n\n\t\tif ( supportsMips ) {\n\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] );\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] );\n\n\t\t\tif ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) {\n\n\t\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] );\n\n\t\t\t}\n\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] );\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] );\n\n\t\t} else {\n\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );\n\n\t\t\tif ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) {\n\n\t\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, _gl.CLAMP_TO_EDGE );\n\n\t\t\t}\n\n\t\t\tif ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );\n\n\t\t\t}\n\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );\n\n\t\t\tif ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar extension = extensions.get( 'EXT_texture_filter_anisotropic' );\n\n\t\tif ( extension ) {\n\n\t\t\tif ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;\n\t\t\tif ( texture.type === HalfFloatType && ( isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;\n\n\t\t\tif ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {\n\n\t\t\t\t_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );\n\t\t\t\tproperties.get( texture ).__currentAnisotropy = texture.anisotropy;\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tfunction initTexture( textureProperties, texture ) {\n\n\t\tif ( textureProperties.__webglInit === undefined ) {\n\n\t\t\ttextureProperties.__webglInit = true;\n\n\t\t\ttexture.addEventListener( 'dispose', onTextureDispose );\n\n\t\t\ttextureProperties.__webglTexture = _gl.createTexture();\n\n\t\t\tinfo.memory.textures ++;\n\n\t\t}\n\n\t}\n\n\tfunction uploadTexture( textureProperties, texture, slot ) {\n\n\t\tvar textureType = _gl.TEXTURE_2D;\n\n\t\tif ( texture.isDataTexture2DArray ) textureType = _gl.TEXTURE_2D_ARRAY;\n\t\tif ( texture.isDataTexture3D ) textureType = _gl.TEXTURE_3D;\n\n\t\tinitTexture( textureProperties, texture );\n\n\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\tstate.bindTexture( textureType, textureProperties.__webglTexture );\n\n\t\t_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );\n\t\t_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );\n\t\t_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );\n\n\t\tvar needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;\n\t\tvar image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );\n\n\t\tvar supportsMips = isPowerOfTwo( image ) || isWebGL2,\n\t\t\tglFormat = utils.convert( texture.format ),\n\t\t\tglType = utils.convert( texture.type ),\n\t\t\tglInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );\n\n\t\tsetTextureParameters( textureType, texture, supportsMips );\n\n\t\tvar mipmap, mipmaps = texture.mipmaps;\n\n\t\tif ( texture.isDepthTexture ) {\n\n\t\t\t// populate depth texture with dummy data\n\n\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT;\n\n\t\t\tif ( isWebGL2 ) {\n\n\t\t\t\tif ( texture.type === FloatType ) {\n\n\t\t\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT32F;\n\n\t\t\t\t} else if ( texture.type === UnsignedIntType ) {\n\n\t\t\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT24;\n\n\t\t\t\t} else if ( texture.type === UnsignedInt248Type ) {\n\n\t\t\t\t\tglInternalFormat = _gl.DEPTH24_STENCIL8;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT16; // WebGL2 requires sized internalformat for glTexImage2D\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif ( texture.type === FloatType ) {\n\n\t\t\t\t\tconsole.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// validation checks for WebGL 1\n\n\t\t\tif ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {\n\n\t\t\t\t// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are\n\t\t\t\t// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT\n\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\n\t\t\t\tif ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {\n\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );\n\n\t\t\t\t\ttexture.type = UnsignedShortType;\n\t\t\t\t\tglType = utils.convert( texture.type );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( texture.format === DepthStencilFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {\n\n\t\t\t\t// Depth stencil textures need the DEPTH_STENCIL internal format\n\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\n\t\t\t\tglInternalFormat = _gl.DEPTH_STENCIL;\n\n\t\t\t\t// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are\n\t\t\t\t// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.\n\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\n\t\t\t\tif ( texture.type !== UnsignedInt248Type ) {\n\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );\n\n\t\t\t\t\ttexture.type = UnsignedInt248Type;\n\t\t\t\t\tglType = utils.convert( texture.type );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t//\n\n\t\t\tstate.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );\n\n\t\t} else if ( texture.isDataTexture ) {\n\n\t\t\t// use manually created mipmaps if available\n\t\t\t// if there are no manual mipmaps\n\t\t\t// set 0 level mipmap and then use GL to generate other mipmap levels\n\n\t\t\tif ( mipmaps.length > 0 && supportsMips ) {\n\n\t\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\n\n\t\t\t\t\tmipmap = mipmaps[ i ];\n\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\n\n\t\t\t\t}\n\n\t\t\t\ttexture.generateMipmaps = false;\n\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\n\n\t\t\t} else {\n\n\t\t\t\tstate.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );\n\t\t\t\ttextureProperties.__maxMipLevel = 0;\n\n\t\t\t}\n\n\t\t} else if ( texture.isCompressedTexture ) {\n\n\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\n\n\t\t\t\tmipmap = mipmaps[ i ];\n\n\t\t\t\tif ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {\n\n\t\t\t\t\tif ( glFormat !== null ) {\n\n\t\t\t\t\t\tstate.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\n\n\t\t} else if ( texture.isDataTexture2DArray ) {\n\n\t\t\tstate.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );\n\t\t\ttextureProperties.__maxMipLevel = 0;\n\n\t\t} else if ( texture.isDataTexture3D ) {\n\n\t\t\tstate.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );\n\t\t\ttextureProperties.__maxMipLevel = 0;\n\n\t\t} else {\n\n\t\t\t// regular Texture (image, video, canvas)\n\n\t\t\t// use manually created mipmaps if available\n\t\t\t// if there are no manual mipmaps\n\t\t\t// set 0 level mipmap and then use GL to generate other mipmap levels\n\n\t\t\tif ( mipmaps.length > 0 && supportsMips ) {\n\n\t\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\n\n\t\t\t\t\tmipmap = mipmaps[ i ];\n\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );\n\n\t\t\t\t}\n\n\t\t\t\ttexture.generateMipmaps = false;\n\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\n\n\t\t\t} else {\n\n\t\t\t\tstate.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );\n\t\t\t\ttextureProperties.__maxMipLevel = 0;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\n\n\t\t\tgenerateMipmap( textureType, texture, image.width, image.height );\n\n\t\t}\n\n\t\ttextureProperties.__version = texture.version;\n\n\t\tif ( texture.onUpdate ) texture.onUpdate( texture );\n\n\t}\n\n\t// Render targets\n\n\t// Setup storage for target texture and bind it to correct framebuffer\n\tfunction setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {\n\n\t\tvar glFormat = utils.convert( renderTarget.texture.format );\n\t\tvar glType = utils.convert( renderTarget.texture.type );\n\t\tvar glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );\n\t\tstate.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );\n\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );\n\t\t_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );\n\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );\n\n\t}\n\n\t// Setup storage for internal depth/stencil buffers and bind to correct framebuffer\n\tfunction setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {\n\n\t\t_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );\n\n\t\tif ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {\n\n\t\t\tvar glInternalFormat = _gl.DEPTH_COMPONENT16;\n\n\t\t\tif ( isMultisample ) {\n\n\t\t\t\tvar depthTexture = renderTarget.depthTexture;\n\n\t\t\t\tif ( depthTexture && depthTexture.isDepthTexture ) {\n\n\t\t\t\t\tif ( depthTexture.type === FloatType ) {\n\n\t\t\t\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT32F;\n\n\t\t\t\t\t} else if ( depthTexture.type === UnsignedIntType ) {\n\n\t\t\t\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT24;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\n\n\t\t\t\t_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );\n\n\t\t\t} else {\n\n\t\t\t\t_gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );\n\n\t\t\t}\n\n\t\t\t_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );\n\n\t\t} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {\n\n\t\t\tif ( isMultisample ) {\n\n\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\n\n\t\t\t\t_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height );\n\n\t\t\t} else {\n\n\t\t\t\t_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );\n\n\t\t\t}\n\n\n\t\t\t_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );\n\n\t\t} else {\n\n\t\t\tvar glFormat = utils.convert( renderTarget.texture.format );\n\t\t\tvar glType = utils.convert( renderTarget.texture.type );\n\t\t\tvar glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );\n\n\t\t\tif ( isMultisample ) {\n\n\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\n\n\t\t\t\t_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );\n\n\t\t\t} else {\n\n\t\t\t\t_gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );\n\n\t\t\t}\n\n\t\t}\n\n\t\t_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );\n\n\t}\n\n\t// Setup resources for a Depth Texture for a FBO (needs an extension)\n\tfunction setupDepthTexture( framebuffer, renderTarget ) {\n\n\t\tvar isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );\n\t\tif ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );\n\n\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );\n\n\t\tif ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {\n\n\t\t\tthrow new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );\n\n\t\t}\n\n\t\t// upload an empty depth texture with framebuffer size\n\t\tif ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||\n\t\t\t\trenderTarget.depthTexture.image.width !== renderTarget.width ||\n\t\t\t\trenderTarget.depthTexture.image.height !== renderTarget.height ) {\n\n\t\t\trenderTarget.depthTexture.image.width = renderTarget.width;\n\t\t\trenderTarget.depthTexture.image.height = renderTarget.height;\n\t\t\trenderTarget.depthTexture.needsUpdate = true;\n\n\t\t}\n\n\t\tsetTexture2D( renderTarget.depthTexture, 0 );\n\n\t\tvar webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;\n\n\t\tif ( renderTarget.depthTexture.format === DepthFormat ) {\n\n\t\t\t_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );\n\n\t\t} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {\n\n\t\t\t_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );\n\n\t\t} else {\n\n\t\t\tthrow new Error( 'Unknown depthTexture format' );\n\n\t\t}\n\n\t}\n\n\t// Setup GL resources for a non-texture depth buffer\n\tfunction setupDepthRenderbuffer( renderTarget ) {\n\n\t\tvar renderTargetProperties = properties.get( renderTarget );\n\n\t\tvar isCube = ( renderTarget.isWebGLCubeRenderTarget === true );\n\n\t\tif ( renderTarget.depthTexture ) {\n\n\t\t\tif ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );\n\n\t\t\tsetupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );\n\n\t\t} else {\n\n\t\t\tif ( isCube ) {\n\n\t\t\t\trenderTargetProperties.__webglDepthbuffer = [];\n\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );\n\t\t\t\t\trenderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();\n\t\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );\n\t\t\t\trenderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();\n\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );\n\n\t\t\t}\n\n\t\t}\n\n\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );\n\n\t}\n\n\t// Set up GL resources for the render target\n\tfunction setupRenderTarget( renderTarget ) {\n\n\t\tvar renderTargetProperties = properties.get( renderTarget );\n\t\tvar textureProperties = properties.get( renderTarget.texture );\n\n\t\trenderTarget.addEventListener( 'dispose', onRenderTargetDispose );\n\n\t\ttextureProperties.__webglTexture = _gl.createTexture();\n\n\t\tinfo.memory.textures ++;\n\n\t\tvar isCube = ( renderTarget.isWebGLCubeRenderTarget === true );\n\t\tvar isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );\n\t\tvar supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;\n\n\t\t// Handles WebGL2 RGBFormat fallback - #18858\n\n\t\tif ( isWebGL2 && renderTarget.texture.format === RGBFormat && ( renderTarget.texture.type === FloatType || renderTarget.texture.type === HalfFloatType ) ) {\n\n\t\t\trenderTarget.texture.format = RGBAFormat;\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.' );\n\n\t\t}\n\n\t\t// Setup framebuffer\n\n\t\tif ( isCube ) {\n\n\t\t\trenderTargetProperties.__webglFramebuffer = [];\n\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\trenderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\trenderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();\n\n\t\t\tif ( isMultisample ) {\n\n\t\t\t\tif ( isWebGL2 ) {\n\n\t\t\t\t\trenderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();\n\t\t\t\t\trenderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();\n\n\t\t\t\t\t_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer );\n\n\t\t\t\t\tvar glFormat = utils.convert( renderTarget.texture.format );\n\t\t\t\t\tvar glType = utils.convert( renderTarget.texture.type );\n\t\t\t\t\tvar glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );\n\t\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\n\t\t\t\t\t_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );\n\n\t\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );\n\t\t\t\t\t_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer );\n\t\t\t\t\t_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );\n\n\t\t\t\t\tif ( renderTarget.depthBuffer ) {\n\n\t\t\t\t\t\trenderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();\n\t\t\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );\n\n\t\t\t\t\t}\n\n\t\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );\n\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Setup color buffer\n\n\t\tif ( isCube ) {\n\n\t\t\tstate.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );\n\t\t\tsetTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, supportsMips );\n\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\tsetupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );\n\n\t\t\t}\n\n\t\t\tif ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {\n\n\t\t\t\tgenerateMipmap( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, renderTarget.width, renderTarget.height );\n\n\t\t\t}\n\n\t\t\tstate.bindTexture( _gl.TEXTURE_CUBE_MAP, null );\n\n\t\t} else {\n\n\t\t\tstate.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );\n\t\t\tsetTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, supportsMips );\n\t\t\tsetupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );\n\n\t\t\tif ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {\n\n\t\t\t\tgenerateMipmap( _gl.TEXTURE_2D, renderTarget.texture, renderTarget.width, renderTarget.height );\n\n\t\t\t}\n\n\t\t\tstate.bindTexture( _gl.TEXTURE_2D, null );\n\n\t\t}\n\n\t\t// Setup depth and stencil buffers\n\n\t\tif ( renderTarget.depthBuffer ) {\n\n\t\t\tsetupDepthRenderbuffer( renderTarget );\n\n\t\t}\n\n\t}\n\n\tfunction updateRenderTargetMipmap( renderTarget ) {\n\n\t\tvar texture = renderTarget.texture;\n\t\tvar supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;\n\n\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\n\n\t\t\tvar target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;\n\t\t\tvar webglTexture = properties.get( texture ).__webglTexture;\n\n\t\t\tstate.bindTexture( target, webglTexture );\n\t\t\tgenerateMipmap( target, texture, renderTarget.width, renderTarget.height );\n\t\t\tstate.bindTexture( target, null );\n\n\t\t}\n\n\t}\n\n\tfunction updateMultisampleRenderTarget( renderTarget ) {\n\n\t\tif ( renderTarget.isWebGLMultisampleRenderTarget ) {\n\n\t\t\tif ( isWebGL2 ) {\n\n\t\t\t\tvar renderTargetProperties = properties.get( renderTarget );\n\n\t\t\t\t_gl.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );\n\t\t\t\t_gl.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );\n\n\t\t\t\tvar width = renderTarget.width;\n\t\t\t\tvar height = renderTarget.height;\n\t\t\t\tvar mask = _gl.COLOR_BUFFER_BIT;\n\n\t\t\t\tif ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT;\n\t\t\t\tif ( renderTarget.stencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT;\n\n\t\t\t\t_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST );\n\n\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); // see #18905\n\n\t\t\t} else {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tfunction getRenderTargetSamples( renderTarget ) {\n\n\t\treturn ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?\n\t\t\tMath.min( maxSamples, renderTarget.samples ) : 0;\n\n\t}\n\n\tfunction updateVideoTexture( texture ) {\n\n\t\tvar frame = info.render.frame;\n\n\t\t// Check the last frame we updated the VideoTexture\n\n\t\tif ( _videoTextures.get( texture ) !== frame ) {\n\n\t\t\t_videoTextures.set( texture, frame );\n\t\t\ttexture.update();\n\n\t\t}\n\n\t}\n\n\t// backwards compatibility\n\n\tvar warnedTexture2D = false;\n\tvar warnedTextureCube = false;\n\n\tfunction safeSetTexture2D( texture, slot ) {\n\n\t\tif ( texture && texture.isWebGLRenderTarget ) {\n\n\t\t\tif ( warnedTexture2D === false ) {\n\n\t\t\t\tconsole.warn( \"THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead.\" );\n\t\t\t\twarnedTexture2D = true;\n\n\t\t\t}\n\n\t\t\ttexture = texture.texture;\n\n\t\t}\n\n\t\tsetTexture2D( texture, slot );\n\n\t}\n\n\tfunction safeSetTextureCube( texture, slot ) {\n\n\t\tif ( texture && texture.isWebGLCubeRenderTarget ) {\n\n\t\t\tif ( warnedTextureCube === false ) {\n\n\t\t\t\tconsole.warn( \"THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead.\" );\n\t\t\t\twarnedTextureCube = true;\n\n\t\t\t}\n\n\t\t\ttexture = texture.texture;\n\n\t\t}\n\n\t\t// currently relying on the fact that WebGLCubeRenderTarget.texture is a Texture and NOT a CubeTexture\n\t\t// TODO: unify these code paths\n\t\tif ( ( texture && texture.isCubeTexture ) ||\n\t\t\t( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {\n\n\t\t\t// CompressedTexture can have Array in image :/\n\n\t\t\t// this function alone should take care of cube textures\n\t\t\tsetTextureCube( texture, slot );\n\n\t\t} else {\n\n\t\t\t// assumed: texture property of THREE.WebGLCubeRenderTarget\n\t\t\tsetTextureCubeDynamic( texture, slot );\n\n\t\t}\n\n\t}\n\n\t//\n\n\tthis.allocateTextureUnit = allocateTextureUnit;\n\tthis.resetTextureUnits = resetTextureUnits;\n\n\tthis.setTexture2D = setTexture2D;\n\tthis.setTexture2DArray = setTexture2DArray;\n\tthis.setTexture3D = setTexture3D;\n\tthis.setTextureCube = setTextureCube;\n\tthis.setTextureCubeDynamic = setTextureCubeDynamic;\n\tthis.setupRenderTarget = setupRenderTarget;\n\tthis.updateRenderTargetMipmap = updateRenderTargetMipmap;\n\tthis.updateMultisampleRenderTarget = updateMultisampleRenderTarget;\n\n\tthis.safeSetTexture2D = safeSetTexture2D;\n\tthis.safeSetTextureCube = safeSetTextureCube;\n\n}\n\nexport { WebGLTextures };\n","/**\n * @author thespite / http://www.twitter.com/thespite\n */\n\nimport { RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RedFormat, RGBAFormat, RGBFormat, AlphaFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBIntegerFormat, RGBAIntegerFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedShort565Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, SRGB8_ALPHA8_ASTC_4x4_Format, SRGB8_ALPHA8_ASTC_5x4_Format, SRGB8_ALPHA8_ASTC_5x5_Format, SRGB8_ALPHA8_ASTC_6x5_Format, SRGB8_ALPHA8_ASTC_6x6_Format, SRGB8_ALPHA8_ASTC_8x5_Format, SRGB8_ALPHA8_ASTC_8x6_Format, SRGB8_ALPHA8_ASTC_8x8_Format, SRGB8_ALPHA8_ASTC_10x5_Format, SRGB8_ALPHA8_ASTC_10x6_Format, SRGB8_ALPHA8_ASTC_10x8_Format, SRGB8_ALPHA8_ASTC_10x10_Format, SRGB8_ALPHA8_ASTC_12x10_Format, SRGB8_ALPHA8_ASTC_12x12_Format, RGBA_BPTC_Format } from '../../constants.js';\n\nfunction WebGLUtils( gl, extensions, capabilities ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\n\tfunction convert( p ) {\n\n\t\tvar extension;\n\n\t\tif ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE;\n\t\tif ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4;\n\t\tif ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1;\n\t\tif ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5;\n\n\t\tif ( p === ByteType ) return gl.BYTE;\n\t\tif ( p === ShortType ) return gl.SHORT;\n\t\tif ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT;\n\t\tif ( p === IntType ) return gl.INT;\n\t\tif ( p === UnsignedIntType ) return gl.UNSIGNED_INT;\n\t\tif ( p === FloatType ) return gl.FLOAT;\n\n\t\tif ( p === HalfFloatType ) {\n\n\t\t\tif ( isWebGL2 ) return gl.HALF_FLOAT;\n\n\t\t\textension = extensions.get( 'OES_texture_half_float' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\treturn extension.HALF_FLOAT_OES;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === AlphaFormat ) return gl.ALPHA;\n\t\tif ( p === RGBFormat ) return gl.RGB;\n\t\tif ( p === RGBAFormat ) return gl.RGBA;\n\t\tif ( p === LuminanceFormat ) return gl.LUMINANCE;\n\t\tif ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA;\n\t\tif ( p === DepthFormat ) return gl.DEPTH_COMPONENT;\n\t\tif ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL;\n\t\tif ( p === RedFormat ) return gl.RED;\n\n\t\t// WebGL2 formats.\n\n\t\tif ( p === RedIntegerFormat ) return gl.RED_INTEGER;\n\t\tif ( p === RGFormat ) return gl.RG;\n\t\tif ( p === RGIntegerFormat ) return gl.RG_INTEGER;\n\t\tif ( p === RGBIntegerFormat ) return gl.RGB_INTEGER;\n\t\tif ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER;\n\n\t\tif ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||\n\t\t\tp === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {\n\n\t\t\textension = extensions.get( 'WEBGL_compressed_texture_s3tc' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\tif ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;\n\t\t\t\tif ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;\n\t\t\t\tif ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;\n\t\t\t\tif ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||\n\t\t\tp === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {\n\n\t\t\textension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\tif ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;\n\t\t\t\tif ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;\n\t\t\t\tif ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;\n\t\t\t\tif ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === RGB_ETC1_Format ) {\n\n\t\t\textension = extensions.get( 'WEBGL_compressed_texture_etc1' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\treturn extension.COMPRESSED_RGB_ETC1_WEBGL;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {\n\n\t\t\textension = extensions.get( 'WEBGL_compressed_texture_etc' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\tif ( p === RGB_ETC2_Format ) return extension.COMPRESSED_RGB8_ETC2;\n\t\t\t\tif ( p === RGBA_ETC2_EAC_Format ) return extension.COMPRESSED_RGBA8_ETC2_EAC;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||\n\t\t\tp === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||\n\t\t\tp === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||\n\t\t\tp === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||\n\t\t\tp === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ||\n\t\t\tp === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format ||\n\t\t\tp === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format ||\n\t\t\tp === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format ||\n\t\t\tp === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format ||\n\t\t\tp === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format ) {\n\n\t\t\textension = extensions.get( 'WEBGL_compressed_texture_astc' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\t// TODO Complete?\n\n\t\t\t\treturn p;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === RGBA_BPTC_Format ) {\n\n\t\t\textension = extensions.get( 'EXT_texture_compression_bptc' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\t// TODO Complete?\n\n\t\t\t\treturn p;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === UnsignedInt248Type ) {\n\n\t\t\tif ( isWebGL2 ) return gl.UNSIGNED_INT_24_8;\n\n\t\t\textension = extensions.get( 'WEBGL_depth_texture' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\treturn extension.UNSIGNED_INT_24_8_WEBGL;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\treturn { convert: convert };\n\n}\n\n\nexport { WebGLUtils };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { PerspectiveCamera } from './PerspectiveCamera.js';\n\nfunction ArrayCamera( array ) {\n\n\tPerspectiveCamera.call( this );\n\n\tthis.cameras = array || [];\n\n}\n\nArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {\n\n\tconstructor: ArrayCamera,\n\n\tisArrayCamera: true\n\n} );\n\n\nexport { ArrayCamera };\n","import { Object3D } from '../core/Object3D.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction Group() {\n\n\tObject3D.call( this );\n\n\tthis.type = 'Group';\n\n}\n\nGroup.prototype = Object.assign( Object.create( Object3D.prototype ), {\n\n\tconstructor: Group,\n\n\tisGroup: true\n\n} );\n\n\nexport { Group };\n","import { Group } from '../../objects/Group.js';\n\n/**\n * @author Mugen87 / https://github.com/Mugen87\n */\n\nfunction WebXRController() {\n\n\tthis._targetRay = null;\n\tthis._grip = null;\n\n}\n\nObject.assign( WebXRController.prototype, {\n\n\tconstructor: WebXRController,\n\n\tgetTargetRaySpace: function () {\n\n\t\tif ( this._targetRay === null ) {\n\n\t\t\tthis._targetRay = new Group();\n\t\t\tthis._targetRay.matrixAutoUpdate = false;\n\t\t\tthis._targetRay.visible = false;\n\n\t\t}\n\n\t\treturn this._targetRay;\n\n\t},\n\n\tgetGripSpace: function () {\n\n\t\tif ( this._grip === null ) {\n\n\t\t\tthis._grip = new Group();\n\t\t\tthis._grip.matrixAutoUpdate = false;\n\t\t\tthis._grip.visible = false;\n\n\t\t}\n\n\t\treturn this._grip;\n\n\t},\n\n\tdispatchEvent: function ( event ) {\n\n\t\tif ( this._targetRay !== null ) {\n\n\t\t\tthis._targetRay.dispatchEvent( event );\n\n\t\t}\n\n\t\tif ( this._grip !== null ) {\n\n\t\t\tthis._grip.dispatchEvent( event );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tdisconnect: function ( inputSource ) {\n\n\t\tthis.dispatchEvent( { type: 'disconnected', data: inputSource } );\n\n\t\tif ( this._targetRay !== null ) {\n\n\t\t\tthis._targetRay.visible = false;\n\n\t\t}\n\n\t\tif ( this._grip !== null ) {\n\n\t\t\tthis._grip.visible = false;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tupdate: function ( inputSource, frame, referenceSpace ) {\n\n\t\tvar inputPose = null;\n\t\tvar gripPose = null;\n\n\t\tvar targetRay = this._targetRay;\n\t\tvar grip = this._grip;\n\n\t\tif ( inputSource ) {\n\n\t\t\tif ( targetRay !== null ) {\n\n\t\t\t\tinputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );\n\n\t\t\t\tif ( inputPose !== null ) {\n\n\t\t\t\t\ttargetRay.matrix.fromArray( inputPose.transform.matrix );\n\t\t\t\t\ttargetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( grip !== null && inputSource.gripSpace ) {\n\n\t\t\t\tgripPose = frame.getPose( inputSource.gripSpace, referenceSpace );\n\n\t\t\t\tif ( gripPose !== null ) {\n\n\t\t\t\t\tgrip.matrix.fromArray( gripPose.transform.matrix );\n\t\t\t\t\tgrip.matrix.decompose( grip.position, grip.rotation, grip.scale );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( targetRay !== null ) {\n\n\t\t\ttargetRay.visible = ( inputPose !== null );\n\n\t\t}\n\n\t\tif ( grip !== null ) {\n\n\t\t\tgrip.visible = ( gripPose !== null );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { WebXRController };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { ArrayCamera } from '../../cameras/ArrayCamera.js';\nimport { EventDispatcher } from '../../core/EventDispatcher.js';\nimport { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js';\nimport { Vector3 } from '../../math/Vector3.js';\nimport { Vector4 } from '../../math/Vector4.js';\nimport { WebGLAnimation } from '../webgl/WebGLAnimation.js';\nimport { WebXRController } from './WebXRController.js';\n\nfunction WebXRManager( renderer, gl ) {\n\n\tvar scope = this;\n\n\tvar session = null;\n\n\tvar framebufferScaleFactor = 1.0;\n\n\tvar referenceSpace = null;\n\tvar referenceSpaceType = 'local-floor';\n\n\tvar pose = null;\n\n\tvar controllers = [];\n\tvar inputSourcesMap = new Map();\n\n\t//\n\n\tvar cameraL = new PerspectiveCamera();\n\tcameraL.layers.enable( 1 );\n\tcameraL.viewport = new Vector4();\n\n\tvar cameraR = new PerspectiveCamera();\n\tcameraR.layers.enable( 2 );\n\tcameraR.viewport = new Vector4();\n\n\tvar cameras = [ cameraL, cameraR ];\n\n\tvar cameraVR = new ArrayCamera();\n\tcameraVR.layers.enable( 1 );\n\tcameraVR.layers.enable( 2 );\n\n\tvar _currentDepthNear = null;\n\tvar _currentDepthFar = null;\n\n\t//\n\n\tthis.enabled = false;\n\n\tthis.isPresenting = false;\n\n\tthis.getController = function ( index ) {\n\n\t\tvar controller = controllers[ index ];\n\n\t\tif ( controller === undefined ) {\n\n\t\t\tcontroller = new WebXRController();\n\t\t\tcontrollers[ index ] = controller;\n\n\t\t}\n\n\t\treturn controller.getTargetRaySpace();\n\n\t};\n\n\tthis.getControllerGrip = function ( index ) {\n\n\t\tvar controller = controllers[ index ];\n\n\t\tif ( controller === undefined ) {\n\n\t\t\tcontroller = new WebXRController();\n\t\t\tcontrollers[ index ] = controller;\n\n\t\t}\n\n\t\treturn controller.getGripSpace();\n\n\t};\n\n\t//\n\n\tfunction onSessionEvent( event ) {\n\n\t\tvar controller = inputSourcesMap.get( event.inputSource );\n\n\t\tif ( controller ) {\n\n\t\t\tcontroller.dispatchEvent( { type: event.type } );\n\n\t\t}\n\n\t}\n\n\tfunction onSessionEnd() {\n\n\t\tinputSourcesMap.forEach( function ( controller, inputSource ) {\n\n\t\t\tcontroller.disconnect( inputSource );\n\n\t\t} );\n\n\t\tinputSourcesMap.clear();\n\n\t\t//\n\n\t\trenderer.setFramebuffer( null );\n\t\trenderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830\n\t\tanimation.stop();\n\n\t\tscope.isPresenting = false;\n\n\t\tscope.dispatchEvent( { type: 'sessionend' } );\n\n\t}\n\n\tfunction onRequestReferenceSpace( value ) {\n\n\t\treferenceSpace = value;\n\n\t\tanimation.setContext( session );\n\t\tanimation.start();\n\n\t\tscope.isPresenting = true;\n\n\t\tscope.dispatchEvent( { type: 'sessionstart' } );\n\n\t}\n\n\tthis.setFramebufferScaleFactor = function ( value ) {\n\n\t\tframebufferScaleFactor = value;\n\n\t\tif ( scope.isPresenting === true ) {\n\n\t\t\tconsole.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );\n\n\t\t}\n\n\t};\n\n\tthis.setReferenceSpaceType = function ( value ) {\n\n\t\treferenceSpaceType = value;\n\n\t\tif ( scope.isPresenting === true ) {\n\n\t\t\tconsole.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );\n\n\t\t}\n\n\t};\n\n\tthis.getReferenceSpace = function () {\n\n\t\treturn referenceSpace;\n\n\t};\n\n\tthis.getSession = function () {\n\n\t\treturn session;\n\n\t};\n\n\tthis.setSession = function ( value ) {\n\n\t\tsession = value;\n\n\t\tif ( session !== null ) {\n\n\t\t\tsession.addEventListener( 'select', onSessionEvent );\n\t\t\tsession.addEventListener( 'selectstart', onSessionEvent );\n\t\t\tsession.addEventListener( 'selectend', onSessionEvent );\n\t\t\tsession.addEventListener( 'squeeze', onSessionEvent );\n\t\t\tsession.addEventListener( 'squeezestart', onSessionEvent );\n\t\t\tsession.addEventListener( 'squeezeend', onSessionEvent );\n\t\t\tsession.addEventListener( 'end', onSessionEnd );\n\n\t\t\tvar attributes = gl.getContextAttributes();\n\n\t\t\tif ( attributes.xrCompatible !== true ) {\n\n\t\t\t\tgl.makeXRCompatible();\n\n\t\t\t}\n\n\t\t\tvar layerInit = {\n\t\t\t\tantialias: attributes.antialias,\n\t\t\t\talpha: attributes.alpha,\n\t\t\t\tdepth: attributes.depth,\n\t\t\t\tstencil: attributes.stencil,\n\t\t\t\tframebufferScaleFactor: framebufferScaleFactor\n\t\t\t};\n\n\t\t\t// eslint-disable-next-line no-undef\n\t\t\tvar baseLayer = new XRWebGLLayer( session, gl, layerInit );\n\n\t\t\tsession.updateRenderState( { baseLayer: baseLayer } );\n\n\t\t\tsession.requestReferenceSpace( referenceSpaceType ).then( onRequestReferenceSpace );\n\n\t\t\t//\n\n\t\t\tsession.addEventListener( 'inputsourceschange', updateInputSources );\n\n\t\t}\n\n\t};\n\n\tfunction updateInputSources( event ) {\n\n\t\tvar inputSources = session.inputSources;\n\n\t\t// Assign inputSources to available controllers\n\n\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\n\n\t\t\tinputSourcesMap.set( inputSources[ i ], controllers[ i ] );\n\n\t\t}\n\n\t\t// Notify disconnected\n\n\t\tfor ( var i = 0; i < event.removed.length; i ++ ) {\n\n\t\t\tvar inputSource = event.removed[ i ];\n\t\t\tvar controller = inputSourcesMap.get( inputSource );\n\n\t\t\tif ( controller ) {\n\n\t\t\t\tcontroller.dispatchEvent( { type: 'disconnected', data: inputSource } );\n\t\t\t\tinputSourcesMap.delete( inputSource );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Notify connected\n\n\t\tfor ( var i = 0; i < event.added.length; i ++ ) {\n\n\t\t\tvar inputSource = event.added[ i ];\n\t\t\tvar controller = inputSourcesMap.get( inputSource );\n\n\t\t\tif ( controller ) {\n\n\t\t\t\tcontroller.dispatchEvent( { type: 'connected', data: inputSource } );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t//\n\n\tvar cameraLPos = new Vector3();\n\tvar cameraRPos = new Vector3();\n\n\t/**\n\t * @author jsantell / https://www.jsantell.com/\n\t *\n\t * Assumes 2 cameras that are parallel and share an X-axis, and that\n\t * the cameras' projection and world matrices have already been set.\n\t * And that near and far planes are identical for both cameras.\n\t * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765\n\t */\n\tfunction setProjectionFromUnion( camera, cameraL, cameraR ) {\n\n\t\tcameraLPos.setFromMatrixPosition( cameraL.matrixWorld );\n\t\tcameraRPos.setFromMatrixPosition( cameraR.matrixWorld );\n\n\t\tvar ipd = cameraLPos.distanceTo( cameraRPos );\n\n\t\tvar projL = cameraL.projectionMatrix.elements;\n\t\tvar projR = cameraR.projectionMatrix.elements;\n\n\t\t// VR systems will have identical far and near planes, and\n\t\t// most likely identical top and bottom frustum extents.\n\t\t// Use the left camera for these values.\n\t\tvar near = projL[ 14 ] / ( projL[ 10 ] - 1 );\n\t\tvar far = projL[ 14 ] / ( projL[ 10 ] + 1 );\n\t\tvar topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];\n\t\tvar bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];\n\n\t\tvar leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];\n\t\tvar rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];\n\t\tvar left = near * leftFov;\n\t\tvar right = near * rightFov;\n\n\t\t// Calculate the new camera's position offset from the\n\t\t// left camera. xOffset should be roughly half `ipd`.\n\t\tvar zOffset = ipd / ( - leftFov + rightFov );\n\t\tvar xOffset = zOffset * - leftFov;\n\n\t\t// TODO: Better way to apply this offset?\n\t\tcameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );\n\t\tcamera.translateX( xOffset );\n\t\tcamera.translateZ( zOffset );\n\t\tcamera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );\n\t\tcamera.matrixWorldInverse.getInverse( camera.matrixWorld );\n\n\t\t// Find the union of the frustum values of the cameras and scale\n\t\t// the values so that the near plane's position does not change in world space,\n\t\t// although must now be relative to the new union camera.\n\t\tvar near2 = near + zOffset;\n\t\tvar far2 = far + zOffset;\n\t\tvar left2 = left - xOffset;\n\t\tvar right2 = right + ( ipd - xOffset );\n\t\tvar top2 = topFov * far / far2 * near2;\n\t\tvar bottom2 = bottomFov * far / far2 * near2;\n\n\t\tcamera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );\n\n\t}\n\n\tfunction updateCamera( camera, parent ) {\n\n\t\tif ( parent === null ) {\n\n\t\t\tcamera.matrixWorld.copy( camera.matrix );\n\n\t\t} else {\n\n\t\t\tcamera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );\n\n\t\t}\n\n\t\tcamera.matrixWorldInverse.getInverse( camera.matrixWorld );\n\n\t}\n\n\tthis.getCamera = function ( camera ) {\n\n\t\tcameraVR.near = cameraR.near = cameraL.near = camera.near;\n\t\tcameraVR.far = cameraR.far = cameraL.far = camera.far;\n\n\t\tif ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {\n\n\t\t\t// Note that the new renderState won't apply until the next frame. See #18320\n\n\t\t\tsession.updateRenderState( {\n\t\t\t\tdepthNear: cameraVR.near,\n\t\t\t\tdepthFar: cameraVR.far\n\t\t\t} );\n\n\t\t\t_currentDepthNear = cameraVR.near;\n\t\t\t_currentDepthFar = cameraVR.far;\n\n\t\t}\n\n\t\tvar parent = camera.parent;\n\t\tvar cameras = cameraVR.cameras;\n\n\t\tupdateCamera( cameraVR, parent );\n\n\t\tfor ( var i = 0; i < cameras.length; i ++ ) {\n\n\t\t\tupdateCamera( cameras[ i ], parent );\n\n\t\t}\n\n\t\t// update camera and its children\n\n\t\tcamera.matrixWorld.copy( cameraVR.matrixWorld );\n\n\t\tvar children = camera.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tchildren[ i ].updateMatrixWorld( true );\n\n\t\t}\n\n\t\t// update projection matrix for proper view frustum culling\n\n\t\tif ( cameras.length === 2 ) {\n\n\t\t\tsetProjectionFromUnion( cameraVR, cameraL, cameraR );\n\n\t\t} else {\n\n\t\t\t// assume single camera setup (AR)\n\n\t\t\tcameraVR.projectionMatrix.copy( cameraL.projectionMatrix );\n\n\t\t}\n\n\t\treturn cameraVR;\n\n\t};\n\n\t// Animation Loop\n\n\tvar onAnimationFrameCallback = null;\n\n\tfunction onAnimationFrame( time, frame ) {\n\n\t\tpose = frame.getViewerPose( referenceSpace );\n\n\t\tif ( pose !== null ) {\n\n\t\t\tvar views = pose.views;\n\t\t\tvar baseLayer = session.renderState.baseLayer;\n\n\t\t\trenderer.setFramebuffer( baseLayer.framebuffer );\n\n\t\t\tvar cameraVRNeedsUpdate = false;\n\n\t\t\t// check if it's necessary to rebuild cameraVR's camera list\n\n\t\t\tif ( views.length !== cameraVR.cameras.length ) {\n\n\t\t\t\tcameraVR.cameras.length = 0;\n\t\t\t\tcameraVRNeedsUpdate = true;\n\n\t\t\t}\n\n\t\t\tfor ( var i = 0; i < views.length; i ++ ) {\n\n\t\t\t\tvar view = views[ i ];\n\t\t\t\tvar viewport = baseLayer.getViewport( view );\n\n\t\t\t\tvar camera = cameras[ i ];\n\t\t\t\tcamera.matrix.fromArray( view.transform.matrix );\n\t\t\t\tcamera.projectionMatrix.fromArray( view.projectionMatrix );\n\t\t\t\tcamera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );\n\n\t\t\t\tif ( i === 0 ) {\n\n\t\t\t\t\tcameraVR.matrix.copy( camera.matrix );\n\n\t\t\t\t}\n\n\t\t\t\tif ( cameraVRNeedsUpdate === true ) {\n\n\t\t\t\t\tcameraVR.cameras.push( camera );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t//\n\n\t\tvar inputSources = session.inputSources;\n\n\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\n\n\t\t\tvar controller = controllers[ i ];\n\t\t\tvar inputSource = inputSources[ i ];\n\n\t\t\tcontroller.update( inputSource, frame, referenceSpace );\n\n\t\t}\n\n\t\tif ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );\n\n\t}\n\n\tvar animation = new WebGLAnimation();\n\tanimation.setAnimationLoop( onAnimationFrame );\n\n\tthis.setAnimationLoop = function ( callback ) {\n\n\t\tonAnimationFrameCallback = callback;\n\n\t};\n\n\tthis.dispose = function () {};\n\n}\n\nObject.assign( WebXRManager.prototype, EventDispatcher.prototype );\n\nexport { WebXRManager };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { BackSide } from \"../../constants.js\";\n\nfunction WebGLMaterials( properties ) {\n\n\tfunction refreshFogUniforms( uniforms, fog ) {\n\n\t\tuniforms.fogColor.value.copy( fog.color );\n\n\t\tif ( fog.isFog ) {\n\n\t\t\tuniforms.fogNear.value = fog.near;\n\t\t\tuniforms.fogFar.value = fog.far;\n\n\t\t} else if ( fog.isFogExp2 ) {\n\n\t\t\tuniforms.fogDensity.value = fog.density;\n\n\t\t}\n\n\t}\n\n\tfunction refreshMaterialUniforms( uniforms, material, environment, pixelRatio, height ) {\n\n\t\tif ( material.isMeshBasicMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\n\t\t} else if ( material.isMeshLambertMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsLambert( uniforms, material );\n\n\t\t} else if ( material.isMeshToonMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsToon( uniforms, material );\n\n\t\t} else if ( material.isMeshPhongMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsPhong( uniforms, material );\n\n\t\t} else if ( material.isMeshStandardMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material, environment );\n\n\t\t\tif ( material.isMeshPhysicalMaterial ) {\n\n\t\t\t\trefreshUniformsPhysical( uniforms, material, environment );\n\n\t\t\t} else {\n\n\t\t\t\trefreshUniformsStandard( uniforms, material, environment );\n\n\t\t\t}\n\n\t\t} else if ( material.isMeshMatcapMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsMatcap( uniforms, material );\n\n\t\t} else if ( material.isMeshDepthMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsDepth( uniforms, material );\n\n\t\t} else if ( material.isMeshDistanceMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsDistance( uniforms, material );\n\n\t\t} else if ( material.isMeshNormalMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsNormal( uniforms, material );\n\n\t\t} else if ( material.isLineBasicMaterial ) {\n\n\t\t\trefreshUniformsLine( uniforms, material );\n\n\t\t\tif ( material.isLineDashedMaterial ) {\n\n\t\t\t\trefreshUniformsDash( uniforms, material );\n\n\t\t\t}\n\n\t\t} else if ( material.isPointsMaterial ) {\n\n\t\t\trefreshUniformsPoints( uniforms, material, pixelRatio, height );\n\n\t\t} else if ( material.isSpriteMaterial ) {\n\n\t\t\trefreshUniformsSprites( uniforms, material );\n\n\t\t} else if ( material.isShadowMaterial ) {\n\n\t\t\tuniforms.color.value.copy( material.color );\n\t\t\tuniforms.opacity.value = material.opacity;\n\n\t\t} else if ( material.isShaderMaterial ) {\n\n\t\t\tmaterial.uniformsNeedUpdate = false; // #15581\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsCommon( uniforms, material, environment ) {\n\n\t\tuniforms.opacity.value = material.opacity;\n\n\t\tif ( material.color ) {\n\n\t\t\tuniforms.diffuse.value.copy( material.color );\n\n\t\t}\n\n\t\tif ( material.emissive ) {\n\n\t\t\tuniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );\n\n\t\t}\n\n\t\tif ( material.map ) {\n\n\t\t\tuniforms.map.value = material.map;\n\n\t\t}\n\n\t\tif ( material.alphaMap ) {\n\n\t\t\tuniforms.alphaMap.value = material.alphaMap;\n\n\t\t}\n\n\t\tif ( material.specularMap ) {\n\n\t\t\tuniforms.specularMap.value = material.specularMap;\n\n\t\t}\n\n\t\tvar envMap = material.envMap || environment;\n\n\t\tif ( envMap ) {\n\n\t\t\tuniforms.envMap.value = envMap;\n\n\t\t\tuniforms.flipEnvMap.value = envMap.isCubeTexture ? - 1 : 1;\n\n\t\t\tuniforms.reflectivity.value = material.reflectivity;\n\t\t\tuniforms.refractionRatio.value = material.refractionRatio;\n\n\t\t\tuniforms.maxMipLevel.value = properties.get( envMap ).__maxMipLevel;\n\n\t\t}\n\n\t\tif ( material.lightMap ) {\n\n\t\t\tuniforms.lightMap.value = material.lightMap;\n\t\t\tuniforms.lightMapIntensity.value = material.lightMapIntensity;\n\n\t\t}\n\n\t\tif ( material.aoMap ) {\n\n\t\t\tuniforms.aoMap.value = material.aoMap;\n\t\t\tuniforms.aoMapIntensity.value = material.aoMapIntensity;\n\n\t\t}\n\n\t\t// uv repeat and offset setting priorities\n\t\t// 1. color map\n\t\t// 2. specular map\n\t\t// 3. normal map\n\t\t// 4. bump map\n\t\t// 5. alpha map\n\t\t// 6. emissive map\n\n\t\tvar uvScaleMap;\n\n\t\tif ( material.map ) {\n\n\t\t\tuvScaleMap = material.map;\n\n\t\t} else if ( material.specularMap ) {\n\n\t\t\tuvScaleMap = material.specularMap;\n\n\t\t} else if ( material.displacementMap ) {\n\n\t\t\tuvScaleMap = material.displacementMap;\n\n\t\t} else if ( material.normalMap ) {\n\n\t\t\tuvScaleMap = material.normalMap;\n\n\t\t} else if ( material.bumpMap ) {\n\n\t\t\tuvScaleMap = material.bumpMap;\n\n\t\t} else if ( material.roughnessMap ) {\n\n\t\t\tuvScaleMap = material.roughnessMap;\n\n\t\t} else if ( material.metalnessMap ) {\n\n\t\t\tuvScaleMap = material.metalnessMap;\n\n\t\t} else if ( material.alphaMap ) {\n\n\t\t\tuvScaleMap = material.alphaMap;\n\n\t\t} else if ( material.emissiveMap ) {\n\n\t\t\tuvScaleMap = material.emissiveMap;\n\n\t\t}\n\n\t\tif ( uvScaleMap !== undefined ) {\n\n\t\t\t// backwards compatibility\n\t\t\tif ( uvScaleMap.isWebGLRenderTarget ) {\n\n\t\t\t\tuvScaleMap = uvScaleMap.texture;\n\n\t\t\t}\n\n\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\n\n\t\t\t\tuvScaleMap.updateMatrix();\n\n\t\t\t}\n\n\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\n\n\t\t}\n\n\t\t// uv repeat and offset setting priorities for uv2\n\t\t// 1. ao map\n\t\t// 2. light map\n\n\t\tvar uv2ScaleMap;\n\n\t\tif ( material.aoMap ) {\n\n\t\t\tuv2ScaleMap = material.aoMap;\n\n\t\t} else if ( material.lightMap ) {\n\n\t\t\tuv2ScaleMap = material.lightMap;\n\n\t\t}\n\n\t\tif ( uv2ScaleMap !== undefined ) {\n\n\t\t\t// backwards compatibility\n\t\t\tif ( uv2ScaleMap.isWebGLRenderTarget ) {\n\n\t\t\t\tuv2ScaleMap = uv2ScaleMap.texture;\n\n\t\t\t}\n\n\t\t\tif ( uv2ScaleMap.matrixAutoUpdate === true ) {\n\n\t\t\t\tuv2ScaleMap.updateMatrix();\n\n\t\t\t}\n\n\t\t\tuniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsLine( uniforms, material ) {\n\n\t\tuniforms.diffuse.value.copy( material.color );\n\t\tuniforms.opacity.value = material.opacity;\n\n\t}\n\n\tfunction refreshUniformsDash( uniforms, material ) {\n\n\t\tuniforms.dashSize.value = material.dashSize;\n\t\tuniforms.totalSize.value = material.dashSize + material.gapSize;\n\t\tuniforms.scale.value = material.scale;\n\n\t}\n\n\tfunction refreshUniformsPoints( uniforms, material, pixelRatio, height ) {\n\n\t\tuniforms.diffuse.value.copy( material.color );\n\t\tuniforms.opacity.value = material.opacity;\n\t\tuniforms.size.value = material.size * pixelRatio;\n\t\tuniforms.scale.value = height * 0.5;\n\n\t\tif ( material.map ) {\n\n\t\t\tuniforms.map.value = material.map;\n\n\t\t}\n\n\t\tif ( material.alphaMap ) {\n\n\t\t\tuniforms.alphaMap.value = material.alphaMap;\n\n\t\t}\n\n\t\t// uv repeat and offset setting priorities\n\t\t// 1. color map\n\t\t// 2. alpha map\n\n\t\tvar uvScaleMap;\n\n\t\tif ( material.map ) {\n\n\t\t\tuvScaleMap = material.map;\n\n\t\t} else if ( material.alphaMap ) {\n\n\t\t\tuvScaleMap = material.alphaMap;\n\n\t\t}\n\n\t\tif ( uvScaleMap !== undefined ) {\n\n\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\n\n\t\t\t\tuvScaleMap.updateMatrix();\n\n\t\t\t}\n\n\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsSprites( uniforms, material ) {\n\n\t\tuniforms.diffuse.value.copy( material.color );\n\t\tuniforms.opacity.value = material.opacity;\n\t\tuniforms.rotation.value = material.rotation;\n\n\t\tif ( material.map ) {\n\n\t\t\tuniforms.map.value = material.map;\n\n\t\t}\n\n\t\tif ( material.alphaMap ) {\n\n\t\t\tuniforms.alphaMap.value = material.alphaMap;\n\n\t\t}\n\n\t\t// uv repeat and offset setting priorities\n\t\t// 1. color map\n\t\t// 2. alpha map\n\n\t\tvar uvScaleMap;\n\n\t\tif ( material.map ) {\n\n\t\t\tuvScaleMap = material.map;\n\n\t\t} else if ( material.alphaMap ) {\n\n\t\t\tuvScaleMap = material.alphaMap;\n\n\t\t}\n\n\t\tif ( uvScaleMap !== undefined ) {\n\n\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\n\n\t\t\t\tuvScaleMap.updateMatrix();\n\n\t\t\t}\n\n\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsLambert( uniforms, material ) {\n\n\t\tif ( material.emissiveMap ) {\n\n\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsPhong( uniforms, material ) {\n\n\t\tuniforms.specular.value.copy( material.specular );\n\t\tuniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )\n\n\t\tif ( material.emissiveMap ) {\n\n\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\n\n\t\t}\n\n\t\tif ( material.bumpMap ) {\n\n\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\tuniforms.bumpScale.value = material.bumpScale;\n\t\t\tif ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;\n\n\t\t}\n\n\t\tif ( material.normalMap ) {\n\n\t\t\tuniforms.normalMap.value = material.normalMap;\n\t\t\tuniforms.normalScale.value.copy( material.normalScale );\n\t\t\tif ( material.side === BackSide ) uniforms.normalScale.value.negate();\n\n\t\t}\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsToon( uniforms, material ) {\n\n\t\tuniforms.specular.value.copy( material.specular );\n\t\tuniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )\n\n\t\tif ( material.gradientMap ) {\n\n\t\t\tuniforms.gradientMap.value = material.gradientMap;\n\n\t\t}\n\n\t\tif ( material.emissiveMap ) {\n\n\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\n\n\t\t}\n\n\t\tif ( material.bumpMap ) {\n\n\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\tuniforms.bumpScale.value = material.bumpScale;\n\t\t\tif ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;\n\n\t\t}\n\n\t\tif ( material.normalMap ) {\n\n\t\t\tuniforms.normalMap.value = material.normalMap;\n\t\t\tuniforms.normalScale.value.copy( material.normalScale );\n\t\t\tif ( material.side === BackSide ) uniforms.normalScale.value.negate();\n\n\t\t}\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsStandard( uniforms, material, environment ) {\n\n\t\tuniforms.roughness.value = material.roughness;\n\t\tuniforms.metalness.value = material.metalness;\n\n\t\tif ( material.roughnessMap ) {\n\n\t\t\tuniforms.roughnessMap.value = material.roughnessMap;\n\n\t\t}\n\n\t\tif ( material.metalnessMap ) {\n\n\t\t\tuniforms.metalnessMap.value = material.metalnessMap;\n\n\t\t}\n\n\t\tif ( material.emissiveMap ) {\n\n\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\n\n\t\t}\n\n\t\tif ( material.bumpMap ) {\n\n\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\tuniforms.bumpScale.value = material.bumpScale;\n\t\t\tif ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;\n\n\t\t}\n\n\t\tif ( material.normalMap ) {\n\n\t\t\tuniforms.normalMap.value = material.normalMap;\n\t\t\tuniforms.normalScale.value.copy( material.normalScale );\n\t\t\tif ( material.side === BackSide ) uniforms.normalScale.value.negate();\n\n\t\t}\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t\tif ( material.envMap || environment ) {\n\n\t\t\t//uniforms.envMap.value = material.envMap; // part of uniforms common\n\t\t\tuniforms.envMapIntensity.value = material.envMapIntensity;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsPhysical( uniforms, material, environment ) {\n\n\t\trefreshUniformsStandard( uniforms, material, environment );\n\n\t\tuniforms.reflectivity.value = material.reflectivity; // also part of uniforms common\n\n\t\tuniforms.clearcoat.value = material.clearcoat;\n\t\tuniforms.clearcoatRoughness.value = material.clearcoatRoughness;\n\t\tif ( material.sheen ) uniforms.sheen.value.copy( material.sheen );\n\n\t\tif ( material.clearcoatMap ) {\n\n\t\t\tuniforms.clearcoatMap.value = material.clearcoatMap;\n\n\t\t}\n\n\t\tif ( material.clearcoatRoughnessMap ) {\n\n\t\t\tuniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;\n\n\t\t}\n\n\t\tif ( material.clearcoatNormalMap ) {\n\n\t\t\tuniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );\n\t\t\tuniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;\n\n\t\t\tif ( material.side === BackSide ) {\n\n\t\t\t\tuniforms.clearcoatNormalScale.value.negate();\n\n\t\t\t}\n\n\t\t}\n\n\t\tuniforms.transparency.value = material.transparency;\n\n\t}\n\n\tfunction refreshUniformsMatcap( uniforms, material ) {\n\n\t\tif ( material.matcap ) {\n\n\t\t\tuniforms.matcap.value = material.matcap;\n\n\t\t}\n\n\t\tif ( material.bumpMap ) {\n\n\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\tuniforms.bumpScale.value = material.bumpScale;\n\t\t\tif ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;\n\n\t\t}\n\n\t\tif ( material.normalMap ) {\n\n\t\t\tuniforms.normalMap.value = material.normalMap;\n\t\t\tuniforms.normalScale.value.copy( material.normalScale );\n\t\t\tif ( material.side === BackSide ) uniforms.normalScale.value.negate();\n\n\t\t}\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsDepth( uniforms, material ) {\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsDistance( uniforms, material ) {\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t\tuniforms.referencePosition.value.copy( material.referencePosition );\n\t\tuniforms.nearDistance.value = material.nearDistance;\n\t\tuniforms.farDistance.value = material.farDistance;\n\n\t}\n\n\tfunction refreshUniformsNormal( uniforms, material ) {\n\n\t\tif ( material.bumpMap ) {\n\n\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\tuniforms.bumpScale.value = material.bumpScale;\n\t\t\tif ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;\n\n\t\t}\n\n\t\tif ( material.normalMap ) {\n\n\t\t\tuniforms.normalMap.value = material.normalMap;\n\t\t\tuniforms.normalScale.value.copy( material.normalScale );\n\t\t\tif ( material.side === BackSide ) uniforms.normalScale.value.negate();\n\n\t\t}\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\trefreshFogUniforms: refreshFogUniforms,\n\t\trefreshMaterialUniforms: refreshMaterialUniforms\n\t};\n\n}\n\nexport { WebGLMaterials };\n","/**\n * @author supereggbert / http://www.paulbrunt.co.uk/\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author szimek / https://github.com/szimek/\n * @author tschw\n */\n\nimport {\n\tRGBAFormat,\n\tHalfFloatType,\n\tFloatType,\n\tUnsignedByteType,\n\tLinearEncoding,\n\tNoToneMapping\n} from '../constants.js';\nimport { MathUtils } from '../math/MathUtils.js';\nimport { DataTexture } from '../textures/DataTexture.js';\nimport { Frustum } from '../math/Frustum.js';\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { UniformsLib } from './shaders/UniformsLib.js';\nimport { Vector2 } from '../math/Vector2.js';\nimport { Vector3 } from '../math/Vector3.js';\nimport { Vector4 } from '../math/Vector4.js';\nimport { Scene } from '../scenes/Scene.js';\nimport { WebGLAnimation } from './webgl/WebGLAnimation.js';\nimport { WebGLAttributes } from './webgl/WebGLAttributes.js';\nimport { WebGLBackground } from './webgl/WebGLBackground.js';\nimport { WebGLBufferRenderer } from './webgl/WebGLBufferRenderer.js';\nimport { WebGLCapabilities } from './webgl/WebGLCapabilities.js';\nimport { WebGLClipping } from './webgl/WebGLClipping.js';\nimport { WebGLExtensions } from './webgl/WebGLExtensions.js';\nimport { WebGLGeometries } from './webgl/WebGLGeometries.js';\nimport { WebGLIndexedBufferRenderer } from './webgl/WebGLIndexedBufferRenderer.js';\nimport { WebGLInfo } from './webgl/WebGLInfo.js';\nimport { WebGLMorphtargets } from './webgl/WebGLMorphtargets.js';\nimport { WebGLObjects } from './webgl/WebGLObjects.js';\nimport { WebGLPrograms } from './webgl/WebGLPrograms.js';\nimport { WebGLProperties } from './webgl/WebGLProperties.js';\nimport { WebGLRenderLists } from './webgl/WebGLRenderLists.js';\nimport { WebGLRenderStates } from './webgl/WebGLRenderStates.js';\nimport { WebGLShadowMap } from './webgl/WebGLShadowMap.js';\nimport { WebGLState } from './webgl/WebGLState.js';\nimport { WebGLTextures } from './webgl/WebGLTextures.js';\nimport { WebGLUniforms } from './webgl/WebGLUniforms.js';\nimport { WebGLUtils } from './webgl/WebGLUtils.js';\nimport { WebXRManager } from './webxr/WebXRManager.js';\nimport { WebGLMaterials } from \"./webgl/WebGLMaterials.js\";\n\nfunction WebGLRenderer( parameters ) {\n\n\tparameters = parameters || {};\n\n\tvar _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),\n\t\t_context = parameters.context !== undefined ? parameters.context : null,\n\n\t\t_alpha = parameters.alpha !== undefined ? parameters.alpha : false,\n\t\t_depth = parameters.depth !== undefined ? parameters.depth : true,\n\t\t_stencil = parameters.stencil !== undefined ? parameters.stencil : true,\n\t\t_antialias = parameters.antialias !== undefined ? parameters.antialias : false,\n\t\t_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,\n\t\t_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,\n\t\t_powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',\n\t\t_failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;\n\n\tvar currentRenderList = null;\n\tvar currentRenderState = null;\n\n\t// public properties\n\n\tthis.domElement = _canvas;\n\n\t// Debug configuration container\n\tthis.debug = {\n\n\t\t/**\n\t\t * Enables error checking and reporting when shader programs are being compiled\n\t\t * @type {boolean}\n\t\t */\n\t\tcheckShaderErrors: true\n\t};\n\n\t// clearing\n\n\tthis.autoClear = true;\n\tthis.autoClearColor = true;\n\tthis.autoClearDepth = true;\n\tthis.autoClearStencil = true;\n\n\t// scene graph\n\n\tthis.sortObjects = true;\n\n\t// user-defined clipping\n\n\tthis.clippingPlanes = [];\n\tthis.localClippingEnabled = false;\n\n\t// physically based shading\n\n\tthis.gammaFactor = 2.0;\t// for backwards compatibility\n\tthis.outputEncoding = LinearEncoding;\n\n\t// physical lights\n\n\tthis.physicallyCorrectLights = false;\n\n\t// tone mapping\n\n\tthis.toneMapping = NoToneMapping;\n\tthis.toneMappingExposure = 1.0;\n\tthis.toneMappingWhitePoint = 1.0;\n\n\t// morphs\n\n\tthis.maxMorphTargets = 8;\n\tthis.maxMorphNormals = 4;\n\n\t// internal properties\n\n\tvar _this = this,\n\n\t\t_isContextLost = false,\n\n\t\t// internal state cache\n\n\t\t_framebuffer = null,\n\n\t\t_currentActiveCubeFace = 0,\n\t\t_currentActiveMipmapLevel = 0,\n\t\t_currentRenderTarget = null,\n\t\t_currentFramebuffer = null,\n\t\t_currentMaterialId = - 1,\n\n\t\t// geometry and program caching\n\n\t\t_currentGeometryProgram = {\n\t\t\tgeometry: null,\n\t\t\tprogram: null,\n\t\t\twireframe: false\n\t\t},\n\n\t\t_currentCamera = null,\n\t\t_currentArrayCamera = null,\n\n\t\t_currentViewport = new Vector4(),\n\t\t_currentScissor = new Vector4(),\n\t\t_currentScissorTest = null,\n\n\t\t//\n\n\t\t_width = _canvas.width,\n\t\t_height = _canvas.height,\n\n\t\t_pixelRatio = 1,\n\t\t_opaqueSort = null,\n\t\t_transparentSort = null,\n\n\t\t_viewport = new Vector4( 0, 0, _width, _height ),\n\t\t_scissor = new Vector4( 0, 0, _width, _height ),\n\t\t_scissorTest = false,\n\n\t\t// frustum\n\n\t\t_frustum = new Frustum(),\n\n\t\t// clipping\n\n\t\t_clipping = new WebGLClipping(),\n\t\t_clippingEnabled = false,\n\t\t_localClippingEnabled = false,\n\n\t\t// camera matrices cache\n\n\t\t_projScreenMatrix = new Matrix4(),\n\n\t\t_vector3 = new Vector3();\n\n\tfunction getTargetPixelRatio() {\n\n\t\treturn _currentRenderTarget === null ? _pixelRatio : 1;\n\n\t}\n\n\t// initialize\n\n\tvar _gl;\n\n\ttry {\n\n\t\tvar contextAttributes = {\n\t\t\talpha: _alpha,\n\t\t\tdepth: _depth,\n\t\t\tstencil: _stencil,\n\t\t\tantialias: _antialias,\n\t\t\tpremultipliedAlpha: _premultipliedAlpha,\n\t\t\tpreserveDrawingBuffer: _preserveDrawingBuffer,\n\t\t\tpowerPreference: _powerPreference,\n\t\t\tfailIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat\n\t\t};\n\n\t\t// event listeners must be registered before WebGL context is created, see #12753\n\n\t\t_canvas.addEventListener( 'webglcontextlost', onContextLost, false );\n\t\t_canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );\n\n\t\t_gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );\n\n\t\tif ( _gl === null ) {\n\n\t\t\tif ( _canvas.getContext( 'webgl' ) !== null ) {\n\n\t\t\t\tthrow new Error( 'Error creating WebGL context with your selected attributes.' );\n\n\t\t\t} else {\n\n\t\t\t\tthrow new Error( 'Error creating WebGL context.' );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Some experimental-webgl implementations do not have getShaderPrecisionFormat\n\n\t\tif ( _gl.getShaderPrecisionFormat === undefined ) {\n\n\t\t\t_gl.getShaderPrecisionFormat = function () {\n\n\t\t\t\treturn { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };\n\n\t\t\t};\n\n\t\t}\n\n\t} catch ( error ) {\n\n\t\tconsole.error( 'THREE.WebGLRenderer: ' + error.message );\n\t\tthrow error;\n\n\t}\n\n\tvar extensions, capabilities, state, info;\n\tvar properties, textures, attributes, geometries, objects;\n\tvar programCache, materials, renderLists, renderStates;\n\n\tvar background, morphtargets, bufferRenderer, indexedBufferRenderer;\n\n\tvar utils;\n\n\tfunction initGLContext() {\n\n\t\textensions = new WebGLExtensions( _gl );\n\n\t\tcapabilities = new WebGLCapabilities( _gl, extensions, parameters );\n\n\t\tif ( capabilities.isWebGL2 === false ) {\n\n\t\t\textensions.get( 'WEBGL_depth_texture' );\n\t\t\textensions.get( 'OES_texture_float' );\n\t\t\textensions.get( 'OES_texture_half_float' );\n\t\t\textensions.get( 'OES_texture_half_float_linear' );\n\t\t\textensions.get( 'OES_standard_derivatives' );\n\t\t\textensions.get( 'OES_element_index_uint' );\n\t\t\textensions.get( 'ANGLE_instanced_arrays' );\n\n\t\t}\n\n\t\textensions.get( 'OES_texture_float_linear' );\n\n\t\tutils = new WebGLUtils( _gl, extensions, capabilities );\n\n\t\tstate = new WebGLState( _gl, extensions, capabilities );\n\t\tstate.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );\n\t\tstate.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );\n\n\t\tinfo = new WebGLInfo( _gl );\n\t\tproperties = new WebGLProperties();\n\t\ttextures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );\n\t\tattributes = new WebGLAttributes( _gl, capabilities );\n\t\tgeometries = new WebGLGeometries( _gl, attributes, info );\n\t\tobjects = new WebGLObjects( _gl, geometries, attributes, info );\n\t\tmorphtargets = new WebGLMorphtargets( _gl );\n\t\tprogramCache = new WebGLPrograms( _this, extensions, capabilities );\n\t\tmaterials = new WebGLMaterials( properties );\n\t\trenderLists = new WebGLRenderLists();\n\t\trenderStates = new WebGLRenderStates();\n\n\t\tbackground = new WebGLBackground( _this, state, objects, _premultipliedAlpha );\n\n\t\tbufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );\n\t\tindexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );\n\n\t\tinfo.programs = programCache.programs;\n\n\t\t_this.capabilities = capabilities;\n\t\t_this.extensions = extensions;\n\t\t_this.properties = properties;\n\t\t_this.renderLists = renderLists;\n\t\t_this.state = state;\n\t\t_this.info = info;\n\n\t}\n\n\tinitGLContext();\n\n\t// xr\n\n\tvar xr = new WebXRManager( _this, _gl );\n\n\tthis.xr = xr;\n\n\t// shadow map\n\n\tvar shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );\n\n\tthis.shadowMap = shadowMap;\n\n\t// API\n\n\tthis.getContext = function () {\n\n\t\treturn _gl;\n\n\t};\n\n\tthis.getContextAttributes = function () {\n\n\t\treturn _gl.getContextAttributes();\n\n\t};\n\n\tthis.forceContextLoss = function () {\n\n\t\tvar extension = extensions.get( 'WEBGL_lose_context' );\n\t\tif ( extension ) extension.loseContext();\n\n\t};\n\n\tthis.forceContextRestore = function () {\n\n\t\tvar extension = extensions.get( 'WEBGL_lose_context' );\n\t\tif ( extension ) extension.restoreContext();\n\n\t};\n\n\tthis.getPixelRatio = function () {\n\n\t\treturn _pixelRatio;\n\n\t};\n\n\tthis.setPixelRatio = function ( value ) {\n\n\t\tif ( value === undefined ) return;\n\n\t\t_pixelRatio = value;\n\n\t\tthis.setSize( _width, _height, false );\n\n\t};\n\n\tthis.getSize = function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'WebGLRenderer: .getsize() now requires a Vector2 as an argument' );\n\n\t\t\ttarget = new Vector2();\n\n\t\t}\n\n\t\treturn target.set( _width, _height );\n\n\t};\n\n\tthis.setSize = function ( width, height, updateStyle ) {\n\n\t\tif ( xr.isPresenting ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: Can\\'t change size while VR device is presenting.' );\n\t\t\treturn;\n\n\t\t}\n\n\t\t_width = width;\n\t\t_height = height;\n\n\t\t_canvas.width = Math.floor( width * _pixelRatio );\n\t\t_canvas.height = Math.floor( height * _pixelRatio );\n\n\t\tif ( updateStyle !== false ) {\n\n\t\t\t_canvas.style.width = width + 'px';\n\t\t\t_canvas.style.height = height + 'px';\n\n\t\t}\n\n\t\tthis.setViewport( 0, 0, width, height );\n\n\t};\n\n\tthis.getDrawingBufferSize = function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument' );\n\n\t\t\ttarget = new Vector2();\n\n\t\t}\n\n\t\treturn target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();\n\n\t};\n\n\tthis.setDrawingBufferSize = function ( width, height, pixelRatio ) {\n\n\t\t_width = width;\n\t\t_height = height;\n\n\t\t_pixelRatio = pixelRatio;\n\n\t\t_canvas.width = Math.floor( width * pixelRatio );\n\t\t_canvas.height = Math.floor( height * pixelRatio );\n\n\t\tthis.setViewport( 0, 0, width, height );\n\n\t};\n\n\tthis.getCurrentViewport = function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument' );\n\n\t\t\ttarget = new Vector4();\n\n\t\t}\n\n\t\treturn target.copy( _currentViewport );\n\n\t};\n\n\tthis.getViewport = function ( target ) {\n\n\t\treturn target.copy( _viewport );\n\n\t};\n\n\tthis.setViewport = function ( x, y, width, height ) {\n\n\t\tif ( x.isVector4 ) {\n\n\t\t\t_viewport.set( x.x, x.y, x.z, x.w );\n\n\t\t} else {\n\n\t\t\t_viewport.set( x, y, width, height );\n\n\t\t}\n\n\t\tstate.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );\n\n\t};\n\n\tthis.getScissor = function ( target ) {\n\n\t\treturn target.copy( _scissor );\n\n\t};\n\n\tthis.setScissor = function ( x, y, width, height ) {\n\n\t\tif ( x.isVector4 ) {\n\n\t\t\t_scissor.set( x.x, x.y, x.z, x.w );\n\n\t\t} else {\n\n\t\t\t_scissor.set( x, y, width, height );\n\n\t\t}\n\n\t\tstate.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );\n\n\t};\n\n\tthis.getScissorTest = function () {\n\n\t\treturn _scissorTest;\n\n\t};\n\n\tthis.setScissorTest = function ( boolean ) {\n\n\t\tstate.setScissorTest( _scissorTest = boolean );\n\n\t};\n\n\tthis.setOpaqueSort = function ( method ) {\n\n\t\t_opaqueSort = method;\n\n\t};\n\n\tthis.setTransparentSort = function ( method ) {\n\n\t\t_transparentSort = method;\n\n\t};\n\n\t// Clearing\n\n\tthis.getClearColor = function () {\n\n\t\treturn background.getClearColor();\n\n\t};\n\n\tthis.setClearColor = function () {\n\n\t\tbackground.setClearColor.apply( background, arguments );\n\n\t};\n\n\tthis.getClearAlpha = function () {\n\n\t\treturn background.getClearAlpha();\n\n\t};\n\n\tthis.setClearAlpha = function () {\n\n\t\tbackground.setClearAlpha.apply( background, arguments );\n\n\t};\n\n\tthis.clear = function ( color, depth, stencil ) {\n\n\t\tvar bits = 0;\n\n\t\tif ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;\n\t\tif ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;\n\t\tif ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;\n\n\t\t_gl.clear( bits );\n\n\t};\n\n\tthis.clearColor = function () {\n\n\t\tthis.clear( true, false, false );\n\n\t};\n\n\tthis.clearDepth = function () {\n\n\t\tthis.clear( false, true, false );\n\n\t};\n\n\tthis.clearStencil = function () {\n\n\t\tthis.clear( false, false, true );\n\n\t};\n\n\t//\n\n\tthis.dispose = function () {\n\n\t\t_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );\n\t\t_canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );\n\n\t\trenderLists.dispose();\n\t\trenderStates.dispose();\n\t\tproperties.dispose();\n\t\tobjects.dispose();\n\n\t\txr.dispose();\n\n\t\tanimation.stop();\n\n\t};\n\n\t// Events\n\n\tfunction onContextLost( event ) {\n\n\t\tevent.preventDefault();\n\n\t\tconsole.log( 'THREE.WebGLRenderer: Context Lost.' );\n\n\t\t_isContextLost = true;\n\n\t}\n\n\tfunction onContextRestore( /* event */ ) {\n\n\t\tconsole.log( 'THREE.WebGLRenderer: Context Restored.' );\n\n\t\t_isContextLost = false;\n\n\t\tinitGLContext();\n\n\t}\n\n\tfunction onMaterialDispose( event ) {\n\n\t\tvar material = event.target;\n\n\t\tmaterial.removeEventListener( 'dispose', onMaterialDispose );\n\n\t\tdeallocateMaterial( material );\n\n\t}\n\n\t// Buffer deallocation\n\n\tfunction deallocateMaterial( material ) {\n\n\t\treleaseMaterialProgramReference( material );\n\n\t\tproperties.remove( material );\n\n\t}\n\n\n\tfunction releaseMaterialProgramReference( material ) {\n\n\t\tvar programInfo = properties.get( material ).program;\n\n\t\tmaterial.program = undefined;\n\n\t\tif ( programInfo !== undefined ) {\n\n\t\t\tprogramCache.releaseProgram( programInfo );\n\n\t\t}\n\n\t}\n\n\t// Buffer rendering\n\n\tfunction renderObjectImmediate( object, program ) {\n\n\t\tobject.render( function ( object ) {\n\n\t\t\t_this.renderBufferImmediate( object, program );\n\n\t\t} );\n\n\t}\n\n\tthis.renderBufferImmediate = function ( object, program ) {\n\n\t\tstate.initAttributes();\n\n\t\tvar buffers = properties.get( object );\n\n\t\tif ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();\n\t\tif ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();\n\t\tif ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();\n\t\tif ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();\n\n\t\tvar programAttributes = program.getAttributes();\n\n\t\tif ( object.hasPositions ) {\n\n\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );\n\t\t\t_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );\n\n\t\t\tstate.enableAttribute( programAttributes.position );\n\t\t\t_gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 );\n\n\t\t}\n\n\t\tif ( object.hasNormals ) {\n\n\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );\n\t\t\t_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );\n\n\t\t\tstate.enableAttribute( programAttributes.normal );\n\t\t\t_gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 );\n\n\t\t}\n\n\t\tif ( object.hasUvs ) {\n\n\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );\n\t\t\t_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );\n\n\t\t\tstate.enableAttribute( programAttributes.uv );\n\t\t\t_gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 );\n\n\t\t}\n\n\t\tif ( object.hasColors ) {\n\n\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );\n\t\t\t_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );\n\n\t\t\tstate.enableAttribute( programAttributes.color );\n\t\t\t_gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 );\n\n\t\t}\n\n\t\tstate.disableUnusedAttributes();\n\n\t\t_gl.drawArrays( _gl.TRIANGLES, 0, object.count );\n\n\t\tobject.count = 0;\n\n\t};\n\n\tvar tempScene = new Scene();\n\n\tthis.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {\n\n\t\tif ( scene === null ) scene = tempScene; // renderBufferDirect second parameter used to be fog (could be null)\n\n\t\tvar frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );\n\n\t\tvar program = setProgram( camera, scene, material, object );\n\n\t\tstate.setMaterial( material, frontFaceCW );\n\n\t\tvar updateBuffers = false;\n\n\t\tif ( _currentGeometryProgram.geometry !== geometry.id ||\n\t\t\t_currentGeometryProgram.program !== program.id ||\n\t\t\t_currentGeometryProgram.wireframe !== ( material.wireframe === true ) ) {\n\n\t\t\t_currentGeometryProgram.geometry = geometry.id;\n\t\t\t_currentGeometryProgram.program = program.id;\n\t\t\t_currentGeometryProgram.wireframe = material.wireframe === true;\n\t\t\tupdateBuffers = true;\n\n\t\t}\n\n\t\tif ( material.morphTargets || material.morphNormals ) {\n\n\t\t\tmorphtargets.update( object, geometry, material, program );\n\n\t\t\tupdateBuffers = true;\n\n\t\t}\n\n\t\tif ( object.isInstancedMesh === true ) {\n\n\t\t\tupdateBuffers = true;\n\n\t\t}\n\n\t\t//\n\n\t\tvar index = geometry.index;\n\t\tvar position = geometry.attributes.position;\n\n\t\t//\n\n\t\tif ( index === null ) {\n\n\t\t\tif ( position === undefined || position.count === 0 ) return;\n\n\t\t} else if ( index.count === 0 ) {\n\n\t\t\treturn;\n\n\t\t}\n\n\t\t//\n\n\t\tvar rangeFactor = 1;\n\n\t\tif ( material.wireframe === true ) {\n\n\t\t\tindex = geometries.getWireframeAttribute( geometry );\n\t\t\trangeFactor = 2;\n\n\t\t}\n\n\t\tvar attribute;\n\t\tvar renderer = bufferRenderer;\n\n\t\tif ( index !== null ) {\n\n\t\t\tattribute = attributes.get( index );\n\n\t\t\trenderer = indexedBufferRenderer;\n\t\t\trenderer.setIndex( attribute );\n\n\t\t}\n\n\t\tif ( updateBuffers ) {\n\n\t\t\tsetupVertexAttributes( object, geometry, material, program );\n\n\t\t\tif ( index !== null ) {\n\n\t\t\t\t_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer );\n\n\t\t\t}\n\n\t\t}\n\n\t\t//\n\n\t\tvar dataCount = ( index !== null ) ? index.count : position.count;\n\n\t\tvar rangeStart = geometry.drawRange.start * rangeFactor;\n\t\tvar rangeCount = geometry.drawRange.count * rangeFactor;\n\n\t\tvar groupStart = group !== null ? group.start * rangeFactor : 0;\n\t\tvar groupCount = group !== null ? group.count * rangeFactor : Infinity;\n\n\t\tvar drawStart = Math.max( rangeStart, groupStart );\n\t\tvar drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;\n\n\t\tvar drawCount = Math.max( 0, drawEnd - drawStart + 1 );\n\n\t\tif ( drawCount === 0 ) return;\n\n\t\t//\n\n\t\tif ( object.isMesh ) {\n\n\t\t\tif ( material.wireframe === true ) {\n\n\t\t\t\tstate.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );\n\t\t\t\trenderer.setMode( _gl.LINES );\n\n\t\t\t} else {\n\n\t\t\t\trenderer.setMode( _gl.TRIANGLES );\n\n\t\t\t}\n\n\t\t} else if ( object.isLine ) {\n\n\t\t\tvar lineWidth = material.linewidth;\n\n\t\t\tif ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material\n\n\t\t\tstate.setLineWidth( lineWidth * getTargetPixelRatio() );\n\n\t\t\tif ( object.isLineSegments ) {\n\n\t\t\t\trenderer.setMode( _gl.LINES );\n\n\t\t\t} else if ( object.isLineLoop ) {\n\n\t\t\t\trenderer.setMode( _gl.LINE_LOOP );\n\n\t\t\t} else {\n\n\t\t\t\trenderer.setMode( _gl.LINE_STRIP );\n\n\t\t\t}\n\n\t\t} else if ( object.isPoints ) {\n\n\t\t\trenderer.setMode( _gl.POINTS );\n\n\t\t} else if ( object.isSprite ) {\n\n\t\t\trenderer.setMode( _gl.TRIANGLES );\n\n\t\t}\n\n\t\tif ( object.isInstancedMesh ) {\n\n\t\t\trenderer.renderInstances( geometry, drawStart, drawCount, object.count );\n\n\t\t} else if ( geometry.isInstancedBufferGeometry ) {\n\n\t\t\tvar instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );\n\n\t\t\trenderer.renderInstances( geometry, drawStart, drawCount, instanceCount );\n\n\t\t} else {\n\n\t\t\trenderer.render( drawStart, drawCount );\n\n\t\t}\n\n\t};\n\n\tfunction setupVertexAttributes( object, geometry, material, program ) {\n\n\t\tif ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {\n\n\t\t\tif ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return;\n\n\t\t}\n\n\t\tstate.initAttributes();\n\n\t\tvar geometryAttributes = geometry.attributes;\n\n\t\tvar programAttributes = program.getAttributes();\n\n\t\tvar materialDefaultAttributeValues = material.defaultAttributeValues;\n\n\t\tfor ( var name in programAttributes ) {\n\n\t\t\tvar programAttribute = programAttributes[ name ];\n\n\t\t\tif ( programAttribute >= 0 ) {\n\n\t\t\t\tvar geometryAttribute = geometryAttributes[ name ];\n\n\t\t\t\tif ( geometryAttribute !== undefined ) {\n\n\t\t\t\t\tvar normalized = geometryAttribute.normalized;\n\t\t\t\t\tvar size = geometryAttribute.itemSize;\n\n\t\t\t\t\tvar attribute = attributes.get( geometryAttribute );\n\n\t\t\t\t\t// TODO Attribute may not be available on context restore\n\n\t\t\t\t\tif ( attribute === undefined ) continue;\n\n\t\t\t\t\tvar buffer = attribute.buffer;\n\t\t\t\t\tvar type = attribute.type;\n\t\t\t\t\tvar bytesPerElement = attribute.bytesPerElement;\n\n\t\t\t\t\tif ( geometryAttribute.isInterleavedBufferAttribute ) {\n\n\t\t\t\t\t\tvar data = geometryAttribute.data;\n\t\t\t\t\t\tvar stride = data.stride;\n\t\t\t\t\t\tvar offset = geometryAttribute.offset;\n\n\t\t\t\t\t\tif ( data && data.isInstancedInterleavedBuffer ) {\n\n\t\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );\n\n\t\t\t\t\t\t\tif ( geometry._maxInstanceCount === undefined ) {\n\n\t\t\t\t\t\t\t\tgeometry._maxInstanceCount = data.meshPerAttribute * data.count;\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tstate.enableAttribute( programAttribute );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );\n\t\t\t\t\t\tstate.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( geometryAttribute.isInstancedBufferAttribute ) {\n\n\t\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );\n\n\t\t\t\t\t\t\tif ( geometry._maxInstanceCount === undefined ) {\n\n\t\t\t\t\t\t\t\tgeometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tstate.enableAttribute( programAttribute );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );\n\t\t\t\t\t\tstate.vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( name === 'instanceMatrix' ) {\n\n\t\t\t\t\tvar attribute = attributes.get( object.instanceMatrix );\n\n\t\t\t\t\t// TODO Attribute may not be available on context restore\n\n\t\t\t\t\tif ( attribute === undefined ) continue;\n\n\t\t\t\t\tvar buffer = attribute.buffer;\n\t\t\t\t\tvar type = attribute.type;\n\n\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 0, 1 );\n\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 1, 1 );\n\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 2, 1 );\n\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 3, 1 );\n\n\t\t\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );\n\n\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 0, 4, type, false, 64, 0 );\n\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 1, 4, type, false, 64, 16 );\n\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );\n\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );\n\n\t\t\t\t} else if ( materialDefaultAttributeValues !== undefined ) {\n\n\t\t\t\t\tvar value = materialDefaultAttributeValues[ name ];\n\n\t\t\t\t\tif ( value !== undefined ) {\n\n\t\t\t\t\t\tswitch ( value.length ) {\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t_gl.vertexAttrib2fv( programAttribute, value );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t_gl.vertexAttrib3fv( programAttribute, value );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\t_gl.vertexAttrib4fv( programAttribute, value );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t_gl.vertexAttrib1fv( programAttribute, value );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tstate.disableUnusedAttributes();\n\n\t}\n\n\t// Compile\n\n\tthis.compile = function ( scene, camera ) {\n\n\t\tcurrentRenderState = renderStates.get( scene, camera );\n\t\tcurrentRenderState.init();\n\n\t\tscene.traverse( function ( object ) {\n\n\t\t\tif ( object.isLight ) {\n\n\t\t\t\tcurrentRenderState.pushLight( object );\n\n\t\t\t\tif ( object.castShadow ) {\n\n\t\t\t\t\tcurrentRenderState.pushShadow( object );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} );\n\n\t\tcurrentRenderState.setupLights( camera );\n\n\t\tconst compiled = {};\n\n\t\tscene.traverse( function ( object ) {\n\n\t\t\tlet material = object.material;\n\n\t\t\tif ( material ) {\n\n\t\t\t\tif ( Array.isArray( material ) ) {\n\n\t\t\t\t\tfor ( let i = 0; i < material.length; i ++ ) {\n\n\t\t\t\t\t\tlet material2 = material[ i ];\n\n\t\t\t\t\t\tif ( material2.uuid in compiled === false ) {\n\n\t\t\t\t\t\t\tinitMaterial( material2, scene, object );\n\t\t\t\t\t\t\tcompiled[ material2.uuid ] = true;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( material.uuid in compiled === false ) {\n\n\t\t\t\t\tinitMaterial( material, scene, object );\n\t\t\t\t\tcompiled[ material.uuid ] = true;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} );\n\n\t};\n\n\t// Animation Loop\n\n\tvar onAnimationFrameCallback = null;\n\n\tfunction onAnimationFrame( time ) {\n\n\t\tif ( xr.isPresenting ) return;\n\t\tif ( onAnimationFrameCallback ) onAnimationFrameCallback( time );\n\n\t}\n\n\tvar animation = new WebGLAnimation();\n\tanimation.setAnimationLoop( onAnimationFrame );\n\n\tif ( typeof window !== 'undefined' ) animation.setContext( window );\n\n\tthis.setAnimationLoop = function ( callback ) {\n\n\t\tonAnimationFrameCallback = callback;\n\t\txr.setAnimationLoop( callback );\n\n\t\tanimation.start();\n\n\t};\n\n\t// Rendering\n\n\tthis.render = function ( scene, camera ) {\n\n\t\tvar renderTarget, forceClear;\n\n\t\tif ( arguments[ 2 ] !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );\n\t\t\trenderTarget = arguments[ 2 ];\n\n\t\t}\n\n\t\tif ( arguments[ 3 ] !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.' );\n\t\t\tforceClear = arguments[ 3 ];\n\n\t\t}\n\n\t\tif ( ! ( camera && camera.isCamera ) ) {\n\n\t\t\tconsole.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( _isContextLost ) return;\n\n\t\t// reset caching for this frame\n\n\t\t_currentGeometryProgram.geometry = null;\n\t\t_currentGeometryProgram.program = null;\n\t\t_currentGeometryProgram.wireframe = false;\n\t\t_currentMaterialId = - 1;\n\t\t_currentCamera = null;\n\n\t\t// update scene graph\n\n\t\tif ( scene.autoUpdate === true ) scene.updateMatrixWorld();\n\n\t\t// update camera matrices and frustum\n\n\t\tif ( camera.parent === null ) camera.updateMatrixWorld();\n\n\t\tif ( xr.enabled && xr.isPresenting ) {\n\n\t\t\tcamera = xr.getCamera( camera );\n\n\t\t}\n\n\t\t//\n\t\tscene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );\n\n\t\tcurrentRenderState = renderStates.get( scene, camera );\n\t\tcurrentRenderState.init();\n\n\t\t_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );\n\t\t_frustum.setFromProjectionMatrix( _projScreenMatrix );\n\n\t\t_localClippingEnabled = this.localClippingEnabled;\n\t\t_clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );\n\n\t\tcurrentRenderList = renderLists.get( scene, camera );\n\t\tcurrentRenderList.init();\n\n\t\tprojectObject( scene, camera, 0, _this.sortObjects );\n\n\t\tcurrentRenderList.finish();\n\n\t\tif ( _this.sortObjects === true ) {\n\n\t\t\tcurrentRenderList.sort( _opaqueSort, _transparentSort );\n\n\t\t}\n\n\t\t//\n\n\t\tif ( _clippingEnabled ) _clipping.beginShadows();\n\n\t\tvar shadowsArray = currentRenderState.state.shadowsArray;\n\n\t\tshadowMap.render( shadowsArray, scene, camera );\n\n\t\tcurrentRenderState.setupLights( camera );\n\n\t\tif ( _clippingEnabled ) _clipping.endShadows();\n\n\t\t//\n\n\t\tif ( this.info.autoReset ) this.info.reset();\n\n\t\tif ( renderTarget !== undefined ) {\n\n\t\t\tthis.setRenderTarget( renderTarget );\n\n\t\t}\n\n\t\t//\n\n\t\tbackground.render( currentRenderList, scene, camera, forceClear );\n\n\t\t// render scene\n\n\t\tvar opaqueObjects = currentRenderList.opaque;\n\t\tvar transparentObjects = currentRenderList.transparent;\n\n\t\tif ( scene.overrideMaterial ) {\n\n\t\t\tvar overrideMaterial = scene.overrideMaterial;\n\n\t\t\tif ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial );\n\t\t\tif ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial );\n\n\t\t} else {\n\n\t\t\t// opaque pass (front-to-back order)\n\n\t\t\tif ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera );\n\n\t\t\t// transparent pass (back-to-front order)\n\n\t\t\tif ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera );\n\n\t\t}\n\n\t\t//\n\n\t\tscene.onAfterRender( _this, scene, camera );\n\n\t\t//\n\n\t\tif ( _currentRenderTarget !== null ) {\n\n\t\t\t// Generate mipmap if we're using any kind of mipmap filtering\n\n\t\t\ttextures.updateRenderTargetMipmap( _currentRenderTarget );\n\n\t\t\t// resolve multisample renderbuffers to a single-sample texture if necessary\n\n\t\t\ttextures.updateMultisampleRenderTarget( _currentRenderTarget );\n\n\t\t}\n\n\t\t// Ensure depth buffer writing is enabled so it can be cleared on next render\n\n\t\tstate.buffers.depth.setTest( true );\n\t\tstate.buffers.depth.setMask( true );\n\t\tstate.buffers.color.setMask( true );\n\n\t\tstate.setPolygonOffset( false );\n\n\t\t// _gl.finish();\n\n\t\tcurrentRenderList = null;\n\t\tcurrentRenderState = null;\n\n\t};\n\n\tfunction projectObject( object, camera, groupOrder, sortObjects ) {\n\n\t\tif ( object.visible === false ) return;\n\n\t\tvar visible = object.layers.test( camera.layers );\n\n\t\tif ( visible ) {\n\n\t\t\tif ( object.isGroup ) {\n\n\t\t\t\tgroupOrder = object.renderOrder;\n\n\t\t\t} else if ( object.isLOD ) {\n\n\t\t\t\tif ( object.autoUpdate === true ) object.update( camera );\n\n\t\t\t} else if ( object.isLight ) {\n\n\t\t\t\tcurrentRenderState.pushLight( object );\n\n\t\t\t\tif ( object.castShadow ) {\n\n\t\t\t\t\tcurrentRenderState.pushShadow( object );\n\n\t\t\t\t}\n\n\t\t\t} else if ( object.isSprite ) {\n\n\t\t\t\tif ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {\n\n\t\t\t\t\tif ( sortObjects ) {\n\n\t\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\n\t\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tvar geometry = objects.update( object );\n\t\t\t\t\tvar material = object.material;\n\n\t\t\t\t\tif ( material.visible ) {\n\n\t\t\t\t\t\tcurrentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( object.isImmediateRenderObject ) {\n\n\t\t\t\tif ( sortObjects ) {\n\n\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\n\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\n\n\t\t\t\t}\n\n\t\t\t\tcurrentRenderList.push( object, null, object.material, groupOrder, _vector3.z, null );\n\n\t\t\t} else if ( object.isMesh || object.isLine || object.isPoints ) {\n\n\t\t\t\tif ( object.isSkinnedMesh ) {\n\n\t\t\t\t\t// update skeleton only once in a frame\n\n\t\t\t\t\tif ( object.skeleton.frame !== info.render.frame ) {\n\n\t\t\t\t\t\tobject.skeleton.update();\n\t\t\t\t\t\tobject.skeleton.frame = info.render.frame;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {\n\n\t\t\t\t\tif ( sortObjects ) {\n\n\t\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\n\t\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tvar geometry = objects.update( object );\n\t\t\t\t\tvar material = object.material;\n\n\t\t\t\t\tif ( Array.isArray( material ) ) {\n\n\t\t\t\t\t\tvar groups = geometry.groups;\n\n\t\t\t\t\t\tfor ( var i = 0, l = groups.length; i < l; i ++ ) {\n\n\t\t\t\t\t\t\tvar group = groups[ i ];\n\t\t\t\t\t\t\tvar groupMaterial = material[ group.materialIndex ];\n\n\t\t\t\t\t\t\tif ( groupMaterial && groupMaterial.visible ) {\n\n\t\t\t\t\t\t\t\tcurrentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( material.visible ) {\n\n\t\t\t\t\t\tcurrentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar children = object.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tprojectObject( children[ i ], camera, groupOrder, sortObjects );\n\n\t\t}\n\n\t}\n\n\tfunction renderObjects( renderList, scene, camera, overrideMaterial ) {\n\n\t\tfor ( var i = 0, l = renderList.length; i < l; i ++ ) {\n\n\t\t\tvar renderItem = renderList[ i ];\n\n\t\t\tvar object = renderItem.object;\n\t\t\tvar geometry = renderItem.geometry;\n\t\t\tvar material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;\n\t\t\tvar group = renderItem.group;\n\n\t\t\tif ( camera.isArrayCamera ) {\n\n\t\t\t\t_currentArrayCamera = camera;\n\n\t\t\t\tvar cameras = camera.cameras;\n\n\t\t\t\tfor ( var j = 0, jl = cameras.length; j < jl; j ++ ) {\n\n\t\t\t\t\tvar camera2 = cameras[ j ];\n\n\t\t\t\t\tif ( object.layers.test( camera2.layers ) ) {\n\n\t\t\t\t\t\tstate.viewport( _currentViewport.copy( camera2.viewport ) );\n\n\t\t\t\t\t\tcurrentRenderState.setupLights( camera2 );\n\n\t\t\t\t\t\trenderObject( object, scene, camera2, geometry, material, group );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t_currentArrayCamera = null;\n\n\t\t\t\trenderObject( object, scene, camera, geometry, material, group );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tfunction renderObject( object, scene, camera, geometry, material, group ) {\n\n\t\tobject.onBeforeRender( _this, scene, camera, geometry, material, group );\n\t\tcurrentRenderState = renderStates.get( scene, _currentArrayCamera || camera );\n\n\t\tobject.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );\n\t\tobject.normalMatrix.getNormalMatrix( object.modelViewMatrix );\n\n\t\tif ( object.isImmediateRenderObject ) {\n\n\t\t\tvar program = setProgram( camera, scene, material, object );\n\n\t\t\tstate.setMaterial( material );\n\n\t\t\t_currentGeometryProgram.geometry = null;\n\t\t\t_currentGeometryProgram.program = null;\n\t\t\t_currentGeometryProgram.wireframe = false;\n\n\t\t\trenderObjectImmediate( object, program );\n\n\t\t} else {\n\n\t\t\t_this.renderBufferDirect( camera, scene, geometry, material, object, group );\n\n\t\t}\n\n\t\tobject.onAfterRender( _this, scene, camera, geometry, material, group );\n\t\tcurrentRenderState = renderStates.get( scene, _currentArrayCamera || camera );\n\n\t}\n\n\tfunction initMaterial( material, scene, object ) {\n\n\t\tvar materialProperties = properties.get( material );\n\n\t\tvar lights = currentRenderState.state.lights;\n\t\tvar shadowsArray = currentRenderState.state.shadowsArray;\n\n\t\tvar lightsStateVersion = lights.state.version;\n\n\t\tvar parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, _clipping.numPlanes, _clipping.numIntersection, object );\n\t\tvar programCacheKey = programCache.getProgramCacheKey( parameters );\n\n\t\tvar program = materialProperties.program;\n\t\tvar programChange = true;\n\n\t\tif ( program === undefined ) {\n\n\t\t\t// new material\n\t\t\tmaterial.addEventListener( 'dispose', onMaterialDispose );\n\n\t\t} else if ( program.cacheKey !== programCacheKey ) {\n\n\t\t\t// changed glsl or parameters\n\t\t\treleaseMaterialProgramReference( material );\n\n\t\t} else if ( materialProperties.lightsStateVersion !== lightsStateVersion ) {\n\n\t\t\tmaterialProperties.lightsStateVersion = lightsStateVersion;\n\n\t\t\tprogramChange = false;\n\n\t\t} else if ( parameters.shaderID !== undefined ) {\n\n\t\t\t// same glsl and uniform list\n\t\t\treturn;\n\n\t\t} else {\n\n\t\t\t// only rebuild uniform list\n\t\t\tprogramChange = false;\n\n\t\t}\n\n\t\tif ( programChange ) {\n\n\t\t\tprogram = programCache.acquireProgram( parameters, programCacheKey );\n\n\t\t\tmaterialProperties.program = program;\n\t\t\tmaterialProperties.uniforms = parameters.uniforms;\n\t\t\tmaterialProperties.outputEncoding = parameters.outputEncoding;\n\t\t\tmaterial.program = program;\n\n\t\t}\n\n\t\tvar programAttributes = program.getAttributes();\n\n\t\tif ( material.morphTargets ) {\n\n\t\t\tmaterial.numSupportedMorphTargets = 0;\n\n\t\t\tfor ( var i = 0; i < _this.maxMorphTargets; i ++ ) {\n\n\t\t\t\tif ( programAttributes[ 'morphTarget' + i ] >= 0 ) {\n\n\t\t\t\t\tmaterial.numSupportedMorphTargets ++;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( material.morphNormals ) {\n\n\t\t\tmaterial.numSupportedMorphNormals = 0;\n\n\t\t\tfor ( var i = 0; i < _this.maxMorphNormals; i ++ ) {\n\n\t\t\t\tif ( programAttributes[ 'morphNormal' + i ] >= 0 ) {\n\n\t\t\t\t\tmaterial.numSupportedMorphNormals ++;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar uniforms = materialProperties.uniforms;\n\n\t\tif ( ! material.isShaderMaterial &&\n\t\t\t! material.isRawShaderMaterial ||\n\t\t\tmaterial.clipping === true ) {\n\n\t\t\tmaterialProperties.numClippingPlanes = _clipping.numPlanes;\n\t\t\tmaterialProperties.numIntersection = _clipping.numIntersection;\n\t\t\tuniforms.clippingPlanes = _clipping.uniform;\n\n\t\t}\n\n\t\tmaterialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;\n\t\tmaterialProperties.fog = scene.fog;\n\n\t\t// store the light setup it was created for\n\n\t\tmaterialProperties.needsLights = materialNeedsLights( material );\n\t\tmaterialProperties.lightsStateVersion = lightsStateVersion;\n\n\t\tif ( materialProperties.needsLights ) {\n\n\t\t\t// wire up the material to this renderer's lighting state\n\n\t\t\tuniforms.ambientLightColor.value = lights.state.ambient;\n\t\t\tuniforms.lightProbe.value = lights.state.probe;\n\t\t\tuniforms.directionalLights.value = lights.state.directional;\n\t\t\tuniforms.directionalLightShadows.value = lights.state.directionalShadow;\n\t\t\tuniforms.spotLights.value = lights.state.spot;\n\t\t\tuniforms.spotLightShadows.value = lights.state.spotShadow;\n\t\t\tuniforms.rectAreaLights.value = lights.state.rectArea;\n\t\t\tuniforms.pointLights.value = lights.state.point;\n\t\t\tuniforms.pointLightShadows.value = lights.state.pointShadow;\n\t\t\tuniforms.hemisphereLights.value = lights.state.hemi;\n\n\t\t\tuniforms.directionalShadowMap.value = lights.state.directionalShadowMap;\n\t\t\tuniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;\n\t\t\tuniforms.spotShadowMap.value = lights.state.spotShadowMap;\n\t\t\tuniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;\n\t\t\tuniforms.pointShadowMap.value = lights.state.pointShadowMap;\n\t\t\tuniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;\n\t\t\t// TODO (abelnation): add area lights shadow info to uniforms\n\n\t\t}\n\n\t\tvar progUniforms = materialProperties.program.getUniforms(),\n\t\t\tuniformsList =\n\t\t\t\tWebGLUniforms.seqWithValue( progUniforms.seq, uniforms );\n\n\t\tmaterialProperties.uniformsList = uniformsList;\n\n\t}\n\n\tfunction setProgram( camera, scene, material, object ) {\n\n\t\ttextures.resetTextureUnits();\n\n\t\tvar fog = scene.fog;\n\t\tvar environment = material.isMeshStandardMaterial ? scene.environment : null;\n\t\tvar encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : _currentRenderTarget.texture.encoding;\n\n\t\tvar materialProperties = properties.get( material );\n\t\tvar lights = currentRenderState.state.lights;\n\n\t\tif ( _clippingEnabled ) {\n\n\t\t\tif ( _localClippingEnabled || camera !== _currentCamera ) {\n\n\t\t\t\tvar useCache =\n\t\t\t\t\tcamera === _currentCamera &&\n\t\t\t\t\tmaterial.id === _currentMaterialId;\n\n\t\t\t\t// we might want to call this function with some ClippingGroup\n\t\t\t\t// object instead of the material, once it becomes feasible\n\t\t\t\t// (#8465, #8379)\n\t\t\t\t_clipping.setState(\n\t\t\t\t\tmaterial.clippingPlanes, material.clipIntersection, material.clipShadows,\n\t\t\t\t\tcamera, materialProperties, useCache );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( material.version === materialProperties.__version ) {\n\n\t\t\tif ( materialProperties.program === undefined ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t} else if ( material.fog && materialProperties.fog !== fog ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t} else if ( materialProperties.environment !== environment ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t} else if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t} else if ( materialProperties.numClippingPlanes !== undefined &&\n\t\t\t\t( materialProperties.numClippingPlanes !== _clipping.numPlanes ||\n\t\t\t\tmaterialProperties.numIntersection !== _clipping.numIntersection ) ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t} else if ( materialProperties.outputEncoding !== encoding ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tinitMaterial( material, scene, object );\n\t\t\tmaterialProperties.__version = material.version;\n\n\t\t}\n\n\t\tvar refreshProgram = false;\n\t\tvar refreshMaterial = false;\n\t\tvar refreshLights = false;\n\n\t\tvar program = materialProperties.program,\n\t\t\tp_uniforms = program.getUniforms(),\n\t\t\tm_uniforms = materialProperties.uniforms;\n\n\t\tif ( state.useProgram( program.program ) ) {\n\n\t\t\trefreshProgram = true;\n\t\t\trefreshMaterial = true;\n\t\t\trefreshLights = true;\n\n\t\t}\n\n\t\tif ( material.id !== _currentMaterialId ) {\n\n\t\t\t_currentMaterialId = material.id;\n\n\t\t\trefreshMaterial = true;\n\n\t\t}\n\n\t\tif ( refreshProgram || _currentCamera !== camera ) {\n\n\t\t\tp_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );\n\n\t\t\tif ( capabilities.logarithmicDepthBuffer ) {\n\n\t\t\t\tp_uniforms.setValue( _gl, 'logDepthBufFC',\n\t\t\t\t\t2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );\n\n\t\t\t}\n\n\t\t\tif ( _currentCamera !== camera ) {\n\n\t\t\t\t_currentCamera = camera;\n\n\t\t\t\t// lighting uniforms depend on the camera so enforce an update\n\t\t\t\t// now, in case this material supports lights - or later, when\n\t\t\t\t// the next material that does gets activated:\n\n\t\t\t\trefreshMaterial = true;\t\t// set to true on material change\n\t\t\t\trefreshLights = true;\t\t// remains set until update done\n\n\t\t\t}\n\n\t\t\t// load material specific uniforms\n\t\t\t// (shader material also gets them for the sake of genericity)\n\n\t\t\tif ( material.isShaderMaterial ||\n\t\t\t\tmaterial.isMeshPhongMaterial ||\n\t\t\t\tmaterial.isMeshToonMaterial ||\n\t\t\t\tmaterial.isMeshStandardMaterial ||\n\t\t\t\tmaterial.envMap ) {\n\n\t\t\t\tvar uCamPos = p_uniforms.map.cameraPosition;\n\n\t\t\t\tif ( uCamPos !== undefined ) {\n\n\t\t\t\t\tuCamPos.setValue( _gl,\n\t\t\t\t\t\t_vector3.setFromMatrixPosition( camera.matrixWorld ) );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( material.isMeshPhongMaterial ||\n\t\t\t\tmaterial.isMeshToonMaterial ||\n\t\t\t\tmaterial.isMeshLambertMaterial ||\n\t\t\t\tmaterial.isMeshBasicMaterial ||\n\t\t\t\tmaterial.isMeshStandardMaterial ||\n\t\t\t\tmaterial.isShaderMaterial ) {\n\n\t\t\t\tp_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );\n\n\t\t\t}\n\n\t\t\tif ( material.isMeshPhongMaterial ||\n\t\t\t\tmaterial.isMeshToonMaterial ||\n\t\t\t\tmaterial.isMeshLambertMaterial ||\n\t\t\t\tmaterial.isMeshBasicMaterial ||\n\t\t\t\tmaterial.isMeshStandardMaterial ||\n\t\t\t\tmaterial.isShaderMaterial ||\n\t\t\t\tmaterial.skinning ) {\n\n\t\t\t\tp_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// skinning uniforms must be set even if material didn't change\n\t\t// auto-setting of texture unit for bone texture must go before other textures\n\t\t// otherwise textures used for skinning can take over texture units reserved for other material textures\n\n\t\tif ( material.skinning ) {\n\n\t\t\tp_uniforms.setOptional( _gl, object, 'bindMatrix' );\n\t\t\tp_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );\n\n\t\t\tvar skeleton = object.skeleton;\n\n\t\t\tif ( skeleton ) {\n\n\t\t\t\tvar bones = skeleton.bones;\n\n\t\t\t\tif ( capabilities.floatVertexTextures ) {\n\n\t\t\t\t\tif ( skeleton.boneTexture === undefined ) {\n\n\t\t\t\t\t\t// layout (1 matrix = 4 pixels)\n\t\t\t\t\t\t// RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)\n\t\t\t\t\t\t// with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)\n\t\t\t\t\t\t// 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)\n\t\t\t\t\t\t// 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)\n\t\t\t\t\t\t// 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)\n\n\n\t\t\t\t\t\tvar size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix\n\t\t\t\t\t\tsize = MathUtils.ceilPowerOfTwo( size );\n\t\t\t\t\t\tsize = Math.max( size, 4 );\n\n\t\t\t\t\t\tvar boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel\n\t\t\t\t\t\tboneMatrices.set( skeleton.boneMatrices ); // copy current values\n\n\t\t\t\t\t\tvar boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );\n\n\t\t\t\t\t\tskeleton.boneMatrices = boneMatrices;\n\t\t\t\t\t\tskeleton.boneTexture = boneTexture;\n\t\t\t\t\t\tskeleton.boneTextureSize = size;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tp_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );\n\t\t\t\t\tp_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tp_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {\n\n\t\t\tmaterialProperties.receiveShadow = object.receiveShadow;\n\t\t\tp_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );\n\n\t\t}\n\n\t\tif ( refreshMaterial ) {\n\n\t\t\tp_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );\n\t\t\tp_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint );\n\n\t\t\tif ( materialProperties.needsLights ) {\n\n\t\t\t\t// the current material requires lighting info\n\n\t\t\t\t// note: all lighting uniforms are always set correctly\n\t\t\t\t// they simply reference the renderer's state for their\n\t\t\t\t// values\n\t\t\t\t//\n\t\t\t\t// use the current material's .needsUpdate flags to set\n\t\t\t\t// the GL state when required\n\n\t\t\t\tmarkUniformsLightsNeedsUpdate( m_uniforms, refreshLights );\n\n\t\t\t}\n\n\t\t\t// refresh uniforms common to several materials\n\n\t\t\tif ( fog && material.fog ) {\n\n\t\t\t\tmaterials.refreshFogUniforms( m_uniforms, fog );\n\n\t\t\t}\n\n\t\t\tmaterials.refreshMaterialUniforms( m_uniforms, material, environment, _pixelRatio, _height );\n\n\t\t\t// RectAreaLight Texture\n\t\t\t// TODO (mrdoob): Find a nicer implementation\n\n\t\t\tif ( m_uniforms.ltc_1 !== undefined ) m_uniforms.ltc_1.value = UniformsLib.LTC_1;\n\t\t\tif ( m_uniforms.ltc_2 !== undefined ) m_uniforms.ltc_2.value = UniformsLib.LTC_2;\n\n\t\t\tWebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );\n\n\t\t}\n\n\t\tif ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {\n\n\t\t\tWebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );\n\t\t\tmaterial.uniformsNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( material.isSpriteMaterial ) {\n\n\t\t\tp_uniforms.setValue( _gl, 'center', object.center );\n\n\t\t}\n\n\t\t// common matrices\n\n\t\tp_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );\n\t\tp_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );\n\t\tp_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );\n\n\t\treturn program;\n\n\t}\n\n\t// If uniforms are marked as clean, they don't need to be loaded to the GPU.\n\n\tfunction markUniformsLightsNeedsUpdate( uniforms, value ) {\n\n\t\tuniforms.ambientLightColor.needsUpdate = value;\n\t\tuniforms.lightProbe.needsUpdate = value;\n\n\t\tuniforms.directionalLights.needsUpdate = value;\n\t\tuniforms.directionalLightShadows.needsUpdate = value;\n\t\tuniforms.pointLights.needsUpdate = value;\n\t\tuniforms.pointLightShadows.needsUpdate = value;\n\t\tuniforms.spotLights.needsUpdate = value;\n\t\tuniforms.spotLightShadows.needsUpdate = value;\n\t\tuniforms.rectAreaLights.needsUpdate = value;\n\t\tuniforms.hemisphereLights.needsUpdate = value;\n\n\t}\n\n\tfunction materialNeedsLights( material ) {\n\n\t\treturn material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||\n\t\t\tmaterial.isMeshStandardMaterial || material.isShadowMaterial ||\n\t\t\t( material.isShaderMaterial && material.lights === true );\n\n\t}\n\n\t//\n\tthis.setFramebuffer = function ( value ) {\n\n\t\tif ( _framebuffer !== value && _currentRenderTarget === null ) _gl.bindFramebuffer( _gl.FRAMEBUFFER, value );\n\n\t\t_framebuffer = value;\n\n\t};\n\n\tthis.getActiveCubeFace = function () {\n\n\t\treturn _currentActiveCubeFace;\n\n\t};\n\n\tthis.getActiveMipmapLevel = function () {\n\n\t\treturn _currentActiveMipmapLevel;\n\n\t};\n\n\tthis.getRenderTarget = function () {\n\n\t\treturn _currentRenderTarget;\n\n\t};\n\n\tthis.setRenderTarget = function ( renderTarget, activeCubeFace, activeMipmapLevel ) {\n\n\t\t_currentRenderTarget = renderTarget;\n\t\t_currentActiveCubeFace = activeCubeFace;\n\t\t_currentActiveMipmapLevel = activeMipmapLevel;\n\n\t\tif ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {\n\n\t\t\ttextures.setupRenderTarget( renderTarget );\n\n\t\t}\n\n\t\tvar framebuffer = _framebuffer;\n\t\tvar isCube = false;\n\n\t\tif ( renderTarget ) {\n\n\t\t\tvar __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;\n\n\t\t\tif ( renderTarget.isWebGLCubeRenderTarget ) {\n\n\t\t\t\tframebuffer = __webglFramebuffer[ activeCubeFace || 0 ];\n\t\t\t\tisCube = true;\n\n\t\t\t} else if ( renderTarget.isWebGLMultisampleRenderTarget ) {\n\n\t\t\t\tframebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;\n\n\t\t\t} else {\n\n\t\t\t\tframebuffer = __webglFramebuffer;\n\n\t\t\t}\n\n\t\t\t_currentViewport.copy( renderTarget.viewport );\n\t\t\t_currentScissor.copy( renderTarget.scissor );\n\t\t\t_currentScissorTest = renderTarget.scissorTest;\n\n\t\t} else {\n\n\t\t\t_currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();\n\t\t\t_currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();\n\t\t\t_currentScissorTest = _scissorTest;\n\n\t\t}\n\n\t\tif ( _currentFramebuffer !== framebuffer ) {\n\n\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );\n\t\t\t_currentFramebuffer = framebuffer;\n\n\t\t}\n\n\t\tstate.viewport( _currentViewport );\n\t\tstate.scissor( _currentScissor );\n\t\tstate.setScissorTest( _currentScissorTest );\n\n\t\tif ( isCube ) {\n\n\t\t\tvar textureProperties = properties.get( renderTarget.texture );\n\t\t\t_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + ( activeCubeFace || 0 ), textureProperties.__webglTexture, activeMipmapLevel || 0 );\n\n\t\t}\n\n\t};\n\n\tthis.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {\n\n\t\tif ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {\n\n\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );\n\t\t\treturn;\n\n\t\t}\n\n\t\tvar framebuffer = properties.get( renderTarget ).__webglFramebuffer;\n\n\t\tif ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {\n\n\t\t\tframebuffer = framebuffer[ activeCubeFaceIndex ];\n\n\t\t}\n\n\t\tif ( framebuffer ) {\n\n\t\t\tvar restore = false;\n\n\t\t\tif ( framebuffer !== _currentFramebuffer ) {\n\n\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );\n\n\t\t\t\trestore = true;\n\n\t\t\t}\n\n\t\t\ttry {\n\n\t\t\t\tvar texture = renderTarget.texture;\n\t\t\t\tvar textureFormat = texture.format;\n\t\t\t\tvar textureType = texture.type;\n\n\t\t\t\tif ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {\n\n\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );\n\t\t\t\t\treturn;\n\n\t\t\t\t}\n\n\t\t\t\tif ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)\n\t\t\t\t\t! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox\n\t\t\t\t\t! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {\n\n\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );\n\t\t\t\t\treturn;\n\n\t\t\t\t}\n\n\t\t\t\tif ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {\n\n\t\t\t\t\t// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)\n\n\t\t\t\t\tif ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {\n\n\t\t\t\t\t\t_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );\n\n\t\t\t\t}\n\n\t\t\t} finally {\n\n\t\t\t\tif ( restore ) {\n\n\t\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t};\n\n\tthis.copyFramebufferToTexture = function ( position, texture, level ) {\n\n\t\tif ( level === undefined ) level = 0;\n\n\t\tvar levelScale = Math.pow( 2, - level );\n\t\tvar width = Math.floor( texture.image.width * levelScale );\n\t\tvar height = Math.floor( texture.image.height * levelScale );\n\t\tvar glFormat = utils.convert( texture.format );\n\n\t\ttextures.setTexture2D( texture, 0 );\n\n\t\t_gl.copyTexImage2D( _gl.TEXTURE_2D, level, glFormat, position.x, position.y, width, height, 0 );\n\n\t\tstate.unbindTexture();\n\n\t};\n\n\tthis.copyTextureToTexture = function ( position, srcTexture, dstTexture, level ) {\n\n\t\tif ( level === undefined ) level = 0;\n\n\t\tvar width = srcTexture.image.width;\n\t\tvar height = srcTexture.image.height;\n\t\tvar glFormat = utils.convert( dstTexture.format );\n\t\tvar glType = utils.convert( dstTexture.type );\n\n\t\ttextures.setTexture2D( dstTexture, 0 );\n\n\t\tif ( srcTexture.isDataTexture ) {\n\n\t\t\t_gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );\n\n\t\t} else {\n\n\t\t\tif ( srcTexture.isCompressedTexture ) {\n\n\t\t\t\t_gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );\n\n\t\t\t} else {\n\n\t\t\t\t_gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Generate mipmaps only when copying level 0\n\t\tif ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D );\n\n\t\tstate.unbindTexture();\n\n\t};\n\n\tthis.initTexture = function ( texture ) {\n\n\t\ttextures.setTexture2D( texture, 0 );\n\n\t\tstate.unbindTexture();\n\n\t};\n\n\tif ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {\n\n\t\t__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef\n\n\t}\n\n}\n\nexport { WebGLRenderer };\n","/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nfunction Clock( autoStart ) {\n\n\tthis.autoStart = ( autoStart !== undefined ) ? autoStart : true;\n\n\tthis.startTime = 0;\n\tthis.oldTime = 0;\n\tthis.elapsedTime = 0;\n\n\tthis.running = false;\n\n}\n\nObject.assign( Clock.prototype, {\n\n\tstart: function () {\n\n\t\tthis.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732\n\n\t\tthis.oldTime = this.startTime;\n\t\tthis.elapsedTime = 0;\n\t\tthis.running = true;\n\n\t},\n\n\tstop: function () {\n\n\t\tthis.getElapsedTime();\n\t\tthis.running = false;\n\t\tthis.autoStart = false;\n\n\t},\n\n\tgetElapsedTime: function () {\n\n\t\tthis.getDelta();\n\t\treturn this.elapsedTime;\n\n\t},\n\n\tgetDelta: function () {\n\n\t\tvar diff = 0;\n\n\t\tif ( this.autoStart && ! this.running ) {\n\n\t\t\tthis.start();\n\t\t\treturn 0;\n\n\t\t}\n\n\t\tif ( this.running ) {\n\n\t\t\tvar newTime = ( typeof performance === 'undefined' ? Date : performance ).now();\n\n\t\t\tdiff = ( newTime - this.oldTime ) / 1000;\n\t\t\tthis.oldTime = newTime;\n\n\t\t\tthis.elapsedTime += diff;\n\n\t\t}\n\n\t\treturn diff;\n\n\t}\n\n} );\n\n\nexport { Clock };\n","import { MathUtils } from './MathUtils.js';\n\n/**\n * @author bhouston / http://clara.io\n * @author WestLangley / http://github.com/WestLangley\n *\n * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system\n *\n * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.\n * The azimuthal angle (theta) is measured from the positive z-axis.\n */\n\nfunction Spherical( radius, phi, theta ) {\n\n\tthis.radius = ( radius !== undefined ) ? radius : 1.0;\n\tthis.phi = ( phi !== undefined ) ? phi : 0; // polar angle\n\tthis.theta = ( theta !== undefined ) ? theta : 0; // azimuthal angle\n\n\treturn this;\n\n}\n\nObject.assign( Spherical.prototype, {\n\n\tset: function ( radius, phi, theta ) {\n\n\t\tthis.radius = radius;\n\t\tthis.phi = phi;\n\t\tthis.theta = theta;\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( other ) {\n\n\t\tthis.radius = other.radius;\n\t\tthis.phi = other.phi;\n\t\tthis.theta = other.theta;\n\n\t\treturn this;\n\n\t},\n\n\t// restrict phi to be betwee EPS and PI-EPS\n\tmakeSafe: function () {\n\n\t\tvar EPS = 0.000001;\n\t\tthis.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromVector3: function ( v ) {\n\n\t\treturn this.setFromCartesianCoords( v.x, v.y, v.z );\n\n\t},\n\n\tsetFromCartesianCoords: function ( x, y, z ) {\n\n\t\tthis.radius = Math.sqrt( x * x + y * y + z * z );\n\n\t\tif ( this.radius === 0 ) {\n\n\t\t\tthis.theta = 0;\n\t\t\tthis.phi = 0;\n\n\t\t} else {\n\n\t\t\tthis.theta = Math.atan2( x, z );\n\t\t\tthis.phi = Math.acos( MathUtils.clamp( y / this.radius, - 1, 1 ) );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Spherical };\n","import { BoxGeometry, DoubleSide, FrontSide, Group, Mesh, MeshBasicMaterial, Object3D, Texture, Vector2 } from \"three\";\n\nfunction toFaceVertices(x1: number, y1: number, x2: number, y2: number, w: number, h: number): Array {\n\treturn [\n\t\tnew Vector2(x1 / w, 1.0 - y2 / h),\n\t\tnew Vector2(x2 / w, 1.0 - y2 / h),\n\t\tnew Vector2(x2 / w, 1.0 - y1 / h),\n\t\tnew Vector2(x1 / w, 1.0 - y1 / h)\n\t];\n}\n\nfunction toSkinVertices(x1: number, y1: number, x2: number, y2: number): Array {\n\treturn toFaceVertices(x1, y1, x2, y2, 64.0, 64.0);\n}\n\nfunction toCapeVertices(x1: number, y1: number, x2: number, y2: number): Array {\n\treturn toFaceVertices(x1, y1, x2, y2, 64.0, 32.0);\n}\n\nfunction setVertices(box: BoxGeometry, top: Array, bottom: Array, left: Array, front: Array, right: Array, back: Array): void {\n\n\tbox.faceVertexUvs[0] = [];\n\tbox.faceVertexUvs[0][0] = [right[3], right[0], right[2]];\n\tbox.faceVertexUvs[0][1] = [right[0], right[1], right[2]];\n\tbox.faceVertexUvs[0][2] = [left[3], left[0], left[2]];\n\tbox.faceVertexUvs[0][3] = [left[0], left[1], left[2]];\n\tbox.faceVertexUvs[0][4] = [top[3], top[0], top[2]];\n\tbox.faceVertexUvs[0][5] = [top[0], top[1], top[2]];\n\tbox.faceVertexUvs[0][6] = [bottom[0], bottom[3], bottom[1]];\n\tbox.faceVertexUvs[0][7] = [bottom[3], bottom[2], bottom[1]];\n\tbox.faceVertexUvs[0][8] = [front[3], front[0], front[2]];\n\tbox.faceVertexUvs[0][9] = [front[0], front[1], front[2]];\n\tbox.faceVertexUvs[0][10] = [back[3], back[0], back[2]];\n\tbox.faceVertexUvs[0][11] = [back[0], back[1], back[2]];\n}\n\n/**\n * Notice that innerLayer and outerLayer may NOT be the direct children of the Group.\n */\nexport class BodyPart extends Group {\n\tconstructor(\n\t\treadonly innerLayer: Object3D,\n\t\treadonly outerLayer: Object3D\n\t) {\n\t\tsuper();\n\t\tinnerLayer.name = \"inner\";\n\t\touterLayer.name = \"outer\";\n\t}\n}\n\nexport class SkinObject extends Group {\n\n\t// body parts\n\treadonly head: BodyPart;\n\treadonly body: BodyPart;\n\treadonly rightArm: BodyPart;\n\treadonly leftArm: BodyPart;\n\treadonly rightLeg: BodyPart;\n\treadonly leftLeg: BodyPart;\n\n\tprivate modelListeners: Array<() => void> = []; // called when model(slim property) is changed\n\tprivate _slim = false;\n\n\tconstructor(texture: Texture) {\n\t\tsuper();\n\n\t\tconst layer1 = {\n\t\t\tmap: texture,\n\t\t\tside: FrontSide\n\t\t};\n\t\tconst layer2 = {\n\t\t\tmap: texture,\n\t\t\tside: DoubleSide,\n\t\t\ttransparent: true,\n\t\t\topacity: 1,\n\t\t\talphaTest: 0.5\n\t\t}\n\n\t\tconst layer1Material = new MeshBasicMaterial(layer1);\n\t\tconst layer2Material = new MeshBasicMaterial(layer2);\n\n\t\t// Head\n\t\tconst headBox = new BoxGeometry(8, 8, 8, 0, 0, 0);\n\t\tsetVertices(headBox,\n\t\t\ttoSkinVertices(8, 0, 16, 8),\n\t\t\ttoSkinVertices(16, 0, 24, 8),\n\t\t\ttoSkinVertices(0, 8, 8, 16),\n\t\t\ttoSkinVertices(8, 8, 16, 16),\n\t\t\ttoSkinVertices(16, 8, 24, 16),\n\t\t\ttoSkinVertices(24, 8, 32, 16)\n\t\t);\n\t\tconst headMesh = new Mesh(headBox, layer1Material);\n\n\t\tconst head2Box = new BoxGeometry(9, 9, 9, 0, 0, 0);\n\t\tsetVertices(head2Box,\n\t\t\ttoSkinVertices(40, 0, 48, 8),\n\t\t\ttoSkinVertices(48, 0, 56, 8),\n\t\t\ttoSkinVertices(32, 8, 40, 16),\n\t\t\ttoSkinVertices(40, 8, 48, 16),\n\t\t\ttoSkinVertices(48, 8, 56, 16),\n\t\t\ttoSkinVertices(56, 8, 64, 16)\n\t\t);\n\t\tconst head2Mesh = new Mesh(head2Box, layer2Material);\n\t\thead2Mesh.renderOrder = -1;\n\n\t\tthis.head = new BodyPart(headMesh, head2Mesh);\n\t\tthis.head.name = \"head\";\n\t\tthis.head.add(headMesh, head2Mesh);\n\t\tthis.add(this.head);\n\n\t\t// Body\n\t\tconst bodyBox = new BoxGeometry(8, 12, 4, 0, 0, 0);\n\t\tsetVertices(bodyBox,\n\t\t\ttoSkinVertices(20, 16, 28, 20),\n\t\t\ttoSkinVertices(28, 16, 36, 20),\n\t\t\ttoSkinVertices(16, 20, 20, 32),\n\t\t\ttoSkinVertices(20, 20, 28, 32),\n\t\t\ttoSkinVertices(28, 20, 32, 32),\n\t\t\ttoSkinVertices(32, 20, 40, 32)\n\t\t);\n\t\tconst bodyMesh = new Mesh(bodyBox, new MeshBasicMaterial({\n\t\t\t...layer1,\n\t\t\t// this pulls bodyMesh towards the camera\n\t\t\t// so body is given priority over others in z-fighting\n\t\t\tpolygonOffset: true,\n\t\t\tpolygonOffsetUnits: -1\n\t\t}));\n\n\t\tconst body2Box = new BoxGeometry(9, 13.5, 4.5, 0, 0, 0);\n\t\tsetVertices(body2Box,\n\t\t\ttoSkinVertices(20, 32, 28, 36),\n\t\t\ttoSkinVertices(28, 32, 36, 36),\n\t\t\ttoSkinVertices(16, 36, 20, 48),\n\t\t\ttoSkinVertices(20, 36, 28, 48),\n\t\t\ttoSkinVertices(28, 36, 32, 48),\n\t\t\ttoSkinVertices(32, 36, 40, 48)\n\t\t);\n\t\tconst body2Mesh = new Mesh(body2Box, new MeshBasicMaterial({\n\t\t\t...layer2,\n\t\t\t// same as above\n\t\t\tpolygonOffset: true,\n\t\t\tpolygonOffsetUnits: -1\n\t\t}));\n\n\t\tthis.body = new BodyPart(bodyMesh, body2Mesh);\n\t\tthis.body.name = \"body\";\n\t\tthis.body.add(bodyMesh, body2Mesh);\n\t\tthis.body.position.y = -10;\n\t\tthis.add(this.body);\n\n\t\t// Right Arm\n\t\tconst rightArmBox = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tconst rightArmMesh = new Mesh(rightArmBox, layer1Material);\n\t\tthis.modelListeners.push(() => {\n\t\t\trightArmMesh.scale.x = this.slim ? 3 : 4;\n\t\t\trightArmMesh.scale.y = 12;\n\t\t\trightArmMesh.scale.z = 4;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(rightArmBox,\n\t\t\t\t\ttoSkinVertices(44, 16, 47, 20),\n\t\t\t\t\ttoSkinVertices(47, 16, 50, 20),\n\t\t\t\t\ttoSkinVertices(40, 20, 44, 32),\n\t\t\t\t\ttoSkinVertices(44, 20, 47, 32),\n\t\t\t\t\ttoSkinVertices(47, 20, 51, 32),\n\t\t\t\t\ttoSkinVertices(51, 20, 54, 32)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(rightArmBox,\n\t\t\t\t\ttoSkinVertices(44, 16, 48, 20),\n\t\t\t\t\ttoSkinVertices(48, 16, 52, 20),\n\t\t\t\t\ttoSkinVertices(40, 20, 44, 32),\n\t\t\t\t\ttoSkinVertices(44, 20, 48, 32),\n\t\t\t\t\ttoSkinVertices(48, 20, 52, 32),\n\t\t\t\t\ttoSkinVertices(52, 20, 56, 32)\n\t\t\t\t);\n\t\t\t}\n\t\t\trightArmBox.uvsNeedUpdate = true;\n\t\t\trightArmBox.elementsNeedUpdate = true;\n\t\t});\n\n\t\tconst rightArm2Box = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tconst rightArm2Mesh = new Mesh(rightArm2Box, layer2Material);\n\t\trightArm2Mesh.renderOrder = 1;\n\t\tthis.modelListeners.push(() => {\n\t\t\trightArm2Mesh.scale.x = this.slim ? 3.375 : 4.5;\n\t\t\trightArm2Mesh.scale.y = 13.5;\n\t\t\trightArm2Mesh.scale.z = 4.5;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(rightArm2Box,\n\t\t\t\t\ttoSkinVertices(44, 32, 47, 36),\n\t\t\t\t\ttoSkinVertices(47, 32, 50, 36),\n\t\t\t\t\ttoSkinVertices(40, 36, 44, 48),\n\t\t\t\t\ttoSkinVertices(44, 36, 47, 48),\n\t\t\t\t\ttoSkinVertices(47, 36, 51, 48),\n\t\t\t\t\ttoSkinVertices(51, 36, 54, 48)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(rightArm2Box,\n\t\t\t\t\ttoSkinVertices(44, 32, 48, 36),\n\t\t\t\t\ttoSkinVertices(48, 32, 52, 36),\n\t\t\t\t\ttoSkinVertices(40, 36, 44, 48),\n\t\t\t\t\ttoSkinVertices(44, 36, 48, 48),\n\t\t\t\t\ttoSkinVertices(48, 36, 52, 48),\n\t\t\t\t\ttoSkinVertices(52, 36, 56, 48)\n\t\t\t\t);\n\t\t\t}\n\t\t\trightArm2Box.uvsNeedUpdate = true;\n\t\t\trightArm2Box.elementsNeedUpdate = true;\n\t\t});\n\n\t\tconst rightArmPivot = new Group();\n\t\trightArmPivot.add(rightArmMesh, rightArm2Mesh);\n\t\trightArmPivot.position.y = -4;\n\n\t\tthis.rightArm = new BodyPart(rightArmMesh, rightArm2Mesh);\n\t\tthis.rightArm.name = \"rightArm\";\n\t\tthis.rightArm.add(rightArmPivot);\n\t\tthis.rightArm.position.y = -6;\n\t\tthis.modelListeners.push(() => {\n\t\t\tthis.rightArm.position.x = this.slim ? -5.5 : -6;\n\t\t});\n\t\tthis.add(this.rightArm);\n\n\t\t// Left Arm\n\t\tconst leftArmBox = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tconst leftArmMesh = new Mesh(leftArmBox, layer1Material);\n\t\tthis.modelListeners.push(() => {\n\t\t\tleftArmMesh.scale.x = this.slim ? 3 : 4;\n\t\t\tleftArmMesh.scale.y = 12;\n\t\t\tleftArmMesh.scale.z = 4;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(leftArmBox,\n\t\t\t\t\ttoSkinVertices(36, 48, 39, 52),\n\t\t\t\t\ttoSkinVertices(39, 48, 42, 52),\n\t\t\t\t\ttoSkinVertices(32, 52, 36, 64),\n\t\t\t\t\ttoSkinVertices(36, 52, 39, 64),\n\t\t\t\t\ttoSkinVertices(39, 52, 43, 64),\n\t\t\t\t\ttoSkinVertices(43, 52, 46, 64)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(leftArmBox,\n\t\t\t\t\ttoSkinVertices(36, 48, 40, 52),\n\t\t\t\t\ttoSkinVertices(40, 48, 44, 52),\n\t\t\t\t\ttoSkinVertices(32, 52, 36, 64),\n\t\t\t\t\ttoSkinVertices(36, 52, 40, 64),\n\t\t\t\t\ttoSkinVertices(40, 52, 44, 64),\n\t\t\t\t\ttoSkinVertices(44, 52, 48, 64)\n\t\t\t\t);\n\t\t\t}\n\t\t\tleftArmBox.uvsNeedUpdate = true;\n\t\t\tleftArmBox.elementsNeedUpdate = true;\n\t\t});\n\n\t\tconst leftArm2Box = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tconst leftArm2Mesh = new Mesh(leftArm2Box, layer2Material);\n\t\tleftArm2Mesh.renderOrder = 1;\n\t\tthis.modelListeners.push(() => {\n\t\t\tleftArm2Mesh.scale.x = this.slim ? 3.375 : 4.5;\n\t\t\tleftArm2Mesh.scale.y = 13.5;\n\t\t\tleftArm2Mesh.scale.z = 4.5;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(leftArm2Box,\n\t\t\t\t\ttoSkinVertices(52, 48, 55, 52),\n\t\t\t\t\ttoSkinVertices(55, 48, 58, 52),\n\t\t\t\t\ttoSkinVertices(48, 52, 52, 64),\n\t\t\t\t\ttoSkinVertices(52, 52, 55, 64),\n\t\t\t\t\ttoSkinVertices(55, 52, 59, 64),\n\t\t\t\t\ttoSkinVertices(59, 52, 62, 64)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(leftArm2Box,\n\t\t\t\t\ttoSkinVertices(52, 48, 56, 52),\n\t\t\t\t\ttoSkinVertices(56, 48, 60, 52),\n\t\t\t\t\ttoSkinVertices(48, 52, 52, 64),\n\t\t\t\t\ttoSkinVertices(52, 52, 56, 64),\n\t\t\t\t\ttoSkinVertices(56, 52, 60, 64),\n\t\t\t\t\ttoSkinVertices(60, 52, 64, 64)\n\t\t\t\t);\n\t\t\t}\n\t\t\tleftArm2Box.uvsNeedUpdate = true;\n\t\t\tleftArm2Box.elementsNeedUpdate = true;\n\t\t});\n\n\t\tconst leftArmPivot = new Group();\n\t\tleftArmPivot.add(leftArmMesh, leftArm2Mesh);\n\t\tleftArmPivot.position.y = -4;\n\n\t\tthis.leftArm = new BodyPart(leftArmMesh, leftArm2Mesh);\n\t\tthis.leftArm.name = \"leftArm\";\n\t\tthis.leftArm.add(leftArmPivot);\n\t\tthis.leftArm.position.y = -6;\n\t\tthis.modelListeners.push(() => {\n\t\t\tthis.leftArm.position.x = this.slim ? 5.5 : 6;\n\t\t});\n\t\tthis.add(this.leftArm);\n\n\t\t// Right Leg\n\t\tconst rightLegBox = new BoxGeometry(4, 12, 4, 0, 0, 0);\n\t\tsetVertices(rightLegBox,\n\t\t\ttoSkinVertices(4, 16, 8, 20),\n\t\t\ttoSkinVertices(8, 16, 12, 20),\n\t\t\ttoSkinVertices(0, 20, 4, 32),\n\t\t\ttoSkinVertices(4, 20, 8, 32),\n\t\t\ttoSkinVertices(8, 20, 12, 32),\n\t\t\ttoSkinVertices(12, 20, 16, 32)\n\t\t);\n\t\tconst rightLegMesh = new Mesh(rightLegBox, layer1Material);\n\n\t\tconst rightLeg2Box = new BoxGeometry(4.5, 13.5, 4.5, 0, 0, 0);\n\t\tsetVertices(rightLeg2Box,\n\t\t\ttoSkinVertices(4, 32, 8, 36),\n\t\t\ttoSkinVertices(8, 32, 12, 36),\n\t\t\ttoSkinVertices(0, 36, 4, 48),\n\t\t\ttoSkinVertices(4, 36, 8, 48),\n\t\t\ttoSkinVertices(8, 36, 12, 48),\n\t\t\ttoSkinVertices(12, 36, 16, 48)\n\t\t);\n\t\tconst rightLeg2Mesh = new Mesh(rightLeg2Box, layer2Material);\n\t\trightLeg2Mesh.renderOrder = 1;\n\n\t\tconst rightLegPivot = new Group();\n\t\trightLegPivot.add(rightLegMesh, rightLeg2Mesh);\n\t\trightLegPivot.position.y = -6;\n\n\t\tthis.rightLeg = new BodyPart(rightLegMesh, rightLeg2Mesh);\n\t\tthis.rightLeg.name = \"rightLeg\";\n\t\tthis.rightLeg.add(rightLegPivot);\n\t\tthis.rightLeg.position.y = -16;\n\t\tthis.rightLeg.position.x = -2;\n\t\tthis.add(this.rightLeg);\n\n\t\t// Left Leg\n\t\tconst leftLegBox = new BoxGeometry(4, 12, 4, 0, 0, 0);\n\t\tsetVertices(leftLegBox,\n\t\t\ttoSkinVertices(20, 48, 24, 52),\n\t\t\ttoSkinVertices(24, 48, 28, 52),\n\t\t\ttoSkinVertices(16, 52, 20, 64),\n\t\t\ttoSkinVertices(20, 52, 24, 64),\n\t\t\ttoSkinVertices(24, 52, 28, 64),\n\t\t\ttoSkinVertices(28, 52, 32, 64)\n\t\t);\n\t\tconst leftLegMesh = new Mesh(leftLegBox, layer1Material);\n\n\t\tconst leftLeg2Box = new BoxGeometry(4.5, 13.5, 4.5, 0, 0, 0);\n\t\tsetVertices(leftLeg2Box,\n\t\t\ttoSkinVertices(4, 48, 8, 52),\n\t\t\ttoSkinVertices(8, 48, 12, 52),\n\t\t\ttoSkinVertices(0, 52, 4, 64),\n\t\t\ttoSkinVertices(4, 52, 8, 64),\n\t\t\ttoSkinVertices(8, 52, 12, 64),\n\t\t\ttoSkinVertices(12, 52, 16, 64)\n\t\t);\n\t\tconst leftLeg2Mesh = new Mesh(leftLeg2Box, layer2Material);\n\t\tleftLeg2Mesh.renderOrder = 1;\n\n\t\tconst leftLegPivot = new Group();\n\t\tleftLegPivot.add(leftLegMesh, leftLeg2Mesh);\n\t\tleftLegPivot.position.y = -6;\n\n\t\tthis.leftLeg = new BodyPart(leftLegMesh, leftLeg2Mesh);\n\t\tthis.leftLeg.name = \"leftLeg\";\n\t\tthis.leftLeg.add(leftLegPivot);\n\t\tthis.leftLeg.position.y = -16;\n\t\tthis.leftLeg.position.x = 2;\n\t\tthis.add(this.leftLeg);\n\n\t\tthis.slim = false;\n\t}\n\n\tget slim(): boolean {\n\t\treturn this._slim;\n\t}\n\n\tset slim(value) {\n\t\tthis._slim = value;\n\t\tthis.modelListeners.forEach(listener => listener());\n\t}\n\n\tprivate getBodyParts(): Array {\n\t\treturn this.children.filter(it => it instanceof BodyPart) as Array;\n\t}\n\n\tsetInnerLayerVisible(value: boolean): void {\n\t\tthis.getBodyParts().forEach(part => part.innerLayer.visible = value);\n\t}\n\n\tsetOuterLayerVisible(value: boolean): void {\n\t\tthis.getBodyParts().forEach(part => part.outerLayer.visible = value);\n\t}\n}\n\nexport class CapeObject extends Group {\n\n\treadonly cape: Mesh;\n\n\tconstructor(texture: Texture) {\n\t\tsuper();\n\n\t\tconst capeMaterial = new MeshBasicMaterial({ map: texture, transparent: true, opacity: 1, side: DoubleSide, alphaTest: 0.5 });\n\n\t\t// back = outside\n\t\t// front = inside\n\t\tconst capeBox = new BoxGeometry(10, 16, 1, 0, 0, 0);\n\t\tsetVertices(capeBox,\n\t\t\ttoCapeVertices(1, 0, 11, 1),\n\t\t\ttoCapeVertices(11, 0, 21, 1),\n\t\t\ttoCapeVertices(11, 1, 12, 17),\n\t\t\ttoCapeVertices(12, 1, 22, 17),\n\t\t\ttoCapeVertices(0, 1, 1, 17),\n\t\t\ttoCapeVertices(1, 1, 11, 17)\n\t\t);\n\t\tthis.cape = new Mesh(capeBox, capeMaterial);\n\t\tthis.cape.position.y = -8;\n\t\tthis.cape.position.z = -0.5;\n\t\tthis.add(this.cape);\n\t}\n}\n\nexport class PlayerObject extends Group {\n\n\treadonly skin: SkinObject;\n\treadonly cape: CapeObject;\n\n\tconstructor(skinTexture: Texture, capeTexture: Texture) {\n\t\tsuper();\n\n\t\tthis.skin = new SkinObject(skinTexture);\n\t\tthis.skin.name = \"skin\";\n\t\tthis.add(this.skin);\n\n\t\tthis.cape = new CapeObject(capeTexture);\n\t\tthis.cape.name = \"cape\";\n\t\tthis.cape.position.z = -2;\n\t\tthis.cape.position.y = -4;\n\t\tthis.cape.rotation.x = 25 * Math.PI / 180;\n\t\tthis.add(this.cape);\n\t}\n}\n","import { Clock } from \"three\";\nimport { PlayerObject } from \"./model.js\";\n\nexport interface IAnimation {\n\tplay(player: PlayerObject, time: number): void;\n}\n\nexport type AnimationFn = (player: PlayerObject, time: number) => void;\n\nexport type Animation = AnimationFn | IAnimation;\n\nexport function invokeAnimation(animation: Animation, player: PlayerObject, time: number): void {\n\tif (animation instanceof Function) {\n\t\tanimation(player, time);\n\t} else {\n\t\t// must be IAnimation here\n\t\tanimation.play(player, time);\n\t}\n}\n\n// This interface is used to control animations\nexport interface AnimationHandle {\n\tspeed: number;\n\tpaused: boolean;\n\tprogress: number;\n\treadonly animation: Animation;\n\n\treset(): void;\n}\n\nexport interface SubAnimationHandle extends AnimationHandle {\n\tremove(): void;\n\tresetAndRemove(): void;\n}\n\nclass AnimationWrapper implements SubAnimationHandle, IAnimation {\n\tspeed: number = 1.0;\n\tpaused: boolean = false;\n\tprogress: number = 0;\n\treadonly animation: Animation;\n\n\tprivate lastTime: number = 0;\n\tprivate started: boolean = false;\n\tprivate toResetAndRemove: boolean = false;\n\n\tconstructor(animation: Animation) {\n\t\tthis.animation = animation;\n\t}\n\n\tplay(player: PlayerObject, time: number): void {\n\t\tif (this.toResetAndRemove) {\n\t\t\tinvokeAnimation(this.animation, player, 0);\n\t\t\tthis.remove();\n\t\t\treturn;\n\t\t}\n\n\t\tlet delta: number;\n\t\tif (this.started) {\n\t\t\tdelta = time - this.lastTime;\n\t\t} else {\n\t\t\tdelta = 0;\n\t\t\tthis.started = true;\n\t\t}\n\t\tthis.lastTime = time;\n\t\tif (!this.paused) {\n\t\t\tthis.progress += delta * this.speed;\n\t\t}\n\t\tinvokeAnimation(this.animation, player, this.progress);\n\t}\n\n\treset(): void {\n\t\tthis.progress = 0;\n\t}\n\n\tremove(): void {\n\t\t// stub get's overriden\n\t}\n\n\tresetAndRemove(): void {\n\t\tthis.toResetAndRemove = true;\n\t}\n}\n\nexport class CompositeAnimation implements IAnimation {\n\n\treadonly handles: Set = new Set();\n\n\tadd(animation: Animation): AnimationHandle {\n\t\tconst handle = new AnimationWrapper(animation);\n\t\thandle.remove = (): void => {\n\t\t\tthis.handles.delete(handle);\n\t\t};\n\t\tthis.handles.add(handle);\n\t\treturn handle;\n\t}\n\n\tplay(player: PlayerObject, time: number): void {\n\t\tthis.handles.forEach(handle => handle.play(player, time));\n\t}\n}\n\nexport class RootAnimation extends CompositeAnimation implements AnimationHandle {\n\tspeed: number = 1.0;\n\tprogress: number = 0.0;\n\treadonly clock: Clock = new Clock(true);\n\n\tget animation(): RootAnimation {\n\t\treturn this;\n\t}\n\n\tget paused(): boolean {\n\t\treturn !this.clock.running;\n\t}\n\n\tset paused(value: boolean) {\n\t\tif (value) {\n\t\t\tthis.clock.stop();\n\t\t} else {\n\t\t\tthis.clock.start();\n\t\t}\n\t}\n\n\trunAnimationLoop(player: PlayerObject): void {\n\t\tif (this.handles.size === 0) {\n\t\t\treturn;\n\t\t}\n\t\tthis.progress += this.clock.getDelta() * this.speed;\n\t\tthis.play(player, this.progress);\n\t}\n\n\treset(): void {\n\t\tthis.progress = 0;\n\t}\n}\n\nexport const WalkingAnimation: Animation = (player, time) => {\n\tconst skin = player.skin;\n\n\t// Multiply by animation's natural speed\n\ttime *= 8;\n\n\t// Leg swing\n\tskin.leftLeg.rotation.x = Math.sin(time) * 0.5;\n\tskin.rightLeg.rotation.x = Math.sin(time + Math.PI) * 0.5;\n\n\t// Arm swing\n\tskin.leftArm.rotation.x = Math.sin(time + Math.PI) * 0.5;\n\tskin.rightArm.rotation.x = Math.sin(time) * 0.5;\n\tconst basicArmRotationZ = Math.PI * 0.02;\n\tskin.leftArm.rotation.z = Math.cos(time) * 0.03 + basicArmRotationZ;\n\tskin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.03 - basicArmRotationZ;\n\n\t// Head shaking with different frequency & amplitude\n\tskin.head.rotation.y = Math.sin(time / 4) * 0.2;\n\tskin.head.rotation.x = Math.sin(time / 5) * 0.1;\n\n\t// Always add an angle for cape around the x axis\n\tconst basicCapeRotationX = Math.PI * 0.06;\n\tplayer.cape.rotation.x = Math.sin(time / 1.5) * 0.06 + basicCapeRotationX;\n};\n\nexport const RunningAnimation: Animation = (player, time) => {\n\tconst skin = player.skin;\n\n\ttime *= 15;\n\n\t// Leg swing with larger amplitude\n\tskin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3;\n\tskin.rightLeg.rotation.x = Math.cos(time) * 1.3;\n\n\t// Arm swing\n\tskin.leftArm.rotation.x = Math.cos(time) * 1.5;\n\tskin.rightArm.rotation.x = Math.cos(time + Math.PI) * 1.5;\n\tconst basicArmRotationZ = Math.PI * 0.1;\n\tskin.leftArm.rotation.z = Math.cos(time) * 0.1 + basicArmRotationZ;\n\tskin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.1 - basicArmRotationZ;\n\n\t// Jumping\n\tplayer.position.y = Math.cos(time * 2);\n\t// Dodging when running\n\tplayer.position.x = Math.cos(time) * 0.15;\n\t// Slightly tilting when running\n\tplayer.rotation.z = Math.cos(time + Math.PI) * 0.01;\n\n\t// Apply higher swing frequency, lower amplitude,\n\t// and greater basic rotation around x axis,\n\t// to cape when running.\n\tconst basicCapeRotationX = Math.PI * 0.3;\n\tplayer.cape.rotation.x = Math.sin(time * 2) * 0.1 + basicCapeRotationX;\n\n\t// What about head shaking?\n\t// You shouldn't glance right and left when running dude :P\n};\n\nexport const RotatingAnimation: Animation = (player, time) => {\n\tplayer.rotation.y = time;\n};\n","function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) {\n var imgData = context.getImageData(sX, sY, w, h);\n if (flipHorizontal) {\n for (var y = 0; y < h; y++) {\n for (var x = 0; x < (w / 2); x++) {\n var index = (x + y * w) * 4;\n var index2 = ((w - x - 1) + y * w) * 4;\n var pA1 = imgData.data[index];\n var pA2 = imgData.data[index + 1];\n var pA3 = imgData.data[index + 2];\n var pA4 = imgData.data[index + 3];\n var pB1 = imgData.data[index2];\n var pB2 = imgData.data[index2 + 1];\n var pB3 = imgData.data[index2 + 2];\n var pB4 = imgData.data[index2 + 3];\n imgData.data[index] = pB1;\n imgData.data[index + 1] = pB2;\n imgData.data[index + 2] = pB3;\n imgData.data[index + 3] = pB4;\n imgData.data[index2] = pA1;\n imgData.data[index2 + 1] = pA2;\n imgData.data[index2 + 2] = pA3;\n imgData.data[index2 + 3] = pA4;\n }\n }\n }\n context.putImageData(imgData, dX, dY);\n}\nfunction hasTransparency(context, x0, y0, w, h) {\n var imgData = context.getImageData(x0, y0, w, h);\n for (var x = 0; x < w; x++) {\n for (var y = 0; y < h; y++) {\n var offset = (x + y * w) * 4;\n if (imgData.data[offset + 3] !== 0xff) {\n return true;\n }\n }\n }\n return false;\n}\nfunction computeSkinScale(width) {\n return width / 64.0;\n}\nfunction fixOpaqueSkin(context, width) {\n // Some ancient skins don't have transparent pixels (nor have helm).\n // We have to make the helm area transparent, otherwise it will be rendered as black.\n if (!hasTransparency(context, 0, 0, width, width / 2)) {\n var scale_1 = computeSkinScale(width);\n var clearArea = function (x, y, w, h) {\n return context.clearRect(x * scale_1, y * scale_1, w * scale_1, h * scale_1);\n };\n clearArea(40, 0, 8, 8); // Helm Top\n clearArea(48, 0, 8, 8); // Helm Bottom\n clearArea(32, 8, 8, 8); // Helm Right\n clearArea(40, 8, 8, 8); // Helm Front\n clearArea(48, 8, 8, 8); // Helm Left\n clearArea(56, 8, 8, 8); // Helm Back\n }\n}\nfunction convertSkinTo1_8(context, width) {\n var scale = computeSkinScale(width);\n var copySkin = function (sX, sY, w, h, dX, dY, flipHorizontal) {\n return copyImage(context, sX * scale, sY * scale, w * scale, h * scale, dX * scale, dY * scale, flipHorizontal);\n };\n fixOpaqueSkin(context, width);\n copySkin(4, 16, 4, 4, 20, 48, true); // Top Leg\n copySkin(8, 16, 4, 4, 24, 48, true); // Bottom Leg\n copySkin(0, 20, 4, 12, 24, 52, true); // Outer Leg\n copySkin(4, 20, 4, 12, 20, 52, true); // Front Leg\n copySkin(8, 20, 4, 12, 16, 52, true); // Inner Leg\n copySkin(12, 20, 4, 12, 28, 52, true); // Back Leg\n copySkin(44, 16, 4, 4, 36, 48, true); // Top Arm\n copySkin(48, 16, 4, 4, 40, 48, true); // Bottom Arm\n copySkin(40, 20, 4, 12, 40, 52, true); // Outer Arm\n copySkin(44, 20, 4, 12, 36, 52, true); // Front Arm\n copySkin(48, 20, 4, 12, 32, 52, true); // Inner Arm\n copySkin(52, 20, 4, 12, 44, 52, true); // Back Arm\n}\nexport function loadSkinToCanvas(canvas, image) {\n var isOldFormat = false;\n if (image.width !== image.height) {\n if (image.width === 2 * image.height) {\n isOldFormat = true;\n }\n else {\n throw new Error(\"Bad skin size: \" + image.width + \"x\" + image.height);\n }\n }\n var context = canvas.getContext(\"2d\");\n if (isOldFormat) {\n var sideLength = image.width;\n canvas.width = sideLength;\n canvas.height = sideLength;\n context.clearRect(0, 0, sideLength, sideLength);\n context.drawImage(image, 0, 0, sideLength, sideLength / 2.0);\n convertSkinTo1_8(context, sideLength);\n }\n else {\n canvas.width = image.width;\n canvas.height = image.height;\n context.clearRect(0, 0, image.width, image.height);\n context.drawImage(image, 0, 0, canvas.width, canvas.height);\n }\n}\nexport function loadCapeToCanvas(canvas, image) {\n var isOldFormat = false;\n if (image.width !== 2 * image.height) {\n if (image.width * 17 === image.height * 22) {\n // width/height = 22/17\n isOldFormat = true;\n }\n else {\n throw new Error(\"Bad cape size: \" + image.width + \"x\" + image.height);\n }\n }\n var context = canvas.getContext(\"2d\");\n if (isOldFormat) {\n var width = image.width * 64 / 22;\n canvas.width = width;\n canvas.height = width / 2;\n }\n else {\n canvas.width = image.width;\n canvas.height = image.height;\n }\n context.clearRect(0, 0, canvas.width, canvas.height);\n context.drawImage(image, 0, 0, image.width, image.height);\n}\nexport function isSlimSkin(canvas) {\n // Detects whether the skin is default or slim.\n //\n // The right arm area of *default* skins:\n // (44,16)->*-------*-------*\n // (40,20) |top |bottom |\n // \\|/ |4x4 |4x4 |\n // *-------*-------*-------*-------*\n // |right |front |left |back |\n // |4x12 |4x12 |4x12 |4x12 |\n // *-------*-------*-------*-------*\n // The right arm area of *slim* skins:\n // (44,16)->*------*------*-*\n // (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4]\n // \\|/ |3x4 |3x4 | |\n // *-------*------*------***-----*-*\n // |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12]\n // |4x12 |3x12 |4x12 |3x12 | |\n // *-------*------*-------*------*-*\n // Compared with default right arms, slim right arms have 2 unused areas.\n //\n // The same is true for left arm:\n // The left arm area of *default* skins:\n // (36,48)->*-------*-------*\n // (32,52) |top |bottom |\n // \\|/ |4x4 |4x4 |\n // *-------*-------*-------*-------*\n // |right |front |left |back |\n // |4x12 |4x12 |4x12 |4x12 |\n // *-------*-------*-------*-------*\n // The left arm area of *slim* skins:\n // (36,48)->*------*------*-*\n // (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4]\n // \\|/ |3x4 |3x4 | |\n // *-------*------*------***-----*-*\n // |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12]\n // |4x12 |3x12 |4x12 |3x12 | |\n // *-------*------*-------*------*-*\n //\n // If there is a transparent pixel in any of the 4 unused areas, the skin must be slim,\n // as transparent pixels are not allowed in the first layer.\n var scale = computeSkinScale(canvas.width);\n var context = canvas.getContext(\"2d\");\n var checkArea = function (x, y, w, h) {\n return hasTransparency(context, x * scale, y * scale, w * scale, h * scale);\n };\n return checkArea(50, 16, 2, 4) ||\n checkArea(54, 20, 2, 12) ||\n checkArea(42, 48, 2, 4) ||\n checkArea(46, 52, 2, 12);\n}\n","/**\n * @author qiao / https://github.com/qiao\n * @author mrdoob / http://mrdoob.com\n * @author alteredq / http://alteredqualia.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author erich666 / http://erichaines.com\n * @author ScieCode / http://github.com/sciecode\n */\n\nimport {\n\tEventDispatcher,\n\tMOUSE,\n\tQuaternion,\n\tSpherical,\n\tTOUCH,\n\tVector2,\n\tVector3\n} from \"../../../build/three.module.js\";\n\n// This set of controls performs orbiting, dollying (zooming), and panning.\n// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n//\n// Orbit - left mouse / touch: one-finger move\n// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish\n// Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move\n\nvar OrbitControls = function ( object, domElement ) {\n\n\tif ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter \"domElement\" is now mandatory.' );\n\tif ( domElement === document ) console.error( 'THREE.OrbitControls: \"document\" should not be used as the target \"domElement\". Please use \"renderer.domElement\" instead.' );\n\n\tthis.object = object;\n\tthis.domElement = domElement;\n\n\t// Set to false to disable this control\n\tthis.enabled = true;\n\n\t// \"target\" sets the location of focus, where the object orbits around\n\tthis.target = new Vector3();\n\n\t// How far you can dolly in and out ( PerspectiveCamera only )\n\tthis.minDistance = 0;\n\tthis.maxDistance = Infinity;\n\n\t// How far you can zoom in and out ( OrthographicCamera only )\n\tthis.minZoom = 0;\n\tthis.maxZoom = Infinity;\n\n\t// How far you can orbit vertically, upper and lower limits.\n\t// Range is 0 to Math.PI radians.\n\tthis.minPolarAngle = 0; // radians\n\tthis.maxPolarAngle = Math.PI; // radians\n\n\t// How far you can orbit horizontally, upper and lower limits.\n\t// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].\n\tthis.minAzimuthAngle = - Infinity; // radians\n\tthis.maxAzimuthAngle = Infinity; // radians\n\n\t// Set to true to enable damping (inertia)\n\t// If damping is enabled, you must call controls.update() in your animation loop\n\tthis.enableDamping = false;\n\tthis.dampingFactor = 0.05;\n\n\t// This option actually enables dollying in and out; left as \"zoom\" for backwards compatibility.\n\t// Set to false to disable zooming\n\tthis.enableZoom = true;\n\tthis.zoomSpeed = 1.0;\n\n\t// Set to false to disable rotating\n\tthis.enableRotate = true;\n\tthis.rotateSpeed = 1.0;\n\n\t// Set to false to disable panning\n\tthis.enablePan = true;\n\tthis.panSpeed = 1.0;\n\tthis.screenSpacePanning = false; // if true, pan in screen-space\n\tthis.keyPanSpeed = 7.0;\t// pixels moved per arrow key push\n\n\t// Set to true to automatically rotate around the target\n\t// If auto-rotate is enabled, you must call controls.update() in your animation loop\n\tthis.autoRotate = false;\n\tthis.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\n\n\t// Set to false to disable use of the keys\n\tthis.enableKeys = true;\n\n\t// The four arrow keys\n\tthis.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\n\n\t// Mouse buttons\n\tthis.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };\n\n\t// Touch fingers\n\tthis.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };\n\n\t// for reset\n\tthis.target0 = this.target.clone();\n\tthis.position0 = this.object.position.clone();\n\tthis.zoom0 = this.object.zoom;\n\n\t//\n\t// public methods\n\t//\n\n\tthis.getPolarAngle = function () {\n\n\t\treturn spherical.phi;\n\n\t};\n\n\tthis.getAzimuthalAngle = function () {\n\n\t\treturn spherical.theta;\n\n\t};\n\n\tthis.saveState = function () {\n\n\t\tscope.target0.copy( scope.target );\n\t\tscope.position0.copy( scope.object.position );\n\t\tscope.zoom0 = scope.object.zoom;\n\n\t};\n\n\tthis.reset = function () {\n\n\t\tscope.target.copy( scope.target0 );\n\t\tscope.object.position.copy( scope.position0 );\n\t\tscope.object.zoom = scope.zoom0;\n\n\t\tscope.object.updateProjectionMatrix();\n\t\tscope.dispatchEvent( changeEvent );\n\n\t\tscope.update();\n\n\t\tstate = STATE.NONE;\n\n\t};\n\n\t// this method is exposed, but perhaps it would be better if we can make it private...\n\tthis.update = function () {\n\n\t\tvar offset = new Vector3();\n\n\t\t// so camera.up is the orbit axis\n\t\tvar quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );\n\t\tvar quatInverse = quat.clone().inverse();\n\n\t\tvar lastPosition = new Vector3();\n\t\tvar lastQuaternion = new Quaternion();\n\n\t\treturn function update() {\n\n\t\t\tvar position = scope.object.position;\n\n\t\t\toffset.copy( position ).sub( scope.target );\n\n\t\t\t// rotate offset to \"y-axis-is-up\" space\n\t\t\toffset.applyQuaternion( quat );\n\n\t\t\t// angle from z-axis around y-axis\n\t\t\tspherical.setFromVector3( offset );\n\n\t\t\tif ( scope.autoRotate && state === STATE.NONE ) {\n\n\t\t\t\trotateLeft( getAutoRotationAngle() );\n\n\t\t\t}\n\n\t\t\tif ( scope.enableDamping ) {\n\n\t\t\t\tspherical.theta += sphericalDelta.theta * scope.dampingFactor;\n\t\t\t\tspherical.phi += sphericalDelta.phi * scope.dampingFactor;\n\n\t\t\t} else {\n\n\t\t\t\tspherical.theta += sphericalDelta.theta;\n\t\t\t\tspherical.phi += sphericalDelta.phi;\n\n\t\t\t}\n\n\t\t\t// restrict theta to be between desired limits\n\t\t\tspherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );\n\n\t\t\t// restrict phi to be between desired limits\n\t\t\tspherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );\n\n\t\t\tspherical.makeSafe();\n\n\n\t\t\tspherical.radius *= scale;\n\n\t\t\t// restrict radius to be between desired limits\n\t\t\tspherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );\n\n\t\t\t// move target to panned location\n\n\t\t\tif ( scope.enableDamping === true ) {\n\n\t\t\t\tscope.target.addScaledVector( panOffset, scope.dampingFactor );\n\n\t\t\t} else {\n\n\t\t\t\tscope.target.add( panOffset );\n\n\t\t\t}\n\n\t\t\toffset.setFromSpherical( spherical );\n\n\t\t\t// rotate offset back to \"camera-up-vector-is-up\" space\n\t\t\toffset.applyQuaternion( quatInverse );\n\n\t\t\tposition.copy( scope.target ).add( offset );\n\n\t\t\tscope.object.lookAt( scope.target );\n\n\t\t\tif ( scope.enableDamping === true ) {\n\n\t\t\t\tsphericalDelta.theta *= ( 1 - scope.dampingFactor );\n\t\t\t\tsphericalDelta.phi *= ( 1 - scope.dampingFactor );\n\n\t\t\t\tpanOffset.multiplyScalar( 1 - scope.dampingFactor );\n\n\t\t\t} else {\n\n\t\t\t\tsphericalDelta.set( 0, 0, 0 );\n\n\t\t\t\tpanOffset.set( 0, 0, 0 );\n\n\t\t\t}\n\n\t\t\tscale = 1;\n\n\t\t\t// update condition is:\n\t\t\t// min(camera displacement, camera rotation in radians)^2 > EPS\n\t\t\t// using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\n\t\t\tif ( zoomChanged ||\n\t\t\t\tlastPosition.distanceToSquared( scope.object.position ) > EPS ||\n\t\t\t\t8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {\n\n\t\t\t\tscope.dispatchEvent( changeEvent );\n\n\t\t\t\tlastPosition.copy( scope.object.position );\n\t\t\t\tlastQuaternion.copy( scope.object.quaternion );\n\t\t\t\tzoomChanged = false;\n\n\t\t\t\treturn true;\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t};\n\n\t}();\n\n\tthis.dispose = function () {\n\n\t\tscope.domElement.removeEventListener( 'contextmenu', onContextMenu, false );\n\t\tscope.domElement.removeEventListener( 'mousedown', onMouseDown, false );\n\t\tscope.domElement.removeEventListener( 'wheel', onMouseWheel, false );\n\n\t\tscope.domElement.removeEventListener( 'touchstart', onTouchStart, false );\n\t\tscope.domElement.removeEventListener( 'touchend', onTouchEnd, false );\n\t\tscope.domElement.removeEventListener( 'touchmove', onTouchMove, false );\n\n\t\tdocument.removeEventListener( 'mousemove', onMouseMove, false );\n\t\tdocument.removeEventListener( 'mouseup', onMouseUp, false );\n\n\t\tscope.domElement.removeEventListener( 'keydown', onKeyDown, false );\n\n\t\t//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?\n\n\t};\n\n\t//\n\t// internals\n\t//\n\n\tvar scope = this;\n\n\tvar changeEvent = { type: 'change' };\n\tvar startEvent = { type: 'start' };\n\tvar endEvent = { type: 'end' };\n\n\tvar STATE = {\n\t\tNONE: - 1,\n\t\tROTATE: 0,\n\t\tDOLLY: 1,\n\t\tPAN: 2,\n\t\tTOUCH_ROTATE: 3,\n\t\tTOUCH_PAN: 4,\n\t\tTOUCH_DOLLY_PAN: 5,\n\t\tTOUCH_DOLLY_ROTATE: 6\n\t};\n\n\tvar state = STATE.NONE;\n\n\tvar EPS = 0.000001;\n\n\t// current position in spherical coordinates\n\tvar spherical = new Spherical();\n\tvar sphericalDelta = new Spherical();\n\n\tvar scale = 1;\n\tvar panOffset = new Vector3();\n\tvar zoomChanged = false;\n\n\tvar rotateStart = new Vector2();\n\tvar rotateEnd = new Vector2();\n\tvar rotateDelta = new Vector2();\n\n\tvar panStart = new Vector2();\n\tvar panEnd = new Vector2();\n\tvar panDelta = new Vector2();\n\n\tvar dollyStart = new Vector2();\n\tvar dollyEnd = new Vector2();\n\tvar dollyDelta = new Vector2();\n\n\tfunction getAutoRotationAngle() {\n\n\t\treturn 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n\n\t}\n\n\tfunction getZoomScale() {\n\n\t\treturn Math.pow( 0.95, scope.zoomSpeed );\n\n\t}\n\n\tfunction rotateLeft( angle ) {\n\n\t\tsphericalDelta.theta -= angle;\n\n\t}\n\n\tfunction rotateUp( angle ) {\n\n\t\tsphericalDelta.phi -= angle;\n\n\t}\n\n\tvar panLeft = function () {\n\n\t\tvar v = new Vector3();\n\n\t\treturn function panLeft( distance, objectMatrix ) {\n\n\t\t\tv.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix\n\t\t\tv.multiplyScalar( - distance );\n\n\t\t\tpanOffset.add( v );\n\n\t\t};\n\n\t}();\n\n\tvar panUp = function () {\n\n\t\tvar v = new Vector3();\n\n\t\treturn function panUp( distance, objectMatrix ) {\n\n\t\t\tif ( scope.screenSpacePanning === true ) {\n\n\t\t\t\tv.setFromMatrixColumn( objectMatrix, 1 );\n\n\t\t\t} else {\n\n\t\t\t\tv.setFromMatrixColumn( objectMatrix, 0 );\n\t\t\t\tv.crossVectors( scope.object.up, v );\n\n\t\t\t}\n\n\t\t\tv.multiplyScalar( distance );\n\n\t\t\tpanOffset.add( v );\n\n\t\t};\n\n\t}();\n\n\t// deltaX and deltaY are in pixels; right and down are positive\n\tvar pan = function () {\n\n\t\tvar offset = new Vector3();\n\n\t\treturn function pan( deltaX, deltaY ) {\n\n\t\t\tvar element = scope.domElement;\n\n\t\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\t\t// perspective\n\t\t\t\tvar position = scope.object.position;\n\t\t\t\toffset.copy( position ).sub( scope.target );\n\t\t\t\tvar targetDistance = offset.length();\n\n\t\t\t\t// half of the fov is center to top of screen\n\t\t\t\ttargetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );\n\n\t\t\t\t// we use only clientHeight here so aspect ratio does not distort speed\n\t\t\t\tpanLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );\n\t\t\t\tpanUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );\n\n\t\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\t\t// orthographic\n\t\t\t\tpanLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );\n\t\t\t\tpanUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );\n\n\t\t\t} else {\n\n\t\t\t\t// camera neither orthographic nor perspective\n\t\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\n\t\t\t\tscope.enablePan = false;\n\n\t\t\t}\n\n\t\t};\n\n\t}();\n\n\tfunction dollyOut( dollyScale ) {\n\n\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\tscale /= dollyScale;\n\n\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\tscope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );\n\t\t\tscope.object.updateProjectionMatrix();\n\t\t\tzoomChanged = true;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n\t\t\tscope.enableZoom = false;\n\n\t\t}\n\n\t}\n\n\tfunction dollyIn( dollyScale ) {\n\n\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\tscale *= dollyScale;\n\n\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\tscope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );\n\t\t\tscope.object.updateProjectionMatrix();\n\t\t\tzoomChanged = true;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n\t\t\tscope.enableZoom = false;\n\n\t\t}\n\n\t}\n\n\t//\n\t// event callbacks - update the object state\n\t//\n\n\tfunction handleMouseDownRotate( event ) {\n\n\t\trotateStart.set( event.clientX, event.clientY );\n\n\t}\n\n\tfunction handleMouseDownDolly( event ) {\n\n\t\tdollyStart.set( event.clientX, event.clientY );\n\n\t}\n\n\tfunction handleMouseDownPan( event ) {\n\n\t\tpanStart.set( event.clientX, event.clientY );\n\n\t}\n\n\tfunction handleMouseMoveRotate( event ) {\n\n\t\trotateEnd.set( event.clientX, event.clientY );\n\n\t\trotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\n\n\t\tvar element = scope.domElement;\n\n\t\trotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height\n\n\t\trotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\n\n\t\trotateStart.copy( rotateEnd );\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleMouseMoveDolly( event ) {\n\n\t\tdollyEnd.set( event.clientX, event.clientY );\n\n\t\tdollyDelta.subVectors( dollyEnd, dollyStart );\n\n\t\tif ( dollyDelta.y > 0 ) {\n\n\t\t\tdollyOut( getZoomScale() );\n\n\t\t} else if ( dollyDelta.y < 0 ) {\n\n\t\t\tdollyIn( getZoomScale() );\n\n\t\t}\n\n\t\tdollyStart.copy( dollyEnd );\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleMouseMovePan( event ) {\n\n\t\tpanEnd.set( event.clientX, event.clientY );\n\n\t\tpanDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\n\n\t\tpan( panDelta.x, panDelta.y );\n\n\t\tpanStart.copy( panEnd );\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleMouseUp( /*event*/ ) {\n\n\t\t// no-op\n\n\t}\n\n\tfunction handleMouseWheel( event ) {\n\n\t\tif ( event.deltaY < 0 ) {\n\n\t\t\tdollyIn( getZoomScale() );\n\n\t\t} else if ( event.deltaY > 0 ) {\n\n\t\t\tdollyOut( getZoomScale() );\n\n\t\t}\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleKeyDown( event ) {\n\n\t\tvar needsUpdate = false;\n\n\t\tswitch ( event.keyCode ) {\n\n\t\t\tcase scope.keys.UP:\n\t\t\t\tpan( 0, scope.keyPanSpeed );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.BOTTOM:\n\t\t\t\tpan( 0, - scope.keyPanSpeed );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.LEFT:\n\t\t\t\tpan( scope.keyPanSpeed, 0 );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.RIGHT:\n\t\t\t\tpan( - scope.keyPanSpeed, 0 );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif ( needsUpdate ) {\n\n\t\t\t// prevent the browser from scrolling on cursor keys\n\t\t\tevent.preventDefault();\n\n\t\t\tscope.update();\n\n\t\t}\n\n\n\t}\n\n\tfunction handleTouchStartRotate( event ) {\n\n\t\tif ( event.touches.length == 1 ) {\n\n\t\t\trotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n\t\t} else {\n\n\t\t\tvar x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\n\t\t\tvar y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\n\n\t\t\trotateStart.set( x, y );\n\n\t\t}\n\n\t}\n\n\tfunction handleTouchStartPan( event ) {\n\n\t\tif ( event.touches.length == 1 ) {\n\n\t\t\tpanStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n\t\t} else {\n\n\t\t\tvar x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\n\t\t\tvar y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\n\n\t\t\tpanStart.set( x, y );\n\n\t\t}\n\n\t}\n\n\tfunction handleTouchStartDolly( event ) {\n\n\t\tvar dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n\t\tvar dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\n\t\tvar distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\tdollyStart.set( 0, distance );\n\n\t}\n\n\tfunction handleTouchStartDollyPan( event ) {\n\n\t\tif ( scope.enableZoom ) handleTouchStartDolly( event );\n\n\t\tif ( scope.enablePan ) handleTouchStartPan( event );\n\n\t}\n\n\tfunction handleTouchStartDollyRotate( event ) {\n\n\t\tif ( scope.enableZoom ) handleTouchStartDolly( event );\n\n\t\tif ( scope.enableRotate ) handleTouchStartRotate( event );\n\n\t}\n\n\tfunction handleTouchMoveRotate( event ) {\n\n\t\tif ( event.touches.length == 1 ) {\n\n\t\t\trotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n\t\t} else {\n\n\t\t\tvar x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\n\t\t\tvar y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\n\n\t\t\trotateEnd.set( x, y );\n\n\t\t}\n\n\t\trotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\n\n\t\tvar element = scope.domElement;\n\n\t\trotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height\n\n\t\trotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\n\n\t\trotateStart.copy( rotateEnd );\n\n\t}\n\n\tfunction handleTouchMovePan( event ) {\n\n\t\tif ( event.touches.length == 1 ) {\n\n\t\t\tpanEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n\t\t} else {\n\n\t\t\tvar x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\n\t\t\tvar y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\n\n\t\t\tpanEnd.set( x, y );\n\n\t\t}\n\n\t\tpanDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\n\n\t\tpan( panDelta.x, panDelta.y );\n\n\t\tpanStart.copy( panEnd );\n\n\t}\n\n\tfunction handleTouchMoveDolly( event ) {\n\n\t\tvar dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n\t\tvar dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\n\t\tvar distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\tdollyEnd.set( 0, distance );\n\n\t\tdollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );\n\n\t\tdollyOut( dollyDelta.y );\n\n\t\tdollyStart.copy( dollyEnd );\n\n\t}\n\n\tfunction handleTouchMoveDollyPan( event ) {\n\n\t\tif ( scope.enableZoom ) handleTouchMoveDolly( event );\n\n\t\tif ( scope.enablePan ) handleTouchMovePan( event );\n\n\t}\n\n\tfunction handleTouchMoveDollyRotate( event ) {\n\n\t\tif ( scope.enableZoom ) handleTouchMoveDolly( event );\n\n\t\tif ( scope.enableRotate ) handleTouchMoveRotate( event );\n\n\t}\n\n\tfunction handleTouchEnd( /*event*/ ) {\n\n\t\t// no-op\n\n\t}\n\n\t//\n\t// event handlers - FSM: listen for events and reset state\n\t//\n\n\tfunction onMouseDown( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\t// Prevent the browser from scrolling.\n\t\tevent.preventDefault();\n\n\t\t// Manually set the focus since calling preventDefault above\n\t\t// prevents the browser from setting it automatically.\n\n\t\tscope.domElement.focus ? scope.domElement.focus() : window.focus();\n\n\t\tvar mouseAction;\n\n\t\tswitch ( event.button ) {\n\n\t\t\tcase 0:\n\n\t\t\t\tmouseAction = scope.mouseButtons.LEFT;\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\n\t\t\t\tmouseAction = scope.mouseButtons.MIDDLE;\n\t\t\t\tbreak;\n\n\t\t\tcase 2:\n\n\t\t\t\tmouseAction = scope.mouseButtons.RIGHT;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tmouseAction = - 1;\n\n\t\t}\n\n\t\tswitch ( mouseAction ) {\n\n\t\t\tcase MOUSE.DOLLY:\n\n\t\t\t\tif ( scope.enableZoom === false ) return;\n\n\t\t\t\thandleMouseDownDolly( event );\n\n\t\t\t\tstate = STATE.DOLLY;\n\n\t\t\t\tbreak;\n\n\t\t\tcase MOUSE.ROTATE:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\thandleMouseDownPan( event );\n\n\t\t\t\t\tstate = STATE.PAN;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\thandleMouseDownRotate( event );\n\n\t\t\t\t\tstate = STATE.ROTATE;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase MOUSE.PAN:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\thandleMouseDownRotate( event );\n\n\t\t\t\t\tstate = STATE.ROTATE;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\thandleMouseDownPan( event );\n\n\t\t\t\t\tstate = STATE.PAN;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tstate = STATE.NONE;\n\n\t\t}\n\n\t\tif ( state !== STATE.NONE ) {\n\n\t\t\tdocument.addEventListener( 'mousemove', onMouseMove, false );\n\t\t\tdocument.addEventListener( 'mouseup', onMouseUp, false );\n\n\t\t\tscope.dispatchEvent( startEvent );\n\n\t\t}\n\n\t}\n\n\tfunction onMouseMove( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\n\t\tswitch ( state ) {\n\n\t\t\tcase STATE.ROTATE:\n\n\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\thandleMouseMoveRotate( event );\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.DOLLY:\n\n\t\t\t\tif ( scope.enableZoom === false ) return;\n\n\t\t\t\thandleMouseMoveDolly( event );\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.PAN:\n\n\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\thandleMouseMovePan( event );\n\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\tfunction onMouseUp( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\thandleMouseUp( event );\n\n\t\tdocument.removeEventListener( 'mousemove', onMouseMove, false );\n\t\tdocument.removeEventListener( 'mouseup', onMouseUp, false );\n\n\t\tscope.dispatchEvent( endEvent );\n\n\t\tstate = STATE.NONE;\n\n\t}\n\n\tfunction onMouseWheel( event ) {\n\n\t\tif ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tscope.dispatchEvent( startEvent );\n\n\t\thandleMouseWheel( event );\n\n\t\tscope.dispatchEvent( endEvent );\n\n\t}\n\n\tfunction onKeyDown( event ) {\n\n\t\tif ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return;\n\n\t\thandleKeyDown( event );\n\n\t}\n\n\tfunction onTouchStart( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault(); // prevent scrolling\n\n\t\tswitch ( event.touches.length ) {\n\n\t\t\tcase 1:\n\n\t\t\t\tswitch ( scope.touches.ONE ) {\n\n\t\t\t\t\tcase TOUCH.ROTATE:\n\n\t\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\t\thandleTouchStartRotate( event );\n\n\t\t\t\t\t\tstate = STATE.TOUCH_ROTATE;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase TOUCH.PAN:\n\n\t\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\t\thandleTouchStartPan( event );\n\n\t\t\t\t\t\tstate = STATE.TOUCH_PAN;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tstate = STATE.NONE;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 2:\n\n\t\t\t\tswitch ( scope.touches.TWO ) {\n\n\t\t\t\t\tcase TOUCH.DOLLY_PAN:\n\n\t\t\t\t\t\tif ( scope.enableZoom === false && scope.enablePan === false ) return;\n\n\t\t\t\t\t\thandleTouchStartDollyPan( event );\n\n\t\t\t\t\t\tstate = STATE.TOUCH_DOLLY_PAN;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase TOUCH.DOLLY_ROTATE:\n\n\t\t\t\t\t\tif ( scope.enableZoom === false && scope.enableRotate === false ) return;\n\n\t\t\t\t\t\thandleTouchStartDollyRotate( event );\n\n\t\t\t\t\t\tstate = STATE.TOUCH_DOLLY_ROTATE;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tstate = STATE.NONE;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tstate = STATE.NONE;\n\n\t\t}\n\n\t\tif ( state !== STATE.NONE ) {\n\n\t\t\tscope.dispatchEvent( startEvent );\n\n\t\t}\n\n\t}\n\n\tfunction onTouchMove( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault(); // prevent scrolling\n\t\tevent.stopPropagation();\n\n\t\tswitch ( state ) {\n\n\t\t\tcase STATE.TOUCH_ROTATE:\n\n\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\thandleTouchMoveRotate( event );\n\n\t\t\t\tscope.update();\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.TOUCH_PAN:\n\n\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\thandleTouchMovePan( event );\n\n\t\t\t\tscope.update();\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.TOUCH_DOLLY_PAN:\n\n\t\t\t\tif ( scope.enableZoom === false && scope.enablePan === false ) return;\n\n\t\t\t\thandleTouchMoveDollyPan( event );\n\n\t\t\t\tscope.update();\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.TOUCH_DOLLY_ROTATE:\n\n\t\t\t\tif ( scope.enableZoom === false && scope.enableRotate === false ) return;\n\n\t\t\t\thandleTouchMoveDollyRotate( event );\n\n\t\t\t\tscope.update();\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tstate = STATE.NONE;\n\n\t\t}\n\n\t}\n\n\tfunction onTouchEnd( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\thandleTouchEnd( event );\n\n\t\tscope.dispatchEvent( endEvent );\n\n\t\tstate = STATE.NONE;\n\n\t}\n\n\tfunction onContextMenu( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\n\t}\n\n\t//\n\n\tscope.domElement.addEventListener( 'contextmenu', onContextMenu, false );\n\n\tscope.domElement.addEventListener( 'mousedown', onMouseDown, false );\n\tscope.domElement.addEventListener( 'wheel', onMouseWheel, false );\n\n\tscope.domElement.addEventListener( 'touchstart', onTouchStart, false );\n\tscope.domElement.addEventListener( 'touchend', onTouchEnd, false );\n\tscope.domElement.addEventListener( 'touchmove', onTouchMove, false );\n\n\tscope.domElement.addEventListener( 'keydown', onKeyDown, false );\n\n\t// make sure element can receive keys.\n\n\tif ( scope.domElement.tabIndex === - 1 ) {\n\n\t\tscope.domElement.tabIndex = 0;\n\n\t}\n\n\t// force an update at start\n\n\tthis.update();\n\n};\n\nOrbitControls.prototype = Object.create( EventDispatcher.prototype );\nOrbitControls.prototype.constructor = OrbitControls;\n\n\n// This set of controls performs orbiting, dollying (zooming), and panning.\n// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n// This is very similar to OrbitControls, another set of touch behavior\n//\n// Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate\n// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish\n// Pan - left mouse, or arrow keys / touch: one-finger move\n\nvar MapControls = function ( object, domElement ) {\n\n\tOrbitControls.call( this, object, domElement );\n\n\tthis.mouseButtons.LEFT = MOUSE.PAN;\n\tthis.mouseButtons.RIGHT = MOUSE.ROTATE;\n\n\tthis.touches.ONE = TOUCH.PAN;\n\tthis.touches.TWO = TOUCH.DOLLY_ROTATE;\n\n};\n\nMapControls.prototype = Object.create( EventDispatcher.prototype );\nMapControls.prototype.constructor = MapControls;\n\nexport { OrbitControls, MapControls };\n","import { NearestFilter, PerspectiveCamera, Scene, Texture, Vector2, WebGLRenderer } from \"three\";\nimport { RootAnimation } from \"./animation.js\";\nimport { PlayerObject } from \"./model.js\";\nimport { isSlimSkin, loadCapeToCanvas, loadSkinToCanvas } from \"skinview-utils\";\n\nexport interface SkinViewerOptions {\n\tdomElement: Node;\n\tskinUrl?: string;\n\tcapeUrl?: string;\n\twidth?: number;\n\theight?: number;\n\tdetectModel?: boolean;\n}\n\nexport class SkinViewer {\n\n\tpublic readonly domElement: Node;\n\tpublic readonly animations: RootAnimation = new RootAnimation();\n\tpublic detectModel: boolean = true;\n\n\tpublic readonly skinImg: HTMLImageElement;\n\tpublic readonly skinCanvas: HTMLCanvasElement;\n\tpublic readonly skinTexture: Texture;\n\n\tpublic readonly capeImg: HTMLImageElement;\n\tpublic readonly capeCanvas: HTMLCanvasElement;\n\tpublic readonly capeTexture: Texture;\n\n\tpublic readonly scene: Scene;\n\tpublic readonly camera: PerspectiveCamera;\n\tpublic readonly renderer: WebGLRenderer;\n\n\tpublic readonly playerObject: PlayerObject;\n\n\tprivate _disposed: boolean = false;\n\tprivate _renderPaused: boolean = false;\n\tprivate _skinSet: boolean = false;\n\tprivate _capeSet: boolean = false;\n\n\tconstructor(options: SkinViewerOptions) {\n\t\tthis.domElement = options.domElement;\n\t\tif (options.detectModel === false) {\n\t\t\tthis.detectModel = false;\n\t\t}\n\n\t\t// texture\n\t\tthis.skinImg = new Image();\n\t\tthis.skinCanvas = document.createElement(\"canvas\");\n\t\tthis.skinTexture = new Texture(this.skinCanvas);\n\t\tthis.skinTexture.magFilter = NearestFilter;\n\t\tthis.skinTexture.minFilter = NearestFilter;\n\n\t\tthis.capeImg = new Image();\n\t\tthis.capeCanvas = document.createElement(\"canvas\");\n\t\tthis.capeTexture = new Texture(this.capeCanvas);\n\t\tthis.capeTexture.magFilter = NearestFilter;\n\t\tthis.capeTexture.minFilter = NearestFilter;\n\n\t\t// scene\n\t\tthis.scene = new Scene();\n\n\t\t// Use smaller fov to avoid distortion\n\t\tthis.camera = new PerspectiveCamera(40);\n\t\tthis.camera.position.y = -12;\n\t\tthis.camera.position.z = 60;\n\n\t\tthis.renderer = new WebGLRenderer({ alpha: true });\n\t\tthis.domElement.appendChild(this.renderer.domElement);\n\n\t\tthis.playerObject = new PlayerObject(this.skinTexture, this.capeTexture);\n\t\tthis.playerObject.name = \"player\";\n\t\tthis.playerObject.skin.visible = false;\n\t\tthis.playerObject.cape.visible = false;\n\t\tthis.scene.add(this.playerObject);\n\n\t\t// texture loading\n\t\tthis.skinImg.crossOrigin = \"anonymous\";\n\t\tthis.skinImg.onerror = (): void => console.error(\"Failed loading \" + this.skinImg.src);\n\t\tthis.skinImg.onload = (): void => {\n\t\t\tloadSkinToCanvas(this.skinCanvas, this.skinImg);\n\n\t\t\tif (this.detectModel) {\n\t\t\t\tthis.playerObject.skin.slim = isSlimSkin(this.skinCanvas);\n\t\t\t}\n\n\t\t\tthis.skinTexture.needsUpdate = true;\n\t\t\tthis.playerObject.skin.visible = true;\n\t\t};\n\n\t\tthis.capeImg.crossOrigin = \"anonymous\";\n\t\tthis.capeImg.onerror = (): void => console.error(\"Failed loading \" + this.capeImg.src);\n\t\tthis.capeImg.onload = (): void => {\n\t\t\tloadCapeToCanvas(this.capeCanvas, this.capeImg);\n\n\t\t\tthis.capeTexture.needsUpdate = true;\n\t\t\tthis.playerObject.cape.visible = true;\n\t\t};\n\n\t\tif (options.skinUrl !== undefined) {\n\t\t\tthis.skinUrl = options.skinUrl;\n\t\t}\n\t\tif (options.capeUrl !== undefined) {\n\t\t\tthis.capeUrl = options.capeUrl;\n\t\t}\n\t\tthis.width = options.width === undefined ? 300 : options.width;\n\t\tthis.height = options.height === undefined ? 300 : options.height;\n\n\t\twindow.requestAnimationFrame(() => this.draw());\n\t}\n\n\tprivate draw(): void {\n\t\tif (this.disposed || this._renderPaused) {\n\t\t\treturn;\n\t\t}\n\t\tthis.animations.runAnimationLoop(this.playerObject);\n\t\tthis.doRender();\n\t\twindow.requestAnimationFrame(() => this.draw());\n\t}\n\n\tprotected doRender(): void {\n\t\tthis.renderer.render(this.scene, this.camera);\n\t}\n\n\tsetSize(width: number, height: number): void {\n\t\tthis.camera.aspect = width / height;\n\t\tthis.camera.updateProjectionMatrix();\n\t\tthis.renderer.setSize(width, height);\n\t}\n\n\tdispose(): void {\n\t\tthis._disposed = true;\n\t\tthis.domElement.removeChild(this.renderer.domElement);\n\t\tthis.renderer.dispose();\n\t\tthis.skinTexture.dispose();\n\t\tthis.capeTexture.dispose();\n\t}\n\n\tget disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\n\tget renderPaused(): boolean {\n\t\treturn this._renderPaused;\n\t}\n\n\tset renderPaused(value: boolean) {\n\t\tconst toResume = !this.disposed && !value && this._renderPaused;\n\t\tthis._renderPaused = value;\n\t\tif (toResume) {\n\t\t\twindow.requestAnimationFrame(() => this.draw());\n\t\t}\n\t}\n\n\tget skinUrl(): string | null {\n\t\treturn this._skinSet ? this.skinImg.src : null;\n\t}\n\n\tset skinUrl(url: string | null) {\n\t\tif (url === null) {\n\t\t\tthis._skinSet = false;\n\t\t\tthis.playerObject.skin.visible = false;\n\t\t} else {\n\t\t\tthis._skinSet = true;\n\t\t\tthis.skinImg.src = url;\n\t\t}\n\t}\n\n\tget capeUrl(): string | null {\n\t\treturn this._capeSet ? this.capeImg.src : null;\n\t}\n\n\tset capeUrl(url: string | null) {\n\t\tif (url === null) {\n\t\t\tthis._capeSet = false;\n\t\t\tthis.playerObject.cape.visible = false;\n\t\t} else {\n\t\t\tthis._capeSet = true;\n\t\t\tthis.capeImg.src = url;\n\t\t}\n\t}\n\n\tget width(): number {\n\t\treturn this.renderer.getSize(new Vector2()).width;\n\t}\n\n\tset width(newWidth: number) {\n\t\tthis.setSize(newWidth, this.height);\n\t}\n\n\tget height(): number {\n\t\treturn this.renderer.getSize(new Vector2()).height;\n\t}\n\n\tset height(newHeight: number) {\n\t\tthis.setSize(this.width, newHeight);\n\t}\n}\n","import { SkinViewer } from \"./viewer.js\";\nimport { Vector3 } from \"three\";\nimport { OrbitControls } from \"three/examples/jsm/controls/OrbitControls.js\";\n\nexport function createOrbitControls(skinViewer: SkinViewer): OrbitControls {\n\tconst control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement);\n\n\t// default configuration\n\tcontrol.enablePan = false;\n\tcontrol.target = new Vector3(0, -12, 0);\n\tcontrol.minDistance = 10;\n\tcontrol.maxDistance = 256;\n\tcontrol.update();\n\n\treturn control;\n}\n"],"names":["Object","Texture","WebGLRenderTarget","Euler","Object3D","Scene","Color","Material","MeshBasicMaterial","Int8BufferAttribute","Uint8BufferAttribute","Uint8ClampedBufferAttribute","Int16BufferAttribute","Uint16BufferAttribute","Int32BufferAttribute","Uint32BufferAttribute","Float32BufferAttribute","Float64BufferAttribute","BufferGeometry","Mesh","Geometry","ShaderMaterial","Camera","PerspectiveCamera","DataTexture","PlaneGeometry","PlaneBufferGeometry","ShaderLib","CubeTexture","DataTexture2DArray","DataTexture3D","PureArrayUniform","StructuredUniform","WebGLUniforms","MeshDepthMaterial","MeshDistanceMaterial","toFaceVertices","x1","y1","x2","y2","w","h","Vector2","toSkinVertices","toCapeVertices","setVertices","box","top","bottom","left","front","right","back","faceVertexUvs","ArrayCamera","Group","BodyPart","[object Object]","innerLayer","outerLayer","super","this","name","SkinObject","texture","layer1","map","side","layer2","transparent","opacity","alphaTest","layer1Material","layer2Material","headBox","BoxGeometry","headMesh","head2Box","head2Mesh","renderOrder","head","add","bodyBox","bodyMesh","polygonOffset","polygonOffsetUnits","body2Box","body2Mesh","body","position","y","rightArmBox","rightArmMesh","modelListeners","push","scale","x","slim","z","uvsNeedUpdate","elementsNeedUpdate","rightArm2Box","rightArm2Mesh","rightArmPivot","rightArm","leftArmBox","leftArmMesh","leftArm2Box","leftArm2Mesh","leftArmPivot","leftArm","rightLegBox","rightLegMesh","rightLeg2Box","rightLeg2Mesh","rightLegPivot","rightLeg","leftLegBox","leftLegMesh","leftLeg2Box","leftLeg2Mesh","leftLegPivot","leftLeg","_slim","value","forEach","listener","children","filter","it","getBodyParts","part","visible","CapeObject","capeMaterial","capeBox","cape","PlayerObject","skinTexture","capeTexture","skin","rotation","Math","PI","invokeAnimation","animation","player","time","Function","play","AnimationWrapper","toResetAndRemove","remove","delta","started","lastTime","paused","progress","speed","CompositeAnimation","Set","handle","handles","delete","RootAnimation","Clock","clock","running","stop","start","size","getDelta","hasTransparency","context","x0","y0","imgData","getImageData","offset","data","computeSkinScale","width","convertSkinTo1_8","copySkin","sX","sY","dX","dY","flipHorizontal","index","index2","pA1","pA2","pA3","pA4","pB1","pB2","pB3","pB4","putImageData","copyImage","scale_1","clearArea","clearRect","fixOpaqueSkin","OrbitControls","MapControls","cos","basicArmRotationZ","basicCapeRotationX","sin","options","domElement","detectModel","skinImg","Image","skinCanvas","document","createElement","magFilter","minFilter","capeImg","capeCanvas","scene","camera","renderer","WebGLRenderer","alpha","appendChild","playerObject","crossOrigin","onerror","console","error","src","onload","canvas","checkArea","image","isOldFormat","height","Error","getContext","sideLength","drawImage","loadSkinToCanvas","needsUpdate","loadCapeToCanvas","undefined","skinUrl","capeUrl","window","requestAnimationFrame","draw","disposed","_renderPaused","animations","runAnimationLoop","doRender","render","aspect","updateProjectionMatrix","setSize","_disposed","removeChild","dispose","renderPaused","toResume","_skinSet","url","_capeSet","getSize","newWidth","newHeight","skinViewer","control","enablePan","target","Vector3","minDistance","maxDistance","update"],"mappings":";0OAIA,cAEAA,0oBCGA,IAFA,yDAQA,svDCRA,wCCAA,kKDOAA,wKAoCAA,8hICzBAA,2tGCjBA,ybCiBA,8tBCjBA,8ECQA,8nBCPA,kFHiEAC,uBACAA,sBAEAA,24EAuPAD,2FCnTAA,wKAoCAA,y2LCVAE,uoBCzBAF,wtBA6FAA,mYAwEAA,kwJC3KA,oBAGA,sDAQAA,0jPCrBA,0EAqBA,gLAmBAA,quRC/BA,oBAGA,yFCVA,yBDmBAG,uDAEAA,qBAEAH,+YAwEAA,01ECzFAA,0SCDA,QAEA,+IAwBA,q2BC7BA,sQD+GAI,yBACAA,6BAEAA,uzOC5FAC,wwBC1BA,mKAqCA,sGA6eA,sPAreAL,wiKC5CA,cAOA,4EAOAA,ssDCfA,mEAaA,0FAOAA,s0HCfA,+BAIA,oFASAA,gqECZA,8FAYA,iGAQAA,q9BAoGAA,smEC1HA,krFA4BA,gFAaA,qGAWA,qFAMA,uECxDA,2OD8DAA,mqJAwgBAM,YCtjBAN,maCfA,SAEA,46BC4BA,8cDwCAO,k9NAmWAP,4FCtWAQ,yCACAA,4BAEAA,oCAEAA,gnBCvEA,aAEA,6RAkYA,sDAUA,uDAUA,8DAUA,uDAUA,wDAUA,uDAUA,wDAUA,yDAUA,yDCxdA,+UCcA,8GFcAR,4FAUAA,kwGAwWAS,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BCjcAjB,4jEEnBA,iEASA,0UA0BAkB,ogWCjCA,+JAuBA,6IAoTA,yRA+BA,ogCAtUAC,kyFClCA,oCAKA,+gBAqCAC,o2XCnDA,4OA0BA,q6CCyBA,2BCpCA,2GC3ByB,oHCAA,glBCUzB,2ICCA,oRCJA,6QL6EAC,yCACAA,4BAEAA,iCAEAA,sdA4BAA,m0BG9FAC,s1BCWAC,shECVAC,wCACAA,4BAEAA,8BCjBA,uBAGA,+JAeAxB,mjDCpBA,kqECJA,mQCAA,udAkBa,wCAIH,+IAQA,+BAIA,gCAIA,+BAIA,8BAIA,iCAIA,8ZC3CV,+LAuBA,imBALAyB,yCACAA,4BA2FAC,yCACAA,4BC1HA,0BAAyB,wGCAA,gFCAA,wFCAA,+bCAA,qGCAA,0DCAA,qHCAA,qrPCAA,0+BCAA,2pBCAA,wJCAA,4FCAA,0FCAA,8ECAA,qECAA,gECAA,6DCAA,g2FCAA,+hHCAA,ulBCAA,yKCAA,wLCAA,uOCAA,sFCAA,8ECAA,6vFCAA,40DCAA,8PCAA,4UCAA,6TCAA,+rGCAA,wpBCAA,sECAA,iECAA,0SCAA,oOCAA,mZCAA,mNCAA,uHCAA,0xFCAA,mrKCAA,0NCAA,mvCCAA,iOCAA,kzCCAA,s2CCAA,ilLCAA,k4HCAA,i5BCAA,gSCAA,6MCAA,iMCAA,yMCAA,4YCAA,sKCAA,yECAA,6WCAA,6NCAA,kMCAA,wFCAA,+VCAA,yOCAA,knBCAA,k5BCAA,qrBCAA,q8BCAA,oGCAA,4XCAA,2RCAA,slDCAA,2FCAA,uOCAA,wGCAA,iWCAA,kMCAA,6FCAA,qtQCAA,wjBCAA,0vBCAA,k6CCAA,uPCAA,giCCAA,iZCAA,2eCAA,oNCAA,wFCAA,uHCAA,qnCCAA,wGCAA,kJCAA,uFCAA,oGCAA,oJCAA,8HCAA,kSCAA,4OCAA,wKCAA,oWCAA,4OCAA,q2BCAA,0vBCAA,+sBCAA,guBCAA,wXCAA,+MCAA,mzBCAA,8iBCAA,+qDCAA,s3BCAA,81ECAA,6oCCAA,6hDCAA,2+BCAA,o8DCAA,wnCCAA,ijECAA,urCCAA,27FCAA,22CCAA,+uBCAA,+yCCAA,gwBCAA,isBCAA,+aCAA,2OCAA,suBCAA,22HCazB,6/DCTA,yeCAA,qFA4BqC,MAAkB,+CACtB,MAAoB,6FAYhB,MAAkB,+CACtB,MAAoB,wZA6BjB,wBACM,wBACH,uBACA,wBAED,wBACI,wBACN,wBACQ,ygBAME,UClF9C,yhCCHA,s6BCIA,unBAuJgC,+XAvEH,uBAMqB,kGAcf,6ICxGnC,0jBCAA,gRAuBQ,kCAIA,8BAIA,8BAIA,0BAIA,wFCvCR,sDAMA,8wBCNA,+OA6B6C,6CC1B7C,yICAA,qNCAA,qNCiSAC,+VHrRAC,wCACAA,4BAEAA,8BAEA5B,+GCCA6B,wCACAA,4BACAA,qCCOAC,wCACAA,4BACAA,gCEgBA,6HAoBA,qMAmCA,iHAcA,0DAYA,mIAyBA,8EAcA,uLA2BA,yUAwCA,yOA+BA,yMA2BA,yMA2BA,yMA6BA,sIAgBA,uIAgBA,kIAgBA,wIAkBA,8EAYA,+EAYA,+EAYA,+EAcA,+EA+DA,2CAOA,2CAMA,2CAMA,2CAMA,2CASA,mEAQA,mEAQA,mEAUA,4EAQA,4EAQA,6EAUA,8HAgBA,gIAuDA,qEA9MA,6hBAyNA,sFAhDA,waA0EA,iDAdAC,uJAuBAC,wHAiBA,kCAWA,6CAOA,4QAoDA,2EAK0C,6FCvzB1C,2FDo0BAC,yFAQAA,sFAWAA,iIAkBAA,+GEp2BA,SAgBA,maA2BA,gDAE6C,+GA3C7C,qHAyDA,mGAcA,0SAuFA,4BAMA,0aAcA,0JAUA,0CAEA,uCAMA,4GAgBA,2OAGA,sDAQA,4KAOA,kJAkBA,iQAgIA,oGA1GA,iMAsBA,kQAmCA,wIAqBA,oPAlPA,6kBAaA,+uNA6kBuC,kBACE,qXA8BD,yJAOsF,mZAjmB9H,qDAI0C,0SC/I1C,83MCLA,uNCAA,8QA8BA,oKAuBA,60BAqHA,6UCrKA,4hBAuIA,SAEA,6DAMA,ulIClJA,6OAkDA,2VC9BA,8SCAA,oTD4BAC,yCACAA,4BAEAA,oCAEAA,gZCNAC,yCACAA,4BAEAA,uCAEAA,wZCtCA,2OCpByB,0ECAA,k1JCOzB,sbA6Ea,QAIC,2HA2BQ,8BAKA,8BAKA,8BAKA,8BAKA,8BAKA,8BAKA,8BAKA,+BAKA,sBAMF,4PA8DN,QAIC,8YA6F6B,gMA2BR,iCAIF,2SA0BR,MAAuB,wBACvB,MAAuB,6CAIhB,WAAkB,KAAS,sTAS5C,QAAiC,KAAe,UAChD,SAAuC,MAAqB,2DAQnE,gCAKA,sBAgHU,UACK,UACO,mBAKC,aACA,oGAgBd,MACD,MACK,QACA,QACQ,QACR,QACA,QACQ,QACA,QACA,QACA,oDAoBnB,gQAWY,2DAYM,EAAQ,IAAwB,EAAQ,8BAIhD,EAAQ,oCAIA,EAAS,EAAS,IAAwB,sCAI1C,EAAS,IAAc,EAAS,qHAchC,IAAc,IAAwB,EAAQ,8BAItD,IAAc,4BAId,EAAS,8BAIT,EAAS,2HAxEjB,gDA0KK,kBAIA,kCAcP,+BAMO,uBAIA,iBAIA,UAQN,iCAwBD,uDAaC,oCAwBiC,kYA7WN,UAAmB,wNAiO5C,QACD,mqBA6HF,QAIC,k+BC9yBZ,0+CAkJoB,WAED,aAA6B,OAC7B,aAAkC,OAClC,aAAqC,QAIpC,WAED,aAA6B,OAC7B,aAAkC,OAClC,aAAqC,QAIpC,WAED,aAA6B,OAC7B,aAAkC,OAClC,aAAqC,QAI9B,WAA+B,WACnC,WAAkC,+FAgB9C,KAID,s7CAoJc,uBACF,6IA8CG,uBACF,sCAEF,0SA2BK,sJAkBW,oKAUX,2HAkBD,uHAOC,gEAMD,kEAMC,kEAeL,+FAUI,uBACF,yDAQC,uBACF,0CAKC,WACK,WACG,eAIT,UACa,UACD,UAEb,UACa,UACD,6CAOG,oCACA,kBAEX,WAAkC,6BAEtB,oCAID,wCACA,0CAIA,MAAoB,yBACpB,MAAoB,OAE/B,WAAkC,6BAEtB,MAAoB,uMAUrB,wCACA,ovBA8Cf,gCAEgC,6BACL,8BAIxB,yDAGJ,6BACA,wCACA,qSAkBG,uBAME,oBAIA,oBAIA,MAIA,oHAgBuC,uMAgBO,aAI/C,sKAkBF,mIAaE,0GASD,4LAeY,gKAUX,+GAUF,0GAKA,yIAgBE,kFASD,wSA4BC,gCACK,+DACL,oDAOC,gDAIE,uEAUD,wBAIA,oDAQe,uDAIX,oDAIG,MAAiB,MAAsB,+FAQ/B,QAA2B,mDAItC,MAAkB,kDAKf,MAAiB,MAA8B,4JAYvC,uDAIX,6CAML,6TAUD,keAyBM,MAAiB,MAAsB,qHAIvC,MAAiB,MAA8B,6GA+BlD,qIAQD,uHAQF,icAtoBA,uBACF,wIAeE,uBACF,kzBA0qBM,0KAMc,8CAEf,kEACQ,MAAiB,MAAuB,qDAC/C,oIASD,qIAiBJ,0BACG,+DAIkE,MAAuB,2BAM9F,gDAIE,+BAIA,yBACG,2CAC4D,MAAuB,wBAIxF,+CAIE,2IAqBiC,MAAuB,4NAmBrD,0DACA,uDAIV,yBAE6B,0BACE,0CAE2B,wBAEhD,yqBCppCzB,wFAQuC,wBACK,yBACA,yBACD,yBAEZ,wBACC,wBACQ,wBACV,wBACQ,wBACN,0BAIN,yFAgBQ,wBACF,wBACC,wBACK,wBACK,wBACT,wBACO,yBACT,wBAIO,yBACR,yBACO,yBACC,yBACC,+1CAsHd,sFC3K1B,gDCAA,6CCAA,mDCMA,y5HCNA,62MC2CA,grKA4e8C,4BACA,0BACI,urBA8H/B,+BACA,sBAAwC,wEAGA,0CAMxC,6BACA,oBAAsC,oEAGA,sCAMtC,yBACA,gBAAkC,4DAGA,yCAMlC,4BACA,mBAAqC,kEAGA,uDAMtC,yxCAgPI,uPAqBA,8SAqBD,ibA/LD,oSA8BE,cAIA,2GAcA,0BAIA,aAIA,6BAMD,yBAIA,gqSA8iCiE,ylBAwE9D,8GAYK,MAAiB,MAAuB,kPA6B5C,kGAYqE,2LAOE,6UASrC,iCAAtB,2PAoBX,wUAqBJ,4OAmBA,qFAMW,2FAIV,uEAOgD,gNCtmEvE,+GCQA,4GCVA,SAASC,GAAeC,EAAYC,EAAYC,EAAYC,EAAYC,EAAWC,GAClF,MAAO,CACN,IAAIC,EAAQN,EAAKI,EAAG,EAAMD,EAAKE,GAC/B,IAAIC,EAAQJ,EAAKE,EAAG,EAAMD,EAAKE,GAC/B,IAAIC,EAAQJ,EAAKE,EAAG,EAAMH,EAAKI,GAC/B,IAAIC,EAAQN,EAAKI,EAAG,EAAMH,EAAKI,IAIjC,SAASE,GAAeP,EAAYC,EAAYC,EAAYC,GAC3D,OAAOJ,GAAeC,EAAIC,EAAIC,EAAIC,EAAI,GAAM,IAG7C,SAASK,GAAeR,EAAYC,EAAYC,EAAYC,GAC3D,OAAOJ,GAAeC,EAAIC,EAAIC,EAAIC,EAAI,GAAM,IAG7C,SAASM,GAAYC,EAAkBC,EAAqBC,EAAwBC,EAAsBC,EAAuBC,EAAuBC,GAEvJN,EAAIO,cAAc,GAAK,GACvBP,EAAIO,cAAc,GAAG,GAAK,CAACF,EAAM,GAAIA,EAAM,GAAIA,EAAM,IACrDL,EAAIO,cAAc,GAAG,GAAK,CAACF,EAAM,GAAIA,EAAM,GAAIA,EAAM,IACrDL,EAAIO,cAAc,GAAG,GAAK,CAACJ,EAAK,GAAIA,EAAK,GAAIA,EAAK,IAClDH,EAAIO,cAAc,GAAG,GAAK,CAACJ,EAAK,GAAIA,EAAK,GAAIA,EAAK,IAClDH,EAAIO,cAAc,GAAG,GAAK,CAACN,EAAI,GAAIA,EAAI,GAAIA,EAAI,IAC/CD,EAAIO,cAAc,GAAG,GAAK,CAACN,EAAI,GAAIA,EAAI,GAAIA,EAAI,IAC/CD,EAAIO,cAAc,GAAG,GAAK,CAACL,EAAO,GAAIA,EAAO,GAAIA,EAAO,IACxDF,EAAIO,cAAc,GAAG,GAAK,CAACL,EAAO,GAAIA,EAAO,GAAIA,EAAO,IACxDF,EAAIO,cAAc,GAAG,GAAK,CAACH,EAAM,GAAIA,EAAM,GAAIA,EAAM,IACrDJ,EAAIO,cAAc,GAAG,GAAK,CAACH,EAAM,GAAIA,EAAM,GAAIA,EAAM,IACrDJ,EAAIO,cAAc,GAAG,IAAM,CAACD,EAAK,GAAIA,EAAK,GAAIA,EAAK,IACnDN,EAAIO,cAAc,GAAG,IAAM,CAACD,EAAK,GAAIA,EAAK,GAAIA,EAAK,IRnBpDE,0FCAAC,mFCDAxD,2lCCidAA,wCG9cAA,0iBCMAA,6mBCiBayD,WAAiBD,GAC7BE,YACUC,EACAC,GAETC,QAHSC,gBAAAH,EACAG,gBAAAF,EAGTD,EAAWI,KAAO,QAClBH,EAAWG,KAAO,eAIPC,WAAmBR,GAa/BE,YAAYO,GACXJ,QAJOC,oBAAoC,GACpCA,YAAQ,EAKf,MAAMI,EAAS,CACdC,IAAKF,EACLG,QAEKC,EAAS,CACdF,IAAKF,EACLG,OACAE,aAAa,EACbC,QAAS,EACTC,UAAW,IAGNC,EAAiB,IAAIjE,GAAkB0D,GACvCQ,EAAiB,IAAIlE,GAAkB6D,GAGvCM,EAAU,IAAIC,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAC/C9B,GAAY6B,EACX/B,GAAe,EAAG,EAAG,GAAI,GACzBA,GAAe,GAAI,EAAG,GAAI,GAC1BA,GAAe,EAAG,EAAG,EAAG,IACxBA,GAAe,EAAG,EAAG,GAAI,IACzBA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,GAAI,EAAG,GAAI,KAE3B,MAAMiC,EAAW,IAAI1D,GAAKwD,EAASF,GAE7BK,EAAW,IAAIF,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAChD9B,GAAYgC,EACXlC,GAAe,GAAI,EAAG,GAAI,GAC1BA,GAAe,GAAI,EAAG,GAAI,GAC1BA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,GAAI,EAAG,GAAI,KAE3B,MAAMmC,EAAY,IAAI5D,GAAK2D,EAAUJ,GACrCK,EAAUC,aAAe,EAEzBlB,KAAKmB,KAAO,IAAIxB,GAASoB,EAAUE,GACnCjB,KAAKmB,KAAKlB,KAAO,OACjBD,KAAKmB,KAAKC,IAAIL,EAAUE,GACxBjB,KAAKoB,IAAIpB,KAAKmB,MAGd,MAAME,EAAU,IAAIP,GAAY,EAAG,GAAI,EAAG,EAAG,EAAG,GAChD9B,GAAYqC,EACXvC,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAMwC,EAAW,IAAIjE,GAAKgE,EAAS,IAAI3E,kCACnC0D,IAGHmB,eAAe,EACfC,oBAAqB,MAGhBC,EAAW,IAAIX,GAAY,EAAG,KAAM,IAAK,EAAG,EAAG,GACrD9B,GAAYyC,EACX3C,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAM4C,EAAY,IAAIrE,GAAKoE,EAAU,IAAI/E,kCACrC6D,IAEHgB,eAAe,EACfC,oBAAqB,MAGtBxB,KAAK2B,KAAO,IAAIhC,GAAS2B,EAAUI,GACnC1B,KAAK2B,KAAK1B,KAAO,OACjBD,KAAK2B,KAAKP,IAAIE,EAAUI,GACxB1B,KAAK2B,KAAKC,SAASC,GAAK,GACxB7B,KAAKoB,IAAIpB,KAAK2B,MAGd,MAAMG,EAAc,IAAIhB,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAC7CiB,EAAe,IAAI1E,GAAKyE,EAAanB,GAC3CX,KAAKgC,eAAeC,KAAK,KACxBF,EAAaG,MAAMC,EAAInC,KAAKoC,KAAO,EAAI,EACvCL,EAAaG,MAAML,EAAI,GACvBE,EAAaG,MAAMG,EAAI,EACnBrC,KAAKoC,KACRpD,GAAY8C,EACXhD,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG5BE,GAAY8C,EACXhD,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG7BgD,EAAYQ,eAAgB,EAC5BR,EAAYS,oBAAqB,IAGlC,MAAMC,EAAe,IAAI1B,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAC9C2B,EAAgB,IAAIpF,GAAKmF,EAAc5B,GAC7C6B,EAAcvB,YAAc,EAC5BlB,KAAKgC,eAAeC,KAAK,KACxBQ,EAAcP,MAAMC,EAAInC,KAAKoC,KAAO,MAAQ,IAC5CK,EAAcP,MAAML,EAAI,KACxBY,EAAcP,MAAMG,EAAI,IACpBrC,KAAKoC,KACRpD,GAAYwD,EACX1D,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG5BE,GAAYwD,EACX1D,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG7B0D,EAAaF,eAAgB,EAC7BE,EAAaD,oBAAqB,IAGnC,MAAMG,EAAgB,IAAIhD,GAC1BgD,EAActB,IAAIW,EAAcU,GAChCC,EAAcd,SAASC,GAAK,EAE5B7B,KAAK2C,SAAW,IAAIhD,GAASoC,EAAcU,GAC3CzC,KAAK2C,SAAS1C,KAAO,WACrBD,KAAK2C,SAASvB,IAAIsB,GAClB1C,KAAK2C,SAASf,SAASC,GAAK,EAC5B7B,KAAKgC,eAAeC,KAAK,KACxBjC,KAAK2C,SAASf,SAASO,EAAInC,KAAKoC,MAAQ,KAAO,IAEhDpC,KAAKoB,IAAIpB,KAAK2C,UAGd,MAAMC,EAAa,IAAI9B,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAC5C+B,EAAc,IAAIxF,GAAKuF,EAAYjC,GACzCX,KAAKgC,eAAeC,KAAK,KACxBY,EAAYX,MAAMC,EAAInC,KAAKoC,KAAO,EAAI,EACtCS,EAAYX,MAAML,EAAI,GACtBgB,EAAYX,MAAMG,EAAI,EAClBrC,KAAKoC,KACRpD,GAAY4D,EACX9D,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG5BE,GAAY4D,EACX9D,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG7B8D,EAAWN,eAAgB,EAC3BM,EAAWL,oBAAqB,IAGjC,MAAMO,EAAc,IAAIhC,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAC7CiC,EAAe,IAAI1F,GAAKyF,EAAalC,GAC3CmC,EAAa7B,YAAc,EAC3BlB,KAAKgC,eAAeC,KAAK,KACxBc,EAAab,MAAMC,EAAInC,KAAKoC,KAAO,MAAQ,IAC3CW,EAAab,MAAML,EAAI,KACvBkB,EAAab,MAAMG,EAAI,IACnBrC,KAAKoC,KACRpD,GAAY8D,EACXhE,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG5BE,GAAY8D,EACXhE,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG7BgE,EAAYR,eAAgB,EAC5BQ,EAAYP,oBAAqB,IAGlC,MAAMS,EAAe,IAAItD,GACzBsD,EAAa5B,IAAIyB,EAAaE,GAC9BC,EAAapB,SAASC,GAAK,EAE3B7B,KAAKiD,QAAU,IAAItD,GAASkD,EAAaE,GACzC/C,KAAKiD,QAAQhD,KAAO,UACpBD,KAAKiD,QAAQ7B,IAAI4B,GACjBhD,KAAKiD,QAAQrB,SAASC,GAAK,EAC3B7B,KAAKgC,eAAeC,KAAK,KACxBjC,KAAKiD,QAAQrB,SAASO,EAAInC,KAAKoC,KAAO,IAAM,IAE7CpC,KAAKoB,IAAIpB,KAAKiD,SAGd,MAAMC,EAAc,IAAIpC,GAAY,EAAG,GAAI,EAAG,EAAG,EAAG,GACpD9B,GAAYkE,EACXpE,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAMqE,EAAe,IAAI9F,GAAK6F,EAAavC,GAErCyC,EAAe,IAAItC,GAAY,IAAK,KAAM,IAAK,EAAG,EAAG,GAC3D9B,GAAYoE,EACXtE,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAMuE,EAAgB,IAAIhG,GAAK+F,EAAcxC,GAC7CyC,EAAcnC,YAAc,EAE5B,MAAMoC,EAAgB,IAAI5D,GAC1B4D,EAAclC,IAAI+B,EAAcE,GAChCC,EAAc1B,SAASC,GAAK,EAE5B7B,KAAKuD,SAAW,IAAI5D,GAASwD,EAAcE,GAC3CrD,KAAKuD,SAAStD,KAAO,WACrBD,KAAKuD,SAASnC,IAAIkC,GAClBtD,KAAKuD,SAAS3B,SAASC,GAAK,GAC5B7B,KAAKuD,SAAS3B,SAASO,GAAK,EAC5BnC,KAAKoB,IAAIpB,KAAKuD,UAGd,MAAMC,EAAa,IAAI1C,GAAY,EAAG,GAAI,EAAG,EAAG,EAAG,GACnD9B,GAAYwE,EACX1E,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAM2E,EAAc,IAAIpG,GAAKmG,EAAY7C,GAEnC+C,EAAc,IAAI5C,GAAY,IAAK,KAAM,IAAK,EAAG,EAAG,GAC1D9B,GAAY0E,EACX5E,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAM6E,EAAe,IAAItG,GAAKqG,EAAa9C,GAC3C+C,EAAazC,YAAc,EAE3B,MAAM0C,EAAe,IAAIlE,GACzBkE,EAAaxC,IAAIqC,EAAaE,GAC9BC,EAAahC,SAASC,GAAK,EAE3B7B,KAAK6D,QAAU,IAAIlE,GAAS8D,EAAaE,GACzC3D,KAAK6D,QAAQ5D,KAAO,UACpBD,KAAK6D,QAAQzC,IAAIwC,GACjB5D,KAAK6D,QAAQjC,SAASC,GAAK,GAC3B7B,KAAK6D,QAAQjC,SAASO,EAAI,EAC1BnC,KAAKoB,IAAIpB,KAAK6D,SAEd7D,KAAKoC,MAAO,EAGbA,WACC,OAAOpC,KAAK8D,MAGb1B,SAAS2B,GACR/D,KAAK8D,MAAQC,EACb/D,KAAKgC,eAAegC,QAAQC,GAAYA,KAGjCrE,eACP,OAAOI,KAAKkE,SAASC,OAAOC,GAAMA,aAAczE,IAGjDC,qBAAqBmE,GACpB/D,KAAKqE,eAAeL,QAAQM,GAAQA,EAAKzE,WAAW0E,QAAUR,GAG/DnE,qBAAqBmE,GACpB/D,KAAKqE,eAAeL,QAAQM,GAAQA,EAAKxE,WAAWyE,QAAUR,UAInDS,WAAmB9E,GAI/BE,YAAYO,GACXJ,QAEA,MAAM0E,EAAe,IAAI/H,GAAkB,CAAE2D,IAAKF,EAASK,aAAa,EAAMC,QAAS,EAAGH,OAAkBI,UAAW,KAIjHgE,EAAU,IAAI5D,GAAY,GAAI,GAAI,EAAG,EAAG,EAAG,GACjD9B,GAAY0F,EACX3F,GAAe,EAAG,EAAG,GAAI,GACzBA,GAAe,GAAI,EAAG,GAAI,GAC1BA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,EAAG,EAAG,EAAG,IACxBA,GAAe,EAAG,EAAG,GAAI,KAE1BiB,KAAK2E,KAAO,IAAItH,GAAKqH,EAASD,GAC9BzE,KAAK2E,KAAK/C,SAASC,GAAK,EACxB7B,KAAK2E,KAAK/C,SAASS,GAAK,GACxBrC,KAAKoB,IAAIpB,KAAK2E,aAIHC,WAAqBlF,GAKjCE,YAAYiF,EAAsBC,GACjC/E,QAEAC,KAAK+E,KAAO,IAAI7E,GAAW2E,GAC3B7E,KAAK+E,KAAK9E,KAAO,OACjBD,KAAKoB,IAAIpB,KAAK+E,MAEd/E,KAAK2E,KAAO,IAAIH,GAAWM,GAC3B9E,KAAK2E,KAAK1E,KAAO,OACjBD,KAAK2E,KAAK/C,SAASS,GAAK,EACxBrC,KAAK2E,KAAK/C,SAASC,GAAK,EACxB7B,KAAK2E,KAAKK,SAAS7C,EAAI,GAAK8C,KAAKC,GAAK,IACtClF,KAAKoB,IAAIpB,KAAK2E,gBCxaAQ,GAAgBC,EAAsBC,EAAsBC,GACvEF,aAAqBG,SACxBH,EAAUC,EAAQC,GAGlBF,EAAUI,KAAKH,EAAQC,GAmBzB,MAAMG,GAUL7F,YAAYwF,GATZpF,WAAgB,EAChBA,aAAkB,EAClBA,cAAmB,EAGXA,cAAmB,EACnBA,cAAmB,EACnBA,uBAA4B,EAGnCA,KAAKoF,UAAYA,EAGlBxF,KAAKyF,EAAsBC,GAC1B,GAAItF,KAAK0F,iBAGR,OAFAP,GAAgBnF,KAAKoF,UAAWC,EAAQ,QACxCrF,KAAK2F,SAIN,IAAIC,EACA5F,KAAK6F,QACRD,EAAQN,EAAOtF,KAAK8F,UAEpBF,EAAQ,EACR5F,KAAK6F,SAAU,GAEhB7F,KAAK8F,SAAWR,EACXtF,KAAK+F,SACT/F,KAAKgG,UAAYJ,EAAQ5F,KAAKiG,OAE/Bd,GAAgBnF,KAAKoF,UAAWC,EAAQrF,KAAKgG,UAG9CpG,QACCI,KAAKgG,SAAW,EAGjBpG,UAIAA,iBACCI,KAAK0F,kBAAmB,SAIbQ,GAAbtG,cAEUI,aAA6C,IAAImG,IAE1DvG,IAAIwF,GACH,MAAMgB,EAAS,IAAIX,GAAiBL,GAKpC,OAJAgB,EAAOT,OAAS,KACf3F,KAAKqG,QAAQC,OAAOF,IAErBpG,KAAKqG,QAAQjF,IAAIgF,GACVA,EAGRxG,KAAKyF,EAAsBC,GAC1BtF,KAAKqG,QAAQrC,QAAQoC,GAAUA,EAAOZ,KAAKH,EAAQC,WAIxCiB,WAAsBL,GAAnCtG,kCACCI,WAAgB,EAChBA,cAAmB,EACVA,WAAe,IAAIwG,IAAM,GAElCpB,gBACC,OAAOpF,KAGR+F,aACC,OAAQ/F,KAAKyG,MAAMC,QAGpBX,WAAWhC,GACNA,EACH/D,KAAKyG,MAAME,OAEX3G,KAAKyG,MAAMG,QAIbhH,iBAAiByF,GACU,IAAtBrF,KAAKqG,QAAQQ,OAGjB7G,KAAKgG,UAAYhG,KAAKyG,MAAMK,WAAa9G,KAAKiG,MAC9CjG,KAAKwF,KAAKH,EAAQrF,KAAKgG,WAGxBpG,QACCI,KAAKgG,SAAW,GCvGlB,SAASe,GAAgBC,EAASC,EAAIC,EAAIvI,EAAGC,GAEzC,IADA,IAAIuI,EAAUH,EAAQI,aAAaH,EAAIC,EAAIvI,EAAGC,GACrCuD,EAAI,EAAGA,EAAIxD,EAAGwD,IACnB,IAAK,IAAIN,EAAI,EAAGA,EAAIjD,EAAGiD,IAAK,CACxB,IAAIwF,EAAuB,GAAblF,EAAIN,EAAIlD,GACtB,GAAiC,MAA7BwI,EAAQG,KAAKD,EAAS,GACtB,OAAO,EAInB,OAAO,EAEX,SAASE,GAAiBC,GACtB,OAAOA,EAAQ,GAkBnB,SAASC,GAAiBT,EAASQ,GAC/B,IAAItF,EAAQqF,GAAiBC,GACzBE,EAAW,SAAUC,EAAIC,EAAIjJ,EAAGC,EAAGiJ,EAAIC,EAAIC,GAC3C,OA9DR,SAAmBf,EAASW,EAAIC,EAAIjJ,EAAGC,EAAGiJ,EAAIC,EAAIC,GAC9C,IAAIZ,EAAUH,EAAQI,aAAaO,EAAIC,EAAIjJ,EAAGC,GAC9C,GAAImJ,EACA,IAAK,IAAIlG,EAAI,EAAGA,EAAIjD,EAAGiD,IACnB,IAAK,IAAIM,EAAI,EAAGA,EAAKxD,EAAI,EAAIwD,IAAK,CAC9B,IAAI6F,EAAsB,GAAb7F,EAAIN,EAAIlD,GACjBsJ,EAAiC,GAAtBtJ,EAAIwD,EAAI,EAAKN,EAAIlD,GAC5BuJ,EAAMf,EAAQG,KAAKU,GACnBG,EAAMhB,EAAQG,KAAKU,EAAQ,GAC3BI,EAAMjB,EAAQG,KAAKU,EAAQ,GAC3BK,EAAMlB,EAAQG,KAAKU,EAAQ,GAC3BM,EAAMnB,EAAQG,KAAKW,GACnBM,EAAMpB,EAAQG,KAAKW,EAAS,GAC5BO,EAAMrB,EAAQG,KAAKW,EAAS,GAC5BQ,EAAMtB,EAAQG,KAAKW,EAAS,GAChCd,EAAQG,KAAKU,GAASM,EACtBnB,EAAQG,KAAKU,EAAQ,GAAKO,EAC1BpB,EAAQG,KAAKU,EAAQ,GAAKQ,EAC1BrB,EAAQG,KAAKU,EAAQ,GAAKS,EAC1BtB,EAAQG,KAAKW,GAAUC,EACvBf,EAAQG,KAAKW,EAAS,GAAKE,EAC3BhB,EAAQG,KAAKW,EAAS,GAAKG,EAC3BjB,EAAQG,KAAKW,EAAS,GAAKI,EAIvCrB,EAAQ0B,aAAavB,EAASU,EAAIC,GAoCvBa,CAAU3B,EAASW,EAAKzF,EAAO0F,EAAK1F,EAAOvD,EAAIuD,EAAOtD,EAAIsD,EAAO2F,EAAK3F,EAAO4F,EAAK5F,EAAO6F,KAnBxG,SAAuBf,EAASQ,GAG5B,IAAKT,GAAgBC,EAAS,EAAG,EAAGQ,EAAOA,EAAQ,GAAI,CACnD,IAAIoB,EAAUrB,GAAiBC,GAC3BqB,EAAY,SAAU1G,EAAGN,EAAGlD,EAAGC,GAC/B,OAAOoI,EAAQ8B,UAAU3G,EAAIyG,EAAS/G,EAAI+G,EAASjK,EAAIiK,EAAShK,EAAIgK,IAExEC,EAAU,GAAI,EAAG,EAAG,GACpBA,EAAU,GAAI,EAAG,EAAG,GACpBA,EAAU,GAAI,EAAG,EAAG,GACpBA,EAAU,GAAI,EAAG,EAAG,GACpBA,EAAU,GAAI,EAAG,EAAG,GACpBA,EAAU,GAAI,EAAG,EAAG,IAQxBE,CAAc/B,EAASQ,GACvBE,EAAS,EAAG,GAAI,EAAG,EAAG,GAAI,IAAI,GAC9BA,EAAS,EAAG,GAAI,EAAG,EAAG,GAAI,IAAI,GAC9BA,EAAS,EAAG,GAAI,EAAG,GAAI,GAAI,IAAI,GAC/BA,EAAS,EAAG,GAAI,EAAG,GAAI,GAAI,IAAI,GAC/BA,EAAS,EAAG,GAAI,EAAG,GAAI,GAAI,IAAI,GAC/BA,EAAS,GAAI,GAAI,EAAG,GAAI,GAAI,IAAI,GAChCA,EAAS,GAAI,GAAI,EAAG,EAAG,GAAI,IAAI,GAC/BA,EAAS,GAAI,GAAI,EAAG,EAAG,GAAI,IAAI,GAC/BA,EAAS,GAAI,GAAI,EAAG,GAAI,GAAI,IAAI,GAChCA,EAAS,GAAI,GAAI,EAAG,GAAI,GAAI,IAAI,GAChCA,EAAS,GAAI,GAAI,EAAG,GAAI,GAAI,IAAI,GAChCA,EAAS,GAAI,GAAI,EAAG,GAAI,GAAI,IAAI,GClDpC,qxTAolCAsB,wDAYA,kIAYAC,uKFp8B4C,CAAC5D,EAAQC,KACpDD,EAAOL,SAASnD,EAAIyD,sBAlCsB,CAACD,EAAQC,KACnD,MAAMP,EAAOM,EAAON,KAEpBO,GAAQ,GAGRP,EAAKlB,QAAQmB,SAAS7C,EAA+B,IAA3B8C,KAAKiE,IAAI5D,EAAOL,KAAKC,IAC/CH,EAAKxB,SAASyB,SAAS7C,EAAqB,IAAjB8C,KAAKiE,IAAI5D,GAGpCP,EAAK9B,QAAQ+B,SAAS7C,EAAqB,IAAjB8C,KAAKiE,IAAI5D,GACnCP,EAAKpC,SAASqC,SAAS7C,EAA+B,IAA3B8C,KAAKiE,IAAI5D,EAAOL,KAAKC,IAChD,MAAMiE,EAA8B,GAAVlE,KAAKC,GAC/BH,EAAK9B,QAAQ+B,SAAS3C,EAAqB,GAAjB4C,KAAKiE,IAAI5D,GAAc6D,EACjDpE,EAAKpC,SAASqC,SAAS3C,EAA+B,GAA3B4C,KAAKiE,IAAI5D,EAAOL,KAAKC,IAAYiE,EAG5D9D,EAAOzD,SAASC,EAAIoD,KAAKiE,IAAW,EAAP5D,GAE7BD,EAAOzD,SAASO,EAAqB,IAAjB8C,KAAKiE,IAAI5D,GAE7BD,EAAOL,SAAS3C,EAA+B,IAA3B4C,KAAKiE,IAAI5D,EAAOL,KAAKC,IAKzC,MAAMkE,EAA+B,GAAVnE,KAAKC,GAChCG,EAAOV,KAAKK,SAAS7C,EAAyB,GAArB8C,KAAKoE,IAAW,EAAP/D,GAAkB8D,sCGrJpDxJ,YAAY0J,GAtBItJ,gBAA4B,IAAIuG,GACzCvG,kBAAuB,EAgBtBA,gBAAqB,EACrBA,oBAAyB,EACzBA,eAAoB,EACpBA,eAAoB,EAG3BA,KAAKuJ,WAAaD,EAAQC,YACE,IAAxBD,EAAQE,cACXxJ,KAAKwJ,aAAc,GAIpBxJ,KAAKyJ,QAAU,IAAIC,MACnB1J,KAAK2J,WAAaC,SAASC,cAAc,UACzC7J,KAAK6E,YAAc,IAAI1I,EAAQ6D,KAAK2J,YACpC3J,KAAK6E,YAAYiF,eACjB9J,KAAK6E,YAAYkF,eAEjB/J,KAAKgK,QAAU,IAAIN,MACnB1J,KAAKiK,WAAaL,SAASC,cAAc,UACzC7J,KAAK8E,YAAc,IAAI3I,EAAQ6D,KAAKiK,YACpCjK,KAAK8E,YAAYgF,eACjB9J,KAAK8E,YAAYiF,eAGjB/J,KAAKkK,MAAQ,IAAI3N,EAGjByD,KAAKmK,OAAS,IAAI1M,GAAkB,IACpCuC,KAAKmK,OAAOvI,SAASC,GAAK,GAC1B7B,KAAKmK,OAAOvI,SAASS,EAAI,GAEzBrC,KAAKoK,SAAW,IAAIC,GAAc,CAAEC,OAAO,IAC3CtK,KAAKuJ,WAAWgB,YAAYvK,KAAKoK,SAASb,YAE1CvJ,KAAKwK,aAAe,IAAI5F,GAAa5E,KAAK6E,YAAa7E,KAAK8E,aAC5D9E,KAAKwK,aAAavK,KAAO,SACzBD,KAAKwK,aAAazF,KAAKR,SAAU,EACjCvE,KAAKwK,aAAa7F,KAAKJ,SAAU,EACjCvE,KAAKkK,MAAM9I,IAAIpB,KAAKwK,cAGpBxK,KAAKyJ,QAAQgB,YAAc,YAC3BzK,KAAKyJ,QAAQiB,QAAU,IAAYC,QAAQC,MAAM,kBAAoB5K,KAAKyJ,QAAQoB,KAClF7K,KAAKyJ,QAAQqB,OAAS,KFkDjB,IAAoBC,EAyCnB7I,EACA8E,EACAgE,GA7FD,SAA0BD,EAAQE,GACrC,IAAIC,GAAc,EAClB,GAAID,EAAMzD,QAAUyD,EAAME,OAAQ,CAC9B,GAAIF,EAAMzD,QAAU,EAAIyD,EAAME,OAI1B,MAAM,IAAIC,MAAM,kBAAoBH,EAAMzD,MAAQ,IAAMyD,EAAME,QAH9DD,GAAc,EAMtB,IAAIlE,EAAU+D,EAAOM,WAAW,MAChC,GAAIH,EAAa,CACb,IAAII,EAAaL,EAAMzD,MACvBuD,EAAOvD,MAAQ8D,EACfP,EAAOI,OAASG,EAChBtE,EAAQ8B,UAAU,EAAG,EAAGwC,EAAYA,GACpCtE,EAAQuE,UAAUN,EAAO,EAAG,EAAGK,EAAYA,EAAa,GACxD7D,GAAiBT,EAASsE,QAG1BP,EAAOvD,MAAQyD,EAAMzD,MACrBuD,EAAOI,OAASF,EAAME,OACtBnE,EAAQ8B,UAAU,EAAG,EAAGmC,EAAMzD,MAAOyD,EAAME,QAC3CnE,EAAQuE,UAAUN,EAAO,EAAG,EAAGF,EAAOvD,MAAOuD,EAAOI,QEtBzDK,CAAiBxL,KAAK2J,WAAY3J,KAAKyJ,SAEnCzJ,KAAKwJ,cACRxJ,KAAKwK,aAAazF,KAAK3C,MF8CA2I,EE9CkB/K,KAAK2J,WFuF1CzH,EAAQqF,GAAiBwD,EAAOvD,OAChCR,EAAU+D,EAAOM,WAAW,OAC5BL,EAAY,SAAU7I,EAAGN,EAAGlD,EAAGC,GAC/B,OAAOmI,GAAgBC,EAAS7E,EAAID,EAAOL,EAAIK,EAAOvD,EAAIuD,EAAOtD,EAAIsD,KAExD,GAAI,GAAI,EAAG,IACxB8I,EAAU,GAAI,GAAI,EAAG,KACrBA,EAAU,GAAI,GAAI,EAAG,IACrBA,EAAU,GAAI,GAAI,EAAG,ME5F1BhL,KAAK6E,YAAY4G,aAAc,EAC/BzL,KAAKwK,aAAazF,KAAKR,SAAU,GAGlCvE,KAAKgK,QAAQS,YAAc,YAC3BzK,KAAKgK,QAAQU,QAAU,IAAYC,QAAQC,MAAM,kBAAoB5K,KAAKgK,QAAQa,KAClF7K,KAAKgK,QAAQc,OAAS,MFajB,SAA0BC,EAAQE,GACrC,IAAIC,GAAc,EAClB,GAAID,EAAMzD,QAAU,EAAIyD,EAAME,OAAQ,CAClC,GAAkB,GAAdF,EAAMzD,OAA8B,GAAfyD,EAAME,OAK3B,MAAM,IAAIC,MAAM,kBAAoBH,EAAMzD,MAAQ,IAAMyD,EAAME,QAH9DD,GAAc,EAMtB,IAAIlE,EAAU+D,EAAOM,WAAW,MAChC,GAAIH,EAAa,CACb,IAAI1D,EAAsB,GAAdyD,EAAMzD,MAAa,GAC/BuD,EAAOvD,MAAQA,EACfuD,EAAOI,OAAS3D,EAAQ,OAGxBuD,EAAOvD,MAAQyD,EAAMzD,MACrBuD,EAAOI,OAASF,EAAME,OAE1BnE,EAAQ8B,UAAU,EAAG,EAAGiC,EAAOvD,MAAOuD,EAAOI,QAC7CnE,EAAQuE,UAAUN,EAAO,EAAG,EAAGA,EAAMzD,MAAOyD,EAAME,QElCnDO,CAAiB1L,KAAKiK,WAAYjK,KAAKgK,SAEvChK,KAAK8E,YAAY2G,aAAc,EAC/BzL,KAAKwK,aAAa7F,KAAKJ,SAAU,QAGVoH,IAApBrC,EAAQsC,UACX5L,KAAK4L,QAAUtC,EAAQsC,cAEAD,IAApBrC,EAAQuC,UACX7L,KAAK6L,QAAUvC,EAAQuC,SAExB7L,KAAKwH,WAA0BmE,IAAlBrC,EAAQ9B,MAAsB,IAAM8B,EAAQ9B,MACzDxH,KAAKmL,YAA4BQ,IAAnBrC,EAAQ6B,OAAuB,IAAM7B,EAAQ6B,OAE3DW,OAAOC,sBAAsB,IAAM/L,KAAKgM,QAGjCpM,OACHI,KAAKiM,UAAYjM,KAAKkM,gBAG1BlM,KAAKmM,WAAWC,iBAAiBpM,KAAKwK,cACtCxK,KAAKqM,WACLP,OAAOC,sBAAsB,IAAM/L,KAAKgM,SAG/BpM,WACTI,KAAKoK,SAASkC,OAAOtM,KAAKkK,MAAOlK,KAAKmK,QAGvCvK,QAAQ4H,EAAe2D,GACtBnL,KAAKmK,OAAOoC,OAAS/E,EAAQ2D,EAC7BnL,KAAKmK,OAAOqC,yBACZxM,KAAKoK,SAASqC,QAAQjF,EAAO2D,GAG9BvL,UACCI,KAAK0M,WAAY,EACjB1M,KAAKuJ,WAAWoD,YAAY3M,KAAKoK,SAASb,YAC1CvJ,KAAKoK,SAASwC,UACd5M,KAAK6E,YAAY+H,UACjB5M,KAAK8E,YAAY8H,UAGlBX,eACC,OAAOjM,KAAK0M,UAGbG,mBACC,OAAO7M,KAAKkM,cAGbW,iBAAiB9I,GAChB,MAAM+I,GAAY9M,KAAKiM,WAAalI,GAAS/D,KAAKkM,cAClDlM,KAAKkM,cAAgBnI,EACjB+I,GACHhB,OAAOC,sBAAsB,IAAM/L,KAAKgM,QAI1CJ,cACC,OAAO5L,KAAK+M,SAAW/M,KAAKyJ,QAAQoB,IAAM,KAG3Ce,YAAYoB,GACC,OAARA,GACHhN,KAAK+M,UAAW,EAChB/M,KAAKwK,aAAazF,KAAKR,SAAU,IAEjCvE,KAAK+M,UAAW,EAChB/M,KAAKyJ,QAAQoB,IAAMmC,GAIrBnB,cACC,OAAO7L,KAAKiN,SAAWjN,KAAKgK,QAAQa,IAAM,KAG3CgB,YAAYmB,GACC,OAARA,GACHhN,KAAKiN,UAAW,EAChBjN,KAAKwK,aAAa7F,KAAKJ,SAAU,IAEjCvE,KAAKiN,UAAW,EAChBjN,KAAKgK,QAAQa,IAAMmC,GAIrBxF,YACC,OAAOxH,KAAKoK,SAAS8C,QAAQ,IAAIrO,GAAW2I,MAG7CA,UAAU2F,GACTnN,KAAKyM,QAAQU,EAAUnN,KAAKmL,QAG7BA,aACC,OAAOnL,KAAKoK,SAAS8C,QAAQ,IAAIrO,GAAWsM,OAG7CA,WAAWiC,GACVpN,KAAKyM,QAAQzM,KAAKwH,MAAO4F,wBH3DgB,CAAC/H,EAAQC,KACnD,MAAMP,EAAOM,EAAON,KAGpBO,GAAQ,EAGRP,EAAKlB,QAAQmB,SAAS7C,EAAqB,GAAjB8C,KAAKoE,IAAI/D,GACnCP,EAAKxB,SAASyB,SAAS7C,EAA+B,GAA3B8C,KAAKoE,IAAI/D,EAAOL,KAAKC,IAGhDH,EAAK9B,QAAQ+B,SAAS7C,EAA+B,GAA3B8C,KAAKoE,IAAI/D,EAAOL,KAAKC,IAC/CH,EAAKpC,SAASqC,SAAS7C,EAAqB,GAAjB8C,KAAKoE,IAAI/D,GACpC,MAAM6D,EAA8B,IAAVlE,KAAKC,GAC/BH,EAAK9B,QAAQ+B,SAAS3C,EAAqB,IAAjB4C,KAAKiE,IAAI5D,GAAe6D,EAClDpE,EAAKpC,SAASqC,SAAS3C,EAA+B,IAA3B4C,KAAKiE,IAAI5D,EAAOL,KAAKC,IAAaiE,EAG7DpE,EAAK5D,KAAK6D,SAASnD,EAAyB,GAArBoD,KAAKoE,IAAI/D,EAAO,GACvCP,EAAK5D,KAAK6D,SAAS7C,EAAyB,GAArB8C,KAAKoE,IAAI/D,EAAO,GAGvC,MAAM8D,EAA+B,IAAVnE,KAAKC,GAChCG,EAAOV,KAAKK,SAAS7C,EAA2B,IAAvB8C,KAAKoE,IAAI/D,EAAO,KAAc8D,kCI1JpBiE,GACnC,MAAMC,EAAU,IAAItE,GAAcqE,EAAWlD,OAAQkD,EAAWjD,SAASb,YASzE,OANA+D,EAAQC,WAAY,EACpBD,EAAQE,OAAS,IAAIC,EAAQ,GAAI,GAAI,GACrCH,EAAQI,YAAc,GACtBJ,EAAQK,YAAc,IACtBL,EAAQM,SAEDN"} \ No newline at end of file +{"version":3,"file":"skinview3d.bundle.js","sources":["../node_modules/three/src/core/EventDispatcher.js","../node_modules/three/src/math/MathUtils.js","../node_modules/three/src/math/Vector2.js","../node_modules/three/src/math/Matrix3.js","../node_modules/three/src/extras/ImageUtils.js","../node_modules/three/src/textures/Texture.js","../node_modules/three/src/math/Vector4.js","../node_modules/three/src/renderers/WebGLRenderTarget.js","../node_modules/three/src/math/Quaternion.js","../node_modules/three/src/math/Vector3.js","../node_modules/three/src/math/Matrix4.js","../node_modules/three/src/math/Euler.js","../node_modules/three/src/core/Layers.js","../node_modules/three/src/core/Object3D.js","../node_modules/three/src/scenes/Scene.js","../node_modules/three/src/math/Box3.js","../node_modules/three/src/math/Sphere.js","../node_modules/three/src/math/Ray.js","../node_modules/three/src/math/Plane.js","../node_modules/three/src/math/Triangle.js","../node_modules/three/src/math/Color.js","../node_modules/three/src/core/Face3.js","../node_modules/three/src/materials/Material.js","../node_modules/three/src/materials/MeshBasicMaterial.js","../node_modules/three/src/core/BufferAttribute.js","../node_modules/three/src/core/DirectGeometry.js","../node_modules/three/src/utils.js","../node_modules/three/src/core/BufferGeometry.js","../node_modules/three/src/objects/Mesh.js","../node_modules/three/src/core/Geometry.js","../node_modules/three/src/geometries/BoxGeometry.js","../node_modules/three/src/renderers/shaders/UniformsUtils.js","../node_modules/three/src/materials/ShaderMaterial.js","../node_modules/three/src/renderers/shaders/ShaderChunk/default_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/default_fragment.glsl.js","../node_modules/three/src/cameras/Camera.js","../node_modules/three/src/cameras/PerspectiveCamera.js","../node_modules/three/src/textures/DataTexture.js","../node_modules/three/src/math/Frustum.js","../node_modules/three/src/renderers/shaders/UniformsLib.js","../node_modules/three/src/renderers/webgl/WebGLAnimation.js","../node_modules/three/src/renderers/webgl/WebGLAttributes.js","../node_modules/three/src/geometries/PlaneGeometry.js","../node_modules/three/src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/alphamap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/aomap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/aomap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/begin_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/beginnormal_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/bsdfs.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clipping_planes_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clipping_planes_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clipping_planes_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clipping_planes_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/color_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/color_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/color_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/color_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/common.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/cube_uv_reflection_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/defaultnormal_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/displacementmap_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/emissivemap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/emissivemap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/encodings_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/encodings_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_common_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_physical_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/envmap_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/fog_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/fog_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/fog_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/fog_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/gradientmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lightmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_pars_begin.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_toon_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_toon_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_physical_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_fragment_begin.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_fragment_maps.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/lights_fragment_end.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/logdepthbuf_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/map_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/map_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/map_particle_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/metalnessmap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/metalnessmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/morphnormal_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/morphtarget_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/morphtarget_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_begin.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_maps.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/clearcoat_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/packing.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/premultiplied_alpha_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/project_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/dithering_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/dithering_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/roughnessmap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/roughnessmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/shadowmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/shadowmap_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/shadowmap_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/shadowmask_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/skinbase_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/skinning_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/skinning_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/skinnormal_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/specularmap_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/specularmap_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/tonemapping_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/tonemapping_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv2_pars_fragment.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv2_pars_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/uv2_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderChunk/worldpos_vertex.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/background_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/background_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/cube_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/cube_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/depth_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/depth_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/distanceRGBA_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/distanceRGBA_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/equirect_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/equirect_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/linedashed_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/linedashed_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshbasic_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshbasic_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshlambert_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshlambert_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshmatcap_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshmatcap_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshtoon_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshtoon_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshphong_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshphong_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshphysical_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/meshphysical_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/normal_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/normal_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/points_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/points_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/shadow_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/shadow_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/sprite_frag.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/sprite_vert.glsl.js","../node_modules/three/src/renderers/webgl/WebGLBackground.js","../node_modules/three/src/renderers/webgl/WebGLBufferRenderer.js","../node_modules/three/src/renderers/webgl/WebGLCapabilities.js","../node_modules/three/src/renderers/webgl/WebGLClipping.js","../node_modules/three/src/renderers/webgl/WebGLExtensions.js","../node_modules/three/src/renderers/webgl/WebGLGeometries.js","../node_modules/three/src/renderers/webgl/WebGLIndexedBufferRenderer.js","../node_modules/three/src/renderers/webgl/WebGLInfo.js","../node_modules/three/src/renderers/webgl/WebGLMorphtargets.js","../node_modules/three/src/renderers/webgl/WebGLObjects.js","../node_modules/three/src/textures/CubeTexture.js","../node_modules/three/src/textures/DataTexture2DArray.js","../node_modules/three/src/textures/DataTexture3D.js","../node_modules/three/src/renderers/shaders/ShaderLib.js","../node_modules/three/src/renderers/webgl/WebGLUniforms.js","../node_modules/three/src/renderers/webgl/WebGLShader.js","../node_modules/three/src/renderers/webgl/WebGLProgram.js","../node_modules/three/src/renderers/webgl/WebGLPrograms.js","../node_modules/three/src/renderers/webgl/WebGLProperties.js","../node_modules/three/src/renderers/webgl/WebGLRenderLists.js","../node_modules/three/src/renderers/webgl/WebGLLights.js","../node_modules/three/src/renderers/webgl/WebGLRenderStates.js","../node_modules/three/src/materials/MeshDepthMaterial.js","../node_modules/three/src/materials/MeshDistanceMaterial.js","../node_modules/three/src/renderers/webgl/WebGLShadowMap.js","../node_modules/three/src/renderers/shaders/ShaderLib/vsm_vert.glsl.js","../node_modules/three/src/renderers/shaders/ShaderLib/vsm_frag.glsl.js","../node_modules/three/src/renderers/webgl/WebGLState.js","../node_modules/three/src/renderers/webgl/WebGLTextures.js","../node_modules/three/src/renderers/webgl/WebGLUtils.js","../node_modules/three/src/cameras/ArrayCamera.js","../node_modules/three/src/objects/Group.js","../node_modules/three/src/renderers/webxr/WebXRController.js","../node_modules/three/src/renderers/webxr/WebXRManager.js","../node_modules/three/src/renderers/webgl/WebGLMaterials.js","../node_modules/three/src/renderers/WebGLRenderer.js","../node_modules/three/src/core/Clock.js","../node_modules/three/src/math/Spherical.js","../src/model.ts","../node_modules/skinview-utils/build/process.js","../node_modules/skinview-utils/build/load-image.js","../node_modules/skinview-utils/build/viewer-mixins.js","../src/animation.ts","../src/viewer.ts","../node_modules/three/examples/jsm/controls/OrbitControls.js","../src/orbit_controls.ts"],"sourcesContent":["/**\n * https://github.com/mrdoob/eventdispatcher.js/\n */\n\nfunction EventDispatcher() {}\n\nObject.assign( EventDispatcher.prototype, {\n\n\taddEventListener: function ( type, listener ) {\n\n\t\tif ( this._listeners === undefined ) this._listeners = {};\n\n\t\tvar listeners = this._listeners;\n\n\t\tif ( listeners[ type ] === undefined ) {\n\n\t\t\tlisteners[ type ] = [];\n\n\t\t}\n\n\t\tif ( listeners[ type ].indexOf( listener ) === - 1 ) {\n\n\t\t\tlisteners[ type ].push( listener );\n\n\t\t}\n\n\t},\n\n\thasEventListener: function ( type, listener ) {\n\n\t\tif ( this._listeners === undefined ) return false;\n\n\t\tvar listeners = this._listeners;\n\n\t\treturn listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1;\n\n\t},\n\n\tremoveEventListener: function ( type, listener ) {\n\n\t\tif ( this._listeners === undefined ) return;\n\n\t\tvar listeners = this._listeners;\n\t\tvar listenerArray = listeners[ type ];\n\n\t\tif ( listenerArray !== undefined ) {\n\n\t\t\tvar index = listenerArray.indexOf( listener );\n\n\t\t\tif ( index !== - 1 ) {\n\n\t\t\t\tlistenerArray.splice( index, 1 );\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\tdispatchEvent: function ( event ) {\n\n\t\tif ( this._listeners === undefined ) return;\n\n\t\tvar listeners = this._listeners;\n\t\tvar listenerArray = listeners[ event.type ];\n\n\t\tif ( listenerArray !== undefined ) {\n\n\t\t\tevent.target = this;\n\n\t\t\t// Make a copy, in case listeners are removed while iterating.\n\t\t\tvar array = listenerArray.slice( 0 );\n\n\t\t\tfor ( var i = 0, l = array.length; i < l; i ++ ) {\n\n\t\t\t\tarray[ i ].call( this, event );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n} );\n\n\nexport { EventDispatcher };\n","/**\n * @author alteredq / http://alteredqualia.com/\n * @author mrdoob / http://mrdoob.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author thezwap\n */\n\nvar _lut = [];\n\nfor ( var i = 0; i < 256; i ++ ) {\n\n\t_lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 );\n\n}\n\nvar MathUtils = {\n\n\tDEG2RAD: Math.PI / 180,\n\tRAD2DEG: 180 / Math.PI,\n\n\tgenerateUUID: function () {\n\n\t\t// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136\n\n\t\tvar d0 = Math.random() * 0xffffffff | 0;\n\t\tvar d1 = Math.random() * 0xffffffff | 0;\n\t\tvar d2 = Math.random() * 0xffffffff | 0;\n\t\tvar d3 = Math.random() * 0xffffffff | 0;\n\t\tvar uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' +\n\t\t\t_lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' +\n\t\t\t_lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +\n\t\t\t_lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];\n\n\t\t// .toUpperCase() here flattens concatenated strings to save heap memory space.\n\t\treturn uuid.toUpperCase();\n\n\t},\n\n\tclamp: function ( value, min, max ) {\n\n\t\treturn Math.max( min, Math.min( max, value ) );\n\n\t},\n\n\t// compute euclidian modulo of m % n\n\t// https://en.wikipedia.org/wiki/Modulo_operation\n\n\teuclideanModulo: function ( n, m ) {\n\n\t\treturn ( ( n % m ) + m ) % m;\n\n\t},\n\n\t// Linear mapping from range to range \n\n\tmapLinear: function ( x, a1, a2, b1, b2 ) {\n\n\t\treturn b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );\n\n\t},\n\n\t// https://en.wikipedia.org/wiki/Linear_interpolation\n\n\tlerp: function ( x, y, t ) {\n\n\t\treturn ( 1 - t ) * x + t * y;\n\n\t},\n\n\t// http://en.wikipedia.org/wiki/Smoothstep\n\n\tsmoothstep: function ( x, min, max ) {\n\n\t\tif ( x <= min ) return 0;\n\t\tif ( x >= max ) return 1;\n\n\t\tx = ( x - min ) / ( max - min );\n\n\t\treturn x * x * ( 3 - 2 * x );\n\n\t},\n\n\tsmootherstep: function ( x, min, max ) {\n\n\t\tif ( x <= min ) return 0;\n\t\tif ( x >= max ) return 1;\n\n\t\tx = ( x - min ) / ( max - min );\n\n\t\treturn x * x * x * ( x * ( x * 6 - 15 ) + 10 );\n\n\t},\n\n\t// Random integer from interval\n\n\trandInt: function ( low, high ) {\n\n\t\treturn low + Math.floor( Math.random() * ( high - low + 1 ) );\n\n\t},\n\n\t// Random float from interval\n\n\trandFloat: function ( low, high ) {\n\n\t\treturn low + Math.random() * ( high - low );\n\n\t},\n\n\t// Random float from <-range/2, range/2> interval\n\n\trandFloatSpread: function ( range ) {\n\n\t\treturn range * ( 0.5 - Math.random() );\n\n\t},\n\n\tdegToRad: function ( degrees ) {\n\n\t\treturn degrees * MathUtils.DEG2RAD;\n\n\t},\n\n\tradToDeg: function ( radians ) {\n\n\t\treturn radians * MathUtils.RAD2DEG;\n\n\t},\n\n\tisPowerOfTwo: function ( value ) {\n\n\t\treturn ( value & ( value - 1 ) ) === 0 && value !== 0;\n\n\t},\n\n\tceilPowerOfTwo: function ( value ) {\n\n\t\treturn Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) );\n\n\t},\n\n\tfloorPowerOfTwo: function ( value ) {\n\n\t\treturn Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) );\n\n\t},\n\n\tsetQuaternionFromProperEuler: function ( q, a, b, c, order ) {\n\n\t\t// Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles\n\n\t\t// rotations are applied to the axes in the order specified by 'order'\n\t\t// rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c'\n\t\t// angles are in radians\n\n\t\tvar cos = Math.cos;\n\t\tvar sin = Math.sin;\n\n\t\tvar c2 = cos( b / 2 );\n\t\tvar s2 = sin( b / 2 );\n\n\t\tvar c13 = cos( ( a + c ) / 2 );\n\t\tvar s13 = sin( ( a + c ) / 2 );\n\n\t\tvar c1_3 = cos( ( a - c ) / 2 );\n\t\tvar s1_3 = sin( ( a - c ) / 2 );\n\n\t\tvar c3_1 = cos( ( c - a ) / 2 );\n\t\tvar s3_1 = sin( ( c - a ) / 2 );\n\n\t\tswitch ( order ) {\n\n\t\t\tcase 'XYX':\n\t\t\t\tq.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tcase 'YZY':\n\t\t\t\tq.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZXZ':\n\t\t\t\tq.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tcase 'XZX':\n\t\t\t\tq.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tcase 'YXY':\n\t\t\t\tq.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZYZ':\n\t\t\t\tq.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tconsole.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );\n\n\t\t}\n\n\t}\n\n};\n\n\nexport { MathUtils };\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author philogb / http://blog.thejit.org/\n * @author egraether / http://egraether.com/\n * @author zz85 / http://www.lab4games.net/zz85/blog\n */\n\nfunction Vector2( x, y ) {\n\n\tthis.x = x || 0;\n\tthis.y = y || 0;\n\n}\n\nObject.defineProperties( Vector2.prototype, {\n\n\t\"width\": {\n\n\t\tget: function () {\n\n\t\t\treturn this.x;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis.x = value;\n\n\t\t}\n\n\t},\n\n\t\"height\": {\n\n\t\tget: function () {\n\n\t\t\treturn this.y;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis.y = value;\n\n\t\t}\n\n\t}\n\n} );\n\nObject.assign( Vector2.prototype, {\n\n\tisVector2: true,\n\n\tset: function ( x, y ) {\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\n\t\treturn this;\n\n\t},\n\n\tsetScalar: function ( scalar ) {\n\n\t\tthis.x = scalar;\n\t\tthis.y = scalar;\n\n\t\treturn this;\n\n\t},\n\n\tsetX: function ( x ) {\n\n\t\tthis.x = x;\n\n\t\treturn this;\n\n\t},\n\n\tsetY: function ( y ) {\n\n\t\tthis.y = y;\n\n\t\treturn this;\n\n\t},\n\n\tsetComponent: function ( index, value ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: this.x = value; break;\n\t\t\tcase 1: this.y = value; break;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tgetComponent: function ( index ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: return this.x;\n\t\t\tcase 1: return this.y;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.x, this.y );\n\n\t},\n\n\tcopy: function ( v ) {\n\n\t\tthis.x = v.x;\n\t\tthis.y = v.y;\n\n\t\treturn this;\n\n\t},\n\n\tadd: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\n\t\t\treturn this.addVectors( v, w );\n\n\t\t}\n\n\t\tthis.x += v.x;\n\t\tthis.y += v.y;\n\n\t\treturn this;\n\n\t},\n\n\taddScalar: function ( s ) {\n\n\t\tthis.x += s;\n\t\tthis.y += s;\n\n\t\treturn this;\n\n\t},\n\n\taddVectors: function ( a, b ) {\n\n\t\tthis.x = a.x + b.x;\n\t\tthis.y = a.y + b.y;\n\n\t\treturn this;\n\n\t},\n\n\taddScaledVector: function ( v, s ) {\n\n\t\tthis.x += v.x * s;\n\t\tthis.y += v.y * s;\n\n\t\treturn this;\n\n\t},\n\n\tsub: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\n\t\t\treturn this.subVectors( v, w );\n\n\t\t}\n\n\t\tthis.x -= v.x;\n\t\tthis.y -= v.y;\n\n\t\treturn this;\n\n\t},\n\n\tsubScalar: function ( s ) {\n\n\t\tthis.x -= s;\n\t\tthis.y -= s;\n\n\t\treturn this;\n\n\t},\n\n\tsubVectors: function ( a, b ) {\n\n\t\tthis.x = a.x - b.x;\n\t\tthis.y = a.y - b.y;\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( v ) {\n\n\t\tthis.x *= v.x;\n\t\tthis.y *= v.y;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( scalar ) {\n\n\t\tthis.x *= scalar;\n\t\tthis.y *= scalar;\n\n\t\treturn this;\n\n\t},\n\n\tdivide: function ( v ) {\n\n\t\tthis.x /= v.x;\n\t\tthis.y /= v.y;\n\n\t\treturn this;\n\n\t},\n\n\tdivideScalar: function ( scalar ) {\n\n\t\treturn this.multiplyScalar( 1 / scalar );\n\n\t},\n\n\tapplyMatrix3: function ( m ) {\n\n\t\tvar x = this.x, y = this.y;\n\t\tvar e = m.elements;\n\n\t\tthis.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ];\n\t\tthis.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ];\n\n\t\treturn this;\n\n\t},\n\n\tmin: function ( v ) {\n\n\t\tthis.x = Math.min( this.x, v.x );\n\t\tthis.y = Math.min( this.y, v.y );\n\n\t\treturn this;\n\n\t},\n\n\tmax: function ( v ) {\n\n\t\tthis.x = Math.max( this.x, v.x );\n\t\tthis.y = Math.max( this.y, v.y );\n\n\t\treturn this;\n\n\t},\n\n\tclamp: function ( min, max ) {\n\n\t\t// assumes min < max, componentwise\n\n\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\n\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampScalar: function ( minVal, maxVal ) {\n\n\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\n\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampLength: function ( min, max ) {\n\n\t\tvar length = this.length();\n\n\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\n\n\t},\n\n\tfloor: function () {\n\n\t\tthis.x = Math.floor( this.x );\n\t\tthis.y = Math.floor( this.y );\n\n\t\treturn this;\n\n\t},\n\n\tceil: function () {\n\n\t\tthis.x = Math.ceil( this.x );\n\t\tthis.y = Math.ceil( this.y );\n\n\t\treturn this;\n\n\t},\n\n\tround: function () {\n\n\t\tthis.x = Math.round( this.x );\n\t\tthis.y = Math.round( this.y );\n\n\t\treturn this;\n\n\t},\n\n\troundToZero: function () {\n\n\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\n\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\n\n\t\treturn this;\n\n\t},\n\n\tnegate: function () {\n\n\t\tthis.x = - this.x;\n\t\tthis.y = - this.y;\n\n\t\treturn this;\n\n\t},\n\n\tdot: function ( v ) {\n\n\t\treturn this.x * v.x + this.y * v.y;\n\n\t},\n\n\tcross: function ( v ) {\n\n\t\treturn this.x * v.y - this.y * v.x;\n\n\t},\n\n\tlengthSq: function () {\n\n\t\treturn this.x * this.x + this.y * this.y;\n\n\t},\n\n\tlength: function () {\n\n\t\treturn Math.sqrt( this.x * this.x + this.y * this.y );\n\n\t},\n\n\tmanhattanLength: function () {\n\n\t\treturn Math.abs( this.x ) + Math.abs( this.y );\n\n\t},\n\n\tnormalize: function () {\n\n\t\treturn this.divideScalar( this.length() || 1 );\n\n\t},\n\n\tangle: function () {\n\n\t\t// computes the angle in radians with respect to the positive x-axis\n\n\t\tvar angle = Math.atan2( - this.y, - this.x ) + Math.PI;\n\n\t\treturn angle;\n\n\t},\n\n\tdistanceTo: function ( v ) {\n\n\t\treturn Math.sqrt( this.distanceToSquared( v ) );\n\n\t},\n\n\tdistanceToSquared: function ( v ) {\n\n\t\tvar dx = this.x - v.x, dy = this.y - v.y;\n\t\treturn dx * dx + dy * dy;\n\n\t},\n\n\tmanhattanDistanceTo: function ( v ) {\n\n\t\treturn Math.abs( this.x - v.x ) + Math.abs( this.y - v.y );\n\n\t},\n\n\tsetLength: function ( length ) {\n\n\t\treturn this.normalize().multiplyScalar( length );\n\n\t},\n\n\tlerp: function ( v, alpha ) {\n\n\t\tthis.x += ( v.x - this.x ) * alpha;\n\t\tthis.y += ( v.y - this.y ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tlerpVectors: function ( v1, v2, alpha ) {\n\n\t\tthis.x = v1.x + ( v2.x - v1.x ) * alpha;\n\t\tthis.y = v1.y + ( v2.y - v1.y ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( v ) {\n\n\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) );\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis.x = array[ offset ];\n\t\tthis.y = array[ offset + 1 ];\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this.x;\n\t\tarray[ offset + 1 ] = this.y;\n\n\t\treturn array;\n\n\t},\n\n\tfromBufferAttribute: function ( attribute, index, offset ) {\n\n\t\tif ( offset !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' );\n\n\t\t}\n\n\t\tthis.x = attribute.getX( index );\n\t\tthis.y = attribute.getY( index );\n\n\t\treturn this;\n\n\t},\n\n\trotateAround: function ( center, angle ) {\n\n\t\tvar c = Math.cos( angle ), s = Math.sin( angle );\n\n\t\tvar x = this.x - center.x;\n\t\tvar y = this.y - center.y;\n\n\t\tthis.x = x * c - y * s + center.x;\n\t\tthis.y = x * s + y * c + center.y;\n\n\t\treturn this;\n\n\t},\n\n\trandom: function () {\n\n\t\tthis.x = Math.random();\n\t\tthis.y = Math.random();\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Vector2 };\n","/**\n * @author alteredq / http://alteredqualia.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author bhouston / http://clara.io\n * @author tschw\n */\n\nfunction Matrix3() {\n\n\tthis.elements = [\n\n\t\t1, 0, 0,\n\t\t0, 1, 0,\n\t\t0, 0, 1\n\n\t];\n\n\tif ( arguments.length > 0 ) {\n\n\t\tconsole.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' );\n\n\t}\n\n}\n\nObject.assign( Matrix3.prototype, {\n\n\tisMatrix3: true,\n\n\tset: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31;\n\t\tte[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32;\n\t\tte[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33;\n\n\t\treturn this;\n\n\t},\n\n\tidentity: function () {\n\n\t\tthis.set(\n\n\t\t\t1, 0, 0,\n\t\t\t0, 1, 0,\n\t\t\t0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().fromArray( this.elements );\n\n\t},\n\n\tcopy: function ( m ) {\n\n\t\tvar te = this.elements;\n\t\tvar me = m.elements;\n\n\t\tte[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ];\n\t\tte[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ];\n\t\tte[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ];\n\n\t\treturn this;\n\n\t},\n\n\textractBasis: function ( xAxis, yAxis, zAxis ) {\n\n\t\txAxis.setFromMatrix3Column( this, 0 );\n\t\tyAxis.setFromMatrix3Column( this, 1 );\n\t\tzAxis.setFromMatrix3Column( this, 2 );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromMatrix4: function ( m ) {\n\n\t\tvar me = m.elements;\n\n\t\tthis.set(\n\n\t\t\tme[ 0 ], me[ 4 ], me[ 8 ],\n\t\t\tme[ 1 ], me[ 5 ], me[ 9 ],\n\t\t\tme[ 2 ], me[ 6 ], me[ 10 ]\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( m ) {\n\n\t\treturn this.multiplyMatrices( this, m );\n\n\t},\n\n\tpremultiply: function ( m ) {\n\n\t\treturn this.multiplyMatrices( m, this );\n\n\t},\n\n\tmultiplyMatrices: function ( a, b ) {\n\n\t\tvar ae = a.elements;\n\t\tvar be = b.elements;\n\t\tvar te = this.elements;\n\n\t\tvar a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ];\n\t\tvar a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ];\n\t\tvar a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ];\n\n\t\tvar b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ];\n\t\tvar b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ];\n\t\tvar b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ];\n\n\t\tte[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;\n\t\tte[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;\n\t\tte[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;\n\n\t\tte[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;\n\t\tte[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;\n\t\tte[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;\n\n\t\tte[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;\n\t\tte[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;\n\t\tte[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( s ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s;\n\t\tte[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s;\n\t\tte[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s;\n\n\t\treturn this;\n\n\t},\n\n\tdeterminant: function () {\n\n\t\tvar te = this.elements;\n\n\t\tvar a = te[ 0 ], b = te[ 1 ], c = te[ 2 ],\n\t\t\td = te[ 3 ], e = te[ 4 ], f = te[ 5 ],\n\t\t\tg = te[ 6 ], h = te[ 7 ], i = te[ 8 ];\n\n\t\treturn a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g;\n\n\t},\n\n\tgetInverse: function ( matrix, throwOnDegenerate ) {\n\n\t\tif ( throwOnDegenerate !== undefined ) {\n\n\t\t\tconsole.warn( \"THREE.Matrix3: .getInverse() can no longer be configured to throw on degenerate.\" );\n\n\t\t}\n\n\t\tvar me = matrix.elements,\n\t\t\tte = this.elements,\n\n\t\t\tn11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ],\n\t\t\tn12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ],\n\t\t\tn13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ],\n\n\t\t\tt11 = n33 * n22 - n32 * n23,\n\t\t\tt12 = n32 * n13 - n33 * n12,\n\t\t\tt13 = n23 * n12 - n22 * n13,\n\n\t\t\tdet = n11 * t11 + n21 * t12 + n31 * t13;\n\n\t\tif ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );\n\n\t\tvar detInv = 1 / det;\n\n\t\tte[ 0 ] = t11 * detInv;\n\t\tte[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;\n\t\tte[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;\n\n\t\tte[ 3 ] = t12 * detInv;\n\t\tte[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;\n\t\tte[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;\n\n\t\tte[ 6 ] = t13 * detInv;\n\t\tte[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;\n\t\tte[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;\n\n\t\treturn this;\n\n\t},\n\n\ttranspose: function () {\n\n\t\tvar tmp, m = this.elements;\n\n\t\ttmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp;\n\t\ttmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp;\n\t\ttmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp;\n\n\t\treturn this;\n\n\t},\n\n\tgetNormalMatrix: function ( matrix4 ) {\n\n\t\treturn this.setFromMatrix4( matrix4 ).getInverse( this ).transpose();\n\n\t},\n\n\ttransposeIntoArray: function ( r ) {\n\n\t\tvar m = this.elements;\n\n\t\tr[ 0 ] = m[ 0 ];\n\t\tr[ 1 ] = m[ 3 ];\n\t\tr[ 2 ] = m[ 6 ];\n\t\tr[ 3 ] = m[ 1 ];\n\t\tr[ 4 ] = m[ 4 ];\n\t\tr[ 5 ] = m[ 7 ];\n\t\tr[ 6 ] = m[ 2 ];\n\t\tr[ 7 ] = m[ 5 ];\n\t\tr[ 8 ] = m[ 8 ];\n\n\t\treturn this;\n\n\t},\n\n\tsetUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) {\n\n\t\tvar c = Math.cos( rotation );\n\t\tvar s = Math.sin( rotation );\n\n\t\tthis.set(\n\t\t\tsx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx,\n\t\t\t- sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty,\n\t\t\t0, 0, 1\n\t\t);\n\n\t},\n\n\tscale: function ( sx, sy ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx;\n\t\tte[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy;\n\n\t\treturn this;\n\n\t},\n\n\trotate: function ( theta ) {\n\n\t\tvar c = Math.cos( theta );\n\t\tvar s = Math.sin( theta );\n\n\t\tvar te = this.elements;\n\n\t\tvar a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ];\n\t\tvar a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ];\n\n\t\tte[ 0 ] = c * a11 + s * a21;\n\t\tte[ 3 ] = c * a12 + s * a22;\n\t\tte[ 6 ] = c * a13 + s * a23;\n\n\t\tte[ 1 ] = - s * a11 + c * a21;\n\t\tte[ 4 ] = - s * a12 + c * a22;\n\t\tte[ 7 ] = - s * a13 + c * a23;\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( tx, ty ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ];\n\t\tte[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ];\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( matrix ) {\n\n\t\tvar te = this.elements;\n\t\tvar me = matrix.elements;\n\n\t\tfor ( var i = 0; i < 9; i ++ ) {\n\n\t\t\tif ( te[ i ] !== me[ i ] ) return false;\n\n\t\t}\n\n\t\treturn true;\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tfor ( var i = 0; i < 9; i ++ ) {\n\n\t\t\tthis.elements[ i ] = array[ i + offset ];\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tvar te = this.elements;\n\n\t\tarray[ offset ] = te[ 0 ];\n\t\tarray[ offset + 1 ] = te[ 1 ];\n\t\tarray[ offset + 2 ] = te[ 2 ];\n\n\t\tarray[ offset + 3 ] = te[ 3 ];\n\t\tarray[ offset + 4 ] = te[ 4 ];\n\t\tarray[ offset + 5 ] = te[ 5 ];\n\n\t\tarray[ offset + 6 ] = te[ 6 ];\n\t\tarray[ offset + 7 ] = te[ 7 ];\n\t\tarray[ offset + 8 ] = te[ 8 ];\n\n\t\treturn array;\n\n\t}\n\n} );\n\n\nexport { Matrix3 };\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author szimek / https://github.com/szimek/\n */\n\nvar _canvas;\n\nvar ImageUtils = {\n\n\tgetDataURL: function ( image ) {\n\n\t\tvar canvas;\n\n\t\tif ( typeof HTMLCanvasElement == 'undefined' ) {\n\n\t\t\treturn image.src;\n\n\t\t} else if ( image instanceof HTMLCanvasElement ) {\n\n\t\t\tcanvas = image;\n\n\t\t} else {\n\n\t\t\tif ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );\n\n\t\t\t_canvas.width = image.width;\n\t\t\t_canvas.height = image.height;\n\n\t\t\tvar context = _canvas.getContext( '2d' );\n\n\t\t\tif ( image instanceof ImageData ) {\n\n\t\t\t\tcontext.putImageData( image, 0, 0 );\n\n\t\t\t} else {\n\n\t\t\t\tcontext.drawImage( image, 0, 0, image.width, image.height );\n\n\t\t\t}\n\n\t\t\tcanvas = _canvas;\n\n\t\t}\n\n\t\tif ( canvas.width > 2048 || canvas.height > 2048 ) {\n\n\t\t\treturn canvas.toDataURL( 'image/jpeg', 0.6 );\n\n\t\t} else {\n\n\t\t\treturn canvas.toDataURL( 'image/png' );\n\n\t\t}\n\n\t}\n\n};\n\nexport { ImageUtils };\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author szimek / https://github.com/szimek/\n */\n\nimport { EventDispatcher } from '../core/EventDispatcher.js';\nimport {\n\tMirroredRepeatWrapping,\n\tClampToEdgeWrapping,\n\tRepeatWrapping,\n\tLinearEncoding,\n\tUnsignedByteType,\n\tRGBAFormat,\n\tLinearMipmapLinearFilter,\n\tLinearFilter,\n\tUVMapping\n} from '../constants.js';\nimport { MathUtils } from '../math/MathUtils.js';\nimport { Vector2 } from '../math/Vector2.js';\nimport { Matrix3 } from '../math/Matrix3.js';\nimport { ImageUtils } from '../extras/ImageUtils.js';\n\nvar textureId = 0;\n\nfunction Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {\n\n\tObject.defineProperty( this, 'id', { value: textureId ++ } );\n\n\tthis.uuid = MathUtils.generateUUID();\n\n\tthis.name = '';\n\n\tthis.image = image !== undefined ? image : Texture.DEFAULT_IMAGE;\n\tthis.mipmaps = [];\n\n\tthis.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING;\n\n\tthis.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping;\n\tthis.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping;\n\n\tthis.magFilter = magFilter !== undefined ? magFilter : LinearFilter;\n\tthis.minFilter = minFilter !== undefined ? minFilter : LinearMipmapLinearFilter;\n\n\tthis.anisotropy = anisotropy !== undefined ? anisotropy : 1;\n\n\tthis.format = format !== undefined ? format : RGBAFormat;\n\tthis.internalFormat = null;\n\tthis.type = type !== undefined ? type : UnsignedByteType;\n\n\tthis.offset = new Vector2( 0, 0 );\n\tthis.repeat = new Vector2( 1, 1 );\n\tthis.center = new Vector2( 0, 0 );\n\tthis.rotation = 0;\n\n\tthis.matrixAutoUpdate = true;\n\tthis.matrix = new Matrix3();\n\n\tthis.generateMipmaps = true;\n\tthis.premultiplyAlpha = false;\n\tthis.flipY = true;\n\tthis.unpackAlignment = 4;\t// valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml)\n\n\t// Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap.\n\t//\n\t// Also changing the encoding after already used by a Material will not automatically make the Material\n\t// update. You need to explicitly call Material.needsUpdate to trigger it to recompile.\n\tthis.encoding = encoding !== undefined ? encoding : LinearEncoding;\n\n\tthis.version = 0;\n\tthis.onUpdate = null;\n\n}\n\nTexture.DEFAULT_IMAGE = undefined;\nTexture.DEFAULT_MAPPING = UVMapping;\n\nTexture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: Texture,\n\n\tisTexture: true,\n\n\tupdateMatrix: function () {\n\n\t\tthis.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y );\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tthis.name = source.name;\n\n\t\tthis.image = source.image;\n\t\tthis.mipmaps = source.mipmaps.slice( 0 );\n\n\t\tthis.mapping = source.mapping;\n\n\t\tthis.wrapS = source.wrapS;\n\t\tthis.wrapT = source.wrapT;\n\n\t\tthis.magFilter = source.magFilter;\n\t\tthis.minFilter = source.minFilter;\n\n\t\tthis.anisotropy = source.anisotropy;\n\n\t\tthis.format = source.format;\n\t\tthis.internalFormat = source.internalFormat;\n\t\tthis.type = source.type;\n\n\t\tthis.offset.copy( source.offset );\n\t\tthis.repeat.copy( source.repeat );\n\t\tthis.center.copy( source.center );\n\t\tthis.rotation = source.rotation;\n\n\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\n\t\tthis.matrix.copy( source.matrix );\n\n\t\tthis.generateMipmaps = source.generateMipmaps;\n\t\tthis.premultiplyAlpha = source.premultiplyAlpha;\n\t\tthis.flipY = source.flipY;\n\t\tthis.unpackAlignment = source.unpackAlignment;\n\t\tthis.encoding = source.encoding;\n\n\t\treturn this;\n\n\t},\n\n\ttoJSON: function ( meta ) {\n\n\t\tvar isRootObject = ( meta === undefined || typeof meta === 'string' );\n\n\t\tif ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) {\n\n\t\t\treturn meta.textures[ this.uuid ];\n\n\t\t}\n\n\t\tvar output = {\n\n\t\t\tmetadata: {\n\t\t\t\tversion: 4.5,\n\t\t\t\ttype: 'Texture',\n\t\t\t\tgenerator: 'Texture.toJSON'\n\t\t\t},\n\n\t\t\tuuid: this.uuid,\n\t\t\tname: this.name,\n\n\t\t\tmapping: this.mapping,\n\n\t\t\trepeat: [ this.repeat.x, this.repeat.y ],\n\t\t\toffset: [ this.offset.x, this.offset.y ],\n\t\t\tcenter: [ this.center.x, this.center.y ],\n\t\t\trotation: this.rotation,\n\n\t\t\twrap: [ this.wrapS, this.wrapT ],\n\n\t\t\tformat: this.format,\n\t\t\ttype: this.type,\n\t\t\tencoding: this.encoding,\n\n\t\t\tminFilter: this.minFilter,\n\t\t\tmagFilter: this.magFilter,\n\t\t\tanisotropy: this.anisotropy,\n\n\t\t\tflipY: this.flipY,\n\n\t\t\tpremultiplyAlpha: this.premultiplyAlpha,\n\t\t\tunpackAlignment: this.unpackAlignment\n\n\t\t};\n\n\t\tif ( this.image !== undefined ) {\n\n\t\t\t// TODO: Move to THREE.Image\n\n\t\t\tvar image = this.image;\n\n\t\t\tif ( image.uuid === undefined ) {\n\n\t\t\t\timage.uuid = MathUtils.generateUUID(); // UGH\n\n\t\t\t}\n\n\t\t\tif ( ! isRootObject && meta.images[ image.uuid ] === undefined ) {\n\n\t\t\t\tvar url;\n\n\t\t\t\tif ( Array.isArray( image ) ) {\n\n\t\t\t\t\t// process array of images e.g. CubeTexture\n\n\t\t\t\t\turl = [];\n\n\t\t\t\t\tfor ( var i = 0, l = image.length; i < l; i ++ ) {\n\n\t\t\t\t\t\turl.push( ImageUtils.getDataURL( image[ i ] ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// process single image\n\n\t\t\t\t\turl = ImageUtils.getDataURL( image );\n\n\t\t\t\t}\n\n\t\t\t\tmeta.images[ image.uuid ] = {\n\t\t\t\t\tuuid: image.uuid,\n\t\t\t\t\turl: url\n\t\t\t\t};\n\n\t\t\t}\n\n\t\t\toutput.image = image.uuid;\n\n\t\t}\n\n\t\tif ( ! isRootObject ) {\n\n\t\t\tmeta.textures[ this.uuid ] = output;\n\n\t\t}\n\n\t\treturn output;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t},\n\n\ttransformUv: function ( uv ) {\n\n\t\tif ( this.mapping !== UVMapping ) return uv;\n\n\t\tuv.applyMatrix3( this.matrix );\n\n\t\tif ( uv.x < 0 || uv.x > 1 ) {\n\n\t\t\tswitch ( this.wrapS ) {\n\n\t\t\t\tcase RepeatWrapping:\n\n\t\t\t\t\tuv.x = uv.x - Math.floor( uv.x );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase ClampToEdgeWrapping:\n\n\t\t\t\t\tuv.x = uv.x < 0 ? 0 : 1;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MirroredRepeatWrapping:\n\n\t\t\t\t\tif ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) {\n\n\t\t\t\t\t\tuv.x = Math.ceil( uv.x ) - uv.x;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tuv.x = uv.x - Math.floor( uv.x );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( uv.y < 0 || uv.y > 1 ) {\n\n\t\t\tswitch ( this.wrapT ) {\n\n\t\t\t\tcase RepeatWrapping:\n\n\t\t\t\t\tuv.y = uv.y - Math.floor( uv.y );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase ClampToEdgeWrapping:\n\n\t\t\t\t\tuv.y = uv.y < 0 ? 0 : 1;\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase MirroredRepeatWrapping:\n\n\t\t\t\t\tif ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) {\n\n\t\t\t\t\t\tuv.y = Math.ceil( uv.y ) - uv.y;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tuv.y = uv.y - Math.floor( uv.y );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.flipY ) {\n\n\t\t\tuv.y = 1 - uv.y;\n\n\t\t}\n\n\t\treturn uv;\n\n\t}\n\n} );\n\nObject.defineProperty( Texture.prototype, \"needsUpdate\", {\n\n\tset: function ( value ) {\n\n\t\tif ( value === true ) this.version ++;\n\n\t}\n\n} );\n\n\nexport { Texture };\n","/**\n * @author supereggbert / http://www.paulbrunt.co.uk/\n * @author philogb / http://blog.thejit.org/\n * @author mikael emtinger / http://gomo.se/\n * @author egraether / http://egraether.com/\n * @author WestLangley / http://github.com/WestLangley\n */\n\nfunction Vector4( x, y, z, w ) {\n\n\tthis.x = x || 0;\n\tthis.y = y || 0;\n\tthis.z = z || 0;\n\tthis.w = ( w !== undefined ) ? w : 1;\n\n}\n\nObject.defineProperties( Vector4.prototype, {\n\n\t\"width\": {\n\n\t\tget: function () {\n\n\t\t\treturn this.z;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis.z = value;\n\n\t\t}\n\n\t},\n\n\t\"height\": {\n\n\t\tget: function () {\n\n\t\t\treturn this.w;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis.w = value;\n\n\t\t}\n\n\t}\n\n} );\n\nObject.assign( Vector4.prototype, {\n\n\tisVector4: true,\n\n\tset: function ( x, y, z, w ) {\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\t\tthis.w = w;\n\n\t\treturn this;\n\n\t},\n\n\tsetScalar: function ( scalar ) {\n\n\t\tthis.x = scalar;\n\t\tthis.y = scalar;\n\t\tthis.z = scalar;\n\t\tthis.w = scalar;\n\n\t\treturn this;\n\n\t},\n\n\tsetX: function ( x ) {\n\n\t\tthis.x = x;\n\n\t\treturn this;\n\n\t},\n\n\tsetY: function ( y ) {\n\n\t\tthis.y = y;\n\n\t\treturn this;\n\n\t},\n\n\tsetZ: function ( z ) {\n\n\t\tthis.z = z;\n\n\t\treturn this;\n\n\t},\n\n\tsetW: function ( w ) {\n\n\t\tthis.w = w;\n\n\t\treturn this;\n\n\t},\n\n\tsetComponent: function ( index, value ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: this.x = value; break;\n\t\t\tcase 1: this.y = value; break;\n\t\t\tcase 2: this.z = value; break;\n\t\t\tcase 3: this.w = value; break;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tgetComponent: function ( index ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: return this.x;\n\t\t\tcase 1: return this.y;\n\t\t\tcase 2: return this.z;\n\t\t\tcase 3: return this.w;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.x, this.y, this.z, this.w );\n\n\t},\n\n\tcopy: function ( v ) {\n\n\t\tthis.x = v.x;\n\t\tthis.y = v.y;\n\t\tthis.z = v.z;\n\t\tthis.w = ( v.w !== undefined ) ? v.w : 1;\n\n\t\treturn this;\n\n\t},\n\n\tadd: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\n\t\t\treturn this.addVectors( v, w );\n\n\t\t}\n\n\t\tthis.x += v.x;\n\t\tthis.y += v.y;\n\t\tthis.z += v.z;\n\t\tthis.w += v.w;\n\n\t\treturn this;\n\n\t},\n\n\taddScalar: function ( s ) {\n\n\t\tthis.x += s;\n\t\tthis.y += s;\n\t\tthis.z += s;\n\t\tthis.w += s;\n\n\t\treturn this;\n\n\t},\n\n\taddVectors: function ( a, b ) {\n\n\t\tthis.x = a.x + b.x;\n\t\tthis.y = a.y + b.y;\n\t\tthis.z = a.z + b.z;\n\t\tthis.w = a.w + b.w;\n\n\t\treturn this;\n\n\t},\n\n\taddScaledVector: function ( v, s ) {\n\n\t\tthis.x += v.x * s;\n\t\tthis.y += v.y * s;\n\t\tthis.z += v.z * s;\n\t\tthis.w += v.w * s;\n\n\t\treturn this;\n\n\t},\n\n\tsub: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\n\t\t\treturn this.subVectors( v, w );\n\n\t\t}\n\n\t\tthis.x -= v.x;\n\t\tthis.y -= v.y;\n\t\tthis.z -= v.z;\n\t\tthis.w -= v.w;\n\n\t\treturn this;\n\n\t},\n\n\tsubScalar: function ( s ) {\n\n\t\tthis.x -= s;\n\t\tthis.y -= s;\n\t\tthis.z -= s;\n\t\tthis.w -= s;\n\n\t\treturn this;\n\n\t},\n\n\tsubVectors: function ( a, b ) {\n\n\t\tthis.x = a.x - b.x;\n\t\tthis.y = a.y - b.y;\n\t\tthis.z = a.z - b.z;\n\t\tthis.w = a.w - b.w;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( scalar ) {\n\n\t\tthis.x *= scalar;\n\t\tthis.y *= scalar;\n\t\tthis.z *= scalar;\n\t\tthis.w *= scalar;\n\n\t\treturn this;\n\n\t},\n\n\tapplyMatrix4: function ( m ) {\n\n\t\tvar x = this.x, y = this.y, z = this.z, w = this.w;\n\t\tvar e = m.elements;\n\n\t\tthis.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w;\n\t\tthis.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w;\n\t\tthis.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w;\n\t\tthis.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w;\n\n\t\treturn this;\n\n\t},\n\n\tdivideScalar: function ( scalar ) {\n\n\t\treturn this.multiplyScalar( 1 / scalar );\n\n\t},\n\n\tsetAxisAngleFromQuaternion: function ( q ) {\n\n\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm\n\n\t\t// q is assumed to be normalized\n\n\t\tthis.w = 2 * Math.acos( q.w );\n\n\t\tvar s = Math.sqrt( 1 - q.w * q.w );\n\n\t\tif ( s < 0.0001 ) {\n\n\t\t\tthis.x = 1;\n\t\t\tthis.y = 0;\n\t\t\tthis.z = 0;\n\n\t\t} else {\n\n\t\t\tthis.x = q.x / s;\n\t\t\tthis.y = q.y / s;\n\t\t\tthis.z = q.z / s;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetAxisAngleFromRotationMatrix: function ( m ) {\n\n\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm\n\n\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\n\n\t\tvar angle, x, y, z,\t\t// variables for result\n\t\t\tepsilon = 0.01,\t\t// margin to allow for rounding errors\n\t\t\tepsilon2 = 0.1,\t\t// margin to distinguish between 0 and 180 degrees\n\n\t\t\tte = m.elements,\n\n\t\t\tm11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],\n\t\t\tm21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],\n\t\t\tm31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];\n\n\t\tif ( ( Math.abs( m12 - m21 ) < epsilon ) &&\n\t\t ( Math.abs( m13 - m31 ) < epsilon ) &&\n\t\t ( Math.abs( m23 - m32 ) < epsilon ) ) {\n\n\t\t\t// singularity found\n\t\t\t// first check for identity matrix which must have +1 for all terms\n\t\t\t// in leading diagonal and zero in other terms\n\n\t\t\tif ( ( Math.abs( m12 + m21 ) < epsilon2 ) &&\n\t\t\t ( Math.abs( m13 + m31 ) < epsilon2 ) &&\n\t\t\t ( Math.abs( m23 + m32 ) < epsilon2 ) &&\n\t\t\t ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {\n\n\t\t\t\t// this singularity is identity matrix so angle = 0\n\n\t\t\t\tthis.set( 1, 0, 0, 0 );\n\n\t\t\t\treturn this; // zero angle, arbitrary axis\n\n\t\t\t}\n\n\t\t\t// otherwise this singularity is angle = 180\n\n\t\t\tangle = Math.PI;\n\n\t\t\tvar xx = ( m11 + 1 ) / 2;\n\t\t\tvar yy = ( m22 + 1 ) / 2;\n\t\t\tvar zz = ( m33 + 1 ) / 2;\n\t\t\tvar xy = ( m12 + m21 ) / 4;\n\t\t\tvar xz = ( m13 + m31 ) / 4;\n\t\t\tvar yz = ( m23 + m32 ) / 4;\n\n\t\t\tif ( ( xx > yy ) && ( xx > zz ) ) {\n\n\t\t\t\t// m11 is the largest diagonal term\n\n\t\t\t\tif ( xx < epsilon ) {\n\n\t\t\t\t\tx = 0;\n\t\t\t\t\ty = 0.707106781;\n\t\t\t\t\tz = 0.707106781;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tx = Math.sqrt( xx );\n\t\t\t\t\ty = xy / x;\n\t\t\t\t\tz = xz / x;\n\n\t\t\t\t}\n\n\t\t\t} else if ( yy > zz ) {\n\n\t\t\t\t// m22 is the largest diagonal term\n\n\t\t\t\tif ( yy < epsilon ) {\n\n\t\t\t\t\tx = 0.707106781;\n\t\t\t\t\ty = 0;\n\t\t\t\t\tz = 0.707106781;\n\n\t\t\t\t} else {\n\n\t\t\t\t\ty = Math.sqrt( yy );\n\t\t\t\t\tx = xy / y;\n\t\t\t\t\tz = yz / y;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t// m33 is the largest diagonal term so base result on this\n\n\t\t\t\tif ( zz < epsilon ) {\n\n\t\t\t\t\tx = 0.707106781;\n\t\t\t\t\ty = 0.707106781;\n\t\t\t\t\tz = 0;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tz = Math.sqrt( zz );\n\t\t\t\t\tx = xz / z;\n\t\t\t\t\ty = yz / z;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.set( x, y, z, angle );\n\n\t\t\treturn this; // return 180 deg rotation\n\n\t\t}\n\n\t\t// as we have reached here there are no singularities so we can handle normally\n\n\t\tvar s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +\n\t\t ( m13 - m31 ) * ( m13 - m31 ) +\n\t\t ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize\n\n\t\tif ( Math.abs( s ) < 0.001 ) s = 1;\n\n\t\t// prevent divide by zero, should not happen if matrix is orthogonal and should be\n\t\t// caught by singularity test above, but I've left it in just in case\n\n\t\tthis.x = ( m32 - m23 ) / s;\n\t\tthis.y = ( m13 - m31 ) / s;\n\t\tthis.z = ( m21 - m12 ) / s;\n\t\tthis.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );\n\n\t\treturn this;\n\n\t},\n\n\tmin: function ( v ) {\n\n\t\tthis.x = Math.min( this.x, v.x );\n\t\tthis.y = Math.min( this.y, v.y );\n\t\tthis.z = Math.min( this.z, v.z );\n\t\tthis.w = Math.min( this.w, v.w );\n\n\t\treturn this;\n\n\t},\n\n\tmax: function ( v ) {\n\n\t\tthis.x = Math.max( this.x, v.x );\n\t\tthis.y = Math.max( this.y, v.y );\n\t\tthis.z = Math.max( this.z, v.z );\n\t\tthis.w = Math.max( this.w, v.w );\n\n\t\treturn this;\n\n\t},\n\n\tclamp: function ( min, max ) {\n\n\t\t// assumes min < max, componentwise\n\n\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\n\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\n\t\tthis.z = Math.max( min.z, Math.min( max.z, this.z ) );\n\t\tthis.w = Math.max( min.w, Math.min( max.w, this.w ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampScalar: function ( minVal, maxVal ) {\n\n\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\n\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\n\t\tthis.z = Math.max( minVal, Math.min( maxVal, this.z ) );\n\t\tthis.w = Math.max( minVal, Math.min( maxVal, this.w ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampLength: function ( min, max ) {\n\n\t\tvar length = this.length();\n\n\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\n\n\t},\n\n\tfloor: function () {\n\n\t\tthis.x = Math.floor( this.x );\n\t\tthis.y = Math.floor( this.y );\n\t\tthis.z = Math.floor( this.z );\n\t\tthis.w = Math.floor( this.w );\n\n\t\treturn this;\n\n\t},\n\n\tceil: function () {\n\n\t\tthis.x = Math.ceil( this.x );\n\t\tthis.y = Math.ceil( this.y );\n\t\tthis.z = Math.ceil( this.z );\n\t\tthis.w = Math.ceil( this.w );\n\n\t\treturn this;\n\n\t},\n\n\tround: function () {\n\n\t\tthis.x = Math.round( this.x );\n\t\tthis.y = Math.round( this.y );\n\t\tthis.z = Math.round( this.z );\n\t\tthis.w = Math.round( this.w );\n\n\t\treturn this;\n\n\t},\n\n\troundToZero: function () {\n\n\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\n\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\n\t\tthis.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );\n\t\tthis.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w );\n\n\t\treturn this;\n\n\t},\n\n\tnegate: function () {\n\n\t\tthis.x = - this.x;\n\t\tthis.y = - this.y;\n\t\tthis.z = - this.z;\n\t\tthis.w = - this.w;\n\n\t\treturn this;\n\n\t},\n\n\tdot: function ( v ) {\n\n\t\treturn this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;\n\n\t},\n\n\tlengthSq: function () {\n\n\t\treturn this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;\n\n\t},\n\n\tlength: function () {\n\n\t\treturn Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );\n\n\t},\n\n\tmanhattanLength: function () {\n\n\t\treturn Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );\n\n\t},\n\n\tnormalize: function () {\n\n\t\treturn this.divideScalar( this.length() || 1 );\n\n\t},\n\n\tsetLength: function ( length ) {\n\n\t\treturn this.normalize().multiplyScalar( length );\n\n\t},\n\n\tlerp: function ( v, alpha ) {\n\n\t\tthis.x += ( v.x - this.x ) * alpha;\n\t\tthis.y += ( v.y - this.y ) * alpha;\n\t\tthis.z += ( v.z - this.z ) * alpha;\n\t\tthis.w += ( v.w - this.w ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tlerpVectors: function ( v1, v2, alpha ) {\n\n\t\tthis.x = v1.x + ( v2.x - v1.x ) * alpha;\n\t\tthis.y = v1.y + ( v2.y - v1.y ) * alpha;\n\t\tthis.z = v1.z + ( v2.z - v1.z ) * alpha;\n\t\tthis.w = v1.w + ( v2.w - v1.w ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( v ) {\n\n\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) );\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis.x = array[ offset ];\n\t\tthis.y = array[ offset + 1 ];\n\t\tthis.z = array[ offset + 2 ];\n\t\tthis.w = array[ offset + 3 ];\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this.x;\n\t\tarray[ offset + 1 ] = this.y;\n\t\tarray[ offset + 2 ] = this.z;\n\t\tarray[ offset + 3 ] = this.w;\n\n\t\treturn array;\n\n\t},\n\n\tfromBufferAttribute: function ( attribute, index, offset ) {\n\n\t\tif ( offset !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' );\n\n\t\t}\n\n\t\tthis.x = attribute.getX( index );\n\t\tthis.y = attribute.getY( index );\n\t\tthis.z = attribute.getZ( index );\n\t\tthis.w = attribute.getW( index );\n\n\t\treturn this;\n\n\t},\n\n\trandom: function () {\n\n\t\tthis.x = Math.random();\n\t\tthis.y = Math.random();\n\t\tthis.z = Math.random();\n\t\tthis.w = Math.random();\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Vector4 };\n","import { EventDispatcher } from '../core/EventDispatcher.js';\nimport { Texture } from '../textures/Texture.js';\nimport { LinearFilter } from '../constants.js';\nimport { Vector4 } from '../math/Vector4.js';\n\n/**\n * @author szimek / https://github.com/szimek/\n * @author alteredq / http://alteredqualia.com/\n * @author Marius Kintel / https://github.com/kintel\n */\n\n/*\n In options, we can specify:\n * Texture parameters for an auto-generated target texture\n * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers\n*/\nfunction WebGLRenderTarget( width, height, options ) {\n\n\tthis.width = width;\n\tthis.height = height;\n\n\tthis.scissor = new Vector4( 0, 0, width, height );\n\tthis.scissorTest = false;\n\n\tthis.viewport = new Vector4( 0, 0, width, height );\n\n\toptions = options || {};\n\n\tthis.texture = new Texture( undefined, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding );\n\n\tthis.texture.image = {};\n\tthis.texture.image.width = width;\n\tthis.texture.image.height = height;\n\n\tthis.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false;\n\tthis.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter;\n\n\tthis.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;\n\tthis.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;\n\tthis.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null;\n\n}\n\nWebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: WebGLRenderTarget,\n\n\tisWebGLRenderTarget: true,\n\n\tsetSize: function ( width, height ) {\n\n\t\tif ( this.width !== width || this.height !== height ) {\n\n\t\t\tthis.width = width;\n\t\t\tthis.height = height;\n\n\t\t\tthis.texture.image.width = width;\n\t\t\tthis.texture.image.height = height;\n\n\t\t\tthis.dispose();\n\n\t\t}\n\n\t\tthis.viewport.set( 0, 0, width, height );\n\t\tthis.scissor.set( 0, 0, width, height );\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tthis.width = source.width;\n\t\tthis.height = source.height;\n\n\t\tthis.viewport.copy( source.viewport );\n\n\t\tthis.texture = source.texture.clone();\n\n\t\tthis.depthBuffer = source.depthBuffer;\n\t\tthis.stencilBuffer = source.stencilBuffer;\n\t\tthis.depthTexture = source.depthTexture;\n\n\t\treturn this;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t}\n\n} );\n\n\nexport { WebGLRenderTarget };\n","/**\n * @author mikael emtinger / http://gomo.se/\n * @author alteredq / http://alteredqualia.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author bhouston / http://clara.io\n */\n\nimport { MathUtils } from './MathUtils.js';\n\nfunction Quaternion( x, y, z, w ) {\n\n\tthis._x = x || 0;\n\tthis._y = y || 0;\n\tthis._z = z || 0;\n\tthis._w = ( w !== undefined ) ? w : 1;\n\n}\n\nObject.assign( Quaternion, {\n\n\tslerp: function ( qa, qb, qm, t ) {\n\n\t\treturn qm.copy( qa ).slerp( qb, t );\n\n\t},\n\n\tslerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) {\n\n\t\t// fuzz-free, array-based Quaternion SLERP operation\n\n\t\tvar x0 = src0[ srcOffset0 + 0 ],\n\t\t\ty0 = src0[ srcOffset0 + 1 ],\n\t\t\tz0 = src0[ srcOffset0 + 2 ],\n\t\t\tw0 = src0[ srcOffset0 + 3 ],\n\n\t\t\tx1 = src1[ srcOffset1 + 0 ],\n\t\t\ty1 = src1[ srcOffset1 + 1 ],\n\t\t\tz1 = src1[ srcOffset1 + 2 ],\n\t\t\tw1 = src1[ srcOffset1 + 3 ];\n\n\t\tif ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {\n\n\t\t\tvar s = 1 - t,\n\n\t\t\t\tcos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,\n\n\t\t\t\tdir = ( cos >= 0 ? 1 : - 1 ),\n\t\t\t\tsqrSin = 1 - cos * cos;\n\n\t\t\t// Skip the Slerp for tiny steps to avoid numeric problems:\n\t\t\tif ( sqrSin > Number.EPSILON ) {\n\n\t\t\t\tvar sin = Math.sqrt( sqrSin ),\n\t\t\t\t\tlen = Math.atan2( sin, cos * dir );\n\n\t\t\t\ts = Math.sin( s * len ) / sin;\n\t\t\t\tt = Math.sin( t * len ) / sin;\n\n\t\t\t}\n\n\t\t\tvar tDir = t * dir;\n\n\t\t\tx0 = x0 * s + x1 * tDir;\n\t\t\ty0 = y0 * s + y1 * tDir;\n\t\t\tz0 = z0 * s + z1 * tDir;\n\t\t\tw0 = w0 * s + w1 * tDir;\n\n\t\t\t// Normalize in case we just did a lerp:\n\t\t\tif ( s === 1 - t ) {\n\n\t\t\t\tvar f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );\n\n\t\t\t\tx0 *= f;\n\t\t\t\ty0 *= f;\n\t\t\t\tz0 *= f;\n\t\t\t\tw0 *= f;\n\n\t\t\t}\n\n\t\t}\n\n\t\tdst[ dstOffset ] = x0;\n\t\tdst[ dstOffset + 1 ] = y0;\n\t\tdst[ dstOffset + 2 ] = z0;\n\t\tdst[ dstOffset + 3 ] = w0;\n\n\t},\n\n\tmultiplyQuaternionsFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {\n\n\t\tvar x0 = src0[ srcOffset0 ];\n\t\tvar y0 = src0[ srcOffset0 + 1 ];\n\t\tvar z0 = src0[ srcOffset0 + 2 ];\n\t\tvar w0 = src0[ srcOffset0 + 3 ];\n\n\t\tvar x1 = src1[ srcOffset1 ];\n\t\tvar y1 = src1[ srcOffset1 + 1 ];\n\t\tvar z1 = src1[ srcOffset1 + 2 ];\n\t\tvar w1 = src1[ srcOffset1 + 3 ];\n\n\t\tdst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;\n\t\tdst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;\n\t\tdst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;\n\t\tdst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;\n\n\t\treturn dst;\n\n\t}\n\n} );\n\nObject.defineProperties( Quaternion.prototype, {\n\n\tx: {\n\n\t\tget: function () {\n\n\t\t\treturn this._x;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._x = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\ty: {\n\n\t\tget: function () {\n\n\t\t\treturn this._y;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._y = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\tz: {\n\n\t\tget: function () {\n\n\t\t\treturn this._z;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._z = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\tw: {\n\n\t\tget: function () {\n\n\t\t\treturn this._w;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._w = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t}\n\n} );\n\nObject.assign( Quaternion.prototype, {\n\n\tisQuaternion: true,\n\n\tset: function ( x, y, z, w ) {\n\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._z = z;\n\t\tthis._w = w;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this._x, this._y, this._z, this._w );\n\n\t},\n\n\tcopy: function ( quaternion ) {\n\n\t\tthis._x = quaternion.x;\n\t\tthis._y = quaternion.y;\n\t\tthis._z = quaternion.z;\n\t\tthis._w = quaternion.w;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromEuler: function ( euler, update ) {\n\n\t\tif ( ! ( euler && euler.isEuler ) ) {\n\n\t\t\tthrow new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );\n\n\t\t}\n\n\t\tvar x = euler._x, y = euler._y, z = euler._z, order = euler.order;\n\n\t\t// http://www.mathworks.com/matlabcentral/fileexchange/\n\t\t// \t20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/\n\t\t//\tcontent/SpinCalc.m\n\n\t\tvar cos = Math.cos;\n\t\tvar sin = Math.sin;\n\n\t\tvar c1 = cos( x / 2 );\n\t\tvar c2 = cos( y / 2 );\n\t\tvar c3 = cos( z / 2 );\n\n\t\tvar s1 = sin( x / 2 );\n\t\tvar s2 = sin( y / 2 );\n\t\tvar s3 = sin( z / 2 );\n\n\t\tswitch ( order ) {\n\n\t\t\tcase 'XYZ':\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tcase 'YXZ':\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZXY':\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZYX':\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tcase 'YZX':\n\t\t\t\tthis._x = s1 * c2 * c3 + c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 + s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 - s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 - s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tcase 'XZY':\n\t\t\t\tthis._x = s1 * c2 * c3 - c1 * s2 * s3;\n\t\t\t\tthis._y = c1 * s2 * c3 - s1 * c2 * s3;\n\t\t\t\tthis._z = c1 * c2 * s3 + s1 * s2 * c3;\n\t\t\t\tthis._w = c1 * c2 * c3 + s1 * s2 * s3;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tconsole.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );\n\n\t\t}\n\n\t\tif ( update !== false ) this._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromAxisAngle: function ( axis, angle ) {\n\n\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm\n\n\t\t// assumes axis is normalized\n\n\t\tvar halfAngle = angle / 2, s = Math.sin( halfAngle );\n\n\t\tthis._x = axis.x * s;\n\t\tthis._y = axis.y * s;\n\t\tthis._z = axis.z * s;\n\t\tthis._w = Math.cos( halfAngle );\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromRotationMatrix: function ( m ) {\n\n\t\t// http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm\n\n\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\n\n\t\tvar te = m.elements,\n\n\t\t\tm11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ],\n\t\t\tm21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ],\n\t\t\tm31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ],\n\n\t\t\ttrace = m11 + m22 + m33,\n\t\t\ts;\n\n\t\tif ( trace > 0 ) {\n\n\t\t\ts = 0.5 / Math.sqrt( trace + 1.0 );\n\n\t\t\tthis._w = 0.25 / s;\n\t\t\tthis._x = ( m32 - m23 ) * s;\n\t\t\tthis._y = ( m13 - m31 ) * s;\n\t\t\tthis._z = ( m21 - m12 ) * s;\n\n\t\t} else if ( m11 > m22 && m11 > m33 ) {\n\n\t\t\ts = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );\n\n\t\t\tthis._w = ( m32 - m23 ) / s;\n\t\t\tthis._x = 0.25 * s;\n\t\t\tthis._y = ( m12 + m21 ) / s;\n\t\t\tthis._z = ( m13 + m31 ) / s;\n\n\t\t} else if ( m22 > m33 ) {\n\n\t\t\ts = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );\n\n\t\t\tthis._w = ( m13 - m31 ) / s;\n\t\t\tthis._x = ( m12 + m21 ) / s;\n\t\t\tthis._y = 0.25 * s;\n\t\t\tthis._z = ( m23 + m32 ) / s;\n\n\t\t} else {\n\n\t\t\ts = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );\n\n\t\t\tthis._w = ( m21 - m12 ) / s;\n\t\t\tthis._x = ( m13 + m31 ) / s;\n\t\t\tthis._y = ( m23 + m32 ) / s;\n\t\t\tthis._z = 0.25 * s;\n\n\t\t}\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromUnitVectors: function ( vFrom, vTo ) {\n\n\t\t// assumes direction vectors vFrom and vTo are normalized\n\n\t\tvar EPS = 0.000001;\n\n\t\tvar r = vFrom.dot( vTo ) + 1;\n\n\t\tif ( r < EPS ) {\n\n\t\t\tr = 0;\n\n\t\t\tif ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) {\n\n\t\t\t\tthis._x = - vFrom.y;\n\t\t\t\tthis._y = vFrom.x;\n\t\t\t\tthis._z = 0;\n\t\t\t\tthis._w = r;\n\n\t\t\t} else {\n\n\t\t\t\tthis._x = 0;\n\t\t\t\tthis._y = - vFrom.z;\n\t\t\t\tthis._z = vFrom.y;\n\t\t\t\tthis._w = r;\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3\n\n\t\t\tthis._x = vFrom.y * vTo.z - vFrom.z * vTo.y;\n\t\t\tthis._y = vFrom.z * vTo.x - vFrom.x * vTo.z;\n\t\t\tthis._z = vFrom.x * vTo.y - vFrom.y * vTo.x;\n\t\t\tthis._w = r;\n\n\t\t}\n\n\t\treturn this.normalize();\n\n\t},\n\n\tangleTo: function ( q ) {\n\n\t\treturn 2 * Math.acos( Math.abs( MathUtils.clamp( this.dot( q ), - 1, 1 ) ) );\n\n\t},\n\n\trotateTowards: function ( q, step ) {\n\n\t\tvar angle = this.angleTo( q );\n\n\t\tif ( angle === 0 ) return this;\n\n\t\tvar t = Math.min( 1, step / angle );\n\n\t\tthis.slerp( q, t );\n\n\t\treturn this;\n\n\t},\n\n\tinverse: function () {\n\n\t\t// quaternion is assumed to have unit length\n\n\t\treturn this.conjugate();\n\n\t},\n\n\tconjugate: function () {\n\n\t\tthis._x *= - 1;\n\t\tthis._y *= - 1;\n\t\tthis._z *= - 1;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tdot: function ( v ) {\n\n\t\treturn this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;\n\n\t},\n\n\tlengthSq: function () {\n\n\t\treturn this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;\n\n\t},\n\n\tlength: function () {\n\n\t\treturn Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );\n\n\t},\n\n\tnormalize: function () {\n\n\t\tvar l = this.length();\n\n\t\tif ( l === 0 ) {\n\n\t\t\tthis._x = 0;\n\t\t\tthis._y = 0;\n\t\t\tthis._z = 0;\n\t\t\tthis._w = 1;\n\n\t\t} else {\n\n\t\t\tl = 1 / l;\n\n\t\t\tthis._x = this._x * l;\n\t\t\tthis._y = this._y * l;\n\t\t\tthis._z = this._z * l;\n\t\t\tthis._w = this._w * l;\n\n\t\t}\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( q, p ) {\n\n\t\tif ( p !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' );\n\t\t\treturn this.multiplyQuaternions( q, p );\n\n\t\t}\n\n\t\treturn this.multiplyQuaternions( this, q );\n\n\t},\n\n\tpremultiply: function ( q ) {\n\n\t\treturn this.multiplyQuaternions( q, this );\n\n\t},\n\n\tmultiplyQuaternions: function ( a, b ) {\n\n\t\t// from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm\n\n\t\tvar qax = a._x, qay = a._y, qaz = a._z, qaw = a._w;\n\t\tvar qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w;\n\n\t\tthis._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;\n\t\tthis._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;\n\t\tthis._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;\n\t\tthis._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tslerp: function ( qb, t ) {\n\n\t\tif ( t === 0 ) return this;\n\t\tif ( t === 1 ) return this.copy( qb );\n\n\t\tvar x = this._x, y = this._y, z = this._z, w = this._w;\n\n\t\t// http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/\n\n\t\tvar cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z;\n\n\t\tif ( cosHalfTheta < 0 ) {\n\n\t\t\tthis._w = - qb._w;\n\t\t\tthis._x = - qb._x;\n\t\t\tthis._y = - qb._y;\n\t\t\tthis._z = - qb._z;\n\n\t\t\tcosHalfTheta = - cosHalfTheta;\n\n\t\t} else {\n\n\t\t\tthis.copy( qb );\n\n\t\t}\n\n\t\tif ( cosHalfTheta >= 1.0 ) {\n\n\t\t\tthis._w = w;\n\t\t\tthis._x = x;\n\t\t\tthis._y = y;\n\t\t\tthis._z = z;\n\n\t\t\treturn this;\n\n\t\t}\n\n\t\tvar sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;\n\n\t\tif ( sqrSinHalfTheta <= Number.EPSILON ) {\n\n\t\t\tvar s = 1 - t;\n\t\t\tthis._w = s * w + t * this._w;\n\t\t\tthis._x = s * x + t * this._x;\n\t\t\tthis._y = s * y + t * this._y;\n\t\t\tthis._z = s * z + t * this._z;\n\n\t\t\tthis.normalize();\n\t\t\tthis._onChangeCallback();\n\n\t\t\treturn this;\n\n\t\t}\n\n\t\tvar sinHalfTheta = Math.sqrt( sqrSinHalfTheta );\n\t\tvar halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta );\n\t\tvar ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,\n\t\t\tratioB = Math.sin( t * halfTheta ) / sinHalfTheta;\n\n\t\tthis._w = ( w * ratioA + this._w * ratioB );\n\t\tthis._x = ( x * ratioA + this._x * ratioB );\n\t\tthis._y = ( y * ratioA + this._y * ratioB );\n\t\tthis._z = ( z * ratioA + this._z * ratioB );\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( quaternion ) {\n\n\t\treturn ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w );\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis._x = array[ offset ];\n\t\tthis._y = array[ offset + 1 ];\n\t\tthis._z = array[ offset + 2 ];\n\t\tthis._w = array[ offset + 3 ];\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this._x;\n\t\tarray[ offset + 1 ] = this._y;\n\t\tarray[ offset + 2 ] = this._z;\n\t\tarray[ offset + 3 ] = this._w;\n\n\t\treturn array;\n\n\t},\n\n\tfromBufferAttribute: function ( attribute, index ) {\n\n\t\tthis._x = attribute.getX( index );\n\t\tthis._y = attribute.getY( index );\n\t\tthis._z = attribute.getZ( index );\n\t\tthis._w = attribute.getW( index );\n\n\t\treturn this;\n\n\t},\n\n\t_onChange: function ( callback ) {\n\n\t\tthis._onChangeCallback = callback;\n\n\t\treturn this;\n\n\t},\n\n\t_onChangeCallback: function () {}\n\n} );\n\n\nexport { Quaternion };\n","import { MathUtils } from './MathUtils.js';\nimport { Quaternion } from './Quaternion.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author kile / http://kile.stravaganza.org/\n * @author philogb / http://blog.thejit.org/\n * @author mikael emtinger / http://gomo.se/\n * @author egraether / http://egraether.com/\n * @author WestLangley / http://github.com/WestLangley\n */\n\nvar _vector = new Vector3();\nvar _quaternion = new Quaternion();\n\nfunction Vector3( x, y, z ) {\n\n\tthis.x = x || 0;\n\tthis.y = y || 0;\n\tthis.z = z || 0;\n\n}\n\nObject.assign( Vector3.prototype, {\n\n\tisVector3: true,\n\n\tset: function ( x, y, z ) {\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\t\tthis.z = z;\n\n\t\treturn this;\n\n\t},\n\n\tsetScalar: function ( scalar ) {\n\n\t\tthis.x = scalar;\n\t\tthis.y = scalar;\n\t\tthis.z = scalar;\n\n\t\treturn this;\n\n\t},\n\n\tsetX: function ( x ) {\n\n\t\tthis.x = x;\n\n\t\treturn this;\n\n\t},\n\n\tsetY: function ( y ) {\n\n\t\tthis.y = y;\n\n\t\treturn this;\n\n\t},\n\n\tsetZ: function ( z ) {\n\n\t\tthis.z = z;\n\n\t\treturn this;\n\n\t},\n\n\tsetComponent: function ( index, value ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: this.x = value; break;\n\t\t\tcase 1: this.y = value; break;\n\t\t\tcase 2: this.z = value; break;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tgetComponent: function ( index ) {\n\n\t\tswitch ( index ) {\n\n\t\t\tcase 0: return this.x;\n\t\t\tcase 1: return this.y;\n\t\t\tcase 2: return this.z;\n\t\t\tdefault: throw new Error( 'index is out of range: ' + index );\n\n\t\t}\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.x, this.y, this.z );\n\n\t},\n\n\tcopy: function ( v ) {\n\n\t\tthis.x = v.x;\n\t\tthis.y = v.y;\n\t\tthis.z = v.z;\n\n\t\treturn this;\n\n\t},\n\n\tadd: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' );\n\t\t\treturn this.addVectors( v, w );\n\n\t\t}\n\n\t\tthis.x += v.x;\n\t\tthis.y += v.y;\n\t\tthis.z += v.z;\n\n\t\treturn this;\n\n\t},\n\n\taddScalar: function ( s ) {\n\n\t\tthis.x += s;\n\t\tthis.y += s;\n\t\tthis.z += s;\n\n\t\treturn this;\n\n\t},\n\n\taddVectors: function ( a, b ) {\n\n\t\tthis.x = a.x + b.x;\n\t\tthis.y = a.y + b.y;\n\t\tthis.z = a.z + b.z;\n\n\t\treturn this;\n\n\t},\n\n\taddScaledVector: function ( v, s ) {\n\n\t\tthis.x += v.x * s;\n\t\tthis.y += v.y * s;\n\t\tthis.z += v.z * s;\n\n\t\treturn this;\n\n\t},\n\n\tsub: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' );\n\t\t\treturn this.subVectors( v, w );\n\n\t\t}\n\n\t\tthis.x -= v.x;\n\t\tthis.y -= v.y;\n\t\tthis.z -= v.z;\n\n\t\treturn this;\n\n\t},\n\n\tsubScalar: function ( s ) {\n\n\t\tthis.x -= s;\n\t\tthis.y -= s;\n\t\tthis.z -= s;\n\n\t\treturn this;\n\n\t},\n\n\tsubVectors: function ( a, b ) {\n\n\t\tthis.x = a.x - b.x;\n\t\tthis.y = a.y - b.y;\n\t\tthis.z = a.z - b.z;\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' );\n\t\t\treturn this.multiplyVectors( v, w );\n\n\t\t}\n\n\t\tthis.x *= v.x;\n\t\tthis.y *= v.y;\n\t\tthis.z *= v.z;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( scalar ) {\n\n\t\tthis.x *= scalar;\n\t\tthis.y *= scalar;\n\t\tthis.z *= scalar;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyVectors: function ( a, b ) {\n\n\t\tthis.x = a.x * b.x;\n\t\tthis.y = a.y * b.y;\n\t\tthis.z = a.z * b.z;\n\n\t\treturn this;\n\n\t},\n\n\tapplyEuler: function ( euler ) {\n\n\t\tif ( ! ( euler && euler.isEuler ) ) {\n\n\t\t\tconsole.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' );\n\n\t\t}\n\n\t\treturn this.applyQuaternion( _quaternion.setFromEuler( euler ) );\n\n\t},\n\n\tapplyAxisAngle: function ( axis, angle ) {\n\n\t\treturn this.applyQuaternion( _quaternion.setFromAxisAngle( axis, angle ) );\n\n\t},\n\n\tapplyMatrix3: function ( m ) {\n\n\t\tvar x = this.x, y = this.y, z = this.z;\n\t\tvar e = m.elements;\n\n\t\tthis.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z;\n\t\tthis.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z;\n\t\tthis.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z;\n\n\t\treturn this;\n\n\t},\n\n\tapplyNormalMatrix: function ( m ) {\n\n\t\treturn this.applyMatrix3( m ).normalize();\n\n\t},\n\n\tapplyMatrix4: function ( m ) {\n\n\t\tvar x = this.x, y = this.y, z = this.z;\n\t\tvar e = m.elements;\n\n\t\tvar w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] );\n\n\t\tthis.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w;\n\t\tthis.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w;\n\t\tthis.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w;\n\n\t\treturn this;\n\n\t},\n\n\tapplyQuaternion: function ( q ) {\n\n\t\tvar x = this.x, y = this.y, z = this.z;\n\t\tvar qx = q.x, qy = q.y, qz = q.z, qw = q.w;\n\n\t\t// calculate quat * vector\n\n\t\tvar ix = qw * x + qy * z - qz * y;\n\t\tvar iy = qw * y + qz * x - qx * z;\n\t\tvar iz = qw * z + qx * y - qy * x;\n\t\tvar iw = - qx * x - qy * y - qz * z;\n\n\t\t// calculate result * inverse quat\n\n\t\tthis.x = ix * qw + iw * - qx + iy * - qz - iz * - qy;\n\t\tthis.y = iy * qw + iw * - qy + iz * - qx - ix * - qz;\n\t\tthis.z = iz * qw + iw * - qz + ix * - qy - iy * - qx;\n\n\t\treturn this;\n\n\t},\n\n\tproject: function ( camera ) {\n\n\t\treturn this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );\n\n\t},\n\n\tunproject: function ( camera ) {\n\n\t\treturn this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );\n\n\t},\n\n\ttransformDirection: function ( m ) {\n\n\t\t// input: THREE.Matrix4 affine matrix\n\t\t// vector interpreted as a direction\n\n\t\tvar x = this.x, y = this.y, z = this.z;\n\t\tvar e = m.elements;\n\n\t\tthis.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z;\n\t\tthis.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z;\n\t\tthis.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z;\n\n\t\treturn this.normalize();\n\n\t},\n\n\tdivide: function ( v ) {\n\n\t\tthis.x /= v.x;\n\t\tthis.y /= v.y;\n\t\tthis.z /= v.z;\n\n\t\treturn this;\n\n\t},\n\n\tdivideScalar: function ( scalar ) {\n\n\t\treturn this.multiplyScalar( 1 / scalar );\n\n\t},\n\n\tmin: function ( v ) {\n\n\t\tthis.x = Math.min( this.x, v.x );\n\t\tthis.y = Math.min( this.y, v.y );\n\t\tthis.z = Math.min( this.z, v.z );\n\n\t\treturn this;\n\n\t},\n\n\tmax: function ( v ) {\n\n\t\tthis.x = Math.max( this.x, v.x );\n\t\tthis.y = Math.max( this.y, v.y );\n\t\tthis.z = Math.max( this.z, v.z );\n\n\t\treturn this;\n\n\t},\n\n\tclamp: function ( min, max ) {\n\n\t\t// assumes min < max, componentwise\n\n\t\tthis.x = Math.max( min.x, Math.min( max.x, this.x ) );\n\t\tthis.y = Math.max( min.y, Math.min( max.y, this.y ) );\n\t\tthis.z = Math.max( min.z, Math.min( max.z, this.z ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampScalar: function ( minVal, maxVal ) {\n\n\t\tthis.x = Math.max( minVal, Math.min( maxVal, this.x ) );\n\t\tthis.y = Math.max( minVal, Math.min( maxVal, this.y ) );\n\t\tthis.z = Math.max( minVal, Math.min( maxVal, this.z ) );\n\n\t\treturn this;\n\n\t},\n\n\tclampLength: function ( min, max ) {\n\n\t\tvar length = this.length();\n\n\t\treturn this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) );\n\n\t},\n\n\tfloor: function () {\n\n\t\tthis.x = Math.floor( this.x );\n\t\tthis.y = Math.floor( this.y );\n\t\tthis.z = Math.floor( this.z );\n\n\t\treturn this;\n\n\t},\n\n\tceil: function () {\n\n\t\tthis.x = Math.ceil( this.x );\n\t\tthis.y = Math.ceil( this.y );\n\t\tthis.z = Math.ceil( this.z );\n\n\t\treturn this;\n\n\t},\n\n\tround: function () {\n\n\t\tthis.x = Math.round( this.x );\n\t\tthis.y = Math.round( this.y );\n\t\tthis.z = Math.round( this.z );\n\n\t\treturn this;\n\n\t},\n\n\troundToZero: function () {\n\n\t\tthis.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x );\n\t\tthis.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y );\n\t\tthis.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z );\n\n\t\treturn this;\n\n\t},\n\n\tnegate: function () {\n\n\t\tthis.x = - this.x;\n\t\tthis.y = - this.y;\n\t\tthis.z = - this.z;\n\n\t\treturn this;\n\n\t},\n\n\tdot: function ( v ) {\n\n\t\treturn this.x * v.x + this.y * v.y + this.z * v.z;\n\n\t},\n\n\t// TODO lengthSquared?\n\n\tlengthSq: function () {\n\n\t\treturn this.x * this.x + this.y * this.y + this.z * this.z;\n\n\t},\n\n\tlength: function () {\n\n\t\treturn Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z );\n\n\t},\n\n\tmanhattanLength: function () {\n\n\t\treturn Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );\n\n\t},\n\n\tnormalize: function () {\n\n\t\treturn this.divideScalar( this.length() || 1 );\n\n\t},\n\n\tsetLength: function ( length ) {\n\n\t\treturn this.normalize().multiplyScalar( length );\n\n\t},\n\n\tlerp: function ( v, alpha ) {\n\n\t\tthis.x += ( v.x - this.x ) * alpha;\n\t\tthis.y += ( v.y - this.y ) * alpha;\n\t\tthis.z += ( v.z - this.z ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tlerpVectors: function ( v1, v2, alpha ) {\n\n\t\tthis.x = v1.x + ( v2.x - v1.x ) * alpha;\n\t\tthis.y = v1.y + ( v2.y - v1.y ) * alpha;\n\t\tthis.z = v1.z + ( v2.z - v1.z ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tcross: function ( v, w ) {\n\n\t\tif ( w !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' );\n\t\t\treturn this.crossVectors( v, w );\n\n\t\t}\n\n\t\treturn this.crossVectors( this, v );\n\n\t},\n\n\tcrossVectors: function ( a, b ) {\n\n\t\tvar ax = a.x, ay = a.y, az = a.z;\n\t\tvar bx = b.x, by = b.y, bz = b.z;\n\n\t\tthis.x = ay * bz - az * by;\n\t\tthis.y = az * bx - ax * bz;\n\t\tthis.z = ax * by - ay * bx;\n\n\t\treturn this;\n\n\t},\n\n\tprojectOnVector: function ( v ) {\n\n\t\tvar denominator = v.lengthSq();\n\n\t\tif ( denominator === 0 ) return this.set( 0, 0, 0 );\n\n\t\tvar scalar = v.dot( this ) / denominator;\n\n\t\treturn this.copy( v ).multiplyScalar( scalar );\n\n\t},\n\n\tprojectOnPlane: function ( planeNormal ) {\n\n\t\t_vector.copy( this ).projectOnVector( planeNormal );\n\n\t\treturn this.sub( _vector );\n\n\t},\n\n\treflect: function ( normal ) {\n\n\t\t// reflect incident vector off plane orthogonal to normal\n\t\t// normal is assumed to have unit length\n\n\t\treturn this.sub( _vector.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) );\n\n\t},\n\n\tangleTo: function ( v ) {\n\n\t\tvar denominator = Math.sqrt( this.lengthSq() * v.lengthSq() );\n\n\t\tif ( denominator === 0 ) return Math.PI / 2;\n\n\t\tvar theta = this.dot( v ) / denominator;\n\n\t\t// clamp, to handle numerical problems\n\n\t\treturn Math.acos( MathUtils.clamp( theta, - 1, 1 ) );\n\n\t},\n\n\tdistanceTo: function ( v ) {\n\n\t\treturn Math.sqrt( this.distanceToSquared( v ) );\n\n\t},\n\n\tdistanceToSquared: function ( v ) {\n\n\t\tvar dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z;\n\n\t\treturn dx * dx + dy * dy + dz * dz;\n\n\t},\n\n\tmanhattanDistanceTo: function ( v ) {\n\n\t\treturn Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z );\n\n\t},\n\n\tsetFromSpherical: function ( s ) {\n\n\t\treturn this.setFromSphericalCoords( s.radius, s.phi, s.theta );\n\n\t},\n\n\tsetFromSphericalCoords: function ( radius, phi, theta ) {\n\n\t\tvar sinPhiRadius = Math.sin( phi ) * radius;\n\n\t\tthis.x = sinPhiRadius * Math.sin( theta );\n\t\tthis.y = Math.cos( phi ) * radius;\n\t\tthis.z = sinPhiRadius * Math.cos( theta );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromCylindrical: function ( c ) {\n\n\t\treturn this.setFromCylindricalCoords( c.radius, c.theta, c.y );\n\n\t},\n\n\tsetFromCylindricalCoords: function ( radius, theta, y ) {\n\n\t\tthis.x = radius * Math.sin( theta );\n\t\tthis.y = y;\n\t\tthis.z = radius * Math.cos( theta );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromMatrixPosition: function ( m ) {\n\n\t\tvar e = m.elements;\n\n\t\tthis.x = e[ 12 ];\n\t\tthis.y = e[ 13 ];\n\t\tthis.z = e[ 14 ];\n\n\t\treturn this;\n\n\t},\n\n\tsetFromMatrixScale: function ( m ) {\n\n\t\tvar sx = this.setFromMatrixColumn( m, 0 ).length();\n\t\tvar sy = this.setFromMatrixColumn( m, 1 ).length();\n\t\tvar sz = this.setFromMatrixColumn( m, 2 ).length();\n\n\t\tthis.x = sx;\n\t\tthis.y = sy;\n\t\tthis.z = sz;\n\n\t\treturn this;\n\n\t},\n\n\tsetFromMatrixColumn: function ( m, index ) {\n\n\t\treturn this.fromArray( m.elements, index * 4 );\n\n\t},\n\n\tsetFromMatrix3Column: function ( m, index ) {\n\n\t\treturn this.fromArray( m.elements, index * 3 );\n\n\t},\n\n\tequals: function ( v ) {\n\n\t\treturn ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis.x = array[ offset ];\n\t\tthis.y = array[ offset + 1 ];\n\t\tthis.z = array[ offset + 2 ];\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this.x;\n\t\tarray[ offset + 1 ] = this.y;\n\t\tarray[ offset + 2 ] = this.z;\n\n\t\treturn array;\n\n\t},\n\n\tfromBufferAttribute: function ( attribute, index, offset ) {\n\n\t\tif ( offset !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' );\n\n\t\t}\n\n\t\tthis.x = attribute.getX( index );\n\t\tthis.y = attribute.getY( index );\n\t\tthis.z = attribute.getZ( index );\n\n\t\treturn this;\n\n\t},\n\n\trandom: function () {\n\n\t\tthis.x = Math.random();\n\t\tthis.y = Math.random();\n\t\tthis.z = Math.random();\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Vector3 };\n","import { Vector3 } from './Vector3.js';\n\nvar _v1 = new Vector3();\nvar _m1 = new Matrix4();\nvar _zero = new Vector3( 0, 0, 0 );\nvar _one = new Vector3( 1, 1, 1 );\nvar _x = new Vector3();\nvar _y = new Vector3();\nvar _z = new Vector3();\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author supereggbert / http://www.paulbrunt.co.uk/\n * @author philogb / http://blog.thejit.org/\n * @author jordi_ros / http://plattsoft.com\n * @author D1plo1d / http://github.com/D1plo1d\n * @author alteredq / http://alteredqualia.com/\n * @author mikael emtinger / http://gomo.se/\n * @author timknip / http://www.floorplanner.com/\n * @author bhouston / http://clara.io\n * @author WestLangley / http://github.com/WestLangley\n */\n\nfunction Matrix4() {\n\n\tthis.elements = [\n\n\t\t1, 0, 0, 0,\n\t\t0, 1, 0, 0,\n\t\t0, 0, 1, 0,\n\t\t0, 0, 0, 1\n\n\t];\n\n\tif ( arguments.length > 0 ) {\n\n\t\tconsole.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' );\n\n\t}\n\n}\n\nObject.assign( Matrix4.prototype, {\n\n\tisMatrix4: true,\n\n\tset: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14;\n\t\tte[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24;\n\t\tte[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34;\n\t\tte[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44;\n\n\t\treturn this;\n\n\t},\n\n\tidentity: function () {\n\n\t\tthis.set(\n\n\t\t\t1, 0, 0, 0,\n\t\t\t0, 1, 0, 0,\n\t\t\t0, 0, 1, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new Matrix4().fromArray( this.elements );\n\n\t},\n\n\tcopy: function ( m ) {\n\n\t\tvar te = this.elements;\n\t\tvar me = m.elements;\n\n\t\tte[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ];\n\t\tte[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ];\n\t\tte[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ];\n\t\tte[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ];\n\n\t\treturn this;\n\n\t},\n\n\tcopyPosition: function ( m ) {\n\n\t\tvar te = this.elements, me = m.elements;\n\n\t\tte[ 12 ] = me[ 12 ];\n\t\tte[ 13 ] = me[ 13 ];\n\t\tte[ 14 ] = me[ 14 ];\n\n\t\treturn this;\n\n\t},\n\n\textractBasis: function ( xAxis, yAxis, zAxis ) {\n\n\t\txAxis.setFromMatrixColumn( this, 0 );\n\t\tyAxis.setFromMatrixColumn( this, 1 );\n\t\tzAxis.setFromMatrixColumn( this, 2 );\n\n\t\treturn this;\n\n\t},\n\n\tmakeBasis: function ( xAxis, yAxis, zAxis ) {\n\n\t\tthis.set(\n\t\t\txAxis.x, yAxis.x, zAxis.x, 0,\n\t\t\txAxis.y, yAxis.y, zAxis.y, 0,\n\t\t\txAxis.z, yAxis.z, zAxis.z, 0,\n\t\t\t0, 0, 0, 1\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\textractRotation: function ( m ) {\n\n\t\t// this method does not support reflection matrices\n\n\t\tvar te = this.elements;\n\t\tvar me = m.elements;\n\n\t\tvar scaleX = 1 / _v1.setFromMatrixColumn( m, 0 ).length();\n\t\tvar scaleY = 1 / _v1.setFromMatrixColumn( m, 1 ).length();\n\t\tvar scaleZ = 1 / _v1.setFromMatrixColumn( m, 2 ).length();\n\n\t\tte[ 0 ] = me[ 0 ] * scaleX;\n\t\tte[ 1 ] = me[ 1 ] * scaleX;\n\t\tte[ 2 ] = me[ 2 ] * scaleX;\n\t\tte[ 3 ] = 0;\n\n\t\tte[ 4 ] = me[ 4 ] * scaleY;\n\t\tte[ 5 ] = me[ 5 ] * scaleY;\n\t\tte[ 6 ] = me[ 6 ] * scaleY;\n\t\tte[ 7 ] = 0;\n\n\t\tte[ 8 ] = me[ 8 ] * scaleZ;\n\t\tte[ 9 ] = me[ 9 ] * scaleZ;\n\t\tte[ 10 ] = me[ 10 ] * scaleZ;\n\t\tte[ 11 ] = 0;\n\n\t\tte[ 12 ] = 0;\n\t\tte[ 13 ] = 0;\n\t\tte[ 14 ] = 0;\n\t\tte[ 15 ] = 1;\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationFromEuler: function ( euler ) {\n\n\t\tif ( ! ( euler && euler.isEuler ) ) {\n\n\t\t\tconsole.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' );\n\n\t\t}\n\n\t\tvar te = this.elements;\n\n\t\tvar x = euler.x, y = euler.y, z = euler.z;\n\t\tvar a = Math.cos( x ), b = Math.sin( x );\n\t\tvar c = Math.cos( y ), d = Math.sin( y );\n\t\tvar e = Math.cos( z ), f = Math.sin( z );\n\n\t\tif ( euler.order === 'XYZ' ) {\n\n\t\t\tvar ae = a * e, af = a * f, be = b * e, bf = b * f;\n\n\t\t\tte[ 0 ] = c * e;\n\t\t\tte[ 4 ] = - c * f;\n\t\t\tte[ 8 ] = d;\n\n\t\t\tte[ 1 ] = af + be * d;\n\t\t\tte[ 5 ] = ae - bf * d;\n\t\t\tte[ 9 ] = - b * c;\n\n\t\t\tte[ 2 ] = bf - ae * d;\n\t\t\tte[ 6 ] = be + af * d;\n\t\t\tte[ 10 ] = a * c;\n\n\t\t} else if ( euler.order === 'YXZ' ) {\n\n\t\t\tvar ce = c * e, cf = c * f, de = d * e, df = d * f;\n\n\t\t\tte[ 0 ] = ce + df * b;\n\t\t\tte[ 4 ] = de * b - cf;\n\t\t\tte[ 8 ] = a * d;\n\n\t\t\tte[ 1 ] = a * f;\n\t\t\tte[ 5 ] = a * e;\n\t\t\tte[ 9 ] = - b;\n\n\t\t\tte[ 2 ] = cf * b - de;\n\t\t\tte[ 6 ] = df + ce * b;\n\t\t\tte[ 10 ] = a * c;\n\n\t\t} else if ( euler.order === 'ZXY' ) {\n\n\t\t\tvar ce = c * e, cf = c * f, de = d * e, df = d * f;\n\n\t\t\tte[ 0 ] = ce - df * b;\n\t\t\tte[ 4 ] = - a * f;\n\t\t\tte[ 8 ] = de + cf * b;\n\n\t\t\tte[ 1 ] = cf + de * b;\n\t\t\tte[ 5 ] = a * e;\n\t\t\tte[ 9 ] = df - ce * b;\n\n\t\t\tte[ 2 ] = - a * d;\n\t\t\tte[ 6 ] = b;\n\t\t\tte[ 10 ] = a * c;\n\n\t\t} else if ( euler.order === 'ZYX' ) {\n\n\t\t\tvar ae = a * e, af = a * f, be = b * e, bf = b * f;\n\n\t\t\tte[ 0 ] = c * e;\n\t\t\tte[ 4 ] = be * d - af;\n\t\t\tte[ 8 ] = ae * d + bf;\n\n\t\t\tte[ 1 ] = c * f;\n\t\t\tte[ 5 ] = bf * d + ae;\n\t\t\tte[ 9 ] = af * d - be;\n\n\t\t\tte[ 2 ] = - d;\n\t\t\tte[ 6 ] = b * c;\n\t\t\tte[ 10 ] = a * c;\n\n\t\t} else if ( euler.order === 'YZX' ) {\n\n\t\t\tvar ac = a * c, ad = a * d, bc = b * c, bd = b * d;\n\n\t\t\tte[ 0 ] = c * e;\n\t\t\tte[ 4 ] = bd - ac * f;\n\t\t\tte[ 8 ] = bc * f + ad;\n\n\t\t\tte[ 1 ] = f;\n\t\t\tte[ 5 ] = a * e;\n\t\t\tte[ 9 ] = - b * e;\n\n\t\t\tte[ 2 ] = - d * e;\n\t\t\tte[ 6 ] = ad * f + bc;\n\t\t\tte[ 10 ] = ac - bd * f;\n\n\t\t} else if ( euler.order === 'XZY' ) {\n\n\t\t\tvar ac = a * c, ad = a * d, bc = b * c, bd = b * d;\n\n\t\t\tte[ 0 ] = c * e;\n\t\t\tte[ 4 ] = - f;\n\t\t\tte[ 8 ] = d * e;\n\n\t\t\tte[ 1 ] = ac * f + bd;\n\t\t\tte[ 5 ] = a * e;\n\t\t\tte[ 9 ] = ad * f - bc;\n\n\t\t\tte[ 2 ] = bc * f - ad;\n\t\t\tte[ 6 ] = b * e;\n\t\t\tte[ 10 ] = bd * f + ac;\n\n\t\t}\n\n\t\t// bottom row\n\t\tte[ 3 ] = 0;\n\t\tte[ 7 ] = 0;\n\t\tte[ 11 ] = 0;\n\n\t\t// last column\n\t\tte[ 12 ] = 0;\n\t\tte[ 13 ] = 0;\n\t\tte[ 14 ] = 0;\n\t\tte[ 15 ] = 1;\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationFromQuaternion: function ( q ) {\n\n\t\treturn this.compose( _zero, q, _one );\n\n\t},\n\n\tlookAt: function ( eye, target, up ) {\n\n\t\tvar te = this.elements;\n\n\t\t_z.subVectors( eye, target );\n\n\t\tif ( _z.lengthSq() === 0 ) {\n\n\t\t\t// eye and target are in the same position\n\n\t\t\t_z.z = 1;\n\n\t\t}\n\n\t\t_z.normalize();\n\t\t_x.crossVectors( up, _z );\n\n\t\tif ( _x.lengthSq() === 0 ) {\n\n\t\t\t// up and z are parallel\n\n\t\t\tif ( Math.abs( up.z ) === 1 ) {\n\n\t\t\t\t_z.x += 0.0001;\n\n\t\t\t} else {\n\n\t\t\t\t_z.z += 0.0001;\n\n\t\t\t}\n\n\t\t\t_z.normalize();\n\t\t\t_x.crossVectors( up, _z );\n\n\t\t}\n\n\t\t_x.normalize();\n\t\t_y.crossVectors( _z, _x );\n\n\t\tte[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x;\n\t\tte[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y;\n\t\tte[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z;\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( m, n ) {\n\n\t\tif ( n !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' );\n\t\t\treturn this.multiplyMatrices( m, n );\n\n\t\t}\n\n\t\treturn this.multiplyMatrices( this, m );\n\n\t},\n\n\tpremultiply: function ( m ) {\n\n\t\treturn this.multiplyMatrices( m, this );\n\n\t},\n\n\tmultiplyMatrices: function ( a, b ) {\n\n\t\tvar ae = a.elements;\n\t\tvar be = b.elements;\n\t\tvar te = this.elements;\n\n\t\tvar a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ];\n\t\tvar a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ];\n\t\tvar a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ];\n\t\tvar a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ];\n\n\t\tvar b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ];\n\t\tvar b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ];\n\t\tvar b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ];\n\t\tvar b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ];\n\n\t\tte[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;\n\t\tte[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;\n\t\tte[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;\n\t\tte[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;\n\n\t\tte[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;\n\t\tte[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;\n\t\tte[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;\n\t\tte[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;\n\n\t\tte[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;\n\t\tte[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;\n\t\tte[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;\n\t\tte[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;\n\n\t\tte[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;\n\t\tte[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;\n\t\tte[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;\n\t\tte[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( s ) {\n\n\t\tvar te = this.elements;\n\n\t\tte[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s;\n\t\tte[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s;\n\t\tte[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s;\n\t\tte[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s;\n\n\t\treturn this;\n\n\t},\n\n\tdeterminant: function () {\n\n\t\tvar te = this.elements;\n\n\t\tvar n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ];\n\t\tvar n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ];\n\t\tvar n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ];\n\t\tvar n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ];\n\n\t\t//TODO: make this more efficient\n\t\t//( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )\n\n\t\treturn (\n\t\t\tn41 * (\n\t\t\t\t+ n14 * n23 * n32\n\t\t\t\t - n13 * n24 * n32\n\t\t\t\t - n14 * n22 * n33\n\t\t\t\t + n12 * n24 * n33\n\t\t\t\t + n13 * n22 * n34\n\t\t\t\t - n12 * n23 * n34\n\t\t\t) +\n\t\t\tn42 * (\n\t\t\t\t+ n11 * n23 * n34\n\t\t\t\t - n11 * n24 * n33\n\t\t\t\t + n14 * n21 * n33\n\t\t\t\t - n13 * n21 * n34\n\t\t\t\t + n13 * n24 * n31\n\t\t\t\t - n14 * n23 * n31\n\t\t\t) +\n\t\t\tn43 * (\n\t\t\t\t+ n11 * n24 * n32\n\t\t\t\t - n11 * n22 * n34\n\t\t\t\t - n14 * n21 * n32\n\t\t\t\t + n12 * n21 * n34\n\t\t\t\t + n14 * n22 * n31\n\t\t\t\t - n12 * n24 * n31\n\t\t\t) +\n\t\t\tn44 * (\n\t\t\t\t- n13 * n22 * n31\n\t\t\t\t - n11 * n23 * n32\n\t\t\t\t + n11 * n22 * n33\n\t\t\t\t + n13 * n21 * n32\n\t\t\t\t - n12 * n21 * n33\n\t\t\t\t + n12 * n23 * n31\n\t\t\t)\n\n\t\t);\n\n\t},\n\n\ttranspose: function () {\n\n\t\tvar te = this.elements;\n\t\tvar tmp;\n\n\t\ttmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp;\n\t\ttmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp;\n\t\ttmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp;\n\n\t\ttmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp;\n\t\ttmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp;\n\t\ttmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp;\n\n\t\treturn this;\n\n\t},\n\n\tsetPosition: function ( x, y, z ) {\n\n\t\tvar te = this.elements;\n\n\t\tif ( x.isVector3 ) {\n\n\t\t\tte[ 12 ] = x.x;\n\t\t\tte[ 13 ] = x.y;\n\t\t\tte[ 14 ] = x.z;\n\n\t\t} else {\n\n\t\t\tte[ 12 ] = x;\n\t\t\tte[ 13 ] = y;\n\t\t\tte[ 14 ] = z;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tgetInverse: function ( m, throwOnDegenerate ) {\n\n\t\tif ( throwOnDegenerate !== undefined ) {\n\n\t\t\tconsole.warn( \"THREE.Matrix4: .getInverse() can no longer be configured to throw on degenerate.\" );\n\n\t\t}\n\n\t\t// based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm\n\t\tvar te = this.elements,\n\t\t\tme = m.elements,\n\n\t\t\tn11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ],\n\t\t\tn12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ],\n\t\t\tn13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ],\n\t\t\tn14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ],\n\n\t\t\tt11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,\n\t\t\tt12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,\n\t\t\tt13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,\n\t\t\tt14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;\n\n\t\tvar det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;\n\n\t\tif ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );\n\n\t\tvar detInv = 1 / det;\n\n\t\tte[ 0 ] = t11 * detInv;\n\t\tte[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;\n\t\tte[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;\n\t\tte[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;\n\n\t\tte[ 4 ] = t12 * detInv;\n\t\tte[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;\n\t\tte[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;\n\t\tte[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;\n\n\t\tte[ 8 ] = t13 * detInv;\n\t\tte[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;\n\t\tte[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;\n\t\tte[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;\n\n\t\tte[ 12 ] = t14 * detInv;\n\t\tte[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;\n\t\tte[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;\n\t\tte[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;\n\n\t\treturn this;\n\n\t},\n\n\tscale: function ( v ) {\n\n\t\tvar te = this.elements;\n\t\tvar x = v.x, y = v.y, z = v.z;\n\n\t\tte[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z;\n\t\tte[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z;\n\t\tte[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z;\n\t\tte[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z;\n\n\t\treturn this;\n\n\t},\n\n\tgetMaxScaleOnAxis: function () {\n\n\t\tvar te = this.elements;\n\n\t\tvar scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ];\n\t\tvar scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ];\n\t\tvar scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ];\n\n\t\treturn Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) );\n\n\t},\n\n\tmakeTranslation: function ( x, y, z ) {\n\n\t\tthis.set(\n\n\t\t\t1, 0, 0, x,\n\t\t\t0, 1, 0, y,\n\t\t\t0, 0, 1, z,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationX: function ( theta ) {\n\n\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\n\n\t\tthis.set(\n\n\t\t\t1, 0, 0, 0,\n\t\t\t0, c, - s, 0,\n\t\t\t0, s, c, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationY: function ( theta ) {\n\n\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\n\n\t\tthis.set(\n\n\t\t\t c, 0, s, 0,\n\t\t\t 0, 1, 0, 0,\n\t\t\t- s, 0, c, 0,\n\t\t\t 0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationZ: function ( theta ) {\n\n\t\tvar c = Math.cos( theta ), s = Math.sin( theta );\n\n\t\tthis.set(\n\n\t\t\tc, - s, 0, 0,\n\t\t\ts, c, 0, 0,\n\t\t\t0, 0, 1, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmakeRotationAxis: function ( axis, angle ) {\n\n\t\t// Based on http://www.gamedev.net/reference/articles/article1199.asp\n\n\t\tvar c = Math.cos( angle );\n\t\tvar s = Math.sin( angle );\n\t\tvar t = 1 - c;\n\t\tvar x = axis.x, y = axis.y, z = axis.z;\n\t\tvar tx = t * x, ty = t * y;\n\n\t\tthis.set(\n\n\t\t\ttx * x + c, tx * y - s * z, tx * z + s * y, 0,\n\t\t\ttx * y + s * z, ty * y + c, ty * z - s * x, 0,\n\t\t\ttx * z - s * y, ty * z + s * x, t * z * z + c, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\t return this;\n\n\t},\n\n\tmakeScale: function ( x, y, z ) {\n\n\t\tthis.set(\n\n\t\t\tx, 0, 0, 0,\n\t\t\t0, y, 0, 0,\n\t\t\t0, 0, z, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tmakeShear: function ( x, y, z ) {\n\n\t\tthis.set(\n\n\t\t\t1, y, z, 0,\n\t\t\tx, 1, z, 0,\n\t\t\tx, y, 1, 0,\n\t\t\t0, 0, 0, 1\n\n\t\t);\n\n\t\treturn this;\n\n\t},\n\n\tcompose: function ( position, quaternion, scale ) {\n\n\t\tvar te = this.elements;\n\n\t\tvar x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w;\n\t\tvar x2 = x + x,\ty2 = y + y, z2 = z + z;\n\t\tvar xx = x * x2, xy = x * y2, xz = x * z2;\n\t\tvar yy = y * y2, yz = y * z2, zz = z * z2;\n\t\tvar wx = w * x2, wy = w * y2, wz = w * z2;\n\n\t\tvar sx = scale.x, sy = scale.y, sz = scale.z;\n\n\t\tte[ 0 ] = ( 1 - ( yy + zz ) ) * sx;\n\t\tte[ 1 ] = ( xy + wz ) * sx;\n\t\tte[ 2 ] = ( xz - wy ) * sx;\n\t\tte[ 3 ] = 0;\n\n\t\tte[ 4 ] = ( xy - wz ) * sy;\n\t\tte[ 5 ] = ( 1 - ( xx + zz ) ) * sy;\n\t\tte[ 6 ] = ( yz + wx ) * sy;\n\t\tte[ 7 ] = 0;\n\n\t\tte[ 8 ] = ( xz + wy ) * sz;\n\t\tte[ 9 ] = ( yz - wx ) * sz;\n\t\tte[ 10 ] = ( 1 - ( xx + yy ) ) * sz;\n\t\tte[ 11 ] = 0;\n\n\t\tte[ 12 ] = position.x;\n\t\tte[ 13 ] = position.y;\n\t\tte[ 14 ] = position.z;\n\t\tte[ 15 ] = 1;\n\n\t\treturn this;\n\n\t},\n\n\tdecompose: function ( position, quaternion, scale ) {\n\n\t\tvar te = this.elements;\n\n\t\tvar sx = _v1.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length();\n\t\tvar sy = _v1.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length();\n\t\tvar sz = _v1.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length();\n\n\t\t// if determine is negative, we need to invert one scale\n\t\tvar det = this.determinant();\n\t\tif ( det < 0 ) sx = - sx;\n\n\t\tposition.x = te[ 12 ];\n\t\tposition.y = te[ 13 ];\n\t\tposition.z = te[ 14 ];\n\n\t\t// scale the rotation part\n\t\t_m1.copy( this );\n\n\t\tvar invSX = 1 / sx;\n\t\tvar invSY = 1 / sy;\n\t\tvar invSZ = 1 / sz;\n\n\t\t_m1.elements[ 0 ] *= invSX;\n\t\t_m1.elements[ 1 ] *= invSX;\n\t\t_m1.elements[ 2 ] *= invSX;\n\n\t\t_m1.elements[ 4 ] *= invSY;\n\t\t_m1.elements[ 5 ] *= invSY;\n\t\t_m1.elements[ 6 ] *= invSY;\n\n\t\t_m1.elements[ 8 ] *= invSZ;\n\t\t_m1.elements[ 9 ] *= invSZ;\n\t\t_m1.elements[ 10 ] *= invSZ;\n\n\t\tquaternion.setFromRotationMatrix( _m1 );\n\n\t\tscale.x = sx;\n\t\tscale.y = sy;\n\t\tscale.z = sz;\n\n\t\treturn this;\n\n\t},\n\n\tmakePerspective: function ( left, right, top, bottom, near, far ) {\n\n\t\tif ( far === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' );\n\n\t\t}\n\n\t\tvar te = this.elements;\n\t\tvar x = 2 * near / ( right - left );\n\t\tvar y = 2 * near / ( top - bottom );\n\n\t\tvar a = ( right + left ) / ( right - left );\n\t\tvar b = ( top + bottom ) / ( top - bottom );\n\t\tvar c = - ( far + near ) / ( far - near );\n\t\tvar d = - 2 * far * near / ( far - near );\n\n\t\tte[ 0 ] = x;\tte[ 4 ] = 0;\tte[ 8 ] = a;\tte[ 12 ] = 0;\n\t\tte[ 1 ] = 0;\tte[ 5 ] = y;\tte[ 9 ] = b;\tte[ 13 ] = 0;\n\t\tte[ 2 ] = 0;\tte[ 6 ] = 0;\tte[ 10 ] = c;\tte[ 14 ] = d;\n\t\tte[ 3 ] = 0;\tte[ 7 ] = 0;\tte[ 11 ] = - 1;\tte[ 15 ] = 0;\n\n\t\treturn this;\n\n\t},\n\n\tmakeOrthographic: function ( left, right, top, bottom, near, far ) {\n\n\t\tvar te = this.elements;\n\t\tvar w = 1.0 / ( right - left );\n\t\tvar h = 1.0 / ( top - bottom );\n\t\tvar p = 1.0 / ( far - near );\n\n\t\tvar x = ( right + left ) * w;\n\t\tvar y = ( top + bottom ) * h;\n\t\tvar z = ( far + near ) * p;\n\n\t\tte[ 0 ] = 2 * w;\tte[ 4 ] = 0;\tte[ 8 ] = 0;\tte[ 12 ] = - x;\n\t\tte[ 1 ] = 0;\tte[ 5 ] = 2 * h;\tte[ 9 ] = 0;\tte[ 13 ] = - y;\n\t\tte[ 2 ] = 0;\tte[ 6 ] = 0;\tte[ 10 ] = - 2 * p;\tte[ 14 ] = - z;\n\t\tte[ 3 ] = 0;\tte[ 7 ] = 0;\tte[ 11 ] = 0;\tte[ 15 ] = 1;\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( matrix ) {\n\n\t\tvar te = this.elements;\n\t\tvar me = matrix.elements;\n\n\t\tfor ( var i = 0; i < 16; i ++ ) {\n\n\t\t\tif ( te[ i ] !== me[ i ] ) return false;\n\n\t\t}\n\n\t\treturn true;\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tfor ( var i = 0; i < 16; i ++ ) {\n\n\t\t\tthis.elements[ i ] = array[ i + offset ];\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tvar te = this.elements;\n\n\t\tarray[ offset ] = te[ 0 ];\n\t\tarray[ offset + 1 ] = te[ 1 ];\n\t\tarray[ offset + 2 ] = te[ 2 ];\n\t\tarray[ offset + 3 ] = te[ 3 ];\n\n\t\tarray[ offset + 4 ] = te[ 4 ];\n\t\tarray[ offset + 5 ] = te[ 5 ];\n\t\tarray[ offset + 6 ] = te[ 6 ];\n\t\tarray[ offset + 7 ] = te[ 7 ];\n\n\t\tarray[ offset + 8 ] = te[ 8 ];\n\t\tarray[ offset + 9 ] = te[ 9 ];\n\t\tarray[ offset + 10 ] = te[ 10 ];\n\t\tarray[ offset + 11 ] = te[ 11 ];\n\n\t\tarray[ offset + 12 ] = te[ 12 ];\n\t\tarray[ offset + 13 ] = te[ 13 ];\n\t\tarray[ offset + 14 ] = te[ 14 ];\n\t\tarray[ offset + 15 ] = te[ 15 ];\n\n\t\treturn array;\n\n\t}\n\n} );\n\n\nexport { Matrix4 };\n","import { Quaternion } from './Quaternion.js';\nimport { Vector3 } from './Vector3.js';\nimport { Matrix4 } from './Matrix4.js';\nimport { MathUtils } from './MathUtils.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author bhouston / http://clara.io\n */\n\nvar _matrix = new Matrix4();\nvar _quaternion = new Quaternion();\n\nfunction Euler( x, y, z, order ) {\n\n\tthis._x = x || 0;\n\tthis._y = y || 0;\n\tthis._z = z || 0;\n\tthis._order = order || Euler.DefaultOrder;\n\n}\n\nEuler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ];\n\nEuler.DefaultOrder = 'XYZ';\n\nObject.defineProperties( Euler.prototype, {\n\n\tx: {\n\n\t\tget: function () {\n\n\t\t\treturn this._x;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._x = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\ty: {\n\n\t\tget: function () {\n\n\t\t\treturn this._y;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._y = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\tz: {\n\n\t\tget: function () {\n\n\t\t\treturn this._z;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._z = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t},\n\n\torder: {\n\n\t\tget: function () {\n\n\t\t\treturn this._order;\n\n\t\t},\n\n\t\tset: function ( value ) {\n\n\t\t\tthis._order = value;\n\t\t\tthis._onChangeCallback();\n\n\t\t}\n\n\t}\n\n} );\n\nObject.assign( Euler.prototype, {\n\n\tisEuler: true,\n\n\tset: function ( x, y, z, order ) {\n\n\t\tthis._x = x;\n\t\tthis._y = y;\n\t\tthis._z = z;\n\t\tthis._order = order || this._order;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this._x, this._y, this._z, this._order );\n\n\t},\n\n\tcopy: function ( euler ) {\n\n\t\tthis._x = euler._x;\n\t\tthis._y = euler._y;\n\t\tthis._z = euler._z;\n\t\tthis._order = euler._order;\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromRotationMatrix: function ( m, order, update ) {\n\n\t\tvar clamp = MathUtils.clamp;\n\n\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\n\n\t\tvar te = m.elements;\n\t\tvar m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ];\n\t\tvar m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ];\n\t\tvar m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ];\n\n\t\torder = order || this._order;\n\n\t\tswitch ( order ) {\n\n\t\t\tcase 'XYZ':\n\n\t\t\t\tthis._y = Math.asin( clamp( m13, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m13 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._x = Math.atan2( - m23, m33 );\n\t\t\t\t\tthis._z = Math.atan2( - m12, m11 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._x = Math.atan2( m32, m22 );\n\t\t\t\t\tthis._z = 0;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'YXZ':\n\n\t\t\t\tthis._x = Math.asin( - clamp( m23, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m23 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._y = Math.atan2( m13, m33 );\n\t\t\t\t\tthis._z = Math.atan2( m21, m22 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._y = Math.atan2( - m31, m11 );\n\t\t\t\t\tthis._z = 0;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZXY':\n\n\t\t\t\tthis._x = Math.asin( clamp( m32, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m32 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._y = Math.atan2( - m31, m33 );\n\t\t\t\t\tthis._z = Math.atan2( - m12, m22 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._y = 0;\n\t\t\t\t\tthis._z = Math.atan2( m21, m11 );\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'ZYX':\n\n\t\t\t\tthis._y = Math.asin( - clamp( m31, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m31 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._x = Math.atan2( m32, m33 );\n\t\t\t\t\tthis._z = Math.atan2( m21, m11 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._x = 0;\n\t\t\t\t\tthis._z = Math.atan2( - m12, m22 );\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'YZX':\n\n\t\t\t\tthis._z = Math.asin( clamp( m21, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m21 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._x = Math.atan2( - m23, m22 );\n\t\t\t\t\tthis._y = Math.atan2( - m31, m11 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._x = 0;\n\t\t\t\t\tthis._y = Math.atan2( m13, m33 );\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 'XZY':\n\n\t\t\t\tthis._z = Math.asin( - clamp( m12, - 1, 1 ) );\n\n\t\t\t\tif ( Math.abs( m12 ) < 0.9999999 ) {\n\n\t\t\t\t\tthis._x = Math.atan2( m32, m22 );\n\t\t\t\t\tthis._y = Math.atan2( m13, m11 );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tthis._x = Math.atan2( - m23, m33 );\n\t\t\t\t\tthis._y = 0;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tconsole.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );\n\n\t\t}\n\n\t\tthis._order = order;\n\n\t\tif ( update !== false ) this._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\tsetFromQuaternion: function ( q, order, update ) {\n\n\t\t_matrix.makeRotationFromQuaternion( q );\n\n\t\treturn this.setFromRotationMatrix( _matrix, order, update );\n\n\t},\n\n\tsetFromVector3: function ( v, order ) {\n\n\t\treturn this.set( v.x, v.y, v.z, order || this._order );\n\n\t},\n\n\treorder: function ( newOrder ) {\n\n\t\t// WARNING: this discards revolution information -bhouston\n\n\t\t_quaternion.setFromEuler( this );\n\n\t\treturn this.setFromQuaternion( _quaternion, newOrder );\n\n\t},\n\n\tequals: function ( euler ) {\n\n\t\treturn ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order );\n\n\t},\n\n\tfromArray: function ( array ) {\n\n\t\tthis._x = array[ 0 ];\n\t\tthis._y = array[ 1 ];\n\t\tthis._z = array[ 2 ];\n\t\tif ( array[ 3 ] !== undefined ) this._order = array[ 3 ];\n\n\t\tthis._onChangeCallback();\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this._x;\n\t\tarray[ offset + 1 ] = this._y;\n\t\tarray[ offset + 2 ] = this._z;\n\t\tarray[ offset + 3 ] = this._order;\n\n\t\treturn array;\n\n\t},\n\n\ttoVector3: function ( optionalResult ) {\n\n\t\tif ( optionalResult ) {\n\n\t\t\treturn optionalResult.set( this._x, this._y, this._z );\n\n\t\t} else {\n\n\t\t\treturn new Vector3( this._x, this._y, this._z );\n\n\t\t}\n\n\t},\n\n\t_onChange: function ( callback ) {\n\n\t\tthis._onChangeCallback = callback;\n\n\t\treturn this;\n\n\t},\n\n\t_onChangeCallback: function () {}\n\n} );\n\n\nexport { Euler };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction Layers() {\n\n\tthis.mask = 1 | 0;\n\n}\n\nObject.assign( Layers.prototype, {\n\n\tset: function ( channel ) {\n\n\t\tthis.mask = 1 << channel | 0;\n\n\t},\n\n\tenable: function ( channel ) {\n\n\t\tthis.mask |= 1 << channel | 0;\n\n\t},\n\n\tenableAll: function () {\n\n\t\tthis.mask = 0xffffffff | 0;\n\n\t},\n\n\ttoggle: function ( channel ) {\n\n\t\tthis.mask ^= 1 << channel | 0;\n\n\t},\n\n\tdisable: function ( channel ) {\n\n\t\tthis.mask &= ~ ( 1 << channel | 0 );\n\n\t},\n\n\tdisableAll: function () {\n\n\t\tthis.mask = 0;\n\n\t},\n\n\ttest: function ( layers ) {\n\n\t\treturn ( this.mask & layers.mask ) !== 0;\n\n\t}\n\n} );\n\n\nexport { Layers };\n","import { Quaternion } from '../math/Quaternion.js';\nimport { Vector3 } from '../math/Vector3.js';\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { EventDispatcher } from './EventDispatcher.js';\nimport { Euler } from '../math/Euler.js';\nimport { Layers } from './Layers.js';\nimport { Matrix3 } from '../math/Matrix3.js';\nimport { MathUtils } from '../math/MathUtils.js';\n\nlet _object3DId = 0;\n\nconst _v1 = new Vector3();\nconst _q1 = new Quaternion();\nconst _m1 = new Matrix4();\nconst _target = new Vector3();\n\nconst _position = new Vector3();\nconst _scale = new Vector3();\nconst _quaternion = new Quaternion();\n\nconst _xAxis = new Vector3( 1, 0, 0 );\nconst _yAxis = new Vector3( 0, 1, 0 );\nconst _zAxis = new Vector3( 0, 0, 1 );\n\nconst _addedEvent = { type: 'added' };\nconst _removedEvent = { type: 'removed' };\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author mikael emtinger / http://gomo.se/\n * @author alteredq / http://alteredqualia.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author elephantatwork / www.elephantatwork.ch\n */\n\nfunction Object3D() {\n\n\tObject.defineProperty( this, 'id', { value: _object3DId ++ } );\n\n\tthis.uuid = MathUtils.generateUUID();\n\n\tthis.name = '';\n\tthis.type = 'Object3D';\n\n\tthis.parent = null;\n\tthis.children = [];\n\n\tthis.up = Object3D.DefaultUp.clone();\n\n\tvar position = new Vector3();\n\tvar rotation = new Euler();\n\tvar quaternion = new Quaternion();\n\tvar scale = new Vector3( 1, 1, 1 );\n\n\tfunction onRotationChange() {\n\n\t\tquaternion.setFromEuler( rotation, false );\n\n\t}\n\n\tfunction onQuaternionChange() {\n\n\t\trotation.setFromQuaternion( quaternion, undefined, false );\n\n\t}\n\n\trotation._onChange( onRotationChange );\n\tquaternion._onChange( onQuaternionChange );\n\n\tObject.defineProperties( this, {\n\t\tposition: {\n\t\t\tconfigurable: true,\n\t\t\tenumerable: true,\n\t\t\tvalue: position\n\t\t},\n\t\trotation: {\n\t\t\tconfigurable: true,\n\t\t\tenumerable: true,\n\t\t\tvalue: rotation\n\t\t},\n\t\tquaternion: {\n\t\t\tconfigurable: true,\n\t\t\tenumerable: true,\n\t\t\tvalue: quaternion\n\t\t},\n\t\tscale: {\n\t\t\tconfigurable: true,\n\t\t\tenumerable: true,\n\t\t\tvalue: scale\n\t\t},\n\t\tmodelViewMatrix: {\n\t\t\tvalue: new Matrix4()\n\t\t},\n\t\tnormalMatrix: {\n\t\t\tvalue: new Matrix3()\n\t\t}\n\t} );\n\n\tthis.matrix = new Matrix4();\n\tthis.matrixWorld = new Matrix4();\n\n\tthis.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate;\n\tthis.matrixWorldNeedsUpdate = false;\n\n\tthis.layers = new Layers();\n\tthis.visible = true;\n\n\tthis.castShadow = false;\n\tthis.receiveShadow = false;\n\n\tthis.frustumCulled = true;\n\tthis.renderOrder = 0;\n\n\tthis.userData = {};\n\n}\n\nObject3D.DefaultUp = new Vector3( 0, 1, 0 );\nObject3D.DefaultMatrixAutoUpdate = true;\n\nObject3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: Object3D,\n\n\tisObject3D: true,\n\n\tonBeforeRender: function () {},\n\tonAfterRender: function () {},\n\n\tapplyMatrix4: function ( matrix ) {\n\n\t\tif ( this.matrixAutoUpdate ) this.updateMatrix();\n\n\t\tthis.matrix.premultiply( matrix );\n\n\t\tthis.matrix.decompose( this.position, this.quaternion, this.scale );\n\n\t},\n\n\tapplyQuaternion: function ( q ) {\n\n\t\tthis.quaternion.premultiply( q );\n\n\t\treturn this;\n\n\t},\n\n\tsetRotationFromAxisAngle: function ( axis, angle ) {\n\n\t\t// assumes axis is normalized\n\n\t\tthis.quaternion.setFromAxisAngle( axis, angle );\n\n\t},\n\n\tsetRotationFromEuler: function ( euler ) {\n\n\t\tthis.quaternion.setFromEuler( euler, true );\n\n\t},\n\n\tsetRotationFromMatrix: function ( m ) {\n\n\t\t// assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)\n\n\t\tthis.quaternion.setFromRotationMatrix( m );\n\n\t},\n\n\tsetRotationFromQuaternion: function ( q ) {\n\n\t\t// assumes q is normalized\n\n\t\tthis.quaternion.copy( q );\n\n\t},\n\n\trotateOnAxis: function ( axis, angle ) {\n\n\t\t// rotate object on axis in object space\n\t\t// axis is assumed to be normalized\n\n\t\t_q1.setFromAxisAngle( axis, angle );\n\n\t\tthis.quaternion.multiply( _q1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateOnWorldAxis: function ( axis, angle ) {\n\n\t\t// rotate object on axis in world space\n\t\t// axis is assumed to be normalized\n\t\t// method assumes no rotated parent\n\n\t\t_q1.setFromAxisAngle( axis, angle );\n\n\t\tthis.quaternion.premultiply( _q1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateX: function ( angle ) {\n\n\t\treturn this.rotateOnAxis( _xAxis, angle );\n\n\t},\n\n\trotateY: function ( angle ) {\n\n\t\treturn this.rotateOnAxis( _yAxis, angle );\n\n\t},\n\n\trotateZ: function ( angle ) {\n\n\t\treturn this.rotateOnAxis( _zAxis, angle );\n\n\t},\n\n\ttranslateOnAxis: function ( axis, distance ) {\n\n\t\t// translate object by distance along axis in object space\n\t\t// axis is assumed to be normalized\n\n\t\t_v1.copy( axis ).applyQuaternion( this.quaternion );\n\n\t\tthis.position.add( _v1.multiplyScalar( distance ) );\n\n\t\treturn this;\n\n\t},\n\n\ttranslateX: function ( distance ) {\n\n\t\treturn this.translateOnAxis( _xAxis, distance );\n\n\t},\n\n\ttranslateY: function ( distance ) {\n\n\t\treturn this.translateOnAxis( _yAxis, distance );\n\n\t},\n\n\ttranslateZ: function ( distance ) {\n\n\t\treturn this.translateOnAxis( _zAxis, distance );\n\n\t},\n\n\tlocalToWorld: function ( vector ) {\n\n\t\treturn vector.applyMatrix4( this.matrixWorld );\n\n\t},\n\n\tworldToLocal: function ( vector ) {\n\n\t\treturn vector.applyMatrix4( _m1.getInverse( this.matrixWorld ) );\n\n\t},\n\n\tlookAt: function ( x, y, z ) {\n\n\t\t// This method does not support objects having non-uniformly-scaled parent(s)\n\n\t\tif ( x.isVector3 ) {\n\n\t\t\t_target.copy( x );\n\n\t\t} else {\n\n\t\t\t_target.set( x, y, z );\n\n\t\t}\n\n\t\tvar parent = this.parent;\n\n\t\tthis.updateWorldMatrix( true, false );\n\n\t\t_position.setFromMatrixPosition( this.matrixWorld );\n\n\t\tif ( this.isCamera || this.isLight ) {\n\n\t\t\t_m1.lookAt( _position, _target, this.up );\n\n\t\t} else {\n\n\t\t\t_m1.lookAt( _target, _position, this.up );\n\n\t\t}\n\n\t\tthis.quaternion.setFromRotationMatrix( _m1 );\n\n\t\tif ( parent ) {\n\n\t\t\t_m1.extractRotation( parent.matrixWorld );\n\t\t\t_q1.setFromRotationMatrix( _m1 );\n\t\t\tthis.quaternion.premultiply( _q1.inverse() );\n\n\t\t}\n\n\t},\n\n\tadd: function ( object ) {\n\n\t\tif ( arguments.length > 1 ) {\n\n\t\t\tfor ( var i = 0; i < arguments.length; i ++ ) {\n\n\t\t\t\tthis.add( arguments[ i ] );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t}\n\n\t\tif ( object === this ) {\n\n\t\t\tconsole.error( \"THREE.Object3D.add: object can't be added as a child of itself.\", object );\n\t\t\treturn this;\n\n\t\t}\n\n\t\tif ( ( object && object.isObject3D ) ) {\n\n\t\t\tif ( object.parent !== null ) {\n\n\t\t\t\tobject.parent.remove( object );\n\n\t\t\t}\n\n\t\t\tobject.parent = this;\n\t\t\tthis.children.push( object );\n\n\t\t\tobject.dispatchEvent( _addedEvent );\n\n\t\t} else {\n\n\t\t\tconsole.error( \"THREE.Object3D.add: object not an instance of THREE.Object3D.\", object );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tremove: function ( object ) {\n\n\t\tif ( arguments.length > 1 ) {\n\n\t\t\tfor ( var i = 0; i < arguments.length; i ++ ) {\n\n\t\t\t\tthis.remove( arguments[ i ] );\n\n\t\t\t}\n\n\t\t\treturn this;\n\n\t\t}\n\n\t\tvar index = this.children.indexOf( object );\n\n\t\tif ( index !== - 1 ) {\n\n\t\t\tobject.parent = null;\n\t\t\tthis.children.splice( index, 1 );\n\n\t\t\tobject.dispatchEvent( _removedEvent );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tattach: function ( object ) {\n\n\t\t// adds object as a child of this, while maintaining the object's world transform\n\n\t\tthis.updateWorldMatrix( true, false );\n\n\t\t_m1.getInverse( this.matrixWorld );\n\n\t\tif ( object.parent !== null ) {\n\n\t\t\tobject.parent.updateWorldMatrix( true, false );\n\n\t\t\t_m1.multiply( object.parent.matrixWorld );\n\n\t\t}\n\n\t\tobject.applyMatrix4( _m1 );\n\n\t\tobject.updateWorldMatrix( false, false );\n\n\t\tthis.add( object );\n\n\t\treturn this;\n\n\t},\n\n\tgetObjectById: function ( id ) {\n\n\t\treturn this.getObjectByProperty( 'id', id );\n\n\t},\n\n\tgetObjectByName: function ( name ) {\n\n\t\treturn this.getObjectByProperty( 'name', name );\n\n\t},\n\n\tgetObjectByProperty: function ( name, value ) {\n\n\t\tif ( this[ name ] === value ) return this;\n\n\t\tfor ( var i = 0, l = this.children.length; i < l; i ++ ) {\n\n\t\t\tvar child = this.children[ i ];\n\t\t\tvar object = child.getObjectByProperty( name, value );\n\n\t\t\tif ( object !== undefined ) {\n\n\t\t\t\treturn object;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn undefined;\n\n\t},\n\n\tgetWorldPosition: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .getWorldPosition() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tthis.updateMatrixWorld( true );\n\n\t\treturn target.setFromMatrixPosition( this.matrixWorld );\n\n\t},\n\n\tgetWorldQuaternion: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' );\n\t\t\ttarget = new Quaternion();\n\n\t\t}\n\n\t\tthis.updateMatrixWorld( true );\n\n\t\tthis.matrixWorld.decompose( _position, target, _scale );\n\n\t\treturn target;\n\n\t},\n\n\tgetWorldScale: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .getWorldScale() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tthis.updateMatrixWorld( true );\n\n\t\tthis.matrixWorld.decompose( _position, _quaternion, target );\n\n\t\treturn target;\n\n\t},\n\n\tgetWorldDirection: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Object3D: .getWorldDirection() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tthis.updateMatrixWorld( true );\n\n\t\tvar e = this.matrixWorld.elements;\n\n\t\treturn target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize();\n\n\t},\n\n\traycast: function () {},\n\n\ttraverse: function ( callback ) {\n\n\t\tcallback( this );\n\n\t\tvar children = this.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tchildren[ i ].traverse( callback );\n\n\t\t}\n\n\t},\n\n\ttraverseVisible: function ( callback ) {\n\n\t\tif ( this.visible === false ) return;\n\n\t\tcallback( this );\n\n\t\tvar children = this.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tchildren[ i ].traverseVisible( callback );\n\n\t\t}\n\n\t},\n\n\ttraverseAncestors: function ( callback ) {\n\n\t\tvar parent = this.parent;\n\n\t\tif ( parent !== null ) {\n\n\t\t\tcallback( parent );\n\n\t\t\tparent.traverseAncestors( callback );\n\n\t\t}\n\n\t},\n\n\tupdateMatrix: function () {\n\n\t\tthis.matrix.compose( this.position, this.quaternion, this.scale );\n\n\t\tthis.matrixWorldNeedsUpdate = true;\n\n\t},\n\n\tupdateMatrixWorld: function ( force ) {\n\n\t\tif ( this.matrixAutoUpdate ) this.updateMatrix();\n\n\t\tif ( this.matrixWorldNeedsUpdate || force ) {\n\n\t\t\tif ( this.parent === null ) {\n\n\t\t\t\tthis.matrixWorld.copy( this.matrix );\n\n\t\t\t} else {\n\n\t\t\t\tthis.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );\n\n\t\t\t}\n\n\t\t\tthis.matrixWorldNeedsUpdate = false;\n\n\t\t\tforce = true;\n\n\t\t}\n\n\t\t// update children\n\n\t\tvar children = this.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tchildren[ i ].updateMatrixWorld( force );\n\n\t\t}\n\n\t},\n\n\tupdateWorldMatrix: function ( updateParents, updateChildren ) {\n\n\t\tvar parent = this.parent;\n\n\t\tif ( updateParents === true && parent !== null ) {\n\n\t\t\tparent.updateWorldMatrix( true, false );\n\n\t\t}\n\n\t\tif ( this.matrixAutoUpdate ) this.updateMatrix();\n\n\t\tif ( this.parent === null ) {\n\n\t\t\tthis.matrixWorld.copy( this.matrix );\n\n\t\t} else {\n\n\t\t\tthis.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );\n\n\t\t}\n\n\t\t// update children\n\n\t\tif ( updateChildren === true ) {\n\n\t\t\tvar children = this.children;\n\n\t\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\t\tchildren[ i ].updateWorldMatrix( false, true );\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\ttoJSON: function ( meta ) {\n\n\t\t// meta is a string when called from JSON.stringify\n\t\tvar isRootObject = ( meta === undefined || typeof meta === 'string' );\n\n\t\tvar output = {};\n\n\t\t// meta is a hash used to collect geometries, materials.\n\t\t// not providing it implies that this is the root object\n\t\t// being serialized.\n\t\tif ( isRootObject ) {\n\n\t\t\t// initialize meta obj\n\t\t\tmeta = {\n\t\t\t\tgeometries: {},\n\t\t\t\tmaterials: {},\n\t\t\t\ttextures: {},\n\t\t\t\timages: {},\n\t\t\t\tshapes: {}\n\t\t\t};\n\n\t\t\toutput.metadata = {\n\t\t\t\tversion: 4.5,\n\t\t\t\ttype: 'Object',\n\t\t\t\tgenerator: 'Object3D.toJSON'\n\t\t\t};\n\n\t\t}\n\n\t\t// standard Object3D serialization\n\n\t\tvar object = {};\n\n\t\tobject.uuid = this.uuid;\n\t\tobject.type = this.type;\n\n\t\tif ( this.name !== '' ) object.name = this.name;\n\t\tif ( this.castShadow === true ) object.castShadow = true;\n\t\tif ( this.receiveShadow === true ) object.receiveShadow = true;\n\t\tif ( this.visible === false ) object.visible = false;\n\t\tif ( this.frustumCulled === false ) object.frustumCulled = false;\n\t\tif ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder;\n\t\tif ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;\n\n\t\tobject.layers = this.layers.mask;\n\t\tobject.matrix = this.matrix.toArray();\n\n\t\tif ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false;\n\n\t\t// object specific properties\n\n\t\tif ( this.isInstancedMesh ) {\n\n\t\t\tobject.type = 'InstancedMesh';\n\t\t\tobject.count = this.count;\n\t\t\tobject.instanceMatrix = this.instanceMatrix.toJSON();\n\n\t\t}\n\n\t\t//\n\n\t\tfunction serialize( library, element ) {\n\n\t\t\tif ( library[ element.uuid ] === undefined ) {\n\n\t\t\t\tlibrary[ element.uuid ] = element.toJSON( meta );\n\n\t\t\t}\n\n\t\t\treturn element.uuid;\n\n\t\t}\n\n\t\tif ( this.isMesh || this.isLine || this.isPoints ) {\n\n\t\t\tobject.geometry = serialize( meta.geometries, this.geometry );\n\n\t\t\tvar parameters = this.geometry.parameters;\n\n\t\t\tif ( parameters !== undefined && parameters.shapes !== undefined ) {\n\n\t\t\t\tvar shapes = parameters.shapes;\n\n\t\t\t\tif ( Array.isArray( shapes ) ) {\n\n\t\t\t\t\tfor ( var i = 0, l = shapes.length; i < l; i ++ ) {\n\n\t\t\t\t\t\tvar shape = shapes[ i ];\n\n\t\t\t\t\t\tserialize( meta.shapes, shape );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tserialize( meta.shapes, shapes );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.material !== undefined ) {\n\n\t\t\tif ( Array.isArray( this.material ) ) {\n\n\t\t\t\tvar uuids = [];\n\n\t\t\t\tfor ( var i = 0, l = this.material.length; i < l; i ++ ) {\n\n\t\t\t\t\tuuids.push( serialize( meta.materials, this.material[ i ] ) );\n\n\t\t\t\t}\n\n\t\t\t\tobject.material = uuids;\n\n\t\t\t} else {\n\n\t\t\t\tobject.material = serialize( meta.materials, this.material );\n\n\t\t\t}\n\n\t\t}\n\n\t\t//\n\n\t\tif ( this.children.length > 0 ) {\n\n\t\t\tobject.children = [];\n\n\t\t\tfor ( var i = 0; i < this.children.length; i ++ ) {\n\n\t\t\t\tobject.children.push( this.children[ i ].toJSON( meta ).object );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( isRootObject ) {\n\n\t\t\tvar geometries = extractFromCache( meta.geometries );\n\t\t\tvar materials = extractFromCache( meta.materials );\n\t\t\tvar textures = extractFromCache( meta.textures );\n\t\t\tvar images = extractFromCache( meta.images );\n\t\t\tvar shapes = extractFromCache( meta.shapes );\n\n\t\t\tif ( geometries.length > 0 ) output.geometries = geometries;\n\t\t\tif ( materials.length > 0 ) output.materials = materials;\n\t\t\tif ( textures.length > 0 ) output.textures = textures;\n\t\t\tif ( images.length > 0 ) output.images = images;\n\t\t\tif ( shapes.length > 0 ) output.shapes = shapes;\n\n\t\t}\n\n\t\toutput.object = object;\n\n\t\treturn output;\n\n\t\t// extract data from the cache hash\n\t\t// remove metadata on each item\n\t\t// and return as array\n\t\tfunction extractFromCache( cache ) {\n\n\t\t\tvar values = [];\n\t\t\tfor ( var key in cache ) {\n\n\t\t\t\tvar data = cache[ key ];\n\t\t\t\tdelete data.metadata;\n\t\t\t\tvalues.push( data );\n\n\t\t\t}\n\n\t\t\treturn values;\n\n\t\t}\n\n\t},\n\n\tclone: function ( recursive ) {\n\n\t\treturn new this.constructor().copy( this, recursive );\n\n\t},\n\n\tcopy: function ( source, recursive ) {\n\n\t\tif ( recursive === undefined ) recursive = true;\n\n\t\tthis.name = source.name;\n\n\t\tthis.up.copy( source.up );\n\n\t\tthis.position.copy( source.position );\n\t\tthis.quaternion.copy( source.quaternion );\n\t\tthis.scale.copy( source.scale );\n\n\t\tthis.matrix.copy( source.matrix );\n\t\tthis.matrixWorld.copy( source.matrixWorld );\n\n\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\n\t\tthis.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;\n\n\t\tthis.layers.mask = source.layers.mask;\n\t\tthis.visible = source.visible;\n\n\t\tthis.castShadow = source.castShadow;\n\t\tthis.receiveShadow = source.receiveShadow;\n\n\t\tthis.frustumCulled = source.frustumCulled;\n\t\tthis.renderOrder = source.renderOrder;\n\n\t\tthis.userData = JSON.parse( JSON.stringify( source.userData ) );\n\n\t\tif ( recursive === true ) {\n\n\t\t\tfor ( var i = 0; i < source.children.length; i ++ ) {\n\n\t\t\t\tvar child = source.children[ i ];\n\t\t\t\tthis.add( child.clone() );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Object3D };\n","import { Object3D } from '../core/Object3D.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction Scene() {\n\n\tObject3D.call( this );\n\n\tthis.type = 'Scene';\n\n\tthis.background = null;\n\tthis.environment = null;\n\tthis.fog = null;\n\n\tthis.overrideMaterial = null;\n\n\tthis.autoUpdate = true; // checked by the renderer\n\n\tif ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {\n\n\t\t__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef\n\n\t}\n\n}\n\nScene.prototype = Object.assign( Object.create( Object3D.prototype ), {\n\n\tconstructor: Scene,\n\n\tisScene: true,\n\n\tcopy: function ( source, recursive ) {\n\n\t\tObject3D.prototype.copy.call( this, source, recursive );\n\n\t\tif ( source.background !== null ) this.background = source.background.clone();\n\t\tif ( source.environment !== null ) this.environment = source.environment.clone();\n\t\tif ( source.fog !== null ) this.fog = source.fog.clone();\n\n\t\tif ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone();\n\n\t\tthis.autoUpdate = source.autoUpdate;\n\t\tthis.matrixAutoUpdate = source.matrixAutoUpdate;\n\n\t\treturn this;\n\n\t},\n\n\ttoJSON: function ( meta ) {\n\n\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\n\n\t\tif ( this.background !== null ) data.object.background = this.background.toJSON( meta );\n\t\tif ( this.environment !== null ) data.object.environment = this.environment.toJSON( meta );\n\t\tif ( this.fog !== null ) data.object.fog = this.fog.toJSON();\n\n\t\treturn data;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t}\n\n} );\n\n\n\nexport { Scene };\n","import { Vector3 } from './Vector3.js';\n\nvar _points = [\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3(),\n\tnew Vector3()\n];\n\nvar _vector = new Vector3();\n\nvar _box = new Box3();\n\n// triangle centered vertices\n\nvar _v0 = new Vector3();\nvar _v1 = new Vector3();\nvar _v2 = new Vector3();\n\n// triangle edge vectors\n\nvar _f0 = new Vector3();\nvar _f1 = new Vector3();\nvar _f2 = new Vector3();\n\nvar _center = new Vector3();\nvar _extents = new Vector3();\nvar _triangleNormal = new Vector3();\nvar _testAxis = new Vector3();\n\n/**\n * @author bhouston / http://clara.io\n * @author WestLangley / http://github.com/WestLangley\n */\n\nfunction Box3( min, max ) {\n\n\tthis.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity );\n\tthis.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity );\n\n}\n\n\nObject.assign( Box3.prototype, {\n\n\tisBox3: true,\n\n\tset: function ( min, max ) {\n\n\t\tthis.min.copy( min );\n\t\tthis.max.copy( max );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromArray: function ( array ) {\n\n\t\tvar minX = + Infinity;\n\t\tvar minY = + Infinity;\n\t\tvar minZ = + Infinity;\n\n\t\tvar maxX = - Infinity;\n\t\tvar maxY = - Infinity;\n\t\tvar maxZ = - Infinity;\n\n\t\tfor ( var i = 0, l = array.length; i < l; i += 3 ) {\n\n\t\t\tvar x = array[ i ];\n\t\t\tvar y = array[ i + 1 ];\n\t\t\tvar z = array[ i + 2 ];\n\n\t\t\tif ( x < minX ) minX = x;\n\t\t\tif ( y < minY ) minY = y;\n\t\t\tif ( z < minZ ) minZ = z;\n\n\t\t\tif ( x > maxX ) maxX = x;\n\t\t\tif ( y > maxY ) maxY = y;\n\t\t\tif ( z > maxZ ) maxZ = z;\n\n\t\t}\n\n\t\tthis.min.set( minX, minY, minZ );\n\t\tthis.max.set( maxX, maxY, maxZ );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromBufferAttribute: function ( attribute ) {\n\n\t\tvar minX = + Infinity;\n\t\tvar minY = + Infinity;\n\t\tvar minZ = + Infinity;\n\n\t\tvar maxX = - Infinity;\n\t\tvar maxY = - Infinity;\n\t\tvar maxZ = - Infinity;\n\n\t\tfor ( var i = 0, l = attribute.count; i < l; i ++ ) {\n\n\t\t\tvar x = attribute.getX( i );\n\t\t\tvar y = attribute.getY( i );\n\t\t\tvar z = attribute.getZ( i );\n\n\t\t\tif ( x < minX ) minX = x;\n\t\t\tif ( y < minY ) minY = y;\n\t\t\tif ( z < minZ ) minZ = z;\n\n\t\t\tif ( x > maxX ) maxX = x;\n\t\t\tif ( y > maxY ) maxY = y;\n\t\t\tif ( z > maxZ ) maxZ = z;\n\n\t\t}\n\n\t\tthis.min.set( minX, minY, minZ );\n\t\tthis.max.set( maxX, maxY, maxZ );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromPoints: function ( points ) {\n\n\t\tthis.makeEmpty();\n\n\t\tfor ( var i = 0, il = points.length; i < il; i ++ ) {\n\n\t\t\tthis.expandByPoint( points[ i ] );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetFromCenterAndSize: function ( center, size ) {\n\n\t\tvar halfSize = _vector.copy( size ).multiplyScalar( 0.5 );\n\n\t\tthis.min.copy( center ).sub( halfSize );\n\t\tthis.max.copy( center ).add( halfSize );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromObject: function ( object ) {\n\n\t\tthis.makeEmpty();\n\n\t\treturn this.expandByObject( object );\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( box ) {\n\n\t\tthis.min.copy( box.min );\n\t\tthis.max.copy( box.max );\n\n\t\treturn this;\n\n\t},\n\n\tmakeEmpty: function () {\n\n\t\tthis.min.x = this.min.y = this.min.z = + Infinity;\n\t\tthis.max.x = this.max.y = this.max.z = - Infinity;\n\n\t\treturn this;\n\n\t},\n\n\tisEmpty: function () {\n\n\t\t// this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes\n\n\t\treturn ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z );\n\n\t},\n\n\tgetCenter: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .getCenter() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );\n\n\t},\n\n\tgetSize: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .getSize() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min );\n\n\t},\n\n\texpandByPoint: function ( point ) {\n\n\t\tthis.min.min( point );\n\t\tthis.max.max( point );\n\n\t\treturn this;\n\n\t},\n\n\texpandByVector: function ( vector ) {\n\n\t\tthis.min.sub( vector );\n\t\tthis.max.add( vector );\n\n\t\treturn this;\n\n\t},\n\n\texpandByScalar: function ( scalar ) {\n\n\t\tthis.min.addScalar( - scalar );\n\t\tthis.max.addScalar( scalar );\n\n\t\treturn this;\n\n\t},\n\n\texpandByObject: function ( object ) {\n\n\t\t// Computes the world-axis-aligned bounding box of an object (including its children),\n\t\t// accounting for both the object's, and children's, world transforms\n\n\t\tobject.updateWorldMatrix( false, false );\n\n\t\tvar geometry = object.geometry;\n\n\t\tif ( geometry !== undefined ) {\n\n\t\t\tif ( geometry.boundingBox === null ) {\n\n\t\t\t\tgeometry.computeBoundingBox();\n\n\t\t\t}\n\n\t\t\t_box.copy( geometry.boundingBox );\n\t\t\t_box.applyMatrix4( object.matrixWorld );\n\n\t\t\tthis.union( _box );\n\n\t\t}\n\n\t\tvar children = object.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tthis.expandByObject( children[ i ] );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcontainsPoint: function ( point ) {\n\n\t\treturn point.x < this.min.x || point.x > this.max.x ||\n\t\t\tpoint.y < this.min.y || point.y > this.max.y ||\n\t\t\tpoint.z < this.min.z || point.z > this.max.z ? false : true;\n\n\t},\n\n\tcontainsBox: function ( box ) {\n\n\t\treturn this.min.x <= box.min.x && box.max.x <= this.max.x &&\n\t\t\tthis.min.y <= box.min.y && box.max.y <= this.max.y &&\n\t\t\tthis.min.z <= box.min.z && box.max.z <= this.max.z;\n\n\t},\n\n\tgetParameter: function ( point, target ) {\n\n\t\t// This can potentially have a divide by zero if the box\n\t\t// has a size dimension of 0.\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .getParameter() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.set(\n\t\t\t( point.x - this.min.x ) / ( this.max.x - this.min.x ),\n\t\t\t( point.y - this.min.y ) / ( this.max.y - this.min.y ),\n\t\t\t( point.z - this.min.z ) / ( this.max.z - this.min.z )\n\t\t);\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\t// using 6 splitting planes to rule out intersections.\n\t\treturn box.max.x < this.min.x || box.min.x > this.max.x ||\n\t\t\tbox.max.y < this.min.y || box.min.y > this.max.y ||\n\t\t\tbox.max.z < this.min.z || box.min.z > this.max.z ? false : true;\n\n\t},\n\n\tintersectsSphere: function ( sphere ) {\n\n\t\t// Find the point on the AABB closest to the sphere center.\n\t\tthis.clampPoint( sphere.center, _vector );\n\n\t\t// If that point is inside the sphere, the AABB and sphere intersect.\n\t\treturn _vector.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );\n\n\t},\n\n\tintersectsPlane: function ( plane ) {\n\n\t\t// We compute the minimum and maximum dot product values. If those values\n\t\t// are on the same side (back or front) of the plane, then there is no intersection.\n\n\t\tvar min, max;\n\n\t\tif ( plane.normal.x > 0 ) {\n\n\t\t\tmin = plane.normal.x * this.min.x;\n\t\t\tmax = plane.normal.x * this.max.x;\n\n\t\t} else {\n\n\t\t\tmin = plane.normal.x * this.max.x;\n\t\t\tmax = plane.normal.x * this.min.x;\n\n\t\t}\n\n\t\tif ( plane.normal.y > 0 ) {\n\n\t\t\tmin += plane.normal.y * this.min.y;\n\t\t\tmax += plane.normal.y * this.max.y;\n\n\t\t} else {\n\n\t\t\tmin += plane.normal.y * this.max.y;\n\t\t\tmax += plane.normal.y * this.min.y;\n\n\t\t}\n\n\t\tif ( plane.normal.z > 0 ) {\n\n\t\t\tmin += plane.normal.z * this.min.z;\n\t\t\tmax += plane.normal.z * this.max.z;\n\n\t\t} else {\n\n\t\t\tmin += plane.normal.z * this.max.z;\n\t\t\tmax += plane.normal.z * this.min.z;\n\n\t\t}\n\n\t\treturn ( min <= - plane.constant && max >= - plane.constant );\n\n\t},\n\n\tintersectsTriangle: function ( triangle ) {\n\n\t\tif ( this.isEmpty() ) {\n\n\t\t\treturn false;\n\n\t\t}\n\n\t\t// compute box center and extents\n\t\tthis.getCenter( _center );\n\t\t_extents.subVectors( this.max, _center );\n\n\t\t// translate triangle to aabb origin\n\t\t_v0.subVectors( triangle.a, _center );\n\t\t_v1.subVectors( triangle.b, _center );\n\t\t_v2.subVectors( triangle.c, _center );\n\n\t\t// compute edge vectors for triangle\n\t\t_f0.subVectors( _v1, _v0 );\n\t\t_f1.subVectors( _v2, _v1 );\n\t\t_f2.subVectors( _v0, _v2 );\n\n\t\t// test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb\n\t\t// make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation\n\t\t// axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned)\n\t\tvar axes = [\n\t\t\t0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,\n\t\t\t_f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,\n\t\t\t- _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0\n\t\t];\n\t\tif ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {\n\n\t\t\treturn false;\n\n\t\t}\n\n\t\t// test 3 face normals from the aabb\n\t\taxes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];\n\t\tif ( ! satForAxes( axes, _v0, _v1, _v2, _extents ) ) {\n\n\t\t\treturn false;\n\n\t\t}\n\n\t\t// finally testing the face normal of the triangle\n\t\t// use already existing triangle edge vectors here\n\t\t_triangleNormal.crossVectors( _f0, _f1 );\n\t\taxes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];\n\n\t\treturn satForAxes( axes, _v0, _v1, _v2, _extents );\n\n\t},\n\n\tclampPoint: function ( point, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Box3: .clampPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.copy( point ).clamp( this.min, this.max );\n\n\t},\n\n\tdistanceToPoint: function ( point ) {\n\n\t\tvar clampedPoint = _vector.copy( point ).clamp( this.min, this.max );\n\n\t\treturn clampedPoint.sub( point ).length();\n\n\t},\n\n\tgetBoundingSphere: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.error( 'THREE.Box3: .getBoundingSphere() target is now required' );\n\t\t\t//target = new Sphere(); // removed to avoid cyclic dependency\n\n\t\t}\n\n\t\tthis.getCenter( target.center );\n\n\t\ttarget.radius = this.getSize( _vector ).length() * 0.5;\n\n\t\treturn target;\n\n\t},\n\n\tintersect: function ( box ) {\n\n\t\tthis.min.max( box.min );\n\t\tthis.max.min( box.max );\n\n\t\t// ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values.\n\t\tif ( this.isEmpty() ) this.makeEmpty();\n\n\t\treturn this;\n\n\t},\n\n\tunion: function ( box ) {\n\n\t\tthis.min.min( box.min );\n\t\tthis.max.max( box.max );\n\n\t\treturn this;\n\n\t},\n\n\tapplyMatrix4: function ( matrix ) {\n\n\t\t// transform of empty box is an empty box.\n\t\tif ( this.isEmpty() ) return this;\n\n\t\t// NOTE: I am using a binary pattern to specify all 2^3 combinations below\n\t\t_points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000\n\t\t_points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001\n\t\t_points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010\n\t\t_points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011\n\t\t_points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100\n\t\t_points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101\n\t\t_points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110\n\t\t_points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111\n\n\t\tthis.setFromPoints( _points );\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( offset ) {\n\n\t\tthis.min.add( offset );\n\t\tthis.max.add( offset );\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( box ) {\n\n\t\treturn box.min.equals( this.min ) && box.max.equals( this.max );\n\n\t}\n\n} );\n\nfunction satForAxes( axes, v0, v1, v2, extents ) {\n\n\tvar i, j;\n\n\tfor ( i = 0, j = axes.length - 3; i <= j; i += 3 ) {\n\n\t\t_testAxis.fromArray( axes, i );\n\t\t// project the aabb onto the seperating axis\n\t\tvar r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z );\n\t\t// project all 3 vertices of the triangle onto the seperating axis\n\t\tvar p0 = v0.dot( _testAxis );\n\t\tvar p1 = v1.dot( _testAxis );\n\t\tvar p2 = v2.dot( _testAxis );\n\t\t// actual test, basically see if either of the most extreme of the triangle points intersects r\n\t\tif ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) {\n\n\t\t\t// points of the projected triangle are outside the projected half-length of the aabb\n\t\t\t// the axis is seperating and we can exit\n\t\t\treturn false;\n\n\t\t}\n\n\t}\n\n\treturn true;\n\n}\n\nexport { Box3 };\n","import { Box3 } from './Box3.js';\nimport { Vector3 } from './Vector3.js';\n\nvar _box = new Box3();\n\n/**\n * @author bhouston / http://clara.io\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction Sphere( center, radius ) {\n\n\tthis.center = ( center !== undefined ) ? center : new Vector3();\n\tthis.radius = ( radius !== undefined ) ? radius : - 1;\n\n}\n\nObject.assign( Sphere.prototype, {\n\n\tset: function ( center, radius ) {\n\n\t\tthis.center.copy( center );\n\t\tthis.radius = radius;\n\n\t\treturn this;\n\n\t},\n\n\tsetFromPoints: function ( points, optionalCenter ) {\n\n\t\tvar center = this.center;\n\n\t\tif ( optionalCenter !== undefined ) {\n\n\t\t\tcenter.copy( optionalCenter );\n\n\t\t} else {\n\n\t\t\t_box.setFromPoints( points ).getCenter( center );\n\n\t\t}\n\n\t\tvar maxRadiusSq = 0;\n\n\t\tfor ( var i = 0, il = points.length; i < il; i ++ ) {\n\n\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) );\n\n\t\t}\n\n\t\tthis.radius = Math.sqrt( maxRadiusSq );\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( sphere ) {\n\n\t\tthis.center.copy( sphere.center );\n\t\tthis.radius = sphere.radius;\n\n\t\treturn this;\n\n\t},\n\n\tisEmpty: function () {\n\n\t\treturn ( this.radius < 0 );\n\n\t},\n\n\tmakeEmpty: function () {\n\n\t\tthis.center.set( 0, 0, 0 );\n\t\tthis.radius = - 1;\n\n\t\treturn this;\n\n\t},\n\n\tcontainsPoint: function ( point ) {\n\n\t\treturn ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) );\n\n\t},\n\n\tdistanceToPoint: function ( point ) {\n\n\t\treturn ( point.distanceTo( this.center ) - this.radius );\n\n\t},\n\n\tintersectsSphere: function ( sphere ) {\n\n\t\tvar radiusSum = this.radius + sphere.radius;\n\n\t\treturn sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\treturn box.intersectsSphere( this );\n\n\t},\n\n\tintersectsPlane: function ( plane ) {\n\n\t\treturn Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius;\n\n\t},\n\n\tclampPoint: function ( point, target ) {\n\n\t\tvar deltaLengthSq = this.center.distanceToSquared( point );\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Sphere: .clampPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\ttarget.copy( point );\n\n\t\tif ( deltaLengthSq > ( this.radius * this.radius ) ) {\n\n\t\t\ttarget.sub( this.center ).normalize();\n\t\t\ttarget.multiplyScalar( this.radius ).add( this.center );\n\n\t\t}\n\n\t\treturn target;\n\n\t},\n\n\tgetBoundingBox: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Sphere: .getBoundingBox() target is now required' );\n\t\t\ttarget = new Box3();\n\n\t\t}\n\n\t\tif ( this.isEmpty() ) {\n\n\t\t\t// Empty sphere produces empty bounding box\n\t\t\ttarget.makeEmpty();\n\t\t\treturn target;\n\n\t\t}\n\n\t\ttarget.set( this.center, this.center );\n\t\ttarget.expandByScalar( this.radius );\n\n\t\treturn target;\n\n\t},\n\n\tapplyMatrix4: function ( matrix ) {\n\n\t\tthis.center.applyMatrix4( matrix );\n\t\tthis.radius = this.radius * matrix.getMaxScaleOnAxis();\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( offset ) {\n\n\t\tthis.center.add( offset );\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( sphere ) {\n\n\t\treturn sphere.center.equals( this.center ) && ( sphere.radius === this.radius );\n\n\t}\n\n} );\n\n\nexport { Sphere };\n","import { Vector3 } from './Vector3.js';\n\nvar _vector = new Vector3();\nvar _segCenter = new Vector3();\nvar _segDir = new Vector3();\nvar _diff = new Vector3();\n\nvar _edge1 = new Vector3();\nvar _edge2 = new Vector3();\nvar _normal = new Vector3();\n\n/**\n * @author bhouston / http://clara.io\n */\n\nfunction Ray( origin, direction ) {\n\n\tthis.origin = ( origin !== undefined ) ? origin : new Vector3();\n\tthis.direction = ( direction !== undefined ) ? direction : new Vector3( 0, 0, - 1 );\n\n}\n\nObject.assign( Ray.prototype, {\n\n\tset: function ( origin, direction ) {\n\n\t\tthis.origin.copy( origin );\n\t\tthis.direction.copy( direction );\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( ray ) {\n\n\t\tthis.origin.copy( ray.origin );\n\t\tthis.direction.copy( ray.direction );\n\n\t\treturn this;\n\n\t},\n\n\tat: function ( t, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Ray: .at() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.copy( this.direction ).multiplyScalar( t ).add( this.origin );\n\n\t},\n\n\tlookAt: function ( v ) {\n\n\t\tthis.direction.copy( v ).sub( this.origin ).normalize();\n\n\t\treturn this;\n\n\t},\n\n\trecast: function ( t ) {\n\n\t\tthis.origin.copy( this.at( t, _vector ) );\n\n\t\treturn this;\n\n\t},\n\n\tclosestPointToPoint: function ( point, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Ray: .closestPointToPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\ttarget.subVectors( point, this.origin );\n\n\t\tvar directionDistance = target.dot( this.direction );\n\n\t\tif ( directionDistance < 0 ) {\n\n\t\t\treturn target.copy( this.origin );\n\n\t\t}\n\n\t\treturn target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );\n\n\t},\n\n\tdistanceToPoint: function ( point ) {\n\n\t\treturn Math.sqrt( this.distanceSqToPoint( point ) );\n\n\t},\n\n\tdistanceSqToPoint: function ( point ) {\n\n\t\tvar directionDistance = _vector.subVectors( point, this.origin ).dot( this.direction );\n\n\t\t// point behind the ray\n\n\t\tif ( directionDistance < 0 ) {\n\n\t\t\treturn this.origin.distanceToSquared( point );\n\n\t\t}\n\n\t\t_vector.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );\n\n\t\treturn _vector.distanceToSquared( point );\n\n\t},\n\n\tdistanceSqToSegment: function ( v0, v1, optionalPointOnRay, optionalPointOnSegment ) {\n\n\t\t// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h\n\t\t// It returns the min distance between the ray and the segment\n\t\t// defined by v0 and v1\n\t\t// It can also set two optional targets :\n\t\t// - The closest point on the ray\n\t\t// - The closest point on the segment\n\n\t\t_segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 );\n\t\t_segDir.copy( v1 ).sub( v0 ).normalize();\n\t\t_diff.copy( this.origin ).sub( _segCenter );\n\n\t\tvar segExtent = v0.distanceTo( v1 ) * 0.5;\n\t\tvar a01 = - this.direction.dot( _segDir );\n\t\tvar b0 = _diff.dot( this.direction );\n\t\tvar b1 = - _diff.dot( _segDir );\n\t\tvar c = _diff.lengthSq();\n\t\tvar det = Math.abs( 1 - a01 * a01 );\n\t\tvar s0, s1, sqrDist, extDet;\n\n\t\tif ( det > 0 ) {\n\n\t\t\t// The ray and segment are not parallel.\n\n\t\t\ts0 = a01 * b1 - b0;\n\t\t\ts1 = a01 * b0 - b1;\n\t\t\textDet = segExtent * det;\n\n\t\t\tif ( s0 >= 0 ) {\n\n\t\t\t\tif ( s1 >= - extDet ) {\n\n\t\t\t\t\tif ( s1 <= extDet ) {\n\n\t\t\t\t\t\t// region 0\n\t\t\t\t\t\t// Minimum at interior points of ray and segment.\n\n\t\t\t\t\t\tvar invDet = 1 / det;\n\t\t\t\t\t\ts0 *= invDet;\n\t\t\t\t\t\ts1 *= invDet;\n\t\t\t\t\t\tsqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c;\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// region 1\n\n\t\t\t\t\t\ts1 = segExtent;\n\t\t\t\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\n\t\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// region 5\n\n\t\t\t\t\ts1 = - segExtent;\n\t\t\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\n\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif ( s1 <= - extDet ) {\n\n\t\t\t\t\t// region 4\n\n\t\t\t\t\ts0 = Math.max( 0, - ( - a01 * segExtent + b0 ) );\n\t\t\t\t\ts1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );\n\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t\t\t} else if ( s1 <= extDet ) {\n\n\t\t\t\t\t// region 3\n\n\t\t\t\t\ts0 = 0;\n\t\t\t\t\ts1 = Math.min( Math.max( - segExtent, - b1 ), segExtent );\n\t\t\t\t\tsqrDist = s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// region 2\n\n\t\t\t\t\ts0 = Math.max( 0, - ( a01 * segExtent + b0 ) );\n\t\t\t\t\ts1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent );\n\t\t\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// Ray and segment are parallel.\n\n\t\t\ts1 = ( a01 > 0 ) ? - segExtent : segExtent;\n\t\t\ts0 = Math.max( 0, - ( a01 * s1 + b0 ) );\n\t\t\tsqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c;\n\n\t\t}\n\n\t\tif ( optionalPointOnRay ) {\n\n\t\t\toptionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin );\n\n\t\t}\n\n\t\tif ( optionalPointOnSegment ) {\n\n\t\t\toptionalPointOnSegment.copy( _segDir ).multiplyScalar( s1 ).add( _segCenter );\n\n\t\t}\n\n\t\treturn sqrDist;\n\n\t},\n\n\tintersectSphere: function ( sphere, target ) {\n\n\t\t_vector.subVectors( sphere.center, this.origin );\n\t\tvar tca = _vector.dot( this.direction );\n\t\tvar d2 = _vector.dot( _vector ) - tca * tca;\n\t\tvar radius2 = sphere.radius * sphere.radius;\n\n\t\tif ( d2 > radius2 ) return null;\n\n\t\tvar thc = Math.sqrt( radius2 - d2 );\n\n\t\t// t0 = first intersect point - entrance on front of sphere\n\t\tvar t0 = tca - thc;\n\n\t\t// t1 = second intersect point - exit point on back of sphere\n\t\tvar t1 = tca + thc;\n\n\t\t// test to see if both t0 and t1 are behind the ray - if so, return null\n\t\tif ( t0 < 0 && t1 < 0 ) return null;\n\n\t\t// test to see if t0 is behind the ray:\n\t\t// if it is, the ray is inside the sphere, so return the second exit point scaled by t1,\n\t\t// in order to always return an intersect point that is in front of the ray.\n\t\tif ( t0 < 0 ) return this.at( t1, target );\n\n\t\t// else t0 is in front of the ray, so return the first collision point scaled by t0\n\t\treturn this.at( t0, target );\n\n\t},\n\n\tintersectsSphere: function ( sphere ) {\n\n\t\treturn this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );\n\n\t},\n\n\tdistanceToPlane: function ( plane ) {\n\n\t\tvar denominator = plane.normal.dot( this.direction );\n\n\t\tif ( denominator === 0 ) {\n\n\t\t\t// line is coplanar, return origin\n\t\t\tif ( plane.distanceToPoint( this.origin ) === 0 ) {\n\n\t\t\t\treturn 0;\n\n\t\t\t}\n\n\t\t\t// Null is preferable to undefined since undefined means.... it is undefined\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tvar t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;\n\n\t\t// Return if the ray never intersects the plane\n\n\t\treturn t >= 0 ? t : null;\n\n\t},\n\n\tintersectPlane: function ( plane, target ) {\n\n\t\tvar t = this.distanceToPlane( plane );\n\n\t\tif ( t === null ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\treturn this.at( t, target );\n\n\t},\n\n\tintersectsPlane: function ( plane ) {\n\n\t\t// check if the ray lies on the plane first\n\n\t\tvar distToPoint = plane.distanceToPoint( this.origin );\n\n\t\tif ( distToPoint === 0 ) {\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\tvar denominator = plane.normal.dot( this.direction );\n\n\t\tif ( denominator * distToPoint < 0 ) {\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\t// ray origin is behind the plane (and is pointing behind it)\n\n\t\treturn false;\n\n\t},\n\n\tintersectBox: function ( box, target ) {\n\n\t\tvar tmin, tmax, tymin, tymax, tzmin, tzmax;\n\n\t\tvar invdirx = 1 / this.direction.x,\n\t\t\tinvdiry = 1 / this.direction.y,\n\t\t\tinvdirz = 1 / this.direction.z;\n\n\t\tvar origin = this.origin;\n\n\t\tif ( invdirx >= 0 ) {\n\n\t\t\ttmin = ( box.min.x - origin.x ) * invdirx;\n\t\t\ttmax = ( box.max.x - origin.x ) * invdirx;\n\n\t\t} else {\n\n\t\t\ttmin = ( box.max.x - origin.x ) * invdirx;\n\t\t\ttmax = ( box.min.x - origin.x ) * invdirx;\n\n\t\t}\n\n\t\tif ( invdiry >= 0 ) {\n\n\t\t\ttymin = ( box.min.y - origin.y ) * invdiry;\n\t\t\ttymax = ( box.max.y - origin.y ) * invdiry;\n\n\t\t} else {\n\n\t\t\ttymin = ( box.max.y - origin.y ) * invdiry;\n\t\t\ttymax = ( box.min.y - origin.y ) * invdiry;\n\n\t\t}\n\n\t\tif ( ( tmin > tymax ) || ( tymin > tmax ) ) return null;\n\n\t\t// These lines also handle the case where tmin or tmax is NaN\n\t\t// (result of 0 * Infinity). x !== x returns true if x is NaN\n\n\t\tif ( tymin > tmin || tmin !== tmin ) tmin = tymin;\n\n\t\tif ( tymax < tmax || tmax !== tmax ) tmax = tymax;\n\n\t\tif ( invdirz >= 0 ) {\n\n\t\t\ttzmin = ( box.min.z - origin.z ) * invdirz;\n\t\t\ttzmax = ( box.max.z - origin.z ) * invdirz;\n\n\t\t} else {\n\n\t\t\ttzmin = ( box.max.z - origin.z ) * invdirz;\n\t\t\ttzmax = ( box.min.z - origin.z ) * invdirz;\n\n\t\t}\n\n\t\tif ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null;\n\n\t\tif ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;\n\n\t\tif ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;\n\n\t\t//return point closest to the ray (positive side)\n\n\t\tif ( tmax < 0 ) return null;\n\n\t\treturn this.at( tmin >= 0 ? tmin : tmax, target );\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\treturn this.intersectBox( box, _vector ) !== null;\n\n\t},\n\n\tintersectTriangle: function ( a, b, c, backfaceCulling, target ) {\n\n\t\t// Compute the offset origin, edges, and normal.\n\n\t\t// from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h\n\n\t\t_edge1.subVectors( b, a );\n\t\t_edge2.subVectors( c, a );\n\t\t_normal.crossVectors( _edge1, _edge2 );\n\n\t\t// Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,\n\t\t// E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by\n\t\t// |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))\n\t\t// |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))\n\t\t// |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)\n\t\tvar DdN = this.direction.dot( _normal );\n\t\tvar sign;\n\n\t\tif ( DdN > 0 ) {\n\n\t\t\tif ( backfaceCulling ) return null;\n\t\t\tsign = 1;\n\n\t\t} else if ( DdN < 0 ) {\n\n\t\t\tsign = - 1;\n\t\t\tDdN = - DdN;\n\n\t\t} else {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t_diff.subVectors( this.origin, a );\n\t\tvar DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );\n\n\t\t// b1 < 0, no intersection\n\t\tif ( DdQxE2 < 0 ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\tvar DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );\n\n\t\t// b2 < 0, no intersection\n\t\tif ( DdE1xQ < 0 ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// b1+b2 > 1, no intersection\n\t\tif ( DdQxE2 + DdE1xQ > DdN ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// Line intersects triangle, check if ray does.\n\t\tvar QdN = - sign * _diff.dot( _normal );\n\n\t\t// t < 0, no intersection\n\t\tif ( QdN < 0 ) {\n\n\t\t\treturn null;\n\n\t\t}\n\n\t\t// Ray intersects triangle.\n\t\treturn this.at( QdN / DdN, target );\n\n\t},\n\n\tapplyMatrix4: function ( matrix4 ) {\n\n\t\tthis.origin.applyMatrix4( matrix4 );\n\t\tthis.direction.transformDirection( matrix4 );\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( ray ) {\n\n\t\treturn ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );\n\n\t}\n\n} );\n\n\nexport { Ray };\n","import { Matrix3 } from './Matrix3.js';\nimport { Vector3 } from './Vector3.js';\n\n/**\n * @author bhouston / http://clara.io\n */\n\nvar _vector1 = new Vector3();\nvar _vector2 = new Vector3();\nvar _normalMatrix = new Matrix3();\n\nfunction Plane( normal, constant ) {\n\n\t// normal is assumed to be normalized\n\n\tthis.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 );\n\tthis.constant = ( constant !== undefined ) ? constant : 0;\n\n}\n\nObject.assign( Plane.prototype, {\n\n\tisPlane: true,\n\n\tset: function ( normal, constant ) {\n\n\t\tthis.normal.copy( normal );\n\t\tthis.constant = constant;\n\n\t\treturn this;\n\n\t},\n\n\tsetComponents: function ( x, y, z, w ) {\n\n\t\tthis.normal.set( x, y, z );\n\t\tthis.constant = w;\n\n\t\treturn this;\n\n\t},\n\n\tsetFromNormalAndCoplanarPoint: function ( normal, point ) {\n\n\t\tthis.normal.copy( normal );\n\t\tthis.constant = - point.dot( this.normal );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromCoplanarPoints: function ( a, b, c ) {\n\n\t\tvar normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize();\n\n\t\t// Q: should an error be thrown if normal is zero (e.g. degenerate plane)?\n\n\t\tthis.setFromNormalAndCoplanarPoint( normal, a );\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( plane ) {\n\n\t\tthis.normal.copy( plane.normal );\n\t\tthis.constant = plane.constant;\n\n\t\treturn this;\n\n\t},\n\n\tnormalize: function () {\n\n\t\t// Note: will lead to a divide by zero if the plane is invalid.\n\n\t\tvar inverseNormalLength = 1.0 / this.normal.length();\n\t\tthis.normal.multiplyScalar( inverseNormalLength );\n\t\tthis.constant *= inverseNormalLength;\n\n\t\treturn this;\n\n\t},\n\n\tnegate: function () {\n\n\t\tthis.constant *= - 1;\n\t\tthis.normal.negate();\n\n\t\treturn this;\n\n\t},\n\n\tdistanceToPoint: function ( point ) {\n\n\t\treturn this.normal.dot( point ) + this.constant;\n\n\t},\n\n\tdistanceToSphere: function ( sphere ) {\n\n\t\treturn this.distanceToPoint( sphere.center ) - sphere.radius;\n\n\t},\n\n\tprojectPoint: function ( point, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Plane: .projectPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point );\n\n\t},\n\n\tintersectLine: function ( line, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Plane: .intersectLine() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tvar direction = line.delta( _vector1 );\n\n\t\tvar denominator = this.normal.dot( direction );\n\n\t\tif ( denominator === 0 ) {\n\n\t\t\t// line is coplanar, return origin\n\t\t\tif ( this.distanceToPoint( line.start ) === 0 ) {\n\n\t\t\t\treturn target.copy( line.start );\n\n\t\t\t}\n\n\t\t\t// Unsure if this is the correct method to handle this case.\n\t\t\treturn undefined;\n\n\t\t}\n\n\t\tvar t = - ( line.start.dot( this.normal ) + this.constant ) / denominator;\n\n\t\tif ( t < 0 || t > 1 ) {\n\n\t\t\treturn undefined;\n\n\t\t}\n\n\t\treturn target.copy( direction ).multiplyScalar( t ).add( line.start );\n\n\t},\n\n\tintersectsLine: function ( line ) {\n\n\t\t// Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it.\n\n\t\tvar startSign = this.distanceToPoint( line.start );\n\t\tvar endSign = this.distanceToPoint( line.end );\n\n\t\treturn ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\treturn box.intersectsPlane( this );\n\n\t},\n\n\tintersectsSphere: function ( sphere ) {\n\n\t\treturn sphere.intersectsPlane( this );\n\n\t},\n\n\tcoplanarPoint: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Plane: .coplanarPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.copy( this.normal ).multiplyScalar( - this.constant );\n\n\t},\n\n\tapplyMatrix4: function ( matrix, optionalNormalMatrix ) {\n\n\t\tvar normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );\n\n\t\tvar referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );\n\n\t\tvar normal = this.normal.applyMatrix3( normalMatrix ).normalize();\n\n\t\tthis.constant = - referencePoint.dot( normal );\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( offset ) {\n\n\t\tthis.constant -= offset.dot( this.normal );\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( plane ) {\n\n\t\treturn plane.normal.equals( this.normal ) && ( plane.constant === this.constant );\n\n\t}\n\n} );\n\n\nexport { Plane };\n","import { Vector3 } from './Vector3.js';\nimport { Plane } from './Plane.js';\n\n/**\n * @author bhouston / http://clara.io\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar _v0 = new Vector3();\nvar _v1 = new Vector3();\nvar _v2 = new Vector3();\nvar _v3 = new Vector3();\n\nvar _vab = new Vector3();\nvar _vac = new Vector3();\nvar _vbc = new Vector3();\nvar _vap = new Vector3();\nvar _vbp = new Vector3();\nvar _vcp = new Vector3();\n\nfunction Triangle( a, b, c ) {\n\n\tthis.a = ( a !== undefined ) ? a : new Vector3();\n\tthis.b = ( b !== undefined ) ? b : new Vector3();\n\tthis.c = ( c !== undefined ) ? c : new Vector3();\n\n}\n\nObject.assign( Triangle, {\n\n\tgetNormal: function ( a, b, c, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .getNormal() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\ttarget.subVectors( c, b );\n\t\t_v0.subVectors( a, b );\n\t\ttarget.cross( _v0 );\n\n\t\tvar targetLengthSq = target.lengthSq();\n\t\tif ( targetLengthSq > 0 ) {\n\n\t\t\treturn target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) );\n\n\t\t}\n\n\t\treturn target.set( 0, 0, 0 );\n\n\t},\n\n\t// static/instance method to calculate barycentric coordinates\n\t// based on: http://www.blackpawn.com/texts/pointinpoly/default.html\n\tgetBarycoord: function ( point, a, b, c, target ) {\n\n\t\t_v0.subVectors( c, a );\n\t\t_v1.subVectors( b, a );\n\t\t_v2.subVectors( point, a );\n\n\t\tvar dot00 = _v0.dot( _v0 );\n\t\tvar dot01 = _v0.dot( _v1 );\n\t\tvar dot02 = _v0.dot( _v2 );\n\t\tvar dot11 = _v1.dot( _v1 );\n\t\tvar dot12 = _v1.dot( _v2 );\n\n\t\tvar denom = ( dot00 * dot11 - dot01 * dot01 );\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .getBarycoord() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\t// collinear or singular triangle\n\t\tif ( denom === 0 ) {\n\n\t\t\t// arbitrary location outside of triangle?\n\t\t\t// not sure if this is the best idea, maybe should be returning undefined\n\t\t\treturn target.set( - 2, - 1, - 1 );\n\n\t\t}\n\n\t\tvar invDenom = 1 / denom;\n\t\tvar u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;\n\t\tvar v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;\n\n\t\t// barycentric coordinates must always sum to 1\n\t\treturn target.set( 1 - u - v, v, u );\n\n\t},\n\n\tcontainsPoint: function ( point, a, b, c ) {\n\n\t\tTriangle.getBarycoord( point, a, b, c, _v3 );\n\n\t\treturn ( _v3.x >= 0 ) && ( _v3.y >= 0 ) && ( ( _v3.x + _v3.y ) <= 1 );\n\n\t},\n\n\tgetUV: function ( point, p1, p2, p3, uv1, uv2, uv3, target ) {\n\n\t\tthis.getBarycoord( point, p1, p2, p3, _v3 );\n\n\t\ttarget.set( 0, 0 );\n\t\ttarget.addScaledVector( uv1, _v3.x );\n\t\ttarget.addScaledVector( uv2, _v3.y );\n\t\ttarget.addScaledVector( uv3, _v3.z );\n\n\t\treturn target;\n\n\t},\n\n\tisFrontFacing: function ( a, b, c, direction ) {\n\n\t\t_v0.subVectors( c, b );\n\t\t_v1.subVectors( a, b );\n\n\t\t// strictly front facing\n\t\treturn ( _v0.cross( _v1 ).dot( direction ) < 0 ) ? true : false;\n\n\t}\n\n} );\n\nObject.assign( Triangle.prototype, {\n\n\tset: function ( a, b, c ) {\n\n\t\tthis.a.copy( a );\n\t\tthis.b.copy( b );\n\t\tthis.c.copy( c );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromPointsAndIndices: function ( points, i0, i1, i2 ) {\n\n\t\tthis.a.copy( points[ i0 ] );\n\t\tthis.b.copy( points[ i1 ] );\n\t\tthis.c.copy( points[ i2 ] );\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( triangle ) {\n\n\t\tthis.a.copy( triangle.a );\n\t\tthis.b.copy( triangle.b );\n\t\tthis.c.copy( triangle.c );\n\n\t\treturn this;\n\n\t},\n\n\tgetArea: function () {\n\n\t\t_v0.subVectors( this.c, this.b );\n\t\t_v1.subVectors( this.a, this.b );\n\n\t\treturn _v0.cross( _v1 ).length() * 0.5;\n\n\t},\n\n\tgetMidpoint: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .getMidpoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\treturn target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 );\n\n\t},\n\n\tgetNormal: function ( target ) {\n\n\t\treturn Triangle.getNormal( this.a, this.b, this.c, target );\n\n\t},\n\n\tgetPlane: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .getPlane() target is now required' );\n\t\t\ttarget = new Plane();\n\n\t\t}\n\n\t\treturn target.setFromCoplanarPoints( this.a, this.b, this.c );\n\n\t},\n\n\tgetBarycoord: function ( point, target ) {\n\n\t\treturn Triangle.getBarycoord( point, this.a, this.b, this.c, target );\n\n\t},\n\n\tgetUV: function ( point, uv1, uv2, uv3, target ) {\n\n\t\treturn Triangle.getUV( point, this.a, this.b, this.c, uv1, uv2, uv3, target );\n\n\t},\n\n\tcontainsPoint: function ( point ) {\n\n\t\treturn Triangle.containsPoint( point, this.a, this.b, this.c );\n\n\t},\n\n\tisFrontFacing: function ( direction ) {\n\n\t\treturn Triangle.isFrontFacing( this.a, this.b, this.c, direction );\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\treturn box.intersectsTriangle( this );\n\n\t},\n\n\tclosestPointToPoint: function ( p, target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tvar a = this.a, b = this.b, c = this.c;\n\t\tvar v, w;\n\n\t\t// algorithm thanks to Real-Time Collision Detection by Christer Ericson,\n\t\t// published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc.,\n\t\t// under the accompanying license; see chapter 5.1.5 for detailed explanation.\n\t\t// basically, we're distinguishing which of the voronoi regions of the triangle\n\t\t// the point lies in with the minimum amount of redundant computation.\n\n\t\t_vab.subVectors( b, a );\n\t\t_vac.subVectors( c, a );\n\t\t_vap.subVectors( p, a );\n\t\tvar d1 = _vab.dot( _vap );\n\t\tvar d2 = _vac.dot( _vap );\n\t\tif ( d1 <= 0 && d2 <= 0 ) {\n\n\t\t\t// vertex region of A; barycentric coords (1, 0, 0)\n\t\t\treturn target.copy( a );\n\n\t\t}\n\n\t\t_vbp.subVectors( p, b );\n\t\tvar d3 = _vab.dot( _vbp );\n\t\tvar d4 = _vac.dot( _vbp );\n\t\tif ( d3 >= 0 && d4 <= d3 ) {\n\n\t\t\t// vertex region of B; barycentric coords (0, 1, 0)\n\t\t\treturn target.copy( b );\n\n\t\t}\n\n\t\tvar vc = d1 * d4 - d3 * d2;\n\t\tif ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {\n\n\t\t\tv = d1 / ( d1 - d3 );\n\t\t\t// edge region of AB; barycentric coords (1-v, v, 0)\n\t\t\treturn target.copy( a ).addScaledVector( _vab, v );\n\n\t\t}\n\n\t\t_vcp.subVectors( p, c );\n\t\tvar d5 = _vab.dot( _vcp );\n\t\tvar d6 = _vac.dot( _vcp );\n\t\tif ( d6 >= 0 && d5 <= d6 ) {\n\n\t\t\t// vertex region of C; barycentric coords (0, 0, 1)\n\t\t\treturn target.copy( c );\n\n\t\t}\n\n\t\tvar vb = d5 * d2 - d1 * d6;\n\t\tif ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {\n\n\t\t\tw = d2 / ( d2 - d6 );\n\t\t\t// edge region of AC; barycentric coords (1-w, 0, w)\n\t\t\treturn target.copy( a ).addScaledVector( _vac, w );\n\n\t\t}\n\n\t\tvar va = d3 * d6 - d5 * d4;\n\t\tif ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {\n\n\t\t\t_vbc.subVectors( c, b );\n\t\t\tw = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );\n\t\t\t// edge region of BC; barycentric coords (0, 1-w, w)\n\t\t\treturn target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC\n\n\t\t}\n\n\t\t// face region\n\t\tvar denom = 1 / ( va + vb + vc );\n\t\t// u = va * denom\n\t\tv = vb * denom;\n\t\tw = vc * denom;\n\n\t\treturn target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w );\n\n\t},\n\n\tequals: function ( triangle ) {\n\n\t\treturn triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c );\n\n\t}\n\n} );\n\n\nexport { Triangle };\n","import { MathUtils } from './MathUtils.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF,\n\t'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2,\n\t'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50,\n\t'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B,\n\t'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B,\n\t'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F,\n\t'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3,\n\t'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222,\n\t'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700,\n\t'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4,\n\t'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00,\n\t'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3,\n\t'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA,\n\t'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32,\n\t'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3,\n\t'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC,\n\t'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD,\n\t'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6,\n\t'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9,\n\t'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F,\n\t'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE,\n\t'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA,\n\t'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0,\n\t'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 };\n\nvar _hslA = { h: 0, s: 0, l: 0 };\nvar _hslB = { h: 0, s: 0, l: 0 };\n\nfunction Color( r, g, b ) {\n\n\tif ( g === undefined && b === undefined ) {\n\n\t\t// r is THREE.Color, hex or string\n\t\treturn this.set( r );\n\n\t}\n\n\treturn this.setRGB( r, g, b );\n\n}\n\nfunction hue2rgb( p, q, t ) {\n\n\tif ( t < 0 ) t += 1;\n\tif ( t > 1 ) t -= 1;\n\tif ( t < 1 / 6 ) return p + ( q - p ) * 6 * t;\n\tif ( t < 1 / 2 ) return q;\n\tif ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t );\n\treturn p;\n\n}\n\nfunction SRGBToLinear( c ) {\n\n\treturn ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 );\n\n}\n\nfunction LinearToSRGB( c ) {\n\n\treturn ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055;\n\n}\n\nObject.assign( Color.prototype, {\n\n\tisColor: true,\n\n\tr: 1, g: 1, b: 1,\n\n\tset: function ( value ) {\n\n\t\tif ( value && value.isColor ) {\n\n\t\t\tthis.copy( value );\n\n\t\t} else if ( typeof value === 'number' ) {\n\n\t\t\tthis.setHex( value );\n\n\t\t} else if ( typeof value === 'string' ) {\n\n\t\t\tthis.setStyle( value );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetScalar: function ( scalar ) {\n\n\t\tthis.r = scalar;\n\t\tthis.g = scalar;\n\t\tthis.b = scalar;\n\n\t\treturn this;\n\n\t},\n\n\tsetHex: function ( hex ) {\n\n\t\thex = Math.floor( hex );\n\n\t\tthis.r = ( hex >> 16 & 255 ) / 255;\n\t\tthis.g = ( hex >> 8 & 255 ) / 255;\n\t\tthis.b = ( hex & 255 ) / 255;\n\n\t\treturn this;\n\n\t},\n\n\tsetRGB: function ( r, g, b ) {\n\n\t\tthis.r = r;\n\t\tthis.g = g;\n\t\tthis.b = b;\n\n\t\treturn this;\n\n\t},\n\n\tsetHSL: function ( h, s, l ) {\n\n\t\t// h,s,l ranges are in 0.0 - 1.0\n\t\th = MathUtils.euclideanModulo( h, 1 );\n\t\ts = MathUtils.clamp( s, 0, 1 );\n\t\tl = MathUtils.clamp( l, 0, 1 );\n\n\t\tif ( s === 0 ) {\n\n\t\t\tthis.r = this.g = this.b = l;\n\n\t\t} else {\n\n\t\t\tvar p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s );\n\t\t\tvar q = ( 2 * l ) - p;\n\n\t\t\tthis.r = hue2rgb( q, p, h + 1 / 3 );\n\t\t\tthis.g = hue2rgb( q, p, h );\n\t\t\tthis.b = hue2rgb( q, p, h - 1 / 3 );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetStyle: function ( style ) {\n\n\t\tfunction handleAlpha( string ) {\n\n\t\t\tif ( string === undefined ) return;\n\n\t\t\tif ( parseFloat( string ) < 1 ) {\n\n\t\t\t\tconsole.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' );\n\n\t\t\t}\n\n\t\t}\n\n\n\t\tvar m;\n\n\t\tif ( m = /^((?:rgb|hsl)a?)\\(\\s*([^\\)]*)\\)/.exec( style ) ) {\n\n\t\t\t// rgb / hsl\n\n\t\t\tvar color;\n\t\t\tvar name = m[ 1 ];\n\t\t\tvar components = m[ 2 ];\n\n\t\t\tswitch ( name ) {\n\n\t\t\t\tcase 'rgb':\n\t\t\t\tcase 'rgba':\n\n\t\t\t\t\tif ( color = /^(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\n\n\t\t\t\t\t\t// rgb(255,0,0) rgba(255,0,0,0.5)\n\t\t\t\t\t\tthis.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255;\n\t\t\t\t\t\tthis.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255;\n\t\t\t\t\t\tthis.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255;\n\n\t\t\t\t\t\thandleAlpha( color[ 5 ] );\n\n\t\t\t\t\t\treturn this;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( color = /^(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\n\n\t\t\t\t\t\t// rgb(100%,0%,0%) rgba(100%,0%,0%,0.5)\n\t\t\t\t\t\tthis.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100;\n\t\t\t\t\t\tthis.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100;\n\t\t\t\t\t\tthis.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100;\n\n\t\t\t\t\t\thandleAlpha( color[ 5 ] );\n\n\t\t\t\t\t\treturn this;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'hsl':\n\t\t\t\tcase 'hsla':\n\n\t\t\t\t\tif ( color = /^([0-9]*\\.?[0-9]+)\\s*,\\s*(\\d+)\\%\\s*,\\s*(\\d+)\\%\\s*(,\\s*([0-9]*\\.?[0-9]+)\\s*)?$/.exec( components ) ) {\n\n\t\t\t\t\t\t// hsl(120,50%,50%) hsla(120,50%,50%,0.5)\n\t\t\t\t\t\tvar h = parseFloat( color[ 1 ] ) / 360;\n\t\t\t\t\t\tvar s = parseInt( color[ 2 ], 10 ) / 100;\n\t\t\t\t\t\tvar l = parseInt( color[ 3 ], 10 ) / 100;\n\n\t\t\t\t\t\thandleAlpha( color[ 5 ] );\n\n\t\t\t\t\t\treturn this.setHSL( h, s, l );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t} else if ( m = /^\\#([A-Fa-f0-9]+)$/.exec( style ) ) {\n\n\t\t\t// hex color\n\n\t\t\tvar hex = m[ 1 ];\n\t\t\tvar size = hex.length;\n\n\t\t\tif ( size === 3 ) {\n\n\t\t\t\t// #ff0\n\t\t\t\tthis.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255;\n\t\t\t\tthis.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255;\n\t\t\t\tthis.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255;\n\n\t\t\t\treturn this;\n\n\t\t\t} else if ( size === 6 ) {\n\n\t\t\t\t// #ff0000\n\t\t\t\tthis.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255;\n\t\t\t\tthis.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255;\n\t\t\t\tthis.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255;\n\n\t\t\t\treturn this;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( style && style.length > 0 ) {\n\n\t\t\treturn this.setColorName( style );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetColorName: function ( style ) {\n\n\t\t// color keywords\n\t\tvar hex = _colorKeywords[ style ];\n\n\t\tif ( hex !== undefined ) {\n\n\t\t\t// red\n\t\t\tthis.setHex( hex );\n\n\t\t} else {\n\n\t\t\t// unknown color\n\t\t\tconsole.warn( 'THREE.Color: Unknown color ' + style );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.r, this.g, this.b );\n\n\t},\n\n\tcopy: function ( color ) {\n\n\t\tthis.r = color.r;\n\t\tthis.g = color.g;\n\t\tthis.b = color.b;\n\n\t\treturn this;\n\n\t},\n\n\tcopyGammaToLinear: function ( color, gammaFactor ) {\n\n\t\tif ( gammaFactor === undefined ) gammaFactor = 2.0;\n\n\t\tthis.r = Math.pow( color.r, gammaFactor );\n\t\tthis.g = Math.pow( color.g, gammaFactor );\n\t\tthis.b = Math.pow( color.b, gammaFactor );\n\n\t\treturn this;\n\n\t},\n\n\tcopyLinearToGamma: function ( color, gammaFactor ) {\n\n\t\tif ( gammaFactor === undefined ) gammaFactor = 2.0;\n\n\t\tvar safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0;\n\n\t\tthis.r = Math.pow( color.r, safeInverse );\n\t\tthis.g = Math.pow( color.g, safeInverse );\n\t\tthis.b = Math.pow( color.b, safeInverse );\n\n\t\treturn this;\n\n\t},\n\n\tconvertGammaToLinear: function ( gammaFactor ) {\n\n\t\tthis.copyGammaToLinear( this, gammaFactor );\n\n\t\treturn this;\n\n\t},\n\n\tconvertLinearToGamma: function ( gammaFactor ) {\n\n\t\tthis.copyLinearToGamma( this, gammaFactor );\n\n\t\treturn this;\n\n\t},\n\n\tcopySRGBToLinear: function ( color ) {\n\n\t\tthis.r = SRGBToLinear( color.r );\n\t\tthis.g = SRGBToLinear( color.g );\n\t\tthis.b = SRGBToLinear( color.b );\n\n\t\treturn this;\n\n\t},\n\n\tcopyLinearToSRGB: function ( color ) {\n\n\t\tthis.r = LinearToSRGB( color.r );\n\t\tthis.g = LinearToSRGB( color.g );\n\t\tthis.b = LinearToSRGB( color.b );\n\n\t\treturn this;\n\n\t},\n\n\tconvertSRGBToLinear: function () {\n\n\t\tthis.copySRGBToLinear( this );\n\n\t\treturn this;\n\n\t},\n\n\tconvertLinearToSRGB: function () {\n\n\t\tthis.copyLinearToSRGB( this );\n\n\t\treturn this;\n\n\t},\n\n\tgetHex: function () {\n\n\t\treturn ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;\n\n\t},\n\n\tgetHexString: function () {\n\n\t\treturn ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 );\n\n\t},\n\n\tgetHSL: function ( target ) {\n\n\t\t// h,s,l ranges are in 0.0 - 1.0\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Color: .getHSL() target is now required' );\n\t\t\ttarget = { h: 0, s: 0, l: 0 };\n\n\t\t}\n\n\t\tvar r = this.r, g = this.g, b = this.b;\n\n\t\tvar max = Math.max( r, g, b );\n\t\tvar min = Math.min( r, g, b );\n\n\t\tvar hue, saturation;\n\t\tvar lightness = ( min + max ) / 2.0;\n\n\t\tif ( min === max ) {\n\n\t\t\thue = 0;\n\t\t\tsaturation = 0;\n\n\t\t} else {\n\n\t\t\tvar delta = max - min;\n\n\t\t\tsaturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min );\n\n\t\t\tswitch ( max ) {\n\n\t\t\t\tcase r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break;\n\t\t\t\tcase g: hue = ( b - r ) / delta + 2; break;\n\t\t\t\tcase b: hue = ( r - g ) / delta + 4; break;\n\n\t\t\t}\n\n\t\t\thue /= 6;\n\n\t\t}\n\n\t\ttarget.h = hue;\n\t\ttarget.s = saturation;\n\t\ttarget.l = lightness;\n\n\t\treturn target;\n\n\t},\n\n\tgetStyle: function () {\n\n\t\treturn 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';\n\n\t},\n\n\toffsetHSL: function ( h, s, l ) {\n\n\t\tthis.getHSL( _hslA );\n\n\t\t_hslA.h += h; _hslA.s += s; _hslA.l += l;\n\n\t\tthis.setHSL( _hslA.h, _hslA.s, _hslA.l );\n\n\t\treturn this;\n\n\t},\n\n\tadd: function ( color ) {\n\n\t\tthis.r += color.r;\n\t\tthis.g += color.g;\n\t\tthis.b += color.b;\n\n\t\treturn this;\n\n\t},\n\n\taddColors: function ( color1, color2 ) {\n\n\t\tthis.r = color1.r + color2.r;\n\t\tthis.g = color1.g + color2.g;\n\t\tthis.b = color1.b + color2.b;\n\n\t\treturn this;\n\n\t},\n\n\taddScalar: function ( s ) {\n\n\t\tthis.r += s;\n\t\tthis.g += s;\n\t\tthis.b += s;\n\n\t\treturn this;\n\n\t},\n\n\tsub: function ( color ) {\n\n\t\tthis.r = Math.max( 0, this.r - color.r );\n\t\tthis.g = Math.max( 0, this.g - color.g );\n\t\tthis.b = Math.max( 0, this.b - color.b );\n\n\t\treturn this;\n\n\t},\n\n\tmultiply: function ( color ) {\n\n\t\tthis.r *= color.r;\n\t\tthis.g *= color.g;\n\t\tthis.b *= color.b;\n\n\t\treturn this;\n\n\t},\n\n\tmultiplyScalar: function ( s ) {\n\n\t\tthis.r *= s;\n\t\tthis.g *= s;\n\t\tthis.b *= s;\n\n\t\treturn this;\n\n\t},\n\n\tlerp: function ( color, alpha ) {\n\n\t\tthis.r += ( color.r - this.r ) * alpha;\n\t\tthis.g += ( color.g - this.g ) * alpha;\n\t\tthis.b += ( color.b - this.b ) * alpha;\n\n\t\treturn this;\n\n\t},\n\n\tlerpHSL: function ( color, alpha ) {\n\n\t\tthis.getHSL( _hslA );\n\t\tcolor.getHSL( _hslB );\n\n\t\tvar h = MathUtils.lerp( _hslA.h, _hslB.h, alpha );\n\t\tvar s = MathUtils.lerp( _hslA.s, _hslB.s, alpha );\n\t\tvar l = MathUtils.lerp( _hslA.l, _hslB.l, alpha );\n\n\t\tthis.setHSL( h, s, l );\n\n\t\treturn this;\n\n\t},\n\n\tequals: function ( c ) {\n\n\t\treturn ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b );\n\n\t},\n\n\tfromArray: function ( array, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis.r = array[ offset ];\n\t\tthis.g = array[ offset + 1 ];\n\t\tthis.b = array[ offset + 2 ];\n\n\t\treturn this;\n\n\t},\n\n\ttoArray: function ( array, offset ) {\n\n\t\tif ( array === undefined ) array = [];\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tarray[ offset ] = this.r;\n\t\tarray[ offset + 1 ] = this.g;\n\t\tarray[ offset + 2 ] = this.b;\n\n\t\treturn array;\n\n\t},\n\n\ttoJSON: function () {\n\n\t\treturn this.getHex();\n\n\t}\n\n} );\n\nColor.NAMES = _colorKeywords;\n\nexport { Color };\n","import { Color } from '../math/Color.js';\nimport { Vector3 } from '../math/Vector3.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n */\n\nfunction Face3( a, b, c, normal, color, materialIndex ) {\n\n\tthis.a = a;\n\tthis.b = b;\n\tthis.c = c;\n\n\tthis.normal = ( normal && normal.isVector3 ) ? normal : new Vector3();\n\tthis.vertexNormals = Array.isArray( normal ) ? normal : [];\n\n\tthis.color = ( color && color.isColor ) ? color : new Color();\n\tthis.vertexColors = Array.isArray( color ) ? color : [];\n\n\tthis.materialIndex = materialIndex !== undefined ? materialIndex : 0;\n\n}\n\nObject.assign( Face3.prototype, {\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tthis.a = source.a;\n\t\tthis.b = source.b;\n\t\tthis.c = source.c;\n\n\t\tthis.normal.copy( source.normal );\n\t\tthis.color.copy( source.color );\n\n\t\tthis.materialIndex = source.materialIndex;\n\n\t\tfor ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) {\n\n\t\t\tthis.vertexNormals[ i ] = source.vertexNormals[ i ].clone();\n\n\t\t}\n\n\t\tfor ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) {\n\n\t\t\tthis.vertexColors[ i ] = source.vertexColors[ i ].clone();\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Face3 };\n","import { EventDispatcher } from '../core/EventDispatcher.js';\nimport { FrontSide, FlatShading, NormalBlending, LessEqualDepth, AddEquation, OneMinusSrcAlphaFactor, SrcAlphaFactor, AlwaysStencilFunc, KeepStencilOp } from '../constants.js';\nimport { MathUtils } from '../math/MathUtils.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n */\n\nvar materialId = 0;\n\nfunction Material() {\n\n\tObject.defineProperty( this, 'id', { value: materialId ++ } );\n\n\tthis.uuid = MathUtils.generateUUID();\n\n\tthis.name = '';\n\tthis.type = 'Material';\n\n\tthis.fog = true;\n\n\tthis.blending = NormalBlending;\n\tthis.side = FrontSide;\n\tthis.flatShading = false;\n\tthis.vertexColors = false;\n\n\tthis.opacity = 1;\n\tthis.transparent = false;\n\n\tthis.blendSrc = SrcAlphaFactor;\n\tthis.blendDst = OneMinusSrcAlphaFactor;\n\tthis.blendEquation = AddEquation;\n\tthis.blendSrcAlpha = null;\n\tthis.blendDstAlpha = null;\n\tthis.blendEquationAlpha = null;\n\n\tthis.depthFunc = LessEqualDepth;\n\tthis.depthTest = true;\n\tthis.depthWrite = true;\n\n\tthis.stencilWriteMask = 0xff;\n\tthis.stencilFunc = AlwaysStencilFunc;\n\tthis.stencilRef = 0;\n\tthis.stencilFuncMask = 0xff;\n\tthis.stencilFail = KeepStencilOp;\n\tthis.stencilZFail = KeepStencilOp;\n\tthis.stencilZPass = KeepStencilOp;\n\tthis.stencilWrite = false;\n\n\tthis.clippingPlanes = null;\n\tthis.clipIntersection = false;\n\tthis.clipShadows = false;\n\n\tthis.shadowSide = null;\n\n\tthis.colorWrite = true;\n\n\tthis.precision = null; // override the renderer's default precision for this material\n\n\tthis.polygonOffset = false;\n\tthis.polygonOffsetFactor = 0;\n\tthis.polygonOffsetUnits = 0;\n\n\tthis.dithering = false;\n\n\tthis.alphaTest = 0;\n\tthis.premultipliedAlpha = false;\n\n\tthis.visible = true;\n\n\tthis.toneMapped = true;\n\n\tthis.userData = {};\n\n\tthis.version = 0;\n\n}\n\nMaterial.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: Material,\n\n\tisMaterial: true,\n\n\tonBeforeCompile: function () {},\n\n\tsetValues: function ( values ) {\n\n\t\tif ( values === undefined ) return;\n\n\t\tfor ( var key in values ) {\n\n\t\t\tvar newValue = values[ key ];\n\n\t\t\tif ( newValue === undefined ) {\n\n\t\t\t\tconsole.warn( \"THREE.Material: '\" + key + \"' parameter is undefined.\" );\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\t// for backward compatability if shading is set in the constructor\n\t\t\tif ( key === 'shading' ) {\n\n\t\t\t\tconsole.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );\n\t\t\t\tthis.flatShading = ( newValue === FlatShading ) ? true : false;\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\tvar currentValue = this[ key ];\n\n\t\t\tif ( currentValue === undefined ) {\n\n\t\t\t\tconsole.warn( \"THREE.\" + this.type + \": '\" + key + \"' is not a property of this material.\" );\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\tif ( currentValue && currentValue.isColor ) {\n\n\t\t\t\tcurrentValue.set( newValue );\n\n\t\t\t} else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {\n\n\t\t\t\tcurrentValue.copy( newValue );\n\n\t\t\t} else {\n\n\t\t\t\tthis[ key ] = newValue;\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\ttoJSON: function ( meta ) {\n\n\t\tvar isRoot = ( meta === undefined || typeof meta === 'string' );\n\n\t\tif ( isRoot ) {\n\n\t\t\tmeta = {\n\t\t\t\ttextures: {},\n\t\t\t\timages: {}\n\t\t\t};\n\n\t\t}\n\n\t\tvar data = {\n\t\t\tmetadata: {\n\t\t\t\tversion: 4.5,\n\t\t\t\ttype: 'Material',\n\t\t\t\tgenerator: 'Material.toJSON'\n\t\t\t}\n\t\t};\n\n\t\t// standard Material serialization\n\t\tdata.uuid = this.uuid;\n\t\tdata.type = this.type;\n\n\t\tif ( this.name !== '' ) data.name = this.name;\n\n\t\tif ( this.color && this.color.isColor ) data.color = this.color.getHex();\n\n\t\tif ( this.roughness !== undefined ) data.roughness = this.roughness;\n\t\tif ( this.metalness !== undefined ) data.metalness = this.metalness;\n\n\t\tif ( this.sheen && this.sheen.isColor ) data.sheen = this.sheen.getHex();\n\t\tif ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();\n\t\tif ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;\n\n\t\tif ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();\n\t\tif ( this.shininess !== undefined ) data.shininess = this.shininess;\n\t\tif ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat;\n\t\tif ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness;\n\n\t\tif ( this.clearcoatMap && this.clearcoatMap.isTexture ) {\n\n\t\t\tdata.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;\n\n\t\t}\n\n\t\tif ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {\n\n\t\t\tdata.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;\n\n\t\t}\n\n\t\tif ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {\n\n\t\t\tdata.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;\n\t\t\tdata.clearcoatNormalScale = this.clearcoatNormalScale.toArray();\n\n\t\t}\n\n\t\tif ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;\n\t\tif ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;\n\t\tif ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;\n\t\tif ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid;\n\n\t\tif ( this.aoMap && this.aoMap.isTexture ) {\n\n\t\t\tdata.aoMap = this.aoMap.toJSON( meta ).uuid;\n\t\t\tdata.aoMapIntensity = this.aoMapIntensity;\n\n\t\t}\n\n\t\tif ( this.bumpMap && this.bumpMap.isTexture ) {\n\n\t\t\tdata.bumpMap = this.bumpMap.toJSON( meta ).uuid;\n\t\t\tdata.bumpScale = this.bumpScale;\n\n\t\t}\n\n\t\tif ( this.normalMap && this.normalMap.isTexture ) {\n\n\t\t\tdata.normalMap = this.normalMap.toJSON( meta ).uuid;\n\t\t\tdata.normalMapType = this.normalMapType;\n\t\t\tdata.normalScale = this.normalScale.toArray();\n\n\t\t}\n\n\t\tif ( this.displacementMap && this.displacementMap.isTexture ) {\n\n\t\t\tdata.displacementMap = this.displacementMap.toJSON( meta ).uuid;\n\t\t\tdata.displacementScale = this.displacementScale;\n\t\t\tdata.displacementBias = this.displacementBias;\n\n\t\t}\n\n\t\tif ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;\n\t\tif ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;\n\n\t\tif ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;\n\t\tif ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;\n\n\t\tif ( this.envMap && this.envMap.isTexture ) {\n\n\t\t\tdata.envMap = this.envMap.toJSON( meta ).uuid;\n\t\t\tdata.reflectivity = this.reflectivity; // Scale behind envMap\n\t\t\tdata.refractionRatio = this.refractionRatio;\n\n\t\t\tif ( this.combine !== undefined ) data.combine = this.combine;\n\t\t\tif ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity;\n\n\t\t}\n\n\t\tif ( this.gradientMap && this.gradientMap.isTexture ) {\n\n\t\t\tdata.gradientMap = this.gradientMap.toJSON( meta ).uuid;\n\n\t\t}\n\n\t\tif ( this.size !== undefined ) data.size = this.size;\n\t\tif ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation;\n\n\t\tif ( this.blending !== NormalBlending ) data.blending = this.blending;\n\t\tif ( this.flatShading === true ) data.flatShading = this.flatShading;\n\t\tif ( this.side !== FrontSide ) data.side = this.side;\n\t\tif ( this.vertexColors ) data.vertexColors = true;\n\n\t\tif ( this.opacity < 1 ) data.opacity = this.opacity;\n\t\tif ( this.transparent === true ) data.transparent = this.transparent;\n\n\t\tdata.depthFunc = this.depthFunc;\n\t\tdata.depthTest = this.depthTest;\n\t\tdata.depthWrite = this.depthWrite;\n\n\t\tdata.stencilWrite = this.stencilWrite;\n\t\tdata.stencilWriteMask = this.stencilWriteMask;\n\t\tdata.stencilFunc = this.stencilFunc;\n\t\tdata.stencilRef = this.stencilRef;\n\t\tdata.stencilFuncMask = this.stencilFuncMask;\n\t\tdata.stencilFail = this.stencilFail;\n\t\tdata.stencilZFail = this.stencilZFail;\n\t\tdata.stencilZPass = this.stencilZPass;\n\n\t\t// rotation (SpriteMaterial)\n\t\tif ( this.rotation && this.rotation !== 0 ) data.rotation = this.rotation;\n\n\t\tif ( this.polygonOffset === true ) data.polygonOffset = true;\n\t\tif ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;\n\t\tif ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;\n\n\t\tif ( this.linewidth && this.linewidth !== 1 ) data.linewidth = this.linewidth;\n\t\tif ( this.dashSize !== undefined ) data.dashSize = this.dashSize;\n\t\tif ( this.gapSize !== undefined ) data.gapSize = this.gapSize;\n\t\tif ( this.scale !== undefined ) data.scale = this.scale;\n\n\t\tif ( this.dithering === true ) data.dithering = true;\n\n\t\tif ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;\n\t\tif ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;\n\n\t\tif ( this.wireframe === true ) data.wireframe = this.wireframe;\n\t\tif ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;\n\t\tif ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;\n\t\tif ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;\n\n\t\tif ( this.morphTargets === true ) data.morphTargets = true;\n\t\tif ( this.morphNormals === true ) data.morphNormals = true;\n\t\tif ( this.skinning === true ) data.skinning = true;\n\n\t\tif ( this.visible === false ) data.visible = false;\n\n\t\tif ( this.toneMapped === false ) data.toneMapped = false;\n\n\t\tif ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;\n\n\t\t// TODO: Copied from Object3D.toJSON\n\n\t\tfunction extractFromCache( cache ) {\n\n\t\t\tvar values = [];\n\n\t\t\tfor ( var key in cache ) {\n\n\t\t\t\tvar data = cache[ key ];\n\t\t\t\tdelete data.metadata;\n\t\t\t\tvalues.push( data );\n\n\t\t\t}\n\n\t\t\treturn values;\n\n\t\t}\n\n\t\tif ( isRoot ) {\n\n\t\t\tvar textures = extractFromCache( meta.textures );\n\t\t\tvar images = extractFromCache( meta.images );\n\n\t\t\tif ( textures.length > 0 ) data.textures = textures;\n\t\t\tif ( images.length > 0 ) data.images = images;\n\n\t\t}\n\n\t\treturn data;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tthis.name = source.name;\n\n\t\tthis.fog = source.fog;\n\n\t\tthis.blending = source.blending;\n\t\tthis.side = source.side;\n\t\tthis.flatShading = source.flatShading;\n\t\tthis.vertexColors = source.vertexColors;\n\n\t\tthis.opacity = source.opacity;\n\t\tthis.transparent = source.transparent;\n\n\t\tthis.blendSrc = source.blendSrc;\n\t\tthis.blendDst = source.blendDst;\n\t\tthis.blendEquation = source.blendEquation;\n\t\tthis.blendSrcAlpha = source.blendSrcAlpha;\n\t\tthis.blendDstAlpha = source.blendDstAlpha;\n\t\tthis.blendEquationAlpha = source.blendEquationAlpha;\n\n\t\tthis.depthFunc = source.depthFunc;\n\t\tthis.depthTest = source.depthTest;\n\t\tthis.depthWrite = source.depthWrite;\n\n\t\tthis.stencilWriteMask = source.stencilWriteMask;\n\t\tthis.stencilFunc = source.stencilFunc;\n\t\tthis.stencilRef = source.stencilRef;\n\t\tthis.stencilFuncMask = source.stencilFuncMask;\n\t\tthis.stencilFail = source.stencilFail;\n\t\tthis.stencilZFail = source.stencilZFail;\n\t\tthis.stencilZPass = source.stencilZPass;\n\t\tthis.stencilWrite = source.stencilWrite;\n\n\t\tvar srcPlanes = source.clippingPlanes,\n\t\t\tdstPlanes = null;\n\n\t\tif ( srcPlanes !== null ) {\n\n\t\t\tvar n = srcPlanes.length;\n\t\t\tdstPlanes = new Array( n );\n\n\t\t\tfor ( var i = 0; i !== n; ++ i )\n\t\t\t\tdstPlanes[ i ] = srcPlanes[ i ].clone();\n\n\t\t}\n\n\t\tthis.clippingPlanes = dstPlanes;\n\t\tthis.clipIntersection = source.clipIntersection;\n\t\tthis.clipShadows = source.clipShadows;\n\n\t\tthis.shadowSide = source.shadowSide;\n\n\t\tthis.colorWrite = source.colorWrite;\n\n\t\tthis.precision = source.precision;\n\n\t\tthis.polygonOffset = source.polygonOffset;\n\t\tthis.polygonOffsetFactor = source.polygonOffsetFactor;\n\t\tthis.polygonOffsetUnits = source.polygonOffsetUnits;\n\n\t\tthis.dithering = source.dithering;\n\n\t\tthis.alphaTest = source.alphaTest;\n\t\tthis.premultipliedAlpha = source.premultipliedAlpha;\n\n\t\tthis.visible = source.visible;\n\n\t\tthis.toneMapped = source.toneMapped;\n\n\t\tthis.userData = JSON.parse( JSON.stringify( source.userData ) );\n\n\t\treturn this;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t}\n\n} );\n\nObject.defineProperty( Material.prototype, 'needsUpdate', {\n\n\tset: function ( value ) {\n\n\t\tif ( value === true ) this.version ++;\n\n\t}\n\n} );\n\nexport { Material };\n","import { Material } from './Material.js';\nimport { MultiplyOperation } from '../constants.js';\nimport { Color } from '../math/Color.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n *\n * parameters = {\n * color: ,\n * opacity: ,\n * map: new THREE.Texture( ),\n *\n * lightMap: new THREE.Texture( ),\n * lightMapIntensity: \n *\n * aoMap: new THREE.Texture( ),\n * aoMapIntensity: \n *\n * specularMap: new THREE.Texture( ),\n *\n * alphaMap: new THREE.Texture( ),\n *\n * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ),\n * combine: THREE.Multiply,\n * reflectivity: ,\n * refractionRatio: ,\n *\n * depthTest: ,\n * depthWrite: ,\n *\n * wireframe: ,\n * wireframeLinewidth: ,\n *\n * skinning: ,\n * morphTargets: \n * }\n */\n\nfunction MeshBasicMaterial( parameters ) {\n\n\tMaterial.call( this );\n\n\tthis.type = 'MeshBasicMaterial';\n\n\tthis.color = new Color( 0xffffff ); // emissive\n\n\tthis.map = null;\n\n\tthis.lightMap = null;\n\tthis.lightMapIntensity = 1.0;\n\n\tthis.aoMap = null;\n\tthis.aoMapIntensity = 1.0;\n\n\tthis.specularMap = null;\n\n\tthis.alphaMap = null;\n\n\tthis.envMap = null;\n\tthis.combine = MultiplyOperation;\n\tthis.reflectivity = 1;\n\tthis.refractionRatio = 0.98;\n\n\tthis.wireframe = false;\n\tthis.wireframeLinewidth = 1;\n\tthis.wireframeLinecap = 'round';\n\tthis.wireframeLinejoin = 'round';\n\n\tthis.skinning = false;\n\tthis.morphTargets = false;\n\n\tthis.setValues( parameters );\n\n}\n\nMeshBasicMaterial.prototype = Object.create( Material.prototype );\nMeshBasicMaterial.prototype.constructor = MeshBasicMaterial;\n\nMeshBasicMaterial.prototype.isMeshBasicMaterial = true;\n\nMeshBasicMaterial.prototype.copy = function ( source ) {\n\n\tMaterial.prototype.copy.call( this, source );\n\n\tthis.color.copy( source.color );\n\n\tthis.map = source.map;\n\n\tthis.lightMap = source.lightMap;\n\tthis.lightMapIntensity = source.lightMapIntensity;\n\n\tthis.aoMap = source.aoMap;\n\tthis.aoMapIntensity = source.aoMapIntensity;\n\n\tthis.specularMap = source.specularMap;\n\n\tthis.alphaMap = source.alphaMap;\n\n\tthis.envMap = source.envMap;\n\tthis.combine = source.combine;\n\tthis.reflectivity = source.reflectivity;\n\tthis.refractionRatio = source.refractionRatio;\n\n\tthis.wireframe = source.wireframe;\n\tthis.wireframeLinewidth = source.wireframeLinewidth;\n\tthis.wireframeLinecap = source.wireframeLinecap;\n\tthis.wireframeLinejoin = source.wireframeLinejoin;\n\n\tthis.skinning = source.skinning;\n\tthis.morphTargets = source.morphTargets;\n\n\treturn this;\n\n};\n\n\nexport { MeshBasicMaterial };\n","import { Vector4 } from '../math/Vector4.js';\nimport { Vector3 } from '../math/Vector3.js';\nimport { Vector2 } from '../math/Vector2.js';\nimport { Color } from '../math/Color.js';\nimport { StaticDrawUsage } from '../constants.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar _vector = new Vector3();\n\nfunction BufferAttribute( array, itemSize, normalized ) {\n\n\tif ( Array.isArray( array ) ) {\n\n\t\tthrow new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' );\n\n\t}\n\n\tthis.name = '';\n\n\tthis.array = array;\n\tthis.itemSize = itemSize;\n\tthis.count = array !== undefined ? array.length / itemSize : 0;\n\tthis.normalized = normalized === true;\n\n\tthis.usage = StaticDrawUsage;\n\tthis.updateRange = { offset: 0, count: - 1 };\n\n\tthis.version = 0;\n\n}\n\nObject.defineProperty( BufferAttribute.prototype, 'needsUpdate', {\n\n\tset: function ( value ) {\n\n\t\tif ( value === true ) this.version ++;\n\n\t}\n\n} );\n\nObject.assign( BufferAttribute.prototype, {\n\n\tisBufferAttribute: true,\n\n\tonUploadCallback: function () {},\n\n\tsetUsage: function ( value ) {\n\n\t\tthis.usage = value;\n\n\t\treturn this;\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tthis.name = source.name;\n\t\tthis.array = new source.array.constructor( source.array );\n\t\tthis.itemSize = source.itemSize;\n\t\tthis.count = source.count;\n\t\tthis.normalized = source.normalized;\n\n\t\tthis.usage = source.usage;\n\n\t\treturn this;\n\n\t},\n\n\tcopyAt: function ( index1, attribute, index2 ) {\n\n\t\tindex1 *= this.itemSize;\n\t\tindex2 *= attribute.itemSize;\n\n\t\tfor ( var i = 0, l = this.itemSize; i < l; i ++ ) {\n\n\t\t\tthis.array[ index1 + i ] = attribute.array[ index2 + i ];\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcopyArray: function ( array ) {\n\n\t\tthis.array.set( array );\n\n\t\treturn this;\n\n\t},\n\n\tcopyColorsArray: function ( colors ) {\n\n\t\tvar array = this.array, offset = 0;\n\n\t\tfor ( var i = 0, l = colors.length; i < l; i ++ ) {\n\n\t\t\tvar color = colors[ i ];\n\n\t\t\tif ( color === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i );\n\t\t\t\tcolor = new Color();\n\n\t\t\t}\n\n\t\t\tarray[ offset ++ ] = color.r;\n\t\t\tarray[ offset ++ ] = color.g;\n\t\t\tarray[ offset ++ ] = color.b;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcopyVector2sArray: function ( vectors ) {\n\n\t\tvar array = this.array, offset = 0;\n\n\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\n\n\t\t\tvar vector = vectors[ i ];\n\n\t\t\tif ( vector === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i );\n\t\t\t\tvector = new Vector2();\n\n\t\t\t}\n\n\t\t\tarray[ offset ++ ] = vector.x;\n\t\t\tarray[ offset ++ ] = vector.y;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcopyVector3sArray: function ( vectors ) {\n\n\t\tvar array = this.array, offset = 0;\n\n\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\n\n\t\t\tvar vector = vectors[ i ];\n\n\t\t\tif ( vector === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i );\n\t\t\t\tvector = new Vector3();\n\n\t\t\t}\n\n\t\t\tarray[ offset ++ ] = vector.x;\n\t\t\tarray[ offset ++ ] = vector.y;\n\t\t\tarray[ offset ++ ] = vector.z;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcopyVector4sArray: function ( vectors ) {\n\n\t\tvar array = this.array, offset = 0;\n\n\t\tfor ( var i = 0, l = vectors.length; i < l; i ++ ) {\n\n\t\t\tvar vector = vectors[ i ];\n\n\t\t\tif ( vector === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i );\n\t\t\t\tvector = new Vector4();\n\n\t\t\t}\n\n\t\t\tarray[ offset ++ ] = vector.x;\n\t\t\tarray[ offset ++ ] = vector.y;\n\t\t\tarray[ offset ++ ] = vector.z;\n\t\t\tarray[ offset ++ ] = vector.w;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tapplyMatrix3: function ( m ) {\n\n\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\n\n\t\t\t_vector.x = this.getX( i );\n\t\t\t_vector.y = this.getY( i );\n\t\t\t_vector.z = this.getZ( i );\n\n\t\t\t_vector.applyMatrix3( m );\n\n\t\t\tthis.setXYZ( i, _vector.x, _vector.y, _vector.z );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tapplyMatrix4: function ( m ) {\n\n\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\n\n\t\t\t_vector.x = this.getX( i );\n\t\t\t_vector.y = this.getY( i );\n\t\t\t_vector.z = this.getZ( i );\n\n\t\t\t_vector.applyMatrix4( m );\n\n\t\t\tthis.setXYZ( i, _vector.x, _vector.y, _vector.z );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tapplyNormalMatrix: function ( m ) {\n\n\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\n\n\t\t\t_vector.x = this.getX( i );\n\t\t\t_vector.y = this.getY( i );\n\t\t\t_vector.z = this.getZ( i );\n\n\t\t\t_vector.applyNormalMatrix( m );\n\n\t\t\tthis.setXYZ( i, _vector.x, _vector.y, _vector.z );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\ttransformDirection: function ( m ) {\n\n\t\tfor ( var i = 0, l = this.count; i < l; i ++ ) {\n\n\t\t\t_vector.x = this.getX( i );\n\t\t\t_vector.y = this.getY( i );\n\t\t\t_vector.z = this.getZ( i );\n\n\t\t\t_vector.transformDirection( m );\n\n\t\t\tthis.setXYZ( i, _vector.x, _vector.y, _vector.z );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tset: function ( value, offset ) {\n\n\t\tif ( offset === undefined ) offset = 0;\n\n\t\tthis.array.set( value, offset );\n\n\t\treturn this;\n\n\t},\n\n\tgetX: function ( index ) {\n\n\t\treturn this.array[ index * this.itemSize ];\n\n\t},\n\n\tsetX: function ( index, x ) {\n\n\t\tthis.array[ index * this.itemSize ] = x;\n\n\t\treturn this;\n\n\t},\n\n\tgetY: function ( index ) {\n\n\t\treturn this.array[ index * this.itemSize + 1 ];\n\n\t},\n\n\tsetY: function ( index, y ) {\n\n\t\tthis.array[ index * this.itemSize + 1 ] = y;\n\n\t\treturn this;\n\n\t},\n\n\tgetZ: function ( index ) {\n\n\t\treturn this.array[ index * this.itemSize + 2 ];\n\n\t},\n\n\tsetZ: function ( index, z ) {\n\n\t\tthis.array[ index * this.itemSize + 2 ] = z;\n\n\t\treturn this;\n\n\t},\n\n\tgetW: function ( index ) {\n\n\t\treturn this.array[ index * this.itemSize + 3 ];\n\n\t},\n\n\tsetW: function ( index, w ) {\n\n\t\tthis.array[ index * this.itemSize + 3 ] = w;\n\n\t\treturn this;\n\n\t},\n\n\tsetXY: function ( index, x, y ) {\n\n\t\tindex *= this.itemSize;\n\n\t\tthis.array[ index + 0 ] = x;\n\t\tthis.array[ index + 1 ] = y;\n\n\t\treturn this;\n\n\t},\n\n\tsetXYZ: function ( index, x, y, z ) {\n\n\t\tindex *= this.itemSize;\n\n\t\tthis.array[ index + 0 ] = x;\n\t\tthis.array[ index + 1 ] = y;\n\t\tthis.array[ index + 2 ] = z;\n\n\t\treturn this;\n\n\t},\n\n\tsetXYZW: function ( index, x, y, z, w ) {\n\n\t\tindex *= this.itemSize;\n\n\t\tthis.array[ index + 0 ] = x;\n\t\tthis.array[ index + 1 ] = y;\n\t\tthis.array[ index + 2 ] = z;\n\t\tthis.array[ index + 3 ] = w;\n\n\t\treturn this;\n\n\t},\n\n\tonUpload: function ( callback ) {\n\n\t\tthis.onUploadCallback = callback;\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.array, this.itemSize ).copy( this );\n\n\t},\n\n\ttoJSON: function () {\n\n\t\treturn {\n\t\t\titemSize: this.itemSize,\n\t\t\ttype: this.array.constructor.name,\n\t\t\tarray: Array.prototype.slice.call( this.array ),\n\t\t\tnormalized: this.normalized\n\t\t};\n\n\t}\n\n} );\n\n//\n\nfunction Int8BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Int8Array( array ), itemSize, normalized );\n\n}\n\nInt8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nInt8BufferAttribute.prototype.constructor = Int8BufferAttribute;\n\n\nfunction Uint8BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized );\n\n}\n\nUint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nUint8BufferAttribute.prototype.constructor = Uint8BufferAttribute;\n\n\nfunction Uint8ClampedBufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized );\n\n}\n\nUint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nUint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute;\n\n\nfunction Int16BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Int16Array( array ), itemSize, normalized );\n\n}\n\nInt16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nInt16BufferAttribute.prototype.constructor = Int16BufferAttribute;\n\n\nfunction Uint16BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized );\n\n}\n\nUint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nUint16BufferAttribute.prototype.constructor = Uint16BufferAttribute;\n\n\nfunction Int32BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Int32Array( array ), itemSize, normalized );\n\n}\n\nInt32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nInt32BufferAttribute.prototype.constructor = Int32BufferAttribute;\n\n\nfunction Uint32BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized );\n\n}\n\nUint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nUint32BufferAttribute.prototype.constructor = Uint32BufferAttribute;\n\n\nfunction Float32BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Float32Array( array ), itemSize, normalized );\n\n}\n\nFloat32BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nFloat32BufferAttribute.prototype.constructor = Float32BufferAttribute;\n\n\nfunction Float64BufferAttribute( array, itemSize, normalized ) {\n\n\tBufferAttribute.call( this, new Float64Array( array ), itemSize, normalized );\n\n}\n\nFloat64BufferAttribute.prototype = Object.create( BufferAttribute.prototype );\nFloat64BufferAttribute.prototype.constructor = Float64BufferAttribute;\n\n//\n\nexport {\n\tFloat64BufferAttribute,\n\tFloat32BufferAttribute,\n\tUint32BufferAttribute,\n\tInt32BufferAttribute,\n\tUint16BufferAttribute,\n\tInt16BufferAttribute,\n\tUint8ClampedBufferAttribute,\n\tUint8BufferAttribute,\n\tInt8BufferAttribute,\n\tBufferAttribute\n};\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { Vector2 } from '../math/Vector2.js';\n\nfunction DirectGeometry() {\n\n\tthis.vertices = [];\n\tthis.normals = [];\n\tthis.colors = [];\n\tthis.uvs = [];\n\tthis.uvs2 = [];\n\n\tthis.groups = [];\n\n\tthis.morphTargets = {};\n\n\tthis.skinWeights = [];\n\tthis.skinIndices = [];\n\n\t// this.lineDistances = [];\n\n\tthis.boundingBox = null;\n\tthis.boundingSphere = null;\n\n\t// update flags\n\n\tthis.verticesNeedUpdate = false;\n\tthis.normalsNeedUpdate = false;\n\tthis.colorsNeedUpdate = false;\n\tthis.uvsNeedUpdate = false;\n\tthis.groupsNeedUpdate = false;\n\n}\n\nObject.assign( DirectGeometry.prototype, {\n\n\tcomputeGroups: function ( geometry ) {\n\n\t\tvar group;\n\t\tvar groups = [];\n\t\tvar materialIndex = undefined;\n\n\t\tvar faces = geometry.faces;\n\n\t\tfor ( var i = 0; i < faces.length; i ++ ) {\n\n\t\t\tvar face = faces[ i ];\n\n\t\t\t// materials\n\n\t\t\tif ( face.materialIndex !== materialIndex ) {\n\n\t\t\t\tmaterialIndex = face.materialIndex;\n\n\t\t\t\tif ( group !== undefined ) {\n\n\t\t\t\t\tgroup.count = ( i * 3 ) - group.start;\n\t\t\t\t\tgroups.push( group );\n\n\t\t\t\t}\n\n\t\t\t\tgroup = {\n\t\t\t\t\tstart: i * 3,\n\t\t\t\t\tmaterialIndex: materialIndex\n\t\t\t\t};\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( group !== undefined ) {\n\n\t\t\tgroup.count = ( i * 3 ) - group.start;\n\t\t\tgroups.push( group );\n\n\t\t}\n\n\t\tthis.groups = groups;\n\n\t},\n\n\tfromGeometry: function ( geometry ) {\n\n\t\tvar faces = geometry.faces;\n\t\tvar vertices = geometry.vertices;\n\t\tvar faceVertexUvs = geometry.faceVertexUvs;\n\n\t\tvar hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;\n\t\tvar hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;\n\n\t\t// morphs\n\n\t\tvar morphTargets = geometry.morphTargets;\n\t\tvar morphTargetsLength = morphTargets.length;\n\n\t\tvar morphTargetsPosition;\n\n\t\tif ( morphTargetsLength > 0 ) {\n\n\t\t\tmorphTargetsPosition = [];\n\n\t\t\tfor ( var i = 0; i < morphTargetsLength; i ++ ) {\n\n\t\t\t\tmorphTargetsPosition[ i ] = {\n\t\t\t\t\tname: morphTargets[ i ].name,\n\t\t\t\t \tdata: []\n\t\t\t\t};\n\n\t\t\t}\n\n\t\t\tthis.morphTargets.position = morphTargetsPosition;\n\n\t\t}\n\n\t\tvar morphNormals = geometry.morphNormals;\n\t\tvar morphNormalsLength = morphNormals.length;\n\n\t\tvar morphTargetsNormal;\n\n\t\tif ( morphNormalsLength > 0 ) {\n\n\t\t\tmorphTargetsNormal = [];\n\n\t\t\tfor ( var i = 0; i < morphNormalsLength; i ++ ) {\n\n\t\t\t\tmorphTargetsNormal[ i ] = {\n\t\t\t\t\tname: morphNormals[ i ].name,\n\t\t\t\t \tdata: []\n\t\t\t\t};\n\n\t\t\t}\n\n\t\t\tthis.morphTargets.normal = morphTargetsNormal;\n\n\t\t}\n\n\t\t// skins\n\n\t\tvar skinIndices = geometry.skinIndices;\n\t\tvar skinWeights = geometry.skinWeights;\n\n\t\tvar hasSkinIndices = skinIndices.length === vertices.length;\n\t\tvar hasSkinWeights = skinWeights.length === vertices.length;\n\n\t\t//\n\n\t\tif ( vertices.length > 0 && faces.length === 0 ) {\n\n\t\t\tconsole.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' );\n\n\t\t}\n\n\t\tfor ( var i = 0; i < faces.length; i ++ ) {\n\n\t\t\tvar face = faces[ i ];\n\n\t\t\tthis.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] );\n\n\t\t\tvar vertexNormals = face.vertexNormals;\n\n\t\t\tif ( vertexNormals.length === 3 ) {\n\n\t\t\t\tthis.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] );\n\n\t\t\t} else {\n\n\t\t\t\tvar normal = face.normal;\n\n\t\t\t\tthis.normals.push( normal, normal, normal );\n\n\t\t\t}\n\n\t\t\tvar vertexColors = face.vertexColors;\n\n\t\t\tif ( vertexColors.length === 3 ) {\n\n\t\t\t\tthis.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] );\n\n\t\t\t} else {\n\n\t\t\t\tvar color = face.color;\n\n\t\t\t\tthis.colors.push( color, color, color );\n\n\t\t\t}\n\n\t\t\tif ( hasFaceVertexUv === true ) {\n\n\t\t\t\tvar vertexUvs = faceVertexUvs[ 0 ][ i ];\n\n\t\t\t\tif ( vertexUvs !== undefined ) {\n\n\t\t\t\t\tthis.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );\n\n\t\t\t\t\tthis.uvs.push( new Vector2(), new Vector2(), new Vector2() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( hasFaceVertexUv2 === true ) {\n\n\t\t\t\tvar vertexUvs = faceVertexUvs[ 1 ][ i ];\n\n\t\t\t\tif ( vertexUvs !== undefined ) {\n\n\t\t\t\t\tthis.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );\n\n\t\t\t\t\tthis.uvs2.push( new Vector2(), new Vector2(), new Vector2() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// morphs\n\n\t\t\tfor ( var j = 0; j < morphTargetsLength; j ++ ) {\n\n\t\t\t\tvar morphTarget = morphTargets[ j ].vertices;\n\n\t\t\t\tmorphTargetsPosition[ j ].data.push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] );\n\n\t\t\t}\n\n\t\t\tfor ( var j = 0; j < morphNormalsLength; j ++ ) {\n\n\t\t\t\tvar morphNormal = morphNormals[ j ].vertexNormals[ i ];\n\n\t\t\t\tmorphTargetsNormal[ j ].data.push( morphNormal.a, morphNormal.b, morphNormal.c );\n\n\t\t\t}\n\n\t\t\t// skins\n\n\t\t\tif ( hasSkinIndices ) {\n\n\t\t\t\tthis.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] );\n\n\t\t\t}\n\n\t\t\tif ( hasSkinWeights ) {\n\n\t\t\t\tthis.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] );\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis.computeGroups( geometry );\n\n\t\tthis.verticesNeedUpdate = geometry.verticesNeedUpdate;\n\t\tthis.normalsNeedUpdate = geometry.normalsNeedUpdate;\n\t\tthis.colorsNeedUpdate = geometry.colorsNeedUpdate;\n\t\tthis.uvsNeedUpdate = geometry.uvsNeedUpdate;\n\t\tthis.groupsNeedUpdate = geometry.groupsNeedUpdate;\n\n\t\tif ( geometry.boundingSphere !== null ) {\n\n\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\n\n\t\t}\n\n\t\tif ( geometry.boundingBox !== null ) {\n\n\t\t\tthis.boundingBox = geometry.boundingBox.clone();\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { DirectGeometry };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction arrayMin( array ) {\n\n\tif ( array.length === 0 ) return Infinity;\n\n\tlet min = array[ 0 ];\n\n\tfor ( let i = 1, l = array.length; i < l; ++ i ) {\n\n\t\tif ( array[ i ] < min ) min = array[ i ];\n\n\t}\n\n\treturn min;\n\n}\n\nfunction arrayMax( array ) {\n\n\tif ( array.length === 0 ) return - Infinity;\n\n\tlet max = array[ 0 ];\n\n\tfor ( let i = 1, l = array.length; i < l; ++ i ) {\n\n\t\tif ( array[ i ] > max ) max = array[ i ];\n\n\t}\n\n\treturn max;\n\n}\n\nexport { arrayMin, arrayMax };\n","import { Vector3 } from '../math/Vector3.js';\nimport { Box3 } from '../math/Box3.js';\nimport { EventDispatcher } from './EventDispatcher.js';\nimport { BufferAttribute, Float32BufferAttribute, Uint16BufferAttribute, Uint32BufferAttribute } from './BufferAttribute.js';\nimport { Sphere } from '../math/Sphere.js';\nimport { DirectGeometry } from './DirectGeometry.js';\nimport { Object3D } from './Object3D.js';\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { Matrix3 } from '../math/Matrix3.js';\nimport { MathUtils } from '../math/MathUtils.js';\nimport { arrayMax } from '../utils.js';\n\n/**\n * @author alteredq / http://alteredqualia.com/\n * @author mrdoob / http://mrdoob.com/\n */\n\nvar _bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id\n\nvar _m1 = new Matrix4();\nvar _obj = new Object3D();\nvar _offset = new Vector3();\nvar _box = new Box3();\nvar _boxMorphTargets = new Box3();\nvar _vector = new Vector3();\n\nfunction BufferGeometry() {\n\n\tObject.defineProperty( this, 'id', { value: _bufferGeometryId += 2 } );\n\n\tthis.uuid = MathUtils.generateUUID();\n\n\tthis.name = '';\n\tthis.type = 'BufferGeometry';\n\n\tthis.index = null;\n\tthis.attributes = {};\n\n\tthis.morphAttributes = {};\n\tthis.morphTargetsRelative = false;\n\n\tthis.groups = [];\n\n\tthis.boundingBox = null;\n\tthis.boundingSphere = null;\n\n\tthis.drawRange = { start: 0, count: Infinity };\n\n\tthis.userData = {};\n\n}\n\nBufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: BufferGeometry,\n\n\tisBufferGeometry: true,\n\n\tgetIndex: function () {\n\n\t\treturn this.index;\n\n\t},\n\n\tsetIndex: function ( index ) {\n\n\t\tif ( Array.isArray( index ) ) {\n\n\t\t\tthis.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );\n\n\t\t} else {\n\n\t\t\tthis.index = index;\n\n\t\t}\n\n\t},\n\n\tgetAttribute: function ( name ) {\n\n\t\treturn this.attributes[ name ];\n\n\t},\n\n\tsetAttribute: function ( name, attribute ) {\n\n\t\tthis.attributes[ name ] = attribute;\n\n\t\treturn this;\n\n\t},\n\n\tdeleteAttribute: function ( name ) {\n\n\t\tdelete this.attributes[ name ];\n\n\t\treturn this;\n\n\t},\n\n\taddGroup: function ( start, count, materialIndex ) {\n\n\t\tthis.groups.push( {\n\n\t\t\tstart: start,\n\t\t\tcount: count,\n\t\t\tmaterialIndex: materialIndex !== undefined ? materialIndex : 0\n\n\t\t} );\n\n\t},\n\n\tclearGroups: function () {\n\n\t\tthis.groups = [];\n\n\t},\n\n\tsetDrawRange: function ( start, count ) {\n\n\t\tthis.drawRange.start = start;\n\t\tthis.drawRange.count = count;\n\n\t},\n\n\tapplyMatrix4: function ( matrix ) {\n\n\t\tvar position = this.attributes.position;\n\n\t\tif ( position !== undefined ) {\n\n\t\t\tposition.applyMatrix4( matrix );\n\n\t\t\tposition.needsUpdate = true;\n\n\t\t}\n\n\t\tvar normal = this.attributes.normal;\n\n\t\tif ( normal !== undefined ) {\n\n\t\t\tvar normalMatrix = new Matrix3().getNormalMatrix( matrix );\n\n\t\t\tnormal.applyNormalMatrix( normalMatrix );\n\n\t\t\tnormal.needsUpdate = true;\n\n\t\t}\n\n\t\tvar tangent = this.attributes.tangent;\n\n\t\tif ( tangent !== undefined ) {\n\n\t\t\ttangent.transformDirection( matrix );\n\n\t\t\ttangent.needsUpdate = true;\n\n\t\t}\n\n\t\tif ( this.boundingBox !== null ) {\n\n\t\t\tthis.computeBoundingBox();\n\n\t\t}\n\n\t\tif ( this.boundingSphere !== null ) {\n\n\t\t\tthis.computeBoundingSphere();\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\trotateX: function ( angle ) {\n\n\t\t// rotate geometry around world x-axis\n\n\t\t_m1.makeRotationX( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateY: function ( angle ) {\n\n\t\t// rotate geometry around world y-axis\n\n\t\t_m1.makeRotationY( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateZ: function ( angle ) {\n\n\t\t// rotate geometry around world z-axis\n\n\t\t_m1.makeRotationZ( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( x, y, z ) {\n\n\t\t// translate geometry\n\n\t\t_m1.makeTranslation( x, y, z );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\tscale: function ( x, y, z ) {\n\n\t\t// scale geometry\n\n\t\t_m1.makeScale( x, y, z );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\tlookAt: function ( vector ) {\n\n\t\t_obj.lookAt( vector );\n\n\t\t_obj.updateMatrix();\n\n\t\tthis.applyMatrix4( _obj.matrix );\n\n\t\treturn this;\n\n\t},\n\n\tcenter: function () {\n\n\t\tthis.computeBoundingBox();\n\n\t\tthis.boundingBox.getCenter( _offset ).negate();\n\n\t\tthis.translate( _offset.x, _offset.y, _offset.z );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromObject: function ( object ) {\n\n\t\t// console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this );\n\n\t\tvar geometry = object.geometry;\n\n\t\tif ( object.isPoints || object.isLine ) {\n\n\t\t\tvar positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 );\n\t\t\tvar colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 );\n\n\t\t\tthis.setAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) );\n\t\t\tthis.setAttribute( 'color', colors.copyColorsArray( geometry.colors ) );\n\n\t\t\tif ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) {\n\n\t\t\t\tvar lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 );\n\n\t\t\t\tthis.setAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) );\n\n\t\t\t}\n\n\t\t\tif ( geometry.boundingSphere !== null ) {\n\n\t\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\n\n\t\t\t}\n\n\t\t\tif ( geometry.boundingBox !== null ) {\n\n\t\t\t\tthis.boundingBox = geometry.boundingBox.clone();\n\n\t\t\t}\n\n\t\t} else if ( object.isMesh ) {\n\n\t\t\tif ( geometry && geometry.isGeometry ) {\n\n\t\t\t\tthis.fromGeometry( geometry );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetFromPoints: function ( points ) {\n\n\t\tvar position = [];\n\n\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\n\n\t\t\tvar point = points[ i ];\n\t\t\tposition.push( point.x, point.y, point.z || 0 );\n\n\t\t}\n\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) );\n\n\t\treturn this;\n\n\t},\n\n\tupdateFromObject: function ( object ) {\n\n\t\tvar geometry = object.geometry;\n\n\t\tif ( object.isMesh ) {\n\n\t\t\tvar direct = geometry.__directGeometry;\n\n\t\t\tif ( geometry.elementsNeedUpdate === true ) {\n\n\t\t\t\tdirect = undefined;\n\t\t\t\tgeometry.elementsNeedUpdate = false;\n\n\t\t\t}\n\n\t\t\tif ( direct === undefined ) {\n\n\t\t\t\treturn this.fromGeometry( geometry );\n\n\t\t\t}\n\n\t\t\tdirect.verticesNeedUpdate = geometry.verticesNeedUpdate;\n\t\t\tdirect.normalsNeedUpdate = geometry.normalsNeedUpdate;\n\t\t\tdirect.colorsNeedUpdate = geometry.colorsNeedUpdate;\n\t\t\tdirect.uvsNeedUpdate = geometry.uvsNeedUpdate;\n\t\t\tdirect.groupsNeedUpdate = geometry.groupsNeedUpdate;\n\n\t\t\tgeometry.verticesNeedUpdate = false;\n\t\t\tgeometry.normalsNeedUpdate = false;\n\t\t\tgeometry.colorsNeedUpdate = false;\n\t\t\tgeometry.uvsNeedUpdate = false;\n\t\t\tgeometry.groupsNeedUpdate = false;\n\n\t\t\tgeometry = direct;\n\n\t\t}\n\n\t\tvar attribute;\n\n\t\tif ( geometry.verticesNeedUpdate === true ) {\n\n\t\t\tattribute = this.attributes.position;\n\n\t\t\tif ( attribute !== undefined ) {\n\n\t\t\t\tattribute.copyVector3sArray( geometry.vertices );\n\t\t\t\tattribute.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tgeometry.verticesNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( geometry.normalsNeedUpdate === true ) {\n\n\t\t\tattribute = this.attributes.normal;\n\n\t\t\tif ( attribute !== undefined ) {\n\n\t\t\t\tattribute.copyVector3sArray( geometry.normals );\n\t\t\t\tattribute.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tgeometry.normalsNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( geometry.colorsNeedUpdate === true ) {\n\n\t\t\tattribute = this.attributes.color;\n\n\t\t\tif ( attribute !== undefined ) {\n\n\t\t\t\tattribute.copyColorsArray( geometry.colors );\n\t\t\t\tattribute.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tgeometry.colorsNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( geometry.uvsNeedUpdate ) {\n\n\t\t\tattribute = this.attributes.uv;\n\n\t\t\tif ( attribute !== undefined ) {\n\n\t\t\t\tattribute.copyVector2sArray( geometry.uvs );\n\t\t\t\tattribute.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tgeometry.uvsNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( geometry.lineDistancesNeedUpdate ) {\n\n\t\t\tattribute = this.attributes.lineDistance;\n\n\t\t\tif ( attribute !== undefined ) {\n\n\t\t\t\tattribute.copyArray( geometry.lineDistances );\n\t\t\t\tattribute.needsUpdate = true;\n\n\t\t\t}\n\n\t\t\tgeometry.lineDistancesNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( geometry.groupsNeedUpdate ) {\n\n\t\t\tgeometry.computeGroups( object.geometry );\n\t\t\tthis.groups = geometry.groups;\n\n\t\t\tgeometry.groupsNeedUpdate = false;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tfromGeometry: function ( geometry ) {\n\n\t\tgeometry.__directGeometry = new DirectGeometry().fromGeometry( geometry );\n\n\t\treturn this.fromDirectGeometry( geometry.__directGeometry );\n\n\t},\n\n\tfromDirectGeometry: function ( geometry ) {\n\n\t\tvar positions = new Float32Array( geometry.vertices.length * 3 );\n\t\tthis.setAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) );\n\n\t\tif ( geometry.normals.length > 0 ) {\n\n\t\t\tvar normals = new Float32Array( geometry.normals.length * 3 );\n\t\t\tthis.setAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) );\n\n\t\t}\n\n\t\tif ( geometry.colors.length > 0 ) {\n\n\t\t\tvar colors = new Float32Array( geometry.colors.length * 3 );\n\t\t\tthis.setAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) );\n\n\t\t}\n\n\t\tif ( geometry.uvs.length > 0 ) {\n\n\t\t\tvar uvs = new Float32Array( geometry.uvs.length * 2 );\n\t\t\tthis.setAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) );\n\n\t\t}\n\n\t\tif ( geometry.uvs2.length > 0 ) {\n\n\t\t\tvar uvs2 = new Float32Array( geometry.uvs2.length * 2 );\n\t\t\tthis.setAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );\n\n\t\t}\n\n\t\t// groups\n\n\t\tthis.groups = geometry.groups;\n\n\t\t// morphs\n\n\t\tfor ( var name in geometry.morphTargets ) {\n\n\t\t\tvar array = [];\n\t\t\tvar morphTargets = geometry.morphTargets[ name ];\n\n\t\t\tfor ( var i = 0, l = morphTargets.length; i < l; i ++ ) {\n\n\t\t\t\tvar morphTarget = morphTargets[ i ];\n\n\t\t\t\tvar attribute = new Float32BufferAttribute( morphTarget.data.length * 3, 3 );\n\t\t\t\tattribute.name = morphTarget.name;\n\n\t\t\t\tarray.push( attribute.copyVector3sArray( morphTarget.data ) );\n\n\t\t\t}\n\n\t\t\tthis.morphAttributes[ name ] = array;\n\n\t\t}\n\n\t\t// skinning\n\n\t\tif ( geometry.skinIndices.length > 0 ) {\n\n\t\t\tvar skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 );\n\t\t\tthis.setAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) );\n\n\t\t}\n\n\t\tif ( geometry.skinWeights.length > 0 ) {\n\n\t\t\tvar skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 );\n\t\t\tthis.setAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) );\n\n\t\t}\n\n\t\t//\n\n\t\tif ( geometry.boundingSphere !== null ) {\n\n\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\n\n\t\t}\n\n\t\tif ( geometry.boundingBox !== null ) {\n\n\t\t\tthis.boundingBox = geometry.boundingBox.clone();\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcomputeBoundingBox: function () {\n\n\t\tif ( this.boundingBox === null ) {\n\n\t\t\tthis.boundingBox = new Box3();\n\n\t\t}\n\n\t\tvar position = this.attributes.position;\n\t\tvar morphAttributesPosition = this.morphAttributes.position;\n\n\t\tif ( position !== undefined ) {\n\n\t\t\tthis.boundingBox.setFromBufferAttribute( position );\n\n\t\t\t// process morph attributes if present\n\n\t\t\tif ( morphAttributesPosition ) {\n\n\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\n\n\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\n\t\t\t\t\t_box.setFromBufferAttribute( morphAttribute );\n\n\t\t\t\t\tif ( this.morphTargetsRelative ) {\n\n\t\t\t\t\t\t_vector.addVectors( this.boundingBox.min, _box.min );\n\t\t\t\t\t\tthis.boundingBox.expandByPoint( _vector );\n\n\t\t\t\t\t\t_vector.addVectors( this.boundingBox.max, _box.max );\n\t\t\t\t\t\tthis.boundingBox.expandByPoint( _vector );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tthis.boundingBox.expandByPoint( _box.min );\n\t\t\t\t\t\tthis.boundingBox.expandByPoint( _box.max );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tthis.boundingBox.makeEmpty();\n\n\t\t}\n\n\t\tif ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The \"position\" attribute is likely to have NaN values.', this );\n\n\t\t}\n\n\t},\n\n\tcomputeBoundingSphere: function () {\n\n\t\tif ( this.boundingSphere === null ) {\n\n\t\t\tthis.boundingSphere = new Sphere();\n\n\t\t}\n\n\t\tvar position = this.attributes.position;\n\t\tvar morphAttributesPosition = this.morphAttributes.position;\n\n\t\tif ( position ) {\n\n\t\t\t// first, find the center of the bounding sphere\n\n\t\t\tvar center = this.boundingSphere.center;\n\n\t\t\t_box.setFromBufferAttribute( position );\n\n\t\t\t// process morph attributes if present\n\n\t\t\tif ( morphAttributesPosition ) {\n\n\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\n\n\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\n\t\t\t\t\t_boxMorphTargets.setFromBufferAttribute( morphAttribute );\n\n\t\t\t\t\tif ( this.morphTargetsRelative ) {\n\n\t\t\t\t\t\t_vector.addVectors( _box.min, _boxMorphTargets.min );\n\t\t\t\t\t\t_box.expandByPoint( _vector );\n\n\t\t\t\t\t\t_vector.addVectors( _box.max, _boxMorphTargets.max );\n\t\t\t\t\t\t_box.expandByPoint( _vector );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t_box.expandByPoint( _boxMorphTargets.min );\n\t\t\t\t\t\t_box.expandByPoint( _boxMorphTargets.max );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t_box.getCenter( center );\n\n\t\t\t// second, try to find a boundingSphere with a radius smaller than the\n\t\t\t// boundingSphere of the boundingBox: sqrt(3) smaller in the best case\n\n\t\t\tvar maxRadiusSq = 0;\n\n\t\t\tfor ( var i = 0, il = position.count; i < il; i ++ ) {\n\n\t\t\t\t_vector.fromBufferAttribute( position, i );\n\n\t\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) );\n\n\t\t\t}\n\n\t\t\t// process morph attributes if present\n\n\t\t\tif ( morphAttributesPosition ) {\n\n\t\t\t\tfor ( var i = 0, il = morphAttributesPosition.length; i < il; i ++ ) {\n\n\t\t\t\t\tvar morphAttribute = morphAttributesPosition[ i ];\n\t\t\t\t\tvar morphTargetsRelative = this.morphTargetsRelative;\n\n\t\t\t\t\tfor ( var j = 0, jl = morphAttribute.count; j < jl; j ++ ) {\n\n\t\t\t\t\t\t_vector.fromBufferAttribute( morphAttribute, j );\n\n\t\t\t\t\t\tif ( morphTargetsRelative ) {\n\n\t\t\t\t\t\t\t_offset.fromBufferAttribute( position, j );\n\t\t\t\t\t\t\t_vector.add( _offset );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tmaxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector ) );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.boundingSphere.radius = Math.sqrt( maxRadiusSq );\n\n\t\t\tif ( isNaN( this.boundingSphere.radius ) ) {\n\n\t\t\t\tconsole.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The \"position\" attribute is likely to have NaN values.', this );\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\tcomputeFaceNormals: function () {\n\n\t\t// backwards compatibility\n\n\t},\n\n\tcomputeVertexNormals: function () {\n\n\t\tvar index = this.index;\n\t\tvar attributes = this.attributes;\n\n\t\tif ( attributes.position ) {\n\n\t\t\tvar positions = attributes.position.array;\n\n\t\t\tif ( attributes.normal === undefined ) {\n\n\t\t\t\tthis.setAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) );\n\n\t\t\t} else {\n\n\t\t\t\t// reset existing normals to zero\n\n\t\t\t\tvar array = attributes.normal.array;\n\n\t\t\t\tfor ( var i = 0, il = array.length; i < il; i ++ ) {\n\n\t\t\t\t\tarray[ i ] = 0;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar normals = attributes.normal.array;\n\n\t\t\tvar vA, vB, vC;\n\t\t\tvar pA = new Vector3(), pB = new Vector3(), pC = new Vector3();\n\t\t\tvar cb = new Vector3(), ab = new Vector3();\n\n\t\t\t// indexed elements\n\n\t\t\tif ( index ) {\n\n\t\t\t\tvar indices = index.array;\n\n\t\t\t\tfor ( var i = 0, il = index.count; i < il; i += 3 ) {\n\n\t\t\t\t\tvA = indices[ i + 0 ] * 3;\n\t\t\t\t\tvB = indices[ i + 1 ] * 3;\n\t\t\t\t\tvC = indices[ i + 2 ] * 3;\n\n\t\t\t\t\tpA.fromArray( positions, vA );\n\t\t\t\t\tpB.fromArray( positions, vB );\n\t\t\t\t\tpC.fromArray( positions, vC );\n\n\t\t\t\t\tcb.subVectors( pC, pB );\n\t\t\t\t\tab.subVectors( pA, pB );\n\t\t\t\t\tcb.cross( ab );\n\n\t\t\t\t\tnormals[ vA ] += cb.x;\n\t\t\t\t\tnormals[ vA + 1 ] += cb.y;\n\t\t\t\t\tnormals[ vA + 2 ] += cb.z;\n\n\t\t\t\t\tnormals[ vB ] += cb.x;\n\t\t\t\t\tnormals[ vB + 1 ] += cb.y;\n\t\t\t\t\tnormals[ vB + 2 ] += cb.z;\n\n\t\t\t\t\tnormals[ vC ] += cb.x;\n\t\t\t\t\tnormals[ vC + 1 ] += cb.y;\n\t\t\t\t\tnormals[ vC + 2 ] += cb.z;\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t// non-indexed elements (unconnected triangle soup)\n\n\t\t\t\tfor ( var i = 0, il = positions.length; i < il; i += 9 ) {\n\n\t\t\t\t\tpA.fromArray( positions, i );\n\t\t\t\t\tpB.fromArray( positions, i + 3 );\n\t\t\t\t\tpC.fromArray( positions, i + 6 );\n\n\t\t\t\t\tcb.subVectors( pC, pB );\n\t\t\t\t\tab.subVectors( pA, pB );\n\t\t\t\t\tcb.cross( ab );\n\n\t\t\t\t\tnormals[ i ] = cb.x;\n\t\t\t\t\tnormals[ i + 1 ] = cb.y;\n\t\t\t\t\tnormals[ i + 2 ] = cb.z;\n\n\t\t\t\t\tnormals[ i + 3 ] = cb.x;\n\t\t\t\t\tnormals[ i + 4 ] = cb.y;\n\t\t\t\t\tnormals[ i + 5 ] = cb.z;\n\n\t\t\t\t\tnormals[ i + 6 ] = cb.x;\n\t\t\t\t\tnormals[ i + 7 ] = cb.y;\n\t\t\t\t\tnormals[ i + 8 ] = cb.z;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.normalizeNormals();\n\n\t\t\tattributes.normal.needsUpdate = true;\n\n\t\t}\n\n\t},\n\n\tmerge: function ( geometry, offset ) {\n\n\t\tif ( ! ( geometry && geometry.isBufferGeometry ) ) {\n\n\t\t\tconsole.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( offset === undefined ) {\n\n\t\t\toffset = 0;\n\n\t\t\tconsole.warn(\n\t\t\t\t'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. '\n\t\t\t\t+ 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.'\n\t\t\t);\n\n\t\t}\n\n\t\tvar attributes = this.attributes;\n\n\t\tfor ( var key in attributes ) {\n\n\t\t\tif ( geometry.attributes[ key ] === undefined ) continue;\n\n\t\t\tvar attribute1 = attributes[ key ];\n\t\t\tvar attributeArray1 = attribute1.array;\n\n\t\t\tvar attribute2 = geometry.attributes[ key ];\n\t\t\tvar attributeArray2 = attribute2.array;\n\n\t\t\tvar attributeOffset = attribute2.itemSize * offset;\n\t\t\tvar length = Math.min( attributeArray2.length, attributeArray1.length - attributeOffset );\n\n\t\t\tfor ( var i = 0, j = attributeOffset; i < length; i ++, j ++ ) {\n\n\t\t\t\tattributeArray1[ j ] = attributeArray2[ i ];\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tnormalizeNormals: function () {\n\n\t\tvar normals = this.attributes.normal;\n\n\t\tfor ( var i = 0, il = normals.count; i < il; i ++ ) {\n\n\t\t\t_vector.x = normals.getX( i );\n\t\t\t_vector.y = normals.getY( i );\n\t\t\t_vector.z = normals.getZ( i );\n\n\t\t\t_vector.normalize();\n\n\t\t\tnormals.setXYZ( i, _vector.x, _vector.y, _vector.z );\n\n\t\t}\n\n\t},\n\n\ttoNonIndexed: function () {\n\n\t\tfunction convertBufferAttribute( attribute, indices ) {\n\n\t\t\tvar array = attribute.array;\n\t\t\tvar itemSize = attribute.itemSize;\n\t\t\tvar normalized = attribute.normalized;\n\n\t\t\tvar array2 = new array.constructor( indices.length * itemSize );\n\n\t\t\tvar index = 0, index2 = 0;\n\n\t\t\tfor ( var i = 0, l = indices.length; i < l; i ++ ) {\n\n\t\t\t\tindex = indices[ i ] * itemSize;\n\n\t\t\t\tfor ( var j = 0; j < itemSize; j ++ ) {\n\n\t\t\t\t\tarray2[ index2 ++ ] = array[ index ++ ];\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\treturn new BufferAttribute( array2, itemSize, normalized );\n\n\t\t}\n\n\t\t//\n\n\t\tif ( this.index === null ) {\n\n\t\t\tconsole.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' );\n\t\t\treturn this;\n\n\t\t}\n\n\t\tvar geometry2 = new BufferGeometry();\n\n\t\tvar indices = this.index.array;\n\t\tvar attributes = this.attributes;\n\n\t\t// attributes\n\n\t\tfor ( var name in attributes ) {\n\n\t\t\tvar attribute = attributes[ name ];\n\n\t\t\tvar newAttribute = convertBufferAttribute( attribute, indices );\n\n\t\t\tgeometry2.setAttribute( name, newAttribute );\n\n\t\t}\n\n\t\t// morph attributes\n\n\t\tvar morphAttributes = this.morphAttributes;\n\n\t\tfor ( name in morphAttributes ) {\n\n\t\t\tvar morphArray = [];\n\t\t\tvar morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes\n\n\t\t\tfor ( var i = 0, il = morphAttribute.length; i < il; i ++ ) {\n\n\t\t\t\tvar attribute = morphAttribute[ i ];\n\n\t\t\t\tvar newAttribute = convertBufferAttribute( attribute, indices );\n\n\t\t\t\tmorphArray.push( newAttribute );\n\n\t\t\t}\n\n\t\t\tgeometry2.morphAttributes[ name ] = morphArray;\n\n\t\t}\n\n\t\tgeometry2.morphTargetsRelative = this.morphTargetsRelative;\n\n\t\t// groups\n\n\t\tvar groups = this.groups;\n\n\t\tfor ( var i = 0, l = groups.length; i < l; i ++ ) {\n\n\t\t\tvar group = groups[ i ];\n\t\t\tgeometry2.addGroup( group.start, group.count, group.materialIndex );\n\n\t\t}\n\n\t\treturn geometry2;\n\n\t},\n\n\ttoJSON: function () {\n\n\t\tvar data = {\n\t\t\tmetadata: {\n\t\t\t\tversion: 4.5,\n\t\t\t\ttype: 'BufferGeometry',\n\t\t\t\tgenerator: 'BufferGeometry.toJSON'\n\t\t\t}\n\t\t};\n\n\t\t// standard BufferGeometry serialization\n\n\t\tdata.uuid = this.uuid;\n\t\tdata.type = this.type;\n\t\tif ( this.name !== '' ) data.name = this.name;\n\t\tif ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData;\n\n\t\tif ( this.parameters !== undefined ) {\n\n\t\t\tvar parameters = this.parameters;\n\n\t\t\tfor ( var key in parameters ) {\n\n\t\t\t\tif ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tdata.data = { attributes: {} };\n\n\t\tvar index = this.index;\n\n\t\tif ( index !== null ) {\n\n\t\t\tdata.data.index = {\n\t\t\t\ttype: index.array.constructor.name,\n\t\t\t\tarray: Array.prototype.slice.call( index.array )\n\t\t\t};\n\n\t\t}\n\n\t\tvar attributes = this.attributes;\n\n\t\tfor ( var key in attributes ) {\n\n\t\t\tvar attribute = attributes[ key ];\n\n\t\t\tvar attributeData = attribute.toJSON();\n\n\t\t\tif ( attribute.name !== '' ) attributeData.name = attribute.name;\n\n\t\t\tdata.data.attributes[ key ] = attributeData;\n\n\t\t}\n\n\t\tvar morphAttributes = {};\n\t\tvar hasMorphAttributes = false;\n\n\t\tfor ( var key in this.morphAttributes ) {\n\n\t\t\tvar attributeArray = this.morphAttributes[ key ];\n\n\t\t\tvar array = [];\n\n\t\t\tfor ( var i = 0, il = attributeArray.length; i < il; i ++ ) {\n\n\t\t\t\tvar attribute = attributeArray[ i ];\n\n\t\t\t\tvar attributeData = attribute.toJSON();\n\n\t\t\t\tif ( attribute.name !== '' ) attributeData.name = attribute.name;\n\n\t\t\t\tarray.push( attributeData );\n\n\t\t\t}\n\n\t\t\tif ( array.length > 0 ) {\n\n\t\t\t\tmorphAttributes[ key ] = array;\n\n\t\t\t\thasMorphAttributes = true;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( hasMorphAttributes ) {\n\n\t\t\tdata.data.morphAttributes = morphAttributes;\n\t\t\tdata.data.morphTargetsRelative = this.morphTargetsRelative;\n\n\t\t}\n\n\t\tvar groups = this.groups;\n\n\t\tif ( groups.length > 0 ) {\n\n\t\t\tdata.data.groups = JSON.parse( JSON.stringify( groups ) );\n\n\t\t}\n\n\t\tvar boundingSphere = this.boundingSphere;\n\n\t\tif ( boundingSphere !== null ) {\n\n\t\t\tdata.data.boundingSphere = {\n\t\t\t\tcenter: boundingSphere.center.toArray(),\n\t\t\t\tradius: boundingSphere.radius\n\t\t\t};\n\n\t\t}\n\n\t\treturn data;\n\n\t},\n\n\tclone: function () {\n\n\t\t/*\n\t\t // Handle primitives\n\n\t\t var parameters = this.parameters;\n\n\t\t if ( parameters !== undefined ) {\n\n\t\t var values = [];\n\n\t\t for ( var key in parameters ) {\n\n\t\t values.push( parameters[ key ] );\n\n\t\t }\n\n\t\t var geometry = Object.create( this.constructor.prototype );\n\t\t this.constructor.apply( geometry, values );\n\t\t return geometry;\n\n\t\t }\n\n\t\t return new this.constructor().copy( this );\n\t\t */\n\n\t\treturn new BufferGeometry().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tvar name, i, l;\n\n\t\t// reset\n\n\t\tthis.index = null;\n\t\tthis.attributes = {};\n\t\tthis.morphAttributes = {};\n\t\tthis.groups = [];\n\t\tthis.boundingBox = null;\n\t\tthis.boundingSphere = null;\n\n\t\t// name\n\n\t\tthis.name = source.name;\n\n\t\t// index\n\n\t\tvar index = source.index;\n\n\t\tif ( index !== null ) {\n\n\t\t\tthis.setIndex( index.clone() );\n\n\t\t}\n\n\t\t// attributes\n\n\t\tvar attributes = source.attributes;\n\n\t\tfor ( name in attributes ) {\n\n\t\t\tvar attribute = attributes[ name ];\n\t\t\tthis.setAttribute( name, attribute.clone() );\n\n\t\t}\n\n\t\t// morph attributes\n\n\t\tvar morphAttributes = source.morphAttributes;\n\n\t\tfor ( name in morphAttributes ) {\n\n\t\t\tvar array = [];\n\t\t\tvar morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes\n\n\t\t\tfor ( i = 0, l = morphAttribute.length; i < l; i ++ ) {\n\n\t\t\t\tarray.push( morphAttribute[ i ].clone() );\n\n\t\t\t}\n\n\t\t\tthis.morphAttributes[ name ] = array;\n\n\t\t}\n\n\t\tthis.morphTargetsRelative = source.morphTargetsRelative;\n\n\t\t// groups\n\n\t\tvar groups = source.groups;\n\n\t\tfor ( i = 0, l = groups.length; i < l; i ++ ) {\n\n\t\t\tvar group = groups[ i ];\n\t\t\tthis.addGroup( group.start, group.count, group.materialIndex );\n\n\t\t}\n\n\t\t// bounding box\n\n\t\tvar boundingBox = source.boundingBox;\n\n\t\tif ( boundingBox !== null ) {\n\n\t\t\tthis.boundingBox = boundingBox.clone();\n\n\t\t}\n\n\t\t// bounding sphere\n\n\t\tvar boundingSphere = source.boundingSphere;\n\n\t\tif ( boundingSphere !== null ) {\n\n\t\t\tthis.boundingSphere = boundingSphere.clone();\n\n\t\t}\n\n\t\t// draw range\n\n\t\tthis.drawRange.start = source.drawRange.start;\n\t\tthis.drawRange.count = source.drawRange.count;\n\n\t\t// user data\n\n\t\tthis.userData = source.userData;\n\n\t\treturn this;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t}\n\n} );\n\n\nexport { BufferGeometry };\n","import { Vector3 } from '../math/Vector3.js';\nimport { Vector2 } from '../math/Vector2.js';\nimport { Sphere } from '../math/Sphere.js';\nimport { Ray } from '../math/Ray.js';\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { Object3D } from '../core/Object3D.js';\nimport { Triangle } from '../math/Triangle.js';\nimport { Face3 } from '../core/Face3.js';\nimport { DoubleSide, BackSide } from '../constants.js';\nimport { MeshBasicMaterial } from '../materials/MeshBasicMaterial.js';\nimport { BufferGeometry } from '../core/BufferGeometry.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author mikael emtinger / http://gomo.se/\n * @author jonobr1 / http://jonobr1.com/\n */\n\nvar _inverseMatrix = new Matrix4();\nvar _ray = new Ray();\nvar _sphere = new Sphere();\n\nvar _vA = new Vector3();\nvar _vB = new Vector3();\nvar _vC = new Vector3();\n\nvar _tempA = new Vector3();\nvar _tempB = new Vector3();\nvar _tempC = new Vector3();\n\nvar _morphA = new Vector3();\nvar _morphB = new Vector3();\nvar _morphC = new Vector3();\n\nvar _uvA = new Vector2();\nvar _uvB = new Vector2();\nvar _uvC = new Vector2();\n\nvar _intersectionPoint = new Vector3();\nvar _intersectionPointWorld = new Vector3();\n\nfunction Mesh( geometry, material ) {\n\n\tObject3D.call( this );\n\n\tthis.type = 'Mesh';\n\n\tthis.geometry = geometry !== undefined ? geometry : new BufferGeometry();\n\tthis.material = material !== undefined ? material : new MeshBasicMaterial();\n\n\tthis.updateMorphTargets();\n\n}\n\nMesh.prototype = Object.assign( Object.create( Object3D.prototype ), {\n\n\tconstructor: Mesh,\n\n\tisMesh: true,\n\n\tcopy: function ( source ) {\n\n\t\tObject3D.prototype.copy.call( this, source );\n\n\t\tif ( source.morphTargetInfluences !== undefined ) {\n\n\t\t\tthis.morphTargetInfluences = source.morphTargetInfluences.slice();\n\n\t\t}\n\n\t\tif ( source.morphTargetDictionary !== undefined ) {\n\n\t\t\tthis.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tupdateMorphTargets: function () {\n\n\t\tvar geometry = this.geometry;\n\t\tvar m, ml, name;\n\n\t\tif ( geometry.isBufferGeometry ) {\n\n\t\t\tvar morphAttributes = geometry.morphAttributes;\n\t\t\tvar keys = Object.keys( morphAttributes );\n\n\t\t\tif ( keys.length > 0 ) {\n\n\t\t\t\tvar morphAttribute = morphAttributes[ keys[ 0 ] ];\n\n\t\t\t\tif ( morphAttribute !== undefined ) {\n\n\t\t\t\t\tthis.morphTargetInfluences = [];\n\t\t\t\t\tthis.morphTargetDictionary = {};\n\n\t\t\t\t\tfor ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) {\n\n\t\t\t\t\t\tname = morphAttribute[ m ].name || String( m );\n\n\t\t\t\t\t\tthis.morphTargetInfluences.push( 0 );\n\t\t\t\t\t\tthis.morphTargetDictionary[ name ] = m;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tvar morphTargets = geometry.morphTargets;\n\n\t\t\tif ( morphTargets !== undefined && morphTargets.length > 0 ) {\n\n\t\t\t\tconsole.error( 'THREE.Mesh.updateMorphTargets() no longer supports THREE.Geometry. Use THREE.BufferGeometry instead.' );\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\traycast: function ( raycaster, intersects ) {\n\n\t\tvar geometry = this.geometry;\n\t\tvar material = this.material;\n\t\tvar matrixWorld = this.matrixWorld;\n\n\t\tif ( material === undefined ) return;\n\n\t\t// Checking boundingSphere distance to ray\n\n\t\tif ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();\n\n\t\t_sphere.copy( geometry.boundingSphere );\n\t\t_sphere.applyMatrix4( matrixWorld );\n\n\t\tif ( raycaster.ray.intersectsSphere( _sphere ) === false ) return;\n\n\t\t//\n\n\t\t_inverseMatrix.getInverse( matrixWorld );\n\t\t_ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );\n\n\t\t// Check boundingBox before continuing\n\n\t\tif ( geometry.boundingBox !== null ) {\n\n\t\t\tif ( _ray.intersectsBox( geometry.boundingBox ) === false ) return;\n\n\t\t}\n\n\t\tvar intersection;\n\n\t\tif ( geometry.isBufferGeometry ) {\n\n\t\t\tvar a, b, c;\n\t\t\tvar index = geometry.index;\n\t\t\tvar position = geometry.attributes.position;\n\t\t\tvar morphPosition = geometry.morphAttributes.position;\n\t\t\tvar morphTargetsRelative = geometry.morphTargetsRelative;\n\t\t\tvar uv = geometry.attributes.uv;\n\t\t\tvar uv2 = geometry.attributes.uv2;\n\t\t\tvar groups = geometry.groups;\n\t\t\tvar drawRange = geometry.drawRange;\n\t\t\tvar i, j, il, jl;\n\t\t\tvar group, groupMaterial;\n\t\t\tvar start, end;\n\n\t\t\tif ( index !== null ) {\n\n\t\t\t\t// indexed buffer geometry\n\n\t\t\t\tif ( Array.isArray( material ) ) {\n\n\t\t\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\n\n\t\t\t\t\t\tgroup = groups[ i ];\n\t\t\t\t\t\tgroupMaterial = material[ group.materialIndex ];\n\n\t\t\t\t\t\tstart = Math.max( group.start, drawRange.start );\n\t\t\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\n\n\t\t\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\n\n\t\t\t\t\t\t\ta = index.getX( j );\n\t\t\t\t\t\t\tb = index.getX( j + 1 );\n\t\t\t\t\t\t\tc = index.getX( j + 2 );\n\n\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\n\n\t\t\t\t\t\t\tif ( intersection ) {\n\n\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics\n\t\t\t\t\t\t\t\tintersection.face.materialIndex = group.materialIndex;\n\t\t\t\t\t\t\t\tintersects.push( intersection );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tstart = Math.max( 0, drawRange.start );\n\t\t\t\t\tend = Math.min( index.count, ( drawRange.start + drawRange.count ) );\n\n\t\t\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\n\n\t\t\t\t\t\ta = index.getX( i );\n\t\t\t\t\t\tb = index.getX( i + 1 );\n\t\t\t\t\t\tc = index.getX( i + 2 );\n\n\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\n\n\t\t\t\t\t\tif ( intersection ) {\n\n\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics\n\t\t\t\t\t\t\tintersects.push( intersection );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( position !== undefined ) {\n\n\t\t\t\t// non-indexed buffer geometry\n\n\t\t\t\tif ( Array.isArray( material ) ) {\n\n\t\t\t\t\tfor ( i = 0, il = groups.length; i < il; i ++ ) {\n\n\t\t\t\t\t\tgroup = groups[ i ];\n\t\t\t\t\t\tgroupMaterial = material[ group.materialIndex ];\n\n\t\t\t\t\t\tstart = Math.max( group.start, drawRange.start );\n\t\t\t\t\t\tend = Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) );\n\n\t\t\t\t\t\tfor ( j = start, jl = end; j < jl; j += 3 ) {\n\n\t\t\t\t\t\t\ta = j;\n\t\t\t\t\t\t\tb = j + 1;\n\t\t\t\t\t\t\tc = j + 2;\n\n\t\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, groupMaterial, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\n\n\t\t\t\t\t\t\tif ( intersection ) {\n\n\t\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics\n\t\t\t\t\t\t\t\tintersection.face.materialIndex = group.materialIndex;\n\t\t\t\t\t\t\t\tintersects.push( intersection );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tstart = Math.max( 0, drawRange.start );\n\t\t\t\t\tend = Math.min( position.count, ( drawRange.start + drawRange.count ) );\n\n\t\t\t\t\tfor ( i = start, il = end; i < il; i += 3 ) {\n\n\t\t\t\t\t\ta = i;\n\t\t\t\t\t\tb = i + 1;\n\t\t\t\t\t\tc = i + 2;\n\n\t\t\t\t\t\tintersection = checkBufferGeometryIntersection( this, material, raycaster, _ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c );\n\n\t\t\t\t\t\tif ( intersection ) {\n\n\t\t\t\t\t\t\tintersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics\n\t\t\t\t\t\t\tintersects.push( intersection );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else if ( geometry.isGeometry ) {\n\n\t\t\tvar fvA, fvB, fvC;\n\t\t\tvar isMultiMaterial = Array.isArray( material );\n\n\t\t\tvar vertices = geometry.vertices;\n\t\t\tvar faces = geometry.faces;\n\t\t\tvar uvs;\n\n\t\t\tvar faceVertexUvs = geometry.faceVertexUvs[ 0 ];\n\t\t\tif ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs;\n\n\t\t\tfor ( var f = 0, fl = faces.length; f < fl; f ++ ) {\n\n\t\t\t\tvar face = faces[ f ];\n\t\t\t\tvar faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material;\n\n\t\t\t\tif ( faceMaterial === undefined ) continue;\n\n\t\t\t\tfvA = vertices[ face.a ];\n\t\t\t\tfvB = vertices[ face.b ];\n\t\t\t\tfvC = vertices[ face.c ];\n\n\t\t\t\tintersection = checkIntersection( this, faceMaterial, raycaster, _ray, fvA, fvB, fvC, _intersectionPoint );\n\n\t\t\t\tif ( intersection ) {\n\n\t\t\t\t\tif ( uvs && uvs[ f ] ) {\n\n\t\t\t\t\t\tvar uvs_f = uvs[ f ];\n\t\t\t\t\t\t_uvA.copy( uvs_f[ 0 ] );\n\t\t\t\t\t\t_uvB.copy( uvs_f[ 1 ] );\n\t\t\t\t\t\t_uvC.copy( uvs_f[ 2 ] );\n\n\t\t\t\t\t\tintersection.uv = Triangle.getUV( _intersectionPoint, fvA, fvB, fvC, _uvA, _uvB, _uvC, new Vector2() );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tintersection.face = face;\n\t\t\t\t\tintersection.faceIndex = f;\n\t\t\t\t\tintersects.push( intersection );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor( this.geometry, this.material ).copy( this );\n\n\t}\n\n} );\n\nfunction checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) {\n\n\tvar intersect;\n\n\tif ( material.side === BackSide ) {\n\n\t\tintersect = ray.intersectTriangle( pC, pB, pA, true, point );\n\n\t} else {\n\n\t\tintersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point );\n\n\t}\n\n\tif ( intersect === null ) return null;\n\n\t_intersectionPointWorld.copy( point );\n\t_intersectionPointWorld.applyMatrix4( object.matrixWorld );\n\n\tvar distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );\n\n\tif ( distance < raycaster.near || distance > raycaster.far ) return null;\n\n\treturn {\n\t\tdistance: distance,\n\t\tpoint: _intersectionPointWorld.clone(),\n\t\tobject: object\n\t};\n\n}\n\nfunction checkBufferGeometryIntersection( object, material, raycaster, ray, position, morphPosition, morphTargetsRelative, uv, uv2, a, b, c ) {\n\n\t_vA.fromBufferAttribute( position, a );\n\t_vB.fromBufferAttribute( position, b );\n\t_vC.fromBufferAttribute( position, c );\n\n\tvar morphInfluences = object.morphTargetInfluences;\n\n\tif ( material.morphTargets && morphPosition && morphInfluences ) {\n\n\t\t_morphA.set( 0, 0, 0 );\n\t\t_morphB.set( 0, 0, 0 );\n\t\t_morphC.set( 0, 0, 0 );\n\n\t\tfor ( var i = 0, il = morphPosition.length; i < il; i ++ ) {\n\n\t\t\tvar influence = morphInfluences[ i ];\n\t\t\tvar morphAttribute = morphPosition[ i ];\n\n\t\t\tif ( influence === 0 ) continue;\n\n\t\t\t_tempA.fromBufferAttribute( morphAttribute, a );\n\t\t\t_tempB.fromBufferAttribute( morphAttribute, b );\n\t\t\t_tempC.fromBufferAttribute( morphAttribute, c );\n\n\t\t\tif ( morphTargetsRelative ) {\n\n\t\t\t\t_morphA.addScaledVector( _tempA, influence );\n\t\t\t\t_morphB.addScaledVector( _tempB, influence );\n\t\t\t\t_morphC.addScaledVector( _tempC, influence );\n\n\t\t\t} else {\n\n\t\t\t\t_morphA.addScaledVector( _tempA.sub( _vA ), influence );\n\t\t\t\t_morphB.addScaledVector( _tempB.sub( _vB ), influence );\n\t\t\t\t_morphC.addScaledVector( _tempC.sub( _vC ), influence );\n\n\t\t\t}\n\n\t\t}\n\n\t\t_vA.add( _morphA );\n\t\t_vB.add( _morphB );\n\t\t_vC.add( _morphC );\n\n\t}\n\n\tif ( object.isSkinnedMesh ) {\n\n\t\tobject.boneTransform( a, _vA );\n\t\tobject.boneTransform( b, _vB );\n\t\tobject.boneTransform( c, _vC );\n\n\t}\n\n\tvar intersection = checkIntersection( object, material, raycaster, ray, _vA, _vB, _vC, _intersectionPoint );\n\n\tif ( intersection ) {\n\n\t\tif ( uv ) {\n\n\t\t\t_uvA.fromBufferAttribute( uv, a );\n\t\t\t_uvB.fromBufferAttribute( uv, b );\n\t\t\t_uvC.fromBufferAttribute( uv, c );\n\n\t\t\tintersection.uv = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );\n\n\t\t}\n\n\t\tif ( uv2 ) {\n\n\t\t\t_uvA.fromBufferAttribute( uv2, a );\n\t\t\t_uvB.fromBufferAttribute( uv2, b );\n\t\t\t_uvC.fromBufferAttribute( uv2, c );\n\n\t\t\tintersection.uv2 = Triangle.getUV( _intersectionPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() );\n\n\t\t}\n\n\t\tvar face = new Face3( a, b, c );\n\t\tTriangle.getNormal( _vA, _vB, _vC, face.normal );\n\n\t\tintersection.face = face;\n\n\t}\n\n\treturn intersection;\n\n}\n\nexport { Mesh };\n","import { EventDispatcher } from './EventDispatcher.js';\nimport { Face3 } from './Face3.js';\nimport { Matrix3 } from '../math/Matrix3.js';\nimport { Sphere } from '../math/Sphere.js';\nimport { Box3 } from '../math/Box3.js';\nimport { Vector3 } from '../math/Vector3.js';\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { Vector2 } from '../math/Vector2.js';\nimport { Color } from '../math/Color.js';\nimport { Object3D } from './Object3D.js';\nimport { MathUtils } from '../math/MathUtils.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author kile / http://kile.stravaganza.org/\n * @author alteredq / http://alteredqualia.com/\n * @author mikael emtinger / http://gomo.se/\n * @author zz85 / http://www.lab4games.net/zz85/blog\n * @author bhouston / http://clara.io\n */\n\nvar _geometryId = 0; // Geometry uses even numbers as Id\nvar _m1 = new Matrix4();\nvar _obj = new Object3D();\nvar _offset = new Vector3();\n\nfunction Geometry() {\n\n\tObject.defineProperty( this, 'id', { value: _geometryId += 2 } );\n\n\tthis.uuid = MathUtils.generateUUID();\n\n\tthis.name = '';\n\tthis.type = 'Geometry';\n\n\tthis.vertices = [];\n\tthis.colors = [];\n\tthis.faces = [];\n\tthis.faceVertexUvs = [[]];\n\n\tthis.morphTargets = [];\n\tthis.morphNormals = [];\n\n\tthis.skinWeights = [];\n\tthis.skinIndices = [];\n\n\tthis.lineDistances = [];\n\n\tthis.boundingBox = null;\n\tthis.boundingSphere = null;\n\n\t// update flags\n\n\tthis.elementsNeedUpdate = false;\n\tthis.verticesNeedUpdate = false;\n\tthis.uvsNeedUpdate = false;\n\tthis.normalsNeedUpdate = false;\n\tthis.colorsNeedUpdate = false;\n\tthis.lineDistancesNeedUpdate = false;\n\tthis.groupsNeedUpdate = false;\n\n}\n\nGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), {\n\n\tconstructor: Geometry,\n\n\tisGeometry: true,\n\n\tapplyMatrix4: function ( matrix ) {\n\n\t\tvar normalMatrix = new Matrix3().getNormalMatrix( matrix );\n\n\t\tfor ( var i = 0, il = this.vertices.length; i < il; i ++ ) {\n\n\t\t\tvar vertex = this.vertices[ i ];\n\t\t\tvertex.applyMatrix4( matrix );\n\n\t\t}\n\n\t\tfor ( var i = 0, il = this.faces.length; i < il; i ++ ) {\n\n\t\t\tvar face = this.faces[ i ];\n\t\t\tface.normal.applyMatrix3( normalMatrix ).normalize();\n\n\t\t\tfor ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {\n\n\t\t\t\tface.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.boundingBox !== null ) {\n\n\t\t\tthis.computeBoundingBox();\n\n\t\t}\n\n\t\tif ( this.boundingSphere !== null ) {\n\n\t\t\tthis.computeBoundingSphere();\n\n\t\t}\n\n\t\tthis.verticesNeedUpdate = true;\n\t\tthis.normalsNeedUpdate = true;\n\n\t\treturn this;\n\n\t},\n\n\trotateX: function ( angle ) {\n\n\t\t// rotate geometry around world x-axis\n\n\t\t_m1.makeRotationX( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateY: function ( angle ) {\n\n\t\t// rotate geometry around world y-axis\n\n\t\t_m1.makeRotationY( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\trotateZ: function ( angle ) {\n\n\t\t// rotate geometry around world z-axis\n\n\t\t_m1.makeRotationZ( angle );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\ttranslate: function ( x, y, z ) {\n\n\t\t// translate geometry\n\n\t\t_m1.makeTranslation( x, y, z );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\tscale: function ( x, y, z ) {\n\n\t\t// scale geometry\n\n\t\t_m1.makeScale( x, y, z );\n\n\t\tthis.applyMatrix4( _m1 );\n\n\t\treturn this;\n\n\t},\n\n\tlookAt: function ( vector ) {\n\n\t\t_obj.lookAt( vector );\n\n\t\t_obj.updateMatrix();\n\n\t\tthis.applyMatrix4( _obj.matrix );\n\n\t\treturn this;\n\n\t},\n\n\tfromBufferGeometry: function ( geometry ) {\n\n\t\tvar scope = this;\n\n\t\tvar indices = geometry.index !== null ? geometry.index.array : undefined;\n\t\tvar attributes = geometry.attributes;\n\n\t\tif ( attributes.position === undefined ) {\n\n\t\t\tconsole.error( 'THREE.Geometry.fromBufferGeometry(): Position attribute required for conversion.' );\n\t\t\treturn this;\n\n\t\t}\n\n\t\tvar positions = attributes.position.array;\n\t\tvar normals = attributes.normal !== undefined ? attributes.normal.array : undefined;\n\t\tvar colors = attributes.color !== undefined ? attributes.color.array : undefined;\n\t\tvar uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;\n\t\tvar uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;\n\n\t\tif ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];\n\n\t\tfor ( var i = 0; i < positions.length; i += 3 ) {\n\n\t\t\tscope.vertices.push( new Vector3().fromArray( positions, i ) );\n\n\t\t\tif ( colors !== undefined ) {\n\n\t\t\t\tscope.colors.push( new Color().fromArray( colors, i ) );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction addFace( a, b, c, materialIndex ) {\n\n\t\t\tvar vertexColors = ( colors === undefined ) ? [] : [\n\t\t\t\tscope.colors[ a ].clone(),\n\t\t\t\tscope.colors[ b ].clone(),\n\t\t\t\tscope.colors[ c ].clone() ];\n\n\t\t\tvar vertexNormals = ( normals === undefined ) ? [] : [\n\t\t\t\tnew Vector3().fromArray( normals, a * 3 ),\n\t\t\t\tnew Vector3().fromArray( normals, b * 3 ),\n\t\t\t\tnew Vector3().fromArray( normals, c * 3 )\n\t\t\t];\n\n\t\t\tvar face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex );\n\n\t\t\tscope.faces.push( face );\n\n\t\t\tif ( uvs !== undefined ) {\n\n\t\t\t\tscope.faceVertexUvs[ 0 ].push( [\n\t\t\t\t\tnew Vector2().fromArray( uvs, a * 2 ),\n\t\t\t\t\tnew Vector2().fromArray( uvs, b * 2 ),\n\t\t\t\t\tnew Vector2().fromArray( uvs, c * 2 )\n\t\t\t\t] );\n\n\t\t\t}\n\n\t\t\tif ( uvs2 !== undefined ) {\n\n\t\t\t\tscope.faceVertexUvs[ 1 ].push( [\n\t\t\t\t\tnew Vector2().fromArray( uvs2, a * 2 ),\n\t\t\t\t\tnew Vector2().fromArray( uvs2, b * 2 ),\n\t\t\t\t\tnew Vector2().fromArray( uvs2, c * 2 )\n\t\t\t\t] );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar groups = geometry.groups;\n\n\t\tif ( groups.length > 0 ) {\n\n\t\t\tfor ( var i = 0; i < groups.length; i ++ ) {\n\n\t\t\t\tvar group = groups[ i ];\n\n\t\t\t\tvar start = group.start;\n\t\t\t\tvar count = group.count;\n\n\t\t\t\tfor ( var j = start, jl = start + count; j < jl; j += 3 ) {\n\n\t\t\t\t\tif ( indices !== undefined ) {\n\n\t\t\t\t\t\taddFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\taddFace( j, j + 1, j + 2, group.materialIndex );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tif ( indices !== undefined ) {\n\n\t\t\t\tfor ( var i = 0; i < indices.length; i += 3 ) {\n\n\t\t\t\t\taddFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tfor ( var i = 0; i < positions.length / 3; i += 3 ) {\n\n\t\t\t\t\taddFace( i, i + 1, i + 2 );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tthis.computeFaceNormals();\n\n\t\tif ( geometry.boundingBox !== null ) {\n\n\t\t\tthis.boundingBox = geometry.boundingBox.clone();\n\n\t\t}\n\n\t\tif ( geometry.boundingSphere !== null ) {\n\n\t\t\tthis.boundingSphere = geometry.boundingSphere.clone();\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tcenter: function () {\n\n\t\tthis.computeBoundingBox();\n\n\t\tthis.boundingBox.getCenter( _offset ).negate();\n\n\t\tthis.translate( _offset.x, _offset.y, _offset.z );\n\n\t\treturn this;\n\n\t},\n\n\tnormalize: function () {\n\n\t\tthis.computeBoundingSphere();\n\n\t\tvar center = this.boundingSphere.center;\n\t\tvar radius = this.boundingSphere.radius;\n\n\t\tvar s = radius === 0 ? 1 : 1.0 / radius;\n\n\t\tvar matrix = new Matrix4();\n\t\tmatrix.set(\n\t\t\ts, 0, 0, - s * center.x,\n\t\t\t0, s, 0, - s * center.y,\n\t\t\t0, 0, s, - s * center.z,\n\t\t\t0, 0, 0, 1\n\t\t);\n\n\t\tthis.applyMatrix4( matrix );\n\n\t\treturn this;\n\n\t},\n\n\tcomputeFaceNormals: function () {\n\n\t\tvar cb = new Vector3(), ab = new Vector3();\n\n\t\tfor ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\tvar face = this.faces[ f ];\n\n\t\t\tvar vA = this.vertices[ face.a ];\n\t\t\tvar vB = this.vertices[ face.b ];\n\t\t\tvar vC = this.vertices[ face.c ];\n\n\t\t\tcb.subVectors( vC, vB );\n\t\t\tab.subVectors( vA, vB );\n\t\t\tcb.cross( ab );\n\n\t\t\tcb.normalize();\n\n\t\t\tface.normal.copy( cb );\n\n\t\t}\n\n\t},\n\n\tcomputeVertexNormals: function ( areaWeighted ) {\n\n\t\tif ( areaWeighted === undefined ) areaWeighted = true;\n\n\t\tvar v, vl, f, fl, face, vertices;\n\n\t\tvertices = new Array( this.vertices.length );\n\n\t\tfor ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {\n\n\t\t\tvertices[ v ] = new Vector3();\n\n\t\t}\n\n\t\tif ( areaWeighted ) {\n\n\t\t\t// vertex normals weighted by triangle areas\n\t\t\t// http://www.iquilezles.org/www/articles/normals/normals.htm\n\n\t\t\tvar vA, vB, vC;\n\t\t\tvar cb = new Vector3(), ab = new Vector3();\n\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\t\tface = this.faces[ f ];\n\n\t\t\t\tvA = this.vertices[ face.a ];\n\t\t\t\tvB = this.vertices[ face.b ];\n\t\t\t\tvC = this.vertices[ face.c ];\n\n\t\t\t\tcb.subVectors( vC, vB );\n\t\t\t\tab.subVectors( vA, vB );\n\t\t\t\tcb.cross( ab );\n\n\t\t\t\tvertices[ face.a ].add( cb );\n\t\t\t\tvertices[ face.b ].add( cb );\n\t\t\t\tvertices[ face.c ].add( cb );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tthis.computeFaceNormals();\n\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\t\tface = this.faces[ f ];\n\n\t\t\t\tvertices[ face.a ].add( face.normal );\n\t\t\t\tvertices[ face.b ].add( face.normal );\n\t\t\t\tvertices[ face.c ].add( face.normal );\n\n\t\t\t}\n\n\t\t}\n\n\t\tfor ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {\n\n\t\t\tvertices[ v ].normalize();\n\n\t\t}\n\n\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\tface = this.faces[ f ];\n\n\t\t\tvar vertexNormals = face.vertexNormals;\n\n\t\t\tif ( vertexNormals.length === 3 ) {\n\n\t\t\t\tvertexNormals[ 0 ].copy( vertices[ face.a ] );\n\t\t\t\tvertexNormals[ 1 ].copy( vertices[ face.b ] );\n\t\t\t\tvertexNormals[ 2 ].copy( vertices[ face.c ] );\n\n\t\t\t} else {\n\n\t\t\t\tvertexNormals[ 0 ] = vertices[ face.a ].clone();\n\t\t\t\tvertexNormals[ 1 ] = vertices[ face.b ].clone();\n\t\t\t\tvertexNormals[ 2 ] = vertices[ face.c ].clone();\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.faces.length > 0 ) {\n\n\t\t\tthis.normalsNeedUpdate = true;\n\n\t\t}\n\n\t},\n\n\tcomputeFlatVertexNormals: function () {\n\n\t\tvar f, fl, face;\n\n\t\tthis.computeFaceNormals();\n\n\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\tface = this.faces[ f ];\n\n\t\t\tvar vertexNormals = face.vertexNormals;\n\n\t\t\tif ( vertexNormals.length === 3 ) {\n\n\t\t\t\tvertexNormals[ 0 ].copy( face.normal );\n\t\t\t\tvertexNormals[ 1 ].copy( face.normal );\n\t\t\t\tvertexNormals[ 2 ].copy( face.normal );\n\n\t\t\t} else {\n\n\t\t\t\tvertexNormals[ 0 ] = face.normal.clone();\n\t\t\t\tvertexNormals[ 1 ] = face.normal.clone();\n\t\t\t\tvertexNormals[ 2 ] = face.normal.clone();\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( this.faces.length > 0 ) {\n\n\t\t\tthis.normalsNeedUpdate = true;\n\n\t\t}\n\n\t},\n\n\tcomputeMorphNormals: function () {\n\n\t\tvar i, il, f, fl, face;\n\n\t\t// save original normals\n\t\t// - create temp variables on first access\n\t\t// otherwise just copy (for faster repeated calls)\n\n\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\tface = this.faces[ f ];\n\n\t\t\tif ( ! face.__originalFaceNormal ) {\n\n\t\t\t\tface.__originalFaceNormal = face.normal.clone();\n\n\t\t\t} else {\n\n\t\t\t\tface.__originalFaceNormal.copy( face.normal );\n\n\t\t\t}\n\n\t\t\tif ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];\n\n\t\t\tfor ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {\n\n\t\t\t\tif ( ! face.__originalVertexNormals[ i ] ) {\n\n\t\t\t\t\tface.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();\n\n\t\t\t\t} else {\n\n\t\t\t\t\tface.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// use temp geometry to compute face and vertex normals for each morph\n\n\t\tvar tmpGeo = new Geometry();\n\t\ttmpGeo.faces = this.faces;\n\n\t\tfor ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {\n\n\t\t\t// create on first access\n\n\t\t\tif ( ! this.morphNormals[ i ] ) {\n\n\t\t\t\tthis.morphNormals[ i ] = {};\n\t\t\t\tthis.morphNormals[ i ].faceNormals = [];\n\t\t\t\tthis.morphNormals[ i ].vertexNormals = [];\n\n\t\t\t\tvar dstNormalsFace = this.morphNormals[ i ].faceNormals;\n\t\t\t\tvar dstNormalsVertex = this.morphNormals[ i ].vertexNormals;\n\n\t\t\t\tvar faceNormal, vertexNormals;\n\n\t\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\t\t\tfaceNormal = new Vector3();\n\t\t\t\t\tvertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() };\n\n\t\t\t\t\tdstNormalsFace.push( faceNormal );\n\t\t\t\t\tdstNormalsVertex.push( vertexNormals );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar morphNormals = this.morphNormals[ i ];\n\n\t\t\t// set vertices to morph target\n\n\t\t\ttmpGeo.vertices = this.morphTargets[ i ].vertices;\n\n\t\t\t// compute morph normals\n\n\t\t\ttmpGeo.computeFaceNormals();\n\t\t\ttmpGeo.computeVertexNormals();\n\n\t\t\t// store morph normals\n\n\t\t\tvar faceNormal, vertexNormals;\n\n\t\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\t\tface = this.faces[ f ];\n\n\t\t\t\tfaceNormal = morphNormals.faceNormals[ f ];\n\t\t\t\tvertexNormals = morphNormals.vertexNormals[ f ];\n\n\t\t\t\tfaceNormal.copy( face.normal );\n\n\t\t\t\tvertexNormals.a.copy( face.vertexNormals[ 0 ] );\n\t\t\t\tvertexNormals.b.copy( face.vertexNormals[ 1 ] );\n\t\t\t\tvertexNormals.c.copy( face.vertexNormals[ 2 ] );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// restore original normals\n\n\t\tfor ( f = 0, fl = this.faces.length; f < fl; f ++ ) {\n\n\t\t\tface = this.faces[ f ];\n\n\t\t\tface.normal = face.__originalFaceNormal;\n\t\t\tface.vertexNormals = face.__originalVertexNormals;\n\n\t\t}\n\n\t},\n\n\tcomputeBoundingBox: function () {\n\n\t\tif ( this.boundingBox === null ) {\n\n\t\t\tthis.boundingBox = new Box3();\n\n\t\t}\n\n\t\tthis.boundingBox.setFromPoints( this.vertices );\n\n\t},\n\n\tcomputeBoundingSphere: function () {\n\n\t\tif ( this.boundingSphere === null ) {\n\n\t\t\tthis.boundingSphere = new Sphere();\n\n\t\t}\n\n\t\tthis.boundingSphere.setFromPoints( this.vertices );\n\n\t},\n\n\tmerge: function ( geometry, matrix, materialIndexOffset ) {\n\n\t\tif ( ! ( geometry && geometry.isGeometry ) ) {\n\n\t\t\tconsole.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry );\n\t\t\treturn;\n\n\t\t}\n\n\t\tvar normalMatrix,\n\t\t\tvertexOffset = this.vertices.length,\n\t\t\tvertices1 = this.vertices,\n\t\t\tvertices2 = geometry.vertices,\n\t\t\tfaces1 = this.faces,\n\t\t\tfaces2 = geometry.faces,\n\t\t\tcolors1 = this.colors,\n\t\t\tcolors2 = geometry.colors;\n\n\t\tif ( materialIndexOffset === undefined ) materialIndexOffset = 0;\n\n\t\tif ( matrix !== undefined ) {\n\n\t\t\tnormalMatrix = new Matrix3().getNormalMatrix( matrix );\n\n\t\t}\n\n\t\t// vertices\n\n\t\tfor ( var i = 0, il = vertices2.length; i < il; i ++ ) {\n\n\t\t\tvar vertex = vertices2[ i ];\n\n\t\t\tvar vertexCopy = vertex.clone();\n\n\t\t\tif ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix );\n\n\t\t\tvertices1.push( vertexCopy );\n\n\t\t}\n\n\t\t// colors\n\n\t\tfor ( var i = 0, il = colors2.length; i < il; i ++ ) {\n\n\t\t\tcolors1.push( colors2[ i ].clone() );\n\n\t\t}\n\n\t\t// faces\n\n\t\tfor ( i = 0, il = faces2.length; i < il; i ++ ) {\n\n\t\t\tvar face = faces2[ i ], faceCopy, normal, color,\n\t\t\t\tfaceVertexNormals = face.vertexNormals,\n\t\t\t\tfaceVertexColors = face.vertexColors;\n\n\t\t\tfaceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );\n\t\t\tfaceCopy.normal.copy( face.normal );\n\n\t\t\tif ( normalMatrix !== undefined ) {\n\n\t\t\t\tfaceCopy.normal.applyMatrix3( normalMatrix ).normalize();\n\n\t\t\t}\n\n\t\t\tfor ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {\n\n\t\t\t\tnormal = faceVertexNormals[ j ].clone();\n\n\t\t\t\tif ( normalMatrix !== undefined ) {\n\n\t\t\t\t\tnormal.applyMatrix3( normalMatrix ).normalize();\n\n\t\t\t\t}\n\n\t\t\t\tfaceCopy.vertexNormals.push( normal );\n\n\t\t\t}\n\n\t\t\tfaceCopy.color.copy( face.color );\n\n\t\t\tfor ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {\n\n\t\t\t\tcolor = faceVertexColors[ j ];\n\t\t\t\tfaceCopy.vertexColors.push( color.clone() );\n\n\t\t\t}\n\n\t\t\tfaceCopy.materialIndex = face.materialIndex + materialIndexOffset;\n\n\t\t\tfaces1.push( faceCopy );\n\n\t\t}\n\n\t\t// uvs\n\n\t\tfor ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {\n\n\t\t\tvar faceVertexUvs2 = geometry.faceVertexUvs[ i ];\n\n\t\t\tif ( this.faceVertexUvs[ i ] === undefined ) this.faceVertexUvs[ i ] = [];\n\n\t\t\tfor ( var j = 0, jl = faceVertexUvs2.length; j < jl; j ++ ) {\n\n\t\t\t\tvar uvs2 = faceVertexUvs2[ j ], uvsCopy = [];\n\n\t\t\t\tfor ( var k = 0, kl = uvs2.length; k < kl; k ++ ) {\n\n\t\t\t\t\tuvsCopy.push( uvs2[ k ].clone() );\n\n\t\t\t\t}\n\n\t\t\t\tthis.faceVertexUvs[ i ].push( uvsCopy );\n\n\t\t\t}\n\n\t\t}\n\n\t},\n\n\tmergeMesh: function ( mesh ) {\n\n\t\tif ( ! ( mesh && mesh.isMesh ) ) {\n\n\t\t\tconsole.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( mesh.matrixAutoUpdate ) mesh.updateMatrix();\n\n\t\tthis.merge( mesh.geometry, mesh.matrix );\n\n\t},\n\n\t/*\n\t * Checks for duplicate vertices with hashmap.\n\t * Duplicated vertices are removed\n\t * and faces' vertices are updated.\n\t */\n\n\tmergeVertices: function () {\n\n\t\tvar verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique)\n\t\tvar unique = [], changes = [];\n\n\t\tvar v, key;\n\t\tvar precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001\n\t\tvar precision = Math.pow( 10, precisionPoints );\n\t\tvar i, il, face;\n\t\tvar indices, j, jl;\n\n\t\tfor ( i = 0, il = this.vertices.length; i < il; i ++ ) {\n\n\t\t\tv = this.vertices[ i ];\n\t\t\tkey = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );\n\n\t\t\tif ( verticesMap[ key ] === undefined ) {\n\n\t\t\t\tverticesMap[ key ] = i;\n\t\t\t\tunique.push( this.vertices[ i ] );\n\t\t\t\tchanges[ i ] = unique.length - 1;\n\n\t\t\t} else {\n\n\t\t\t\t//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);\n\t\t\t\tchanges[ i ] = changes[ verticesMap[ key ] ];\n\n\t\t\t}\n\n\t\t}\n\n\n\t\t// if faces are completely degenerate after merging vertices, we\n\t\t// have to remove them from the geometry.\n\t\tvar faceIndicesToRemove = [];\n\n\t\tfor ( i = 0, il = this.faces.length; i < il; i ++ ) {\n\n\t\t\tface = this.faces[ i ];\n\n\t\t\tface.a = changes[ face.a ];\n\t\t\tface.b = changes[ face.b ];\n\t\t\tface.c = changes[ face.c ];\n\n\t\t\tindices = [ face.a, face.b, face.c ];\n\n\t\t\t// if any duplicate vertices are found in a Face3\n\t\t\t// we have to remove the face as nothing can be saved\n\t\t\tfor ( var n = 0; n < 3; n ++ ) {\n\n\t\t\t\tif ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) {\n\n\t\t\t\t\tfaceIndicesToRemove.push( i );\n\t\t\t\t\tbreak;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tfor ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {\n\n\t\t\tvar idx = faceIndicesToRemove[ i ];\n\n\t\t\tthis.faces.splice( idx, 1 );\n\n\t\t\tfor ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {\n\n\t\t\t\tthis.faceVertexUvs[ j ].splice( idx, 1 );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Use unique set of vertices\n\n\t\tvar diff = this.vertices.length - unique.length;\n\t\tthis.vertices = unique;\n\t\treturn diff;\n\n\t},\n\n\tsetFromPoints: function ( points ) {\n\n\t\tthis.vertices = [];\n\n\t\tfor ( var i = 0, l = points.length; i < l; i ++ ) {\n\n\t\t\tvar point = points[ i ];\n\t\t\tthis.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsortFacesByMaterialIndex: function () {\n\n\t\tvar faces = this.faces;\n\t\tvar length = faces.length;\n\n\t\t// tag faces\n\n\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\tfaces[ i ]._id = i;\n\n\t\t}\n\n\t\t// sort faces\n\n\t\tfunction materialIndexSort( a, b ) {\n\n\t\t\treturn a.materialIndex - b.materialIndex;\n\n\t\t}\n\n\t\tfaces.sort( materialIndexSort );\n\n\t\t// sort uvs\n\n\t\tvar uvs1 = this.faceVertexUvs[ 0 ];\n\t\tvar uvs2 = this.faceVertexUvs[ 1 ];\n\n\t\tvar newUvs1, newUvs2;\n\n\t\tif ( uvs1 && uvs1.length === length ) newUvs1 = [];\n\t\tif ( uvs2 && uvs2.length === length ) newUvs2 = [];\n\n\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\tvar id = faces[ i ]._id;\n\n\t\t\tif ( newUvs1 ) newUvs1.push( uvs1[ id ] );\n\t\t\tif ( newUvs2 ) newUvs2.push( uvs2[ id ] );\n\n\t\t}\n\n\t\tif ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1;\n\t\tif ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2;\n\n\t},\n\n\ttoJSON: function () {\n\n\t\tvar data = {\n\t\t\tmetadata: {\n\t\t\t\tversion: 4.5,\n\t\t\t\ttype: 'Geometry',\n\t\t\t\tgenerator: 'Geometry.toJSON'\n\t\t\t}\n\t\t};\n\n\t\t// standard Geometry serialization\n\n\t\tdata.uuid = this.uuid;\n\t\tdata.type = this.type;\n\t\tif ( this.name !== '' ) data.name = this.name;\n\n\t\tif ( this.parameters !== undefined ) {\n\n\t\t\tvar parameters = this.parameters;\n\n\t\t\tfor ( var key in parameters ) {\n\n\t\t\t\tif ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ];\n\n\t\t\t}\n\n\t\t\treturn data;\n\n\t\t}\n\n\t\tvar vertices = [];\n\n\t\tfor ( var i = 0; i < this.vertices.length; i ++ ) {\n\n\t\t\tvar vertex = this.vertices[ i ];\n\t\t\tvertices.push( vertex.x, vertex.y, vertex.z );\n\n\t\t}\n\n\t\tvar faces = [];\n\t\tvar normals = [];\n\t\tvar normalsHash = {};\n\t\tvar colors = [];\n\t\tvar colorsHash = {};\n\t\tvar uvs = [];\n\t\tvar uvsHash = {};\n\n\t\tfor ( var i = 0; i < this.faces.length; i ++ ) {\n\n\t\t\tvar face = this.faces[ i ];\n\n\t\t\tvar hasMaterial = true;\n\t\t\tvar hasFaceUv = false; // deprecated\n\t\t\tvar hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined;\n\t\t\tvar hasFaceNormal = face.normal.length() > 0;\n\t\t\tvar hasFaceVertexNormal = face.vertexNormals.length > 0;\n\t\t\tvar hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1;\n\t\t\tvar hasFaceVertexColor = face.vertexColors.length > 0;\n\n\t\t\tvar faceType = 0;\n\n\t\t\tfaceType = setBit( faceType, 0, 0 ); // isQuad\n\t\t\tfaceType = setBit( faceType, 1, hasMaterial );\n\t\t\tfaceType = setBit( faceType, 2, hasFaceUv );\n\t\t\tfaceType = setBit( faceType, 3, hasFaceVertexUv );\n\t\t\tfaceType = setBit( faceType, 4, hasFaceNormal );\n\t\t\tfaceType = setBit( faceType, 5, hasFaceVertexNormal );\n\t\t\tfaceType = setBit( faceType, 6, hasFaceColor );\n\t\t\tfaceType = setBit( faceType, 7, hasFaceVertexColor );\n\n\t\t\tfaces.push( faceType );\n\t\t\tfaces.push( face.a, face.b, face.c );\n\t\t\tfaces.push( face.materialIndex );\n\n\t\t\tif ( hasFaceVertexUv ) {\n\n\t\t\t\tvar faceVertexUvs = this.faceVertexUvs[ 0 ][ i ];\n\n\t\t\t\tfaces.push(\n\t\t\t\t\tgetUvIndex( faceVertexUvs[ 0 ] ),\n\t\t\t\t\tgetUvIndex( faceVertexUvs[ 1 ] ),\n\t\t\t\t\tgetUvIndex( faceVertexUvs[ 2 ] )\n\t\t\t\t);\n\n\t\t\t}\n\n\t\t\tif ( hasFaceNormal ) {\n\n\t\t\t\tfaces.push( getNormalIndex( face.normal ) );\n\n\t\t\t}\n\n\t\t\tif ( hasFaceVertexNormal ) {\n\n\t\t\t\tvar vertexNormals = face.vertexNormals;\n\n\t\t\t\tfaces.push(\n\t\t\t\t\tgetNormalIndex( vertexNormals[ 0 ] ),\n\t\t\t\t\tgetNormalIndex( vertexNormals[ 1 ] ),\n\t\t\t\t\tgetNormalIndex( vertexNormals[ 2 ] )\n\t\t\t\t);\n\n\t\t\t}\n\n\t\t\tif ( hasFaceColor ) {\n\n\t\t\t\tfaces.push( getColorIndex( face.color ) );\n\n\t\t\t}\n\n\t\t\tif ( hasFaceVertexColor ) {\n\n\t\t\t\tvar vertexColors = face.vertexColors;\n\n\t\t\t\tfaces.push(\n\t\t\t\t\tgetColorIndex( vertexColors[ 0 ] ),\n\t\t\t\t\tgetColorIndex( vertexColors[ 1 ] ),\n\t\t\t\t\tgetColorIndex( vertexColors[ 2 ] )\n\t\t\t\t);\n\n\t\t\t}\n\n\t\t}\n\n\t\tfunction setBit( value, position, enabled ) {\n\n\t\t\treturn enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) );\n\n\t\t}\n\n\t\tfunction getNormalIndex( normal ) {\n\n\t\t\tvar hash = normal.x.toString() + normal.y.toString() + normal.z.toString();\n\n\t\t\tif ( normalsHash[ hash ] !== undefined ) {\n\n\t\t\t\treturn normalsHash[ hash ];\n\n\t\t\t}\n\n\t\t\tnormalsHash[ hash ] = normals.length / 3;\n\t\t\tnormals.push( normal.x, normal.y, normal.z );\n\n\t\t\treturn normalsHash[ hash ];\n\n\t\t}\n\n\t\tfunction getColorIndex( color ) {\n\n\t\t\tvar hash = color.r.toString() + color.g.toString() + color.b.toString();\n\n\t\t\tif ( colorsHash[ hash ] !== undefined ) {\n\n\t\t\t\treturn colorsHash[ hash ];\n\n\t\t\t}\n\n\t\t\tcolorsHash[ hash ] = colors.length;\n\t\t\tcolors.push( color.getHex() );\n\n\t\t\treturn colorsHash[ hash ];\n\n\t\t}\n\n\t\tfunction getUvIndex( uv ) {\n\n\t\t\tvar hash = uv.x.toString() + uv.y.toString();\n\n\t\t\tif ( uvsHash[ hash ] !== undefined ) {\n\n\t\t\t\treturn uvsHash[ hash ];\n\n\t\t\t}\n\n\t\t\tuvsHash[ hash ] = uvs.length / 2;\n\t\t\tuvs.push( uv.x, uv.y );\n\n\t\t\treturn uvsHash[ hash ];\n\n\t\t}\n\n\t\tdata.data = {};\n\n\t\tdata.data.vertices = vertices;\n\t\tdata.data.normals = normals;\n\t\tif ( colors.length > 0 ) data.data.colors = colors;\n\t\tif ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility\n\t\tdata.data.faces = faces;\n\n\t\treturn data;\n\n\t},\n\n\tclone: function () {\n\n\t\t/*\n\t\t // Handle primitives\n\n\t\t var parameters = this.parameters;\n\n\t\t if ( parameters !== undefined ) {\n\n\t\t var values = [];\n\n\t\t for ( var key in parameters ) {\n\n\t\t values.push( parameters[ key ] );\n\n\t\t }\n\n\t\t var geometry = Object.create( this.constructor.prototype );\n\t\t this.constructor.apply( geometry, values );\n\t\t return geometry;\n\n\t\t }\n\n\t\t return new this.constructor().copy( this );\n\t\t */\n\n\t\treturn new Geometry().copy( this );\n\n\t},\n\n\tcopy: function ( source ) {\n\n\t\tvar i, il, j, jl, k, kl;\n\n\t\t// reset\n\n\t\tthis.vertices = [];\n\t\tthis.colors = [];\n\t\tthis.faces = [];\n\t\tthis.faceVertexUvs = [[]];\n\t\tthis.morphTargets = [];\n\t\tthis.morphNormals = [];\n\t\tthis.skinWeights = [];\n\t\tthis.skinIndices = [];\n\t\tthis.lineDistances = [];\n\t\tthis.boundingBox = null;\n\t\tthis.boundingSphere = null;\n\n\t\t// name\n\n\t\tthis.name = source.name;\n\n\t\t// vertices\n\n\t\tvar vertices = source.vertices;\n\n\t\tfor ( i = 0, il = vertices.length; i < il; i ++ ) {\n\n\t\t\tthis.vertices.push( vertices[ i ].clone() );\n\n\t\t}\n\n\t\t// colors\n\n\t\tvar colors = source.colors;\n\n\t\tfor ( i = 0, il = colors.length; i < il; i ++ ) {\n\n\t\t\tthis.colors.push( colors[ i ].clone() );\n\n\t\t}\n\n\t\t// faces\n\n\t\tvar faces = source.faces;\n\n\t\tfor ( i = 0, il = faces.length; i < il; i ++ ) {\n\n\t\t\tthis.faces.push( faces[ i ].clone() );\n\n\t\t}\n\n\t\t// face vertex uvs\n\n\t\tfor ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) {\n\n\t\t\tvar faceVertexUvs = source.faceVertexUvs[ i ];\n\n\t\t\tif ( this.faceVertexUvs[ i ] === undefined ) {\n\n\t\t\t\tthis.faceVertexUvs[ i ] = [];\n\n\t\t\t}\n\n\t\t\tfor ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) {\n\n\t\t\t\tvar uvs = faceVertexUvs[ j ], uvsCopy = [];\n\n\t\t\t\tfor ( k = 0, kl = uvs.length; k < kl; k ++ ) {\n\n\t\t\t\t\tvar uv = uvs[ k ];\n\n\t\t\t\t\tuvsCopy.push( uv.clone() );\n\n\t\t\t\t}\n\n\t\t\t\tthis.faceVertexUvs[ i ].push( uvsCopy );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// morph targets\n\n\t\tvar morphTargets = source.morphTargets;\n\n\t\tfor ( i = 0, il = morphTargets.length; i < il; i ++ ) {\n\n\t\t\tvar morphTarget = {};\n\t\t\tmorphTarget.name = morphTargets[ i ].name;\n\n\t\t\t// vertices\n\n\t\t\tif ( morphTargets[ i ].vertices !== undefined ) {\n\n\t\t\t\tmorphTarget.vertices = [];\n\n\t\t\t\tfor ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) {\n\n\t\t\t\t\tmorphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// normals\n\n\t\t\tif ( morphTargets[ i ].normals !== undefined ) {\n\n\t\t\t\tmorphTarget.normals = [];\n\n\t\t\t\tfor ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) {\n\n\t\t\t\t\tmorphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.morphTargets.push( morphTarget );\n\n\t\t}\n\n\t\t// morph normals\n\n\t\tvar morphNormals = source.morphNormals;\n\n\t\tfor ( i = 0, il = morphNormals.length; i < il; i ++ ) {\n\n\t\t\tvar morphNormal = {};\n\n\t\t\t// vertex normals\n\n\t\t\tif ( morphNormals[ i ].vertexNormals !== undefined ) {\n\n\t\t\t\tmorphNormal.vertexNormals = [];\n\n\t\t\t\tfor ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) {\n\n\t\t\t\t\tvar srcVertexNormal = morphNormals[ i ].vertexNormals[ j ];\n\t\t\t\t\tvar destVertexNormal = {};\n\n\t\t\t\t\tdestVertexNormal.a = srcVertexNormal.a.clone();\n\t\t\t\t\tdestVertexNormal.b = srcVertexNormal.b.clone();\n\t\t\t\t\tdestVertexNormal.c = srcVertexNormal.c.clone();\n\n\t\t\t\t\tmorphNormal.vertexNormals.push( destVertexNormal );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// face normals\n\n\t\t\tif ( morphNormals[ i ].faceNormals !== undefined ) {\n\n\t\t\t\tmorphNormal.faceNormals = [];\n\n\t\t\t\tfor ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) {\n\n\t\t\t\t\tmorphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis.morphNormals.push( morphNormal );\n\n\t\t}\n\n\t\t// skin weights\n\n\t\tvar skinWeights = source.skinWeights;\n\n\t\tfor ( i = 0, il = skinWeights.length; i < il; i ++ ) {\n\n\t\t\tthis.skinWeights.push( skinWeights[ i ].clone() );\n\n\t\t}\n\n\t\t// skin indices\n\n\t\tvar skinIndices = source.skinIndices;\n\n\t\tfor ( i = 0, il = skinIndices.length; i < il; i ++ ) {\n\n\t\t\tthis.skinIndices.push( skinIndices[ i ].clone() );\n\n\t\t}\n\n\t\t// line distances\n\n\t\tvar lineDistances = source.lineDistances;\n\n\t\tfor ( i = 0, il = lineDistances.length; i < il; i ++ ) {\n\n\t\t\tthis.lineDistances.push( lineDistances[ i ] );\n\n\t\t}\n\n\t\t// bounding box\n\n\t\tvar boundingBox = source.boundingBox;\n\n\t\tif ( boundingBox !== null ) {\n\n\t\t\tthis.boundingBox = boundingBox.clone();\n\n\t\t}\n\n\t\t// bounding sphere\n\n\t\tvar boundingSphere = source.boundingSphere;\n\n\t\tif ( boundingSphere !== null ) {\n\n\t\t\tthis.boundingSphere = boundingSphere.clone();\n\n\t\t}\n\n\t\t// update flags\n\n\t\tthis.elementsNeedUpdate = source.elementsNeedUpdate;\n\t\tthis.verticesNeedUpdate = source.verticesNeedUpdate;\n\t\tthis.uvsNeedUpdate = source.uvsNeedUpdate;\n\t\tthis.normalsNeedUpdate = source.normalsNeedUpdate;\n\t\tthis.colorsNeedUpdate = source.colorsNeedUpdate;\n\t\tthis.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate;\n\t\tthis.groupsNeedUpdate = source.groupsNeedUpdate;\n\n\t\treturn this;\n\n\t},\n\n\tdispose: function () {\n\n\t\tthis.dispatchEvent( { type: 'dispose' } );\n\n\t}\n\n} );\n\n\nexport { Geometry };\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author Mugen87 / https://github.com/Mugen87\n */\n\nimport { Geometry } from '../core/Geometry.js';\nimport { BufferGeometry } from '../core/BufferGeometry.js';\nimport { Float32BufferAttribute } from '../core/BufferAttribute.js';\nimport { Vector3 } from '../math/Vector3.js';\n\n// BoxGeometry\n\nclass BoxGeometry extends Geometry {\n\n\tconstructor( width, height, depth, widthSegments, heightSegments, depthSegments ) {\n\n\t\tsuper();\n\n\t\tthis.type = 'BoxGeometry';\n\n\t\tthis.parameters = {\n\t\t\twidth: width,\n\t\t\theight: height,\n\t\t\tdepth: depth,\n\t\t\twidthSegments: widthSegments,\n\t\t\theightSegments: heightSegments,\n\t\t\tdepthSegments: depthSegments\n\t\t};\n\n\t\tthis.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) );\n\t\tthis.mergeVertices();\n\n\t}\n\n}\n\n// BoxBufferGeometry\n\nclass BoxBufferGeometry extends BufferGeometry {\n\n\tconstructor( width, height, depth, widthSegments, heightSegments, depthSegments ) {\n\n\t\tsuper();\n\n\t\tthis.type = 'BoxBufferGeometry';\n\n\t\tthis.parameters = {\n\t\t\twidth: width,\n\t\t\theight: height,\n\t\t\tdepth: depth,\n\t\t\twidthSegments: widthSegments,\n\t\t\theightSegments: heightSegments,\n\t\t\tdepthSegments: depthSegments\n\t\t};\n\n\t\tconst scope = this;\n\n\t\twidth = width || 1;\n\t\theight = height || 1;\n\t\tdepth = depth || 1;\n\n\t\t// segments\n\n\t\twidthSegments = Math.floor( widthSegments ) || 1;\n\t\theightSegments = Math.floor( heightSegments ) || 1;\n\t\tdepthSegments = Math.floor( depthSegments ) || 1;\n\n\t\t// buffers\n\n\t\tconst indices = [];\n\t\tconst vertices = [];\n\t\tconst normals = [];\n\t\tconst uvs = [];\n\n\t\t// helper variables\n\n\t\tlet numberOfVertices = 0;\n\t\tlet groupStart = 0;\n\n\t\t// build each side of the box geometry\n\n\t\tbuildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px\n\t\tbuildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx\n\t\tbuildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py\n\t\tbuildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny\n\t\tbuildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz\n\t\tbuildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz\n\n\t\t// build geometry\n\n\t\tthis.setIndex( indices );\n\t\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\n\t\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\n\t\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\n\n\t\tfunction buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {\n\n\t\t\tconst segmentWidth = width / gridX;\n\t\t\tconst segmentHeight = height / gridY;\n\n\t\t\tconst widthHalf = width / 2;\n\t\t\tconst heightHalf = height / 2;\n\t\t\tconst depthHalf = depth / 2;\n\n\t\t\tconst gridX1 = gridX + 1;\n\t\t\tconst gridY1 = gridY + 1;\n\n\t\t\tlet vertexCounter = 0;\n\t\t\tlet groupCount = 0;\n\n\t\t\tconst vector = new Vector3();\n\n\t\t\t// generate vertices, normals and uvs\n\n\t\t\tfor ( let iy = 0; iy < gridY1; iy ++ ) {\n\n\t\t\t\tconst y = iy * segmentHeight - heightHalf;\n\n\t\t\t\tfor ( let ix = 0; ix < gridX1; ix ++ ) {\n\n\t\t\t\t\tconst x = ix * segmentWidth - widthHalf;\n\n\t\t\t\t\t// set values to correct vector component\n\n\t\t\t\t\tvector[ u ] = x * udir;\n\t\t\t\t\tvector[ v ] = y * vdir;\n\t\t\t\t\tvector[ w ] = depthHalf;\n\n\t\t\t\t\t// now apply vector to vertex buffer\n\n\t\t\t\t\tvertices.push( vector.x, vector.y, vector.z );\n\n\t\t\t\t\t// set values to correct vector component\n\n\t\t\t\t\tvector[ u ] = 0;\n\t\t\t\t\tvector[ v ] = 0;\n\t\t\t\t\tvector[ w ] = depth > 0 ? 1 : - 1;\n\n\t\t\t\t\t// now apply vector to normal buffer\n\n\t\t\t\t\tnormals.push( vector.x, vector.y, vector.z );\n\n\t\t\t\t\t// uvs\n\n\t\t\t\t\tuvs.push( ix / gridX );\n\t\t\t\t\tuvs.push( 1 - ( iy / gridY ) );\n\n\t\t\t\t\t// counters\n\n\t\t\t\t\tvertexCounter += 1;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// indices\n\n\t\t\t// 1. you need three indices to draw a single face\n\t\t\t// 2. a single segment consists of two faces\n\t\t\t// 3. so we need to generate six (2*3) indices per segment\n\n\t\t\tfor ( let iy = 0; iy < gridY; iy ++ ) {\n\n\t\t\t\tfor ( let ix = 0; ix < gridX; ix ++ ) {\n\n\t\t\t\t\tconst a = numberOfVertices + ix + gridX1 * iy;\n\t\t\t\t\tconst b = numberOfVertices + ix + gridX1 * ( iy + 1 );\n\t\t\t\t\tconst c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );\n\t\t\t\t\tconst d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;\n\n\t\t\t\t\t// faces\n\n\t\t\t\t\tindices.push( a, b, d );\n\t\t\t\t\tindices.push( b, c, d );\n\n\t\t\t\t\t// increase counter\n\n\t\t\t\t\tgroupCount += 6;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// add a group to the geometry. this will ensure multi material support\n\n\t\t\tscope.addGroup( groupStart, groupCount, materialIndex );\n\n\t\t\t// calculate new start value for groups\n\n\t\t\tgroupStart += groupCount;\n\n\t\t\t// update total number of vertices\n\n\t\t\tnumberOfVertices += vertexCounter;\n\n\t\t}\n\n\t}\n\n}\n\nexport { BoxGeometry, BoxBufferGeometry };\n","/**\n * Uniform Utilities\n */\n\nexport function cloneUniforms( src ) {\n\n\tvar dst = {};\n\n\tfor ( var u in src ) {\n\n\t\tdst[ u ] = {};\n\n\t\tfor ( var p in src[ u ] ) {\n\n\t\t\tvar property = src[ u ][ p ];\n\n\t\t\tif ( property && ( property.isColor ||\n\t\t\t\tproperty.isMatrix3 || property.isMatrix4 ||\n\t\t\t\tproperty.isVector2 || property.isVector3 || property.isVector4 ||\n\t\t\t\tproperty.isTexture ) ) {\n\n\t\t\t\tdst[ u ][ p ] = property.clone();\n\n\t\t\t} else if ( Array.isArray( property ) ) {\n\n\t\t\t\tdst[ u ][ p ] = property.slice();\n\n\t\t\t} else {\n\n\t\t\t\tdst[ u ][ p ] = property;\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\treturn dst;\n\n}\n\nexport function mergeUniforms( uniforms ) {\n\n\tvar merged = {};\n\n\tfor ( var u = 0; u < uniforms.length; u ++ ) {\n\n\t\tvar tmp = cloneUniforms( uniforms[ u ] );\n\n\t\tfor ( var p in tmp ) {\n\n\t\t\tmerged[ p ] = tmp[ p ];\n\n\t\t}\n\n\t}\n\n\treturn merged;\n\n}\n\n// Legacy\n\nvar UniformsUtils = { clone: cloneUniforms, merge: mergeUniforms };\n\nexport { UniformsUtils };\n","/**\n * @author alteredq / http://alteredqualia.com/\n *\n * parameters = {\n * defines: { \"label\" : \"value\" },\n * uniforms: { \"parameter1\": { value: 1.0 }, \"parameter2\": { value2: 2 } },\n *\n * fragmentShader: ,\n * vertexShader: ,\n *\n * wireframe: ,\n * wireframeLinewidth: ,\n *\n * lights: ,\n *\n * skinning: ,\n * morphTargets: ,\n * morphNormals: \n * }\n */\n\nimport { Material } from './Material.js';\nimport { cloneUniforms } from '../renderers/shaders/UniformsUtils.js';\n\nimport default_vertex from '../renderers/shaders/ShaderChunk/default_vertex.glsl.js';\nimport default_fragment from '../renderers/shaders/ShaderChunk/default_fragment.glsl.js';\n\nfunction ShaderMaterial( parameters ) {\n\n\tMaterial.call( this );\n\n\tthis.type = 'ShaderMaterial';\n\n\tthis.defines = {};\n\tthis.uniforms = {};\n\n\tthis.vertexShader = default_vertex;\n\tthis.fragmentShader = default_fragment;\n\n\tthis.linewidth = 1;\n\n\tthis.wireframe = false;\n\tthis.wireframeLinewidth = 1;\n\n\tthis.fog = false; // set to use scene fog\n\tthis.lights = false; // set to use scene lights\n\tthis.clipping = false; // set to use user-defined clipping planes\n\n\tthis.skinning = false; // set to use skinning attribute streams\n\tthis.morphTargets = false; // set to use morph targets\n\tthis.morphNormals = false; // set to use morph normals\n\n\tthis.extensions = {\n\t\tderivatives: false, // set to use derivatives\n\t\tfragDepth: false, // set to use fragment depth values\n\t\tdrawBuffers: false, // set to use draw buffers\n\t\tshaderTextureLOD: false // set to use shader texture LOD\n\t};\n\n\t// When rendered geometry doesn't include these attributes but the material does,\n\t// use these default values in WebGL. This avoids errors when buffer data is missing.\n\tthis.defaultAttributeValues = {\n\t\t'color': [ 1, 1, 1 ],\n\t\t'uv': [ 0, 0 ],\n\t\t'uv2': [ 0, 0 ]\n\t};\n\n\tthis.index0AttributeName = undefined;\n\tthis.uniformsNeedUpdate = false;\n\n\tif ( parameters !== undefined ) {\n\n\t\tif ( parameters.attributes !== undefined ) {\n\n\t\t\tconsole.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' );\n\n\t\t}\n\n\t\tthis.setValues( parameters );\n\n\t}\n\n}\n\nShaderMaterial.prototype = Object.create( Material.prototype );\nShaderMaterial.prototype.constructor = ShaderMaterial;\n\nShaderMaterial.prototype.isShaderMaterial = true;\n\nShaderMaterial.prototype.copy = function ( source ) {\n\n\tMaterial.prototype.copy.call( this, source );\n\n\tthis.fragmentShader = source.fragmentShader;\n\tthis.vertexShader = source.vertexShader;\n\n\tthis.uniforms = cloneUniforms( source.uniforms );\n\n\tthis.defines = Object.assign( {}, source.defines );\n\n\tthis.wireframe = source.wireframe;\n\tthis.wireframeLinewidth = source.wireframeLinewidth;\n\n\tthis.lights = source.lights;\n\tthis.clipping = source.clipping;\n\n\tthis.skinning = source.skinning;\n\n\tthis.morphTargets = source.morphTargets;\n\tthis.morphNormals = source.morphNormals;\n\n\tthis.extensions = Object.assign( {}, source.extensions );\n\n\treturn this;\n\n};\n\nShaderMaterial.prototype.toJSON = function ( meta ) {\n\n\tvar data = Material.prototype.toJSON.call( this, meta );\n\n\tdata.uniforms = {};\n\n\tfor ( var name in this.uniforms ) {\n\n\t\tvar uniform = this.uniforms[ name ];\n\t\tvar value = uniform.value;\n\n\t\tif ( value && value.isTexture ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 't',\n\t\t\t\tvalue: value.toJSON( meta ).uuid\n\t\t\t};\n\n\t\t} else if ( value && value.isColor ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'c',\n\t\t\t\tvalue: value.getHex()\n\t\t\t};\n\n\t\t} else if ( value && value.isVector2 ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'v2',\n\t\t\t\tvalue: value.toArray()\n\t\t\t};\n\n\t\t} else if ( value && value.isVector3 ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'v3',\n\t\t\t\tvalue: value.toArray()\n\t\t\t};\n\n\t\t} else if ( value && value.isVector4 ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'v4',\n\t\t\t\tvalue: value.toArray()\n\t\t\t};\n\n\t\t} else if ( value && value.isMatrix3 ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'm3',\n\t\t\t\tvalue: value.toArray()\n\t\t\t};\n\n\t\t} else if ( value && value.isMatrix4 ) {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\ttype: 'm4',\n\t\t\t\tvalue: value.toArray()\n\t\t\t};\n\n\t\t} else {\n\n\t\t\tdata.uniforms[ name ] = {\n\t\t\t\tvalue: value\n\t\t\t};\n\n\t\t\t// note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far\n\n\t\t}\n\n\t}\n\n\tif ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines;\n\n\tdata.vertexShader = this.vertexShader;\n\tdata.fragmentShader = this.fragmentShader;\n\n\tvar extensions = {};\n\n\tfor ( var key in this.extensions ) {\n\n\t\tif ( this.extensions[ key ] === true ) extensions[ key ] = true;\n\n\t}\n\n\tif ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;\n\n\treturn data;\n\n};\n\n\nexport { ShaderMaterial };\n","export default /* glsl */`\nvoid main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}\n`;\n","export default /* glsl */`\nvoid main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}\n`;\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author mikael emtinger / http://gomo.se/\n * @author WestLangley / http://github.com/WestLangley\n*/\n\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { Object3D } from '../core/Object3D.js';\nimport { Vector3 } from '../math/Vector3.js';\n\nfunction Camera() {\n\n\tObject3D.call( this );\n\n\tthis.type = 'Camera';\n\n\tthis.matrixWorldInverse = new Matrix4();\n\n\tthis.projectionMatrix = new Matrix4();\n\tthis.projectionMatrixInverse = new Matrix4();\n\n}\n\nCamera.prototype = Object.assign( Object.create( Object3D.prototype ), {\n\n\tconstructor: Camera,\n\n\tisCamera: true,\n\n\tcopy: function ( source, recursive ) {\n\n\t\tObject3D.prototype.copy.call( this, source, recursive );\n\n\t\tthis.matrixWorldInverse.copy( source.matrixWorldInverse );\n\n\t\tthis.projectionMatrix.copy( source.projectionMatrix );\n\t\tthis.projectionMatrixInverse.copy( source.projectionMatrixInverse );\n\n\t\treturn this;\n\n\t},\n\n\tgetWorldDirection: function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'THREE.Camera: .getWorldDirection() target is now required' );\n\t\t\ttarget = new Vector3();\n\n\t\t}\n\n\t\tthis.updateMatrixWorld( true );\n\n\t\tvar e = this.matrixWorld.elements;\n\n\t\treturn target.set( - e[ 8 ], - e[ 9 ], - e[ 10 ] ).normalize();\n\n\t},\n\n\tupdateMatrixWorld: function ( force ) {\n\n\t\tObject3D.prototype.updateMatrixWorld.call( this, force );\n\n\t\tthis.matrixWorldInverse.getInverse( this.matrixWorld );\n\n\t},\n\n\tupdateWorldMatrix: function ( updateParents, updateChildren ) {\n\n\t\tObject3D.prototype.updateWorldMatrix.call( this, updateParents, updateChildren );\n\n\t\tthis.matrixWorldInverse.getInverse( this.matrixWorld );\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t}\n\n} );\n\nexport { Camera };\n","import { Camera } from './Camera.js';\nimport { Object3D } from '../core/Object3D.js';\nimport { MathUtils } from '../math/MathUtils.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author greggman / http://games.greggman.com/\n * @author zz85 / http://www.lab4games.net/zz85/blog\n * @author tschw\n */\n\nfunction PerspectiveCamera( fov, aspect, near, far ) {\n\n\tCamera.call( this );\n\n\tthis.type = 'PerspectiveCamera';\n\n\tthis.fov = fov !== undefined ? fov : 50;\n\tthis.zoom = 1;\n\n\tthis.near = near !== undefined ? near : 0.1;\n\tthis.far = far !== undefined ? far : 2000;\n\tthis.focus = 10;\n\n\tthis.aspect = aspect !== undefined ? aspect : 1;\n\tthis.view = null;\n\n\tthis.filmGauge = 35;\t// width of the film (default in millimeters)\n\tthis.filmOffset = 0;\t// horizontal film offset (same unit as gauge)\n\n\tthis.updateProjectionMatrix();\n\n}\n\nPerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), {\n\n\tconstructor: PerspectiveCamera,\n\n\tisPerspectiveCamera: true,\n\n\tcopy: function ( source, recursive ) {\n\n\t\tCamera.prototype.copy.call( this, source, recursive );\n\n\t\tthis.fov = source.fov;\n\t\tthis.zoom = source.zoom;\n\n\t\tthis.near = source.near;\n\t\tthis.far = source.far;\n\t\tthis.focus = source.focus;\n\n\t\tthis.aspect = source.aspect;\n\t\tthis.view = source.view === null ? null : Object.assign( {}, source.view );\n\n\t\tthis.filmGauge = source.filmGauge;\n\t\tthis.filmOffset = source.filmOffset;\n\n\t\treturn this;\n\n\t},\n\n\t/**\n\t * Sets the FOV by focal length in respect to the current .filmGauge.\n\t *\n\t * The default film gauge is 35, so that the focal length can be specified for\n\t * a 35mm (full frame) camera.\n\t *\n\t * Values for focal length and film gauge must have the same unit.\n\t */\n\tsetFocalLength: function ( focalLength ) {\n\n\t\t// see http://www.bobatkins.com/photography/technical/field_of_view.html\n\t\tvar vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;\n\n\t\tthis.fov = MathUtils.RAD2DEG * 2 * Math.atan( vExtentSlope );\n\t\tthis.updateProjectionMatrix();\n\n\t},\n\n\t/**\n\t * Calculates the focal length from the current .fov and .filmGauge.\n\t */\n\tgetFocalLength: function () {\n\n\t\tvar vExtentSlope = Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov );\n\n\t\treturn 0.5 * this.getFilmHeight() / vExtentSlope;\n\n\t},\n\n\tgetEffectiveFOV: function () {\n\n\t\treturn MathUtils.RAD2DEG * 2 * Math.atan(\n\t\t\tMath.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom );\n\n\t},\n\n\tgetFilmWidth: function () {\n\n\t\t// film not completely covered in portrait format (aspect < 1)\n\t\treturn this.filmGauge * Math.min( this.aspect, 1 );\n\n\t},\n\n\tgetFilmHeight: function () {\n\n\t\t// film not completely covered in landscape format (aspect > 1)\n\t\treturn this.filmGauge / Math.max( this.aspect, 1 );\n\n\t},\n\n\t/**\n\t * Sets an offset in a larger frustum. This is useful for multi-window or\n\t * multi-monitor/multi-machine setups.\n\t *\n\t * For example, if you have 3x2 monitors and each monitor is 1920x1080 and\n\t * the monitors are in grid like this\n\t *\n\t * +---+---+---+\n\t * | A | B | C |\n\t * +---+---+---+\n\t * | D | E | F |\n\t * +---+---+---+\n\t *\n\t * then for each monitor you would call it like this\n\t *\n\t * var w = 1920;\n\t * var h = 1080;\n\t * var fullWidth = w * 3;\n\t * var fullHeight = h * 2;\n\t *\n\t * --A--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );\n\t * --B--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );\n\t * --C--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );\n\t * --D--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );\n\t * --E--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );\n\t * --F--\n\t * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );\n\t *\n\t * Note there is no reason monitors have to be the same size or in a grid.\n\t */\n\tsetViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) {\n\n\t\tthis.aspect = fullWidth / fullHeight;\n\n\t\tif ( this.view === null ) {\n\n\t\t\tthis.view = {\n\t\t\t\tenabled: true,\n\t\t\t\tfullWidth: 1,\n\t\t\t\tfullHeight: 1,\n\t\t\t\toffsetX: 0,\n\t\t\t\toffsetY: 0,\n\t\t\t\twidth: 1,\n\t\t\t\theight: 1\n\t\t\t};\n\n\t\t}\n\n\t\tthis.view.enabled = true;\n\t\tthis.view.fullWidth = fullWidth;\n\t\tthis.view.fullHeight = fullHeight;\n\t\tthis.view.offsetX = x;\n\t\tthis.view.offsetY = y;\n\t\tthis.view.width = width;\n\t\tthis.view.height = height;\n\n\t\tthis.updateProjectionMatrix();\n\n\t},\n\n\tclearViewOffset: function () {\n\n\t\tif ( this.view !== null ) {\n\n\t\t\tthis.view.enabled = false;\n\n\t\t}\n\n\t\tthis.updateProjectionMatrix();\n\n\t},\n\n\tupdateProjectionMatrix: function () {\n\n\t\tvar near = this.near,\n\t\t\ttop = near * Math.tan( MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom,\n\t\t\theight = 2 * top,\n\t\t\twidth = this.aspect * height,\n\t\t\tleft = - 0.5 * width,\n\t\t\tview = this.view;\n\n\t\tif ( this.view !== null && this.view.enabled ) {\n\n\t\t\tvar fullWidth = view.fullWidth,\n\t\t\t\tfullHeight = view.fullHeight;\n\n\t\t\tleft += view.offsetX * width / fullWidth;\n\t\t\ttop -= view.offsetY * height / fullHeight;\n\t\t\twidth *= view.width / fullWidth;\n\t\t\theight *= view.height / fullHeight;\n\n\t\t}\n\n\t\tvar skew = this.filmOffset;\n\t\tif ( skew !== 0 ) left += near * skew / this.getFilmWidth();\n\n\t\tthis.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far );\n\n\t\tthis.projectionMatrixInverse.getInverse( this.projectionMatrix );\n\n\t},\n\n\ttoJSON: function ( meta ) {\n\n\t\tvar data = Object3D.prototype.toJSON.call( this, meta );\n\n\t\tdata.object.fov = this.fov;\n\t\tdata.object.zoom = this.zoom;\n\n\t\tdata.object.near = this.near;\n\t\tdata.object.far = this.far;\n\t\tdata.object.focus = this.focus;\n\n\t\tdata.object.aspect = this.aspect;\n\n\t\tif ( this.view !== null ) data.object.view = Object.assign( {}, this.view );\n\n\t\tdata.object.filmGauge = this.filmGauge;\n\t\tdata.object.filmOffset = this.filmOffset;\n\n\t\treturn data;\n\n\t}\n\n} );\n\n\nexport { PerspectiveCamera };\n","/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nimport { Texture } from './Texture.js';\nimport { NearestFilter } from '../constants.js';\n\nfunction DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) {\n\n\tTexture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );\n\n\tthis.image = { data: data || null, width: width || 1, height: height || 1 };\n\n\tthis.magFilter = magFilter !== undefined ? magFilter : NearestFilter;\n\tthis.minFilter = minFilter !== undefined ? minFilter : NearestFilter;\n\n\tthis.generateMipmaps = false;\n\tthis.flipY = false;\n\tthis.unpackAlignment = 1;\n\n\tthis.needsUpdate = true;\n\n}\n\nDataTexture.prototype = Object.create( Texture.prototype );\nDataTexture.prototype.constructor = DataTexture;\n\nDataTexture.prototype.isDataTexture = true;\n\n\nexport { DataTexture };\n","import { Vector3 } from './Vector3.js';\nimport { Sphere } from './Sphere.js';\nimport { Plane } from './Plane.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author bhouston / http://clara.io\n */\n\nvar _sphere = new Sphere();\nvar _vector = new Vector3();\n\nfunction Frustum( p0, p1, p2, p3, p4, p5 ) {\n\n\tthis.planes = [\n\n\t\t( p0 !== undefined ) ? p0 : new Plane(),\n\t\t( p1 !== undefined ) ? p1 : new Plane(),\n\t\t( p2 !== undefined ) ? p2 : new Plane(),\n\t\t( p3 !== undefined ) ? p3 : new Plane(),\n\t\t( p4 !== undefined ) ? p4 : new Plane(),\n\t\t( p5 !== undefined ) ? p5 : new Plane()\n\n\t];\n\n}\n\nObject.assign( Frustum.prototype, {\n\n\tset: function ( p0, p1, p2, p3, p4, p5 ) {\n\n\t\tvar planes = this.planes;\n\n\t\tplanes[ 0 ].copy( p0 );\n\t\tplanes[ 1 ].copy( p1 );\n\t\tplanes[ 2 ].copy( p2 );\n\t\tplanes[ 3 ].copy( p3 );\n\t\tplanes[ 4 ].copy( p4 );\n\t\tplanes[ 5 ].copy( p5 );\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( frustum ) {\n\n\t\tvar planes = this.planes;\n\n\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\tplanes[ i ].copy( frustum.planes[ i ] );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tsetFromProjectionMatrix: function ( m ) {\n\n\t\tvar planes = this.planes;\n\t\tvar me = m.elements;\n\t\tvar me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];\n\t\tvar me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];\n\t\tvar me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];\n\t\tvar me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];\n\n\t\tplanes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();\n\t\tplanes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();\n\t\tplanes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();\n\t\tplanes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();\n\t\tplanes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();\n\t\tplanes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();\n\n\t\treturn this;\n\n\t},\n\n\tintersectsObject: function ( object ) {\n\n\t\tvar geometry = object.geometry;\n\n\t\tif ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();\n\n\t\t_sphere.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld );\n\n\t\treturn this.intersectsSphere( _sphere );\n\n\t},\n\n\tintersectsSprite: function ( sprite ) {\n\n\t\t_sphere.center.set( 0, 0, 0 );\n\t\t_sphere.radius = 0.7071067811865476;\n\t\t_sphere.applyMatrix4( sprite.matrixWorld );\n\n\t\treturn this.intersectsSphere( _sphere );\n\n\t},\n\n\tintersectsSphere: function ( sphere ) {\n\n\t\tvar planes = this.planes;\n\t\tvar center = sphere.center;\n\t\tvar negRadius = - sphere.radius;\n\n\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\tvar distance = planes[ i ].distanceToPoint( center );\n\n\t\t\tif ( distance < negRadius ) {\n\n\t\t\t\treturn false;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn true;\n\n\t},\n\n\tintersectsBox: function ( box ) {\n\n\t\tvar planes = this.planes;\n\n\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\tvar plane = planes[ i ];\n\n\t\t\t// corner at max distance\n\n\t\t\t_vector.x = plane.normal.x > 0 ? box.max.x : box.min.x;\n\t\t\t_vector.y = plane.normal.y > 0 ? box.max.y : box.min.y;\n\t\t\t_vector.z = plane.normal.z > 0 ? box.max.z : box.min.z;\n\n\t\t\tif ( plane.distanceToPoint( _vector ) < 0 ) {\n\n\t\t\t\treturn false;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn true;\n\n\t},\n\n\tcontainsPoint: function ( point ) {\n\n\t\tvar planes = this.planes;\n\n\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\tif ( planes[ i ].distanceToPoint( point ) < 0 ) {\n\n\t\t\t\treturn false;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn true;\n\n\t}\n\n} );\n\n\nexport { Frustum };\n","import { Color } from '../../math/Color.js';\nimport { Vector2 } from '../../math/Vector2.js';\nimport { Matrix3 } from '../../math/Matrix3.js';\n\n/**\n * Uniforms library for shared webgl shaders\n */\n\nvar UniformsLib = {\n\n\tcommon: {\n\n\t\tdiffuse: { value: new Color( 0xeeeeee ) },\n\t\topacity: { value: 1.0 },\n\n\t\tmap: { value: null },\n\t\tuvTransform: { value: new Matrix3() },\n\t\tuv2Transform: { value: new Matrix3() },\n\n\t\talphaMap: { value: null },\n\n\t},\n\n\tspecularmap: {\n\n\t\tspecularMap: { value: null },\n\n\t},\n\n\tenvmap: {\n\n\t\tenvMap: { value: null },\n\t\tflipEnvMap: { value: - 1 },\n\t\treflectivity: { value: 1.0 },\n\t\trefractionRatio: { value: 0.98 },\n\t\tmaxMipLevel: { value: 0 }\n\n\t},\n\n\taomap: {\n\n\t\taoMap: { value: null },\n\t\taoMapIntensity: { value: 1 }\n\n\t},\n\n\tlightmap: {\n\n\t\tlightMap: { value: null },\n\t\tlightMapIntensity: { value: 1 }\n\n\t},\n\n\temissivemap: {\n\n\t\temissiveMap: { value: null }\n\n\t},\n\n\tbumpmap: {\n\n\t\tbumpMap: { value: null },\n\t\tbumpScale: { value: 1 }\n\n\t},\n\n\tnormalmap: {\n\n\t\tnormalMap: { value: null },\n\t\tnormalScale: { value: new Vector2( 1, 1 ) }\n\n\t},\n\n\tdisplacementmap: {\n\n\t\tdisplacementMap: { value: null },\n\t\tdisplacementScale: { value: 1 },\n\t\tdisplacementBias: { value: 0 }\n\n\t},\n\n\troughnessmap: {\n\n\t\troughnessMap: { value: null }\n\n\t},\n\n\tmetalnessmap: {\n\n\t\tmetalnessMap: { value: null }\n\n\t},\n\n\tgradientmap: {\n\n\t\tgradientMap: { value: null }\n\n\t},\n\n\tfog: {\n\n\t\tfogDensity: { value: 0.00025 },\n\t\tfogNear: { value: 1 },\n\t\tfogFar: { value: 2000 },\n\t\tfogColor: { value: new Color( 0xffffff ) }\n\n\t},\n\n\tlights: {\n\n\t\tambientLightColor: { value: [] },\n\n\t\tlightProbe: { value: [] },\n\n\t\tdirectionalLights: { value: [], properties: {\n\t\t\tdirection: {},\n\t\t\tcolor: {}\n\t\t} },\n\n\t\tdirectionalLightShadows: { value: [], properties: {\n\t\t\tshadowBias: {},\n\t\t\tshadowRadius: {},\n\t\t\tshadowMapSize: {}\n\t\t} },\n\n\t\tdirectionalShadowMap: { value: [] },\n\t\tdirectionalShadowMatrix: { value: [] },\n\n\t\tspotLights: { value: [], properties: {\n\t\t\tcolor: {},\n\t\t\tposition: {},\n\t\t\tdirection: {},\n\t\t\tdistance: {},\n\t\t\tconeCos: {},\n\t\t\tpenumbraCos: {},\n\t\t\tdecay: {}\n\t\t} },\n\n\t\tspotLightShadows: { value: [], properties: {\n\t\t\tshadowBias: {},\n\t\t\tshadowRadius: {},\n\t\t\tshadowMapSize: {}\n\t\t} },\n\n\t\tspotShadowMap: { value: [] },\n\t\tspotShadowMatrix: { value: [] },\n\n\t\tpointLights: { value: [], properties: {\n\t\t\tcolor: {},\n\t\t\tposition: {},\n\t\t\tdecay: {},\n\t\t\tdistance: {}\n\t\t} },\n\n\t\tpointLightShadows: { value: [], properties: {\n\t\t\tshadowBias: {},\n\t\t\tshadowRadius: {},\n\t\t\tshadowMapSize: {},\n\t\t\tshadowCameraNear: {},\n\t\t\tshadowCameraFar: {}\n\t\t} },\n\n\t\tpointShadowMap: { value: [] },\n\t\tpointShadowMatrix: { value: [] },\n\n\t\themisphereLights: { value: [], properties: {\n\t\t\tdirection: {},\n\t\t\tskyColor: {},\n\t\t\tgroundColor: {}\n\t\t} },\n\n\t\t// TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src\n\t\trectAreaLights: { value: [], properties: {\n\t\t\tcolor: {},\n\t\t\tposition: {},\n\t\t\twidth: {},\n\t\t\theight: {}\n\t\t} }\n\n\t},\n\n\tpoints: {\n\n\t\tdiffuse: { value: new Color( 0xeeeeee ) },\n\t\topacity: { value: 1.0 },\n\t\tsize: { value: 1.0 },\n\t\tscale: { value: 1.0 },\n\t\tmap: { value: null },\n\t\talphaMap: { value: null },\n\t\tuvTransform: { value: new Matrix3() }\n\n\t},\n\n\tsprite: {\n\n\t\tdiffuse: { value: new Color( 0xeeeeee ) },\n\t\topacity: { value: 1.0 },\n\t\tcenter: { value: new Vector2( 0.5, 0.5 ) },\n\t\trotation: { value: 0.0 },\n\t\tmap: { value: null },\n\t\talphaMap: { value: null },\n\t\tuvTransform: { value: new Matrix3() }\n\n\t}\n\n};\n\nexport { UniformsLib };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLAnimation() {\n\n\tvar context = null;\n\tvar isAnimating = false;\n\tvar animationLoop = null;\n\n\tfunction onAnimationFrame( time, frame ) {\n\n\t\tif ( isAnimating === false ) return;\n\n\t\tanimationLoop( time, frame );\n\n\t\tcontext.requestAnimationFrame( onAnimationFrame );\n\n\t}\n\n\treturn {\n\n\t\tstart: function () {\n\n\t\t\tif ( isAnimating === true ) return;\n\t\t\tif ( animationLoop === null ) return;\n\n\t\t\tcontext.requestAnimationFrame( onAnimationFrame );\n\n\t\t\tisAnimating = true;\n\n\t\t},\n\n\t\tstop: function () {\n\n\t\t\tisAnimating = false;\n\n\t\t},\n\n\t\tsetAnimationLoop: function ( callback ) {\n\n\t\t\tanimationLoop = callback;\n\n\t\t},\n\n\t\tsetContext: function ( value ) {\n\n\t\t\tcontext = value;\n\n\t\t}\n\n\t};\n\n}\n\nexport { WebGLAnimation };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLAttributes( gl, capabilities ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\n\tvar buffers = new WeakMap();\n\n\tfunction createBuffer( attribute, bufferType ) {\n\n\t\tvar array = attribute.array;\n\t\tvar usage = attribute.usage;\n\n\t\tvar buffer = gl.createBuffer();\n\n\t\tgl.bindBuffer( bufferType, buffer );\n\t\tgl.bufferData( bufferType, array, usage );\n\n\t\tattribute.onUploadCallback();\n\n\t\tvar type = gl.FLOAT;\n\n\t\tif ( array instanceof Float32Array ) {\n\n\t\t\ttype = gl.FLOAT;\n\n\t\t} else if ( array instanceof Float64Array ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' );\n\n\t\t} else if ( array instanceof Uint16Array ) {\n\n\t\t\ttype = gl.UNSIGNED_SHORT;\n\n\t\t} else if ( array instanceof Int16Array ) {\n\n\t\t\ttype = gl.SHORT;\n\n\t\t} else if ( array instanceof Uint32Array ) {\n\n\t\t\ttype = gl.UNSIGNED_INT;\n\n\t\t} else if ( array instanceof Int32Array ) {\n\n\t\t\ttype = gl.INT;\n\n\t\t} else if ( array instanceof Int8Array ) {\n\n\t\t\ttype = gl.BYTE;\n\n\t\t} else if ( array instanceof Uint8Array ) {\n\n\t\t\ttype = gl.UNSIGNED_BYTE;\n\n\t\t}\n\n\t\treturn {\n\t\t\tbuffer: buffer,\n\t\t\ttype: type,\n\t\t\tbytesPerElement: array.BYTES_PER_ELEMENT,\n\t\t\tversion: attribute.version\n\t\t};\n\n\t}\n\n\tfunction updateBuffer( buffer, attribute, bufferType ) {\n\n\t\tvar array = attribute.array;\n\t\tvar updateRange = attribute.updateRange;\n\n\t\tgl.bindBuffer( bufferType, buffer );\n\n\t\tif ( updateRange.count === - 1 ) {\n\n\t\t\t// Not using update ranges\n\n\t\t\tgl.bufferSubData( bufferType, 0, array );\n\n\t\t} else {\n\n\t\t\tif ( isWebGL2 ) {\n\n\t\t\t\tgl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,\n\t\t\t\t\tarray, updateRange.offset, updateRange.count );\n\n\t\t\t} else {\n\n\t\t\t\tgl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,\n\t\t\t\t\tarray.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );\n\n\t\t\t}\n\n\t\t\tupdateRange.count = - 1; // reset range\n\n\t\t}\n\n\t}\n\n\t//\n\n\tfunction get( attribute ) {\n\n\t\tif ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;\n\n\t\treturn buffers.get( attribute );\n\n\t}\n\n\tfunction remove( attribute ) {\n\n\t\tif ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;\n\n\t\tvar data = buffers.get( attribute );\n\n\t\tif ( data ) {\n\n\t\t\tgl.deleteBuffer( data.buffer );\n\n\t\t\tbuffers.delete( attribute );\n\n\t\t}\n\n\t}\n\n\tfunction update( attribute, bufferType ) {\n\n\t\tif ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;\n\n\t\tvar data = buffers.get( attribute );\n\n\t\tif ( data === undefined ) {\n\n\t\t\tbuffers.set( attribute, createBuffer( attribute, bufferType ) );\n\n\t\t} else if ( data.version < attribute.version ) {\n\n\t\t\tupdateBuffer( data.buffer, attribute, bufferType );\n\n\t\t\tdata.version = attribute.version;\n\n\t\t}\n\n\t}\n\n\treturn {\n\n\t\tget: get,\n\t\tremove: remove,\n\t\tupdate: update\n\n\t};\n\n}\n\n\nexport { WebGLAttributes };\n","/**\n * @author mrdoob / http://mrdoob.com/\n * @author Mugen87 / https://github.com/Mugen87\n */\n\nimport { Geometry } from '../core/Geometry.js';\nimport { BufferGeometry } from '../core/BufferGeometry.js';\nimport { Float32BufferAttribute } from '../core/BufferAttribute.js';\n\n// PlaneGeometry\n\nfunction PlaneGeometry( width, height, widthSegments, heightSegments ) {\n\n\tGeometry.call( this );\n\n\tthis.type = 'PlaneGeometry';\n\n\tthis.parameters = {\n\t\twidth: width,\n\t\theight: height,\n\t\twidthSegments: widthSegments,\n\t\theightSegments: heightSegments\n\t};\n\n\tthis.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );\n\tthis.mergeVertices();\n\n}\n\nPlaneGeometry.prototype = Object.create( Geometry.prototype );\nPlaneGeometry.prototype.constructor = PlaneGeometry;\n\n// PlaneBufferGeometry\n\nfunction PlaneBufferGeometry( width, height, widthSegments, heightSegments ) {\n\n\tBufferGeometry.call( this );\n\n\tthis.type = 'PlaneBufferGeometry';\n\n\tthis.parameters = {\n\t\twidth: width,\n\t\theight: height,\n\t\twidthSegments: widthSegments,\n\t\theightSegments: heightSegments\n\t};\n\n\twidth = width || 1;\n\theight = height || 1;\n\n\tvar width_half = width / 2;\n\tvar height_half = height / 2;\n\n\tvar gridX = Math.floor( widthSegments ) || 1;\n\tvar gridY = Math.floor( heightSegments ) || 1;\n\n\tvar gridX1 = gridX + 1;\n\tvar gridY1 = gridY + 1;\n\n\tvar segment_width = width / gridX;\n\tvar segment_height = height / gridY;\n\n\tvar ix, iy;\n\n\t// buffers\n\n\tvar indices = [];\n\tvar vertices = [];\n\tvar normals = [];\n\tvar uvs = [];\n\n\t// generate vertices, normals and uvs\n\n\tfor ( iy = 0; iy < gridY1; iy ++ ) {\n\n\t\tvar y = iy * segment_height - height_half;\n\n\t\tfor ( ix = 0; ix < gridX1; ix ++ ) {\n\n\t\t\tvar x = ix * segment_width - width_half;\n\n\t\t\tvertices.push( x, - y, 0 );\n\n\t\t\tnormals.push( 0, 0, 1 );\n\n\t\t\tuvs.push( ix / gridX );\n\t\t\tuvs.push( 1 - ( iy / gridY ) );\n\n\t\t}\n\n\t}\n\n\t// indices\n\n\tfor ( iy = 0; iy < gridY; iy ++ ) {\n\n\t\tfor ( ix = 0; ix < gridX; ix ++ ) {\n\n\t\t\tvar a = ix + gridX1 * iy;\n\t\t\tvar b = ix + gridX1 * ( iy + 1 );\n\t\t\tvar c = ( ix + 1 ) + gridX1 * ( iy + 1 );\n\t\t\tvar d = ( ix + 1 ) + gridX1 * iy;\n\n\t\t\t// faces\n\n\t\t\tindices.push( a, b, d );\n\t\t\tindices.push( b, c, d );\n\n\t\t}\n\n\t}\n\n\t// build geometry\n\n\tthis.setIndex( indices );\n\tthis.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );\n\tthis.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );\n\tthis.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );\n\n}\n\nPlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype );\nPlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry;\n\n\nexport { PlaneGeometry, PlaneBufferGeometry };\n","export default /* glsl */`\n#ifdef USE_ALPHAMAP\n\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ALPHAMAP\n\n\tuniform sampler2D alphaMap;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef ALPHATEST\n\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_AOMAP\n\n\t// reads channel R, compatible with a combined OcclusionRoughnessMetallic (RGB) texture\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_AOMAP\n\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n\n#endif\n`;\n","export default /* glsl */`\nvec3 transformed = vec3( position );\n`;\n","export default /* glsl */`\nvec3 objectNormal = vec3( normal );\n\n#ifdef USE_TANGENT\n\n\tvec3 objectTangent = vec3( tangent.xyz );\n\n#endif\n`;\n","export default /* glsl */`\n\n// Analytical approximation of the DFG LUT, one half of the\n// split-sum approximation used in indirect specular lighting.\n// via 'environmentBRDF' from \"Physically Based Shading on Mobile\"\n// https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile\nvec2 integrateSpecularBRDF( const in float dotNV, const in float roughness ) {\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\n\tvec4 r = roughness * c0 + c1;\n\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\n\treturn vec2( -1.04, 1.04 ) * a004 + r.zw;\n\n}\n\nfloat punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\n\t// based upon Frostbite 3 Moving to Physically-based Rendering\n\t// page 32, equation 26: E[window1]\n\t// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\n\t// this is intended to be used on spot and point lights who are represented as luminous intensity\n\t// but who must be converted to luminous irradiance for surface lighting calculation\n\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\n\tif( cutoffDistance > 0.0 ) {\n\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\n\t}\n\n\treturn distanceFalloff;\n\n#else\n\n\tif( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\n\t}\n\n\treturn 1.0;\n\n#endif\n\n}\n\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\n\treturn RECIPROCAL_PI * diffuseColor;\n\n} // validated\n\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\n\t// Original approximation by Christophe Schlick '94\n\t// float fresnel = pow( 1.0 - dotLH, 5.0 );\n\n\t// Optimized variant (presented by Epic at SIGGRAPH '13)\n\t// https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n\n} // validated\n\nvec3 F_Schlick_RoughnessDependent( const in vec3 F0, const in float dotNV, const in float roughness ) {\n\n\t// See F_Schlick\n\tfloat fresnel = exp2( ( -5.55473 * dotNV - 6.98316 ) * dotNV );\n\tvec3 Fr = max( vec3( 1.0 - roughness ), F0 ) - F0;\n\n\treturn Fr * fresnel + F0;\n\n}\n\n\n// Microfacet Models for Refraction through Rough Surfaces - equation (34)\n// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html\n// alpha is \"roughness squared\" in Disney’s reparameterization\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\n\t// geometry term (normalized) = G(l)⋅G(v) / 4(n⋅l)(n⋅v)\n\t// also see #12151\n\n\tfloat a2 = pow2( alpha );\n\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\n\treturn 1.0 / ( gl * gv );\n\n} // validated\n\n// Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2\n// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\n\tfloat a2 = pow2( alpha );\n\n\t// dotNL and dotNV are explicitly swapped. This is not a mistake.\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\n\treturn 0.5 / max( gv + gl, EPSILON );\n\n}\n\n// Microfacet Models for Refraction through Rough Surfaces - equation (33)\n// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html\n// alpha is \"roughness squared\" in Disney’s reparameterization\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\n\tfloat a2 = pow2( alpha );\n\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0; // avoid alpha = 0 with dotNH = 1\n\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n\n}\n\n// GGX Distribution, Schlick Fresnel, GGX-Smith Visibility\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\n\tfloat alpha = pow2( roughness ); // UE4's roughness\n\n\tvec3 halfDir = normalize( incidentLight.direction + viewDir );\n\n\tfloat dotNL = saturate( dot( normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\n\tfloat D = D_GGX( alpha, dotNH );\n\n\treturn F * ( G * D );\n\n} // validated\n\n// Rect Area Light\n\n// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines\n// by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt\n// code: https://github.com/selfshadow/ltc_code/\n\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\n\tfloat dotNV = saturate( dot( N, V ) );\n\n\t// texture parameterized by sqrt( GGX alpha ) and sqrt( 1 - cos( theta ) )\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\n\treturn uv;\n\n}\n\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\n\t// Real-Time Area Lighting: a Journey from Research to Production (p.102)\n\t// An approximation of the form factor of a horizon-clipped rectangle.\n\n\tfloat l = length( f );\n\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n\n}\n\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\n\tfloat x = dot( v1, v2 );\n\n\tfloat y = abs( x );\n\n\t// rational polynomial approximation to theta / sin( theta ) / 2PI\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\n\treturn cross( v1, v2 ) * theta_sintheta;\n\n}\n\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\n\t// bail if point is on back side of plane of light\n\t// assumes ccw winding order of light vertices\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\n\t// construct orthonormal basis around N\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 ); // negated from paper; possibly due to a different handedness of world coordinate system\n\n\t// compute transform\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\n\t// transform rect\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\n\t// project rect onto sphere\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\n\t// calculate vector form factor\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\n\t// adjust for horizon clipping\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\n/*\n\t// alternate method of adjusting for horizon clipping (see referece)\n\t// refactoring required\n\tfloat len = length( vectorFormFactor );\n\tfloat z = vectorFormFactor.z / len;\n\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\n\t// tabulated horizon-clipped sphere, apparently...\n\tvec2 uv = vec2( z * 0.5 + 0.5, len );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\n\tfloat scale = texture2D( ltc_2, uv ).w;\n\n\tfloat result = len * scale;\n*/\n\n\treturn vec3( result );\n\n}\n\n// End Rect Area Light\n\n// ref: https://www.unrealengine.com/blog/physically-based-shading-on-mobile - environmentBRDF for GGX on mobile\nvec3 BRDF_Specular_GGX_Environment( const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float roughness ) {\n\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\n\treturn specularColor * brdf.x + brdf.y;\n\n} // validated\n\n// Fdez-Agüera's \"Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting\"\n// Approximates multiscattering in order to preserve energy.\n// http://www.jcgt.org/published/0008/01/03/\nvoid BRDF_Specular_Multiscattering_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\n\tvec3 F = F_Schlick_RoughnessDependent( specularColor, dotNV, roughness );\n\tvec2 brdf = integrateSpecularBRDF( dotNV, roughness );\n\tvec3 FssEss = F * brdf.x + brdf.y;\n\n\tfloat Ess = brdf.x + brdf.y;\n\tfloat Ems = 1.0 - Ess;\n\n\tvec3 Favg = specularColor + ( 1.0 - specularColor ) * 0.047619; // 1/21\n\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n\n}\n\nfloat G_BlinnPhong_Implicit( /* const in float dotNL, const in float dotNV */ ) {\n\n\t// geometry term is (n dot l)(n dot v) / 4(n dot l)(n dot v)\n\treturn 0.25;\n\n}\n\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n\n}\n\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\n\t//float dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\t//float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\n\tfloat G = G_BlinnPhong_Implicit( /* dotNL, dotNV */ );\n\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\n\treturn F * ( G * D );\n\n} // validated\n\n// source: http://simonstechblog.blogspot.ca/2011/12/microfacet-brdf.html\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\n\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n\n#if defined( USE_SHEEN )\n\n// https://github.com/google/filament/blob/master/shaders/src/brdf.fs#L94\nfloat D_Charlie(float roughness, float NoH) {\n\t// Estevez and Kulla 2017, \"Production Friendly Microfacet Sheen BRDF\"\n\tfloat invAlpha = 1.0 / roughness;\n\tfloat cos2h = NoH * NoH;\n\tfloat sin2h = max(1.0 - cos2h, 0.0078125); // 2^(-14/2), so sin2h^2 > 0 in fp16\n\treturn (2.0 + invAlpha) * pow(sin2h, invAlpha * 0.5) / (2.0 * PI);\n}\n\n// https://github.com/google/filament/blob/master/shaders/src/brdf.fs#L136\nfloat V_Neubelt(float NoV, float NoL) {\n\t// Neubelt and Pettineo 2013, \"Crafting a Next-gen Material Pipeline for The Order: 1886\"\n\treturn saturate(1.0 / (4.0 * (NoL + NoV - NoL * NoV)));\n}\n\nvec3 BRDF_Specular_Sheen( const in float roughness, const in vec3 L, const in GeometricContext geometry, vec3 specularColor ) {\n\n\tvec3 N = geometry.normal;\n\tvec3 V = geometry.viewDir;\n\n\tvec3 H = normalize( V + L );\n\tfloat dotNH = saturate( dot( N, H ) );\n\n\treturn specularColor * D_Charlie( roughness, dotNH ) * V_Neubelt( dot(N, V), dot(N, L) );\n\n}\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_BUMPMAP\n\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\n\t// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen\n\t// http://api.unrealengine.com/attachments/Engine/Rendering/LightingAndShadows/BumpMappingWithoutTangentSpace/mm_sfgrad_bump.pdf\n\n\t// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)\n\n\tvec2 dHdxy_fwd() {\n\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\n\t\treturn vec2( dBx, dBy );\n\n\t}\n\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\n\t\t// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988\n\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\t\t// normalized\n\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\n\t}\n\n#endif\n`;\n","export default /* glsl */`\n#if NUM_CLIPPING_PLANES > 0\n\n\tvec4 plane;\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\n\t\tbool clipped = true;\n\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\n\t\t}\n\t\t#pragma unroll_loop_end\n\n\t\tif ( clipped ) discard;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#if NUM_CLIPPING_PLANES > 0\n\n\tvarying vec3 vClipPosition;\n\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n\n#endif\n`;\n","export default /* glsl */`\n#if NUM_CLIPPING_PLANES > 0\n\n\tvarying vec3 vClipPosition;\n\n#endif\n`;\n","export default /* glsl */`\n#if NUM_CLIPPING_PLANES > 0\n\n\tvClipPosition = - mvPosition.xyz;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_COLOR\n\n\tdiffuseColor.rgb *= vColor;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_COLOR\n\n\tvarying vec3 vColor;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_COLOR\n\n\tvarying vec3 vColor;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_COLOR\n\n\tvColor.xyz = color.xyz;\n\n#endif\n`;\n","export default /* glsl */`\n#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n\n#ifndef saturate\n// may have defined saturate() already\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement(a) ( 1.0 - saturate( a ) )\n\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\n// expects values in the range of [0,1]x[0,1], returns values in the [0,1] range.\n// do not collapse into a single function per: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\n\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat max3( vec3 v ) { return max( max( v.x, v.y ), v.z ); }\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\n\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\n\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n#ifdef CLEARCOAT\n\tvec3 clearcoatNormal;\n#endif\n};\n\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n\n}\n\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\n\t// dir can be either a direction vector or a normal vector\n\t// upper-left 3x3 of matrix is assumed to be orthogonal\n\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n\n}\n\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\n\treturn - distance * planeNormal + point;\n\n}\n\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n\n}\n\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n\n}\n\nmat3 transposeMat3( const in mat3 m ) {\n\n\tmat3 tmp;\n\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\n\treturn tmp;\n\n}\n\n// https://en.wikipedia.org/wiki/Relative_luminance\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\n\treturn dot( weights, color.rgb );\n\n}\n\nbool isPerspectiveMatrix( mat4 m ) {\n\n return m[ 2 ][ 3 ] == - 1.0;\n\n}\n\nvec2 equirectUv( in vec3 dir ) {\n\n\t// dir is assumed to be unit length\n\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\n\treturn vec2( u, v );\n\n}\n`;\n","export default /* glsl */`\n#ifdef ENVMAP_TYPE_CUBE_UV\n\n#define cubeUV_maxMipLevel 8.0\n#define cubeUV_minMipLevel 4.0\n#define cubeUV_maxTileSize 256.0\n#define cubeUV_minTileSize 16.0\n\n// These shader functions convert between the UV coordinates of a single face of\n// a cubemap, the 0-5 integer index of a cube face, and the direction vector for\n// sampling a textureCube (not generally normalized).\n\nfloat getFace(vec3 direction) {\n vec3 absDirection = abs(direction);\n float face = -1.0;\n if (absDirection.x > absDirection.z) {\n if (absDirection.x > absDirection.y)\n face = direction.x > 0.0 ? 0.0 : 3.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n } else {\n if (absDirection.z > absDirection.y)\n face = direction.z > 0.0 ? 2.0 : 5.0;\n else\n face = direction.y > 0.0 ? 1.0 : 4.0;\n }\n return face;\n}\n\n// RH coordinate system; PMREM face-indexing convention\nvec2 getUV(vec3 direction, float face) {\n vec2 uv;\n if (face == 0.0) {\n uv = vec2(direction.z, direction.y) / abs(direction.x); // pos x\n } else if (face == 1.0) {\n uv = vec2(-direction.x, -direction.z) / abs(direction.y); // pos y\n } else if (face == 2.0) {\n uv = vec2(-direction.x, direction.y) / abs(direction.z); // pos z\n } else if (face == 3.0) {\n uv = vec2(-direction.z, direction.y) / abs(direction.x); // neg x\n } else if (face == 4.0) {\n uv = vec2(-direction.x, direction.z) / abs(direction.y); // neg y\n } else {\n uv = vec2(direction.x, direction.y) / abs(direction.z); // neg z\n }\n return 0.5 * (uv + 1.0);\n}\n\nvec3 bilinearCubeUV(sampler2D envMap, vec3 direction, float mipInt) {\n float face = getFace(direction);\n float filterInt = max(cubeUV_minMipLevel - mipInt, 0.0);\n mipInt = max(mipInt, cubeUV_minMipLevel);\n float faceSize = exp2(mipInt);\n\n float texelSize = 1.0 / (3.0 * cubeUV_maxTileSize);\n\n vec2 uv = getUV(direction, face) * (faceSize - 1.0);\n vec2 f = fract(uv);\n uv += 0.5 - f;\n if (face > 2.0) {\n uv.y += faceSize;\n face -= 3.0;\n }\n uv.x += face * faceSize;\n if(mipInt < cubeUV_maxMipLevel){\n uv.y += 2.0 * cubeUV_maxTileSize;\n }\n uv.y += filterInt * 2.0 * cubeUV_minTileSize;\n uv.x += 3.0 * max(0.0, cubeUV_maxTileSize - 2.0 * faceSize);\n uv *= texelSize;\n\n vec3 tl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.x += texelSize;\n vec3 tr = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.y += texelSize;\n vec3 br = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n uv.x -= texelSize;\n vec3 bl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;\n vec3 tm = mix(tl, tr, f.x);\n vec3 bm = mix(bl, br, f.x);\n return mix(tm, bm, f.y);\n}\n\n// These defines must match with PMREMGenerator\n\n#define r0 1.0\n#define v0 0.339\n#define m0 -2.0\n#define r1 0.8\n#define v1 0.276\n#define m1 -1.0\n#define r4 0.4\n#define v4 0.046\n#define m4 2.0\n#define r5 0.305\n#define v5 0.016\n#define m5 3.0\n#define r6 0.21\n#define v6 0.0038\n#define m6 4.0\n\nfloat roughnessToMip(float roughness) {\n float mip = 0.0;\n if (roughness >= r1) {\n mip = (r0 - roughness) * (m1 - m0) / (r0 - r1) + m0;\n } else if (roughness >= r4) {\n mip = (r1 - roughness) * (m4 - m1) / (r1 - r4) + m1;\n } else if (roughness >= r5) {\n mip = (r4 - roughness) * (m5 - m4) / (r4 - r5) + m4;\n } else if (roughness >= r6) {\n mip = (r5 - roughness) * (m6 - m5) / (r5 - r6) + m5;\n } else {\n mip = -2.0 * log2(1.16 * roughness);// 1.16 = 1.79^0.25\n }\n return mip;\n}\n\nvec4 textureCubeUV(sampler2D envMap, vec3 sampleDir, float roughness) {\n float mip = clamp(roughnessToMip(roughness), m0, cubeUV_maxMipLevel);\n float mipF = fract(mip);\n float mipInt = floor(mip);\n\n vec3 color0 = bilinearCubeUV(envMap, sampleDir, mipInt);\n if (mipF == 0.0) {\n return vec4(color0, 1.0);\n } else {\n vec3 color1 = bilinearCubeUV(envMap, sampleDir, mipInt + 1.0);\n return vec4(mix(color0, color1, mipF), 1.0);\n }\n}\n#endif\n`;\n","export default /* glsl */`\nvec3 transformedNormal = objectNormal;\n\n#ifdef USE_INSTANCING\n\n\t// this is in lieu of a per-instance normal-matrix\n\t// shear transforms in the instance matrix are not supported\n\n\tmat3 m = mat3( instanceMatrix );\n\n\ttransformedNormal /= vec3( dot( m[ 0 ], m[ 0 ] ), dot( m[ 1 ], m[ 1 ] ), dot( m[ 2 ], m[ 2 ] ) );\n\n\ttransformedNormal = m * transformedNormal;\n\n#endif\n\ntransformedNormal = normalMatrix * transformedNormal;\n\n#ifdef FLIP_SIDED\n\n\ttransformedNormal = - transformedNormal;\n\n#endif\n\n#ifdef USE_TANGENT\n\n\tvec3 transformedTangent = ( modelViewMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\n\t#ifdef FLIP_SIDED\n\n\t\ttransformedTangent = - transformedTangent;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_DISPLACEMENTMAP\n\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_DISPLACEMENTMAP\n\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vUv ).x * displacementScale + displacementBias );\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_EMISSIVEMAP\n\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_EMISSIVEMAP\n\n\tuniform sampler2D emissiveMap;\n\n#endif\n`;\n","export default /* glsl */`\ngl_FragColor = linearToOutputTexel( gl_FragColor );\n`;\n","export default /* glsl */`\n// For a discussion of what this is, please read this: http://lousodrome.net/blog/light/2013/05/26/gamma-correct-and-hdr-rendering-in-a-32-bits-buffer/\n\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\n\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( gammaFactor ) ), value.a );\n}\n\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.rgb, vec3( 1.0 / gammaFactor ) ), value.a );\n}\n\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.a );\n}\n\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\n\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}\n\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n// return vec4( value.brg, ( 3.0 + 128.0 ) / 256.0 );\n}\n\n// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * value.a * maxRange, 1.0 );\n}\n\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\n\n// reference: http://iwasbeingirony.blogspot.ca/2010/06/difference-between-rgbm-and-rgbd.html\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\n\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.r, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\t// NOTE: The implementation with min causes the shader to not compile on\n\t// a common Alcatel A502DL in Chrome 78/Android 8.1. Some research suggests \n\t// that the chipset is Mediatek MT6739 w/ IMG PowerVR GE8100 GPU.\n\t// D = min( floor( D ) / 255.0, 1.0 );\n\tD = clamp( floor( D ) / 255.0, 0.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\n\n// LogLuv reference: http://graphicrants.blogspot.ca/2009/04/rgbm-color-encoding.html\n\n// M matrix, for encoding\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = cLogLuvM * value.rgb;\n\tXp_Y_XYZp = max( Xp_Y_XYZp, vec3( 1e-6, 1e-6, 1e-6 ) );\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract( Le );\n\tvResult.z = ( Le - ( floor( vResult.w * 255.0 ) ) / 255.0 ) / 255.0;\n\treturn vResult;\n}\n\n// Inverse M matrix, for decoding\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2( ( Le - 127.0 ) / 2.0 );\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = cLogLuvInverseM * Xp_Y_XYZp.rgb;\n\treturn vec4( max( vRGB, 0.0 ), 1.0 );\n}\n`;\n","export default /* glsl */`\n#ifdef USE_ENVMAP\n\n\t#ifdef ENV_WORLDPOS\n\n\t\tvec3 cameraToFrag;\n\t\t\n\t\tif ( isOrthographic ) {\n\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\n\t\t} else {\n\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\n\t\t}\n\n\t\t// Transforming Normal Vectors with the Inverse Transformation\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\n\t\t#else\n\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\n\t\t#endif\n\n\t#else\n\n\t\tvec3 reflectVec = vReflect;\n\n\t#endif\n\n\t#ifdef ENVMAP_TYPE_CUBE\n\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\n\t\tvec4 envColor = textureCubeUV( envMap, reflectVec, 0.0 );\n\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\n\t\treflectVec = normalize( reflectVec );\n\n\t\tvec2 sampleUV = equirectUv( reflectVec );\n\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\n\t\treflectVec = normalize( reflectVec );\n\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\n\t#else\n\n\t\tvec4 envColor = vec4( 0.0 );\n\n\t#endif\n\n\t#ifndef ENVMAP_TYPE_CUBE_UV\n\n\t\tenvColor = envMapTexelToLinear( envColor );\n\n\t#endif\n\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ENVMAP\n\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ENVMAP\n\n\tuniform float reflectivity;\n\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\n\t\t#define ENV_WORLDPOS\n\n\t#endif\n\n\t#ifdef ENV_WORLDPOS\n\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ENVMAP\n\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) ||defined( PHONG )\n\n\t\t#define ENV_WORLDPOS\n\n\t#endif\n\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\n\t#else\n\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_ENVMAP )\n\n\t#ifdef ENVMAP_MODE_REFRACTION\n\t\tuniform float refractionRatio;\n\t#endif\n\n\tvec3 getLightProbeIndirectIrradiance( /*const in SpecularLightProbe specularLightProbe,*/ const in GeometricContext geometry, const in int maxMIPLevel ) {\n\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\n\t\t\t// TODO: replace with properly filtered cubemaps and access the irradiance LOD level, be it the last LOD level\n\t\t\t// of a specular cubemap, or just the default level of a specially created irradiance cubemap.\n\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\n\t\t\t#else\n\n\t\t\t\t// force the bias high to get the last LOD level as it is the most blurred.\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\n\t\t\t#endif\n\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\n\t\t#else\n\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\n\t\t#endif\n\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\n\t}\n\n\t// Trowbridge-Reitz distribution to Mip level, following the logic of http://casual-effects.blogspot.ca/2011/08/plausible-environment-lighting-in-two.html\n\tfloat getSpecularMIPLevel( const in float roughness, const in int maxMIPLevel ) {\n\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\n\t\tfloat sigma = PI * roughness * roughness / ( 1.0 + roughness );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + log2( sigma );\n\n\t\t// clamp to allowable LOD ranges.\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\n\t}\n\n\tvec3 getLightProbeIndirectRadiance( /*const in SpecularLightProbe specularLightProbe,*/ const in vec3 viewDir, const in vec3 normal, const in float roughness, const in int maxMIPLevel ) {\n\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\n\t\t vec3 reflectVec = reflect( -viewDir, normal );\n\n\t\t // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane.\n\t\t reflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\n\t\t#else\n\n\t\t vec3 reflectVec = refract( -viewDir, normal, refractionRatio );\n\n\t\t#endif\n\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( roughness, maxMIPLevel );\n\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\n\t\t\t#else\n\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\n\t\t\t#endif\n\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\n\t\t\tvec2 sampleUV = equirectUv( reflectVec );\n\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\n\t\t\t#else\n\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\n\t\t\t#endif\n\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\n\t\t\t#else\n\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\n\t\t\t#endif\n\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\n\t\t#endif\n\n\t\treturn envMapColor.rgb * envMapIntensity;\n\n\t}\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ENVMAP\n\n\t#ifdef ENV_WORLDPOS\n\n\t\tvWorldPosition = worldPosition.xyz;\n\n\t#else\n\n\t\tvec3 cameraToVertex;\n\n\t\tif ( isOrthographic ) { \n\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\n\t\t} else {\n\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\n\t\t}\n\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\n\t\t#else\n\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\n\t\t#endif\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_FOG\n\n\tfogDepth = -mvPosition.z;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_FOG\n\n\tvarying float fogDepth;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_FOG\n\n\t#ifdef FOG_EXP2\n\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * fogDepth * fogDepth );\n\n\t#else\n\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\n\t#endif\n\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_FOG\n\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\n\t#ifdef FOG_EXP2\n\n\t\tuniform float fogDensity;\n\n\t#else\n\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n\n#ifdef USE_GRADIENTMAP\n\n\tuniform sampler2D gradientMap;\n\n#endif\n\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\n\t// dotNL will be from -1.0 to 1.0\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\n\t#ifdef USE_GRADIENTMAP\n\n\t\treturn texture2D( gradientMap, coord ).rgb;\n\n\t#else\n\n\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\n\t#endif\n\n}\n\n`;\n","export default /* glsl */`\n#ifdef USE_LIGHTMAP\n\n\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\treflectedLight.indirectDiffuse += PI * lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity; // factor of PI should not be present; included here to prevent breakage\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_LIGHTMAP\n\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n\n#endif\n`;\n","export default /* glsl */`\nvec3 diffuse = vec3( 1.0 );\n\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( -mvPosition.xyz );\n\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\n\nvLightFront = vec3( 0.0 );\nvIndirectFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n\tvIndirectBack = vec3( 0.0 );\n#endif\n\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n\nvIndirectFront += getAmbientLightIrradiance( ambientLightColor );\n\nvIndirectFront += getLightProbeIrradiance( lightProbe, geometry );\n\n#ifdef DOUBLE_SIDED\n\n\tvIndirectBack += getAmbientLightIrradiance( ambientLightColor );\n\n\tvIndirectBack += getLightProbeIrradiance( lightProbe, backGeometry );\n\n#endif\n\n#if NUM_POINT_LIGHTS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\n\t\t#endif\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if NUM_SPOT_LIGHTS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\n\t\t#endif\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n/*\n#if NUM_RECT_AREA_LIGHTS > 0\n\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\n\t\t// TODO (abelnation): implement\n\n\t}\n\n#endif\n*/\n\n#if NUM_DIR_LIGHTS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\n\t\t#endif\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if NUM_HEMI_LIGHTS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\n\t\tvIndirectFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\tvIndirectBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\n\t\t#endif\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n`;\n","export default /* glsl */`\nuniform bool receiveShadow;\nuniform vec3 ambientLightColor;\nuniform vec3 lightProbe[ 9 ];\n\n// get the irradiance (radiance convolved with cosine lobe) at the point 'normal' on the unit sphere\n// source: https://graphics.stanford.edu/papers/envmap/envmap.pdf\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\n\t// normal is assumed to have unit length\n\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\n\t// band 0\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\n\t// band 1\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\n\t// band 2\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\n\treturn result;\n\n}\n\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in GeometricContext geometry ) {\n\n\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\n\treturn irradiance;\n\n}\n\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\n\tvec3 irradiance = ambientLightColor;\n\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\tirradiance *= PI;\n\n\t#endif\n\n\treturn irradiance;\n\n}\n\n#if NUM_DIR_LIGHTS > 0\n\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\n\t#endif\n\n\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\n\t}\n\n#endif\n\n\n#if NUM_POINT_LIGHTS > 0\n\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t// directLight is an out parameter as having it as a return value caused compiler errors on some devices\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\n\t\tfloat lightDistance = length( lVector );\n\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\n\t}\n\n#endif\n\n\n#if NUM_SPOT_LIGHTS > 0\n\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t// directLight is an out parameter as having it as a return value caused compiler errors on some devices\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\n\t\tif ( angleCos > spotLight.coneCos ) {\n\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\n\t\t} else {\n\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\n\t\t}\n\t}\n\n#endif\n\n\n#if NUM_RECT_AREA_LIGHTS > 0\n\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\n\t// Pre-computed values of LinearTransformedCosine approximation of BRDF\n\t// BRDF approximation Texture is 64x64\n\tuniform sampler2D ltc_1; // RGBA Float\n\tuniform sampler2D ltc_2; // RGBA Float\n\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n\n#endif\n\n\n#if NUM_HEMI_LIGHTS > 0\n\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\t\tirradiance *= PI;\n\n\t\t#endif\n\n\t\treturn irradiance;\n\n\t}\n\n#endif\n`;\n","export default /* glsl */`\nToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n`;\n","export default /* glsl */`\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n\nstruct ToonMaterial {\n\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n\n};\n\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\n\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\tirradiance *= PI; // punctual light\n\n\t#endif\n\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n\n}\n\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in GeometricContext geometry, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\n}\n\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon\n\n#define Material_LightProbeLOD( material )\t(0)\n`;\n","export default /* glsl */`\nBlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n`;\n","export default /* glsl */`\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n\nstruct BlinnPhongMaterial {\n\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n\n};\n\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\tirradiance *= PI; // punctual light\n\n\t#endif\n\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n\n}\n\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\n}\n\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n\n#define Material_LightProbeLOD( material )\t(0)\n`;\n","export default /* glsl */`\nPhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\n\nvec3 dxy = max( abs( dFdx( geometryNormal ) ), abs( dFdy( geometryNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\n\nmaterial.specularRoughness = max( roughnessFactor, 0.0525 );// 0.0525 corresponds to the base mip of a 256 cubemap.\nmaterial.specularRoughness += geometryRoughness;\nmaterial.specularRoughness = min( material.specularRoughness, 1.0 );\n\n#ifdef REFLECTIVITY\n\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\n#else\n\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n\n#endif\n\n#ifdef CLEARCOAT\n\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\n\t#ifdef USE_CLEARCOATMAP\n\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vUv ).x;\n\n\t#endif\n\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vUv ).y;\n\n\t#endif\n\n\tmaterial.clearcoat = saturate( material.clearcoat ); // Burley clearcoat model\n\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n\n#endif\n\n#ifdef USE_SHEEN\n\n\tmaterial.sheenColor = sheen;\n\n#endif\n`;\n","export default /* glsl */`\nstruct PhysicalMaterial {\n\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\n#ifdef CLEARCOAT\n\tfloat clearcoat;\n\tfloat clearcoatRoughness;\n#endif\n#ifdef USE_SHEEN\n\tvec3 sheenColor;\n#endif\n\n};\n\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\n\n// Clear coat directional hemishperical reflectance (this approximation should be improved)\nfloat clearcoatDHRApprox( const in float roughness, const in float dotNL ) {\n\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n\n}\n\n#if NUM_RECT_AREA_LIGHTS > 0\n\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight; // counterclockwise; light shines in local neg z direction\n\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\n\t\t// LTC Fresnel Approximation by Stephen Hill\n\t\t// http://blog.selfshadow.com/publications/s2016-advances/s2016_ltc_fresnel.pdf\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\n\t}\n\n#endif\n\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\n\tvec3 irradiance = dotNL * directLight.color;\n\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\tirradiance *= PI; // punctual light\n\n\t#endif\n\n\t#ifdef CLEARCOAT\n\n\t\tfloat ccDotNL = saturate( dot( geometry.clearcoatNormal, directLight.direction ) );\n\n\t\tvec3 ccIrradiance = ccDotNL * directLight.color;\n\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\t\tccIrradiance *= PI; // punctual light\n\n\t\t#endif\n\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\n\t\treflectedLight.directSpecular += ccIrradiance * material.clearcoat * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\n\t#else\n\n\t\tfloat clearcoatDHR = 0.0;\n\n\t#endif\n\n\t#ifdef USE_SHEEN\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_Sheen(\n\t\t\tmaterial.specularRoughness,\n\t\t\tdirectLight.direction,\n\t\t\tgeometry,\n\t\t\tmaterial.sheenColor\n\t\t);\n\t#else\n\t\treflectedLight.directSpecular += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry.viewDir, geometry.normal, material.specularColor, material.specularRoughness);\n\t#endif\n\n\treflectedLight.directDiffuse += ( 1.0 - clearcoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\n}\n\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\n\t#ifdef CLEARCOAT\n\n\t\tfloat ccDotNV = saturate( dot( geometry.clearcoatNormal, geometry.viewDir ) );\n\n\t\treflectedLight.indirectSpecular += clearcoatRadiance * material.clearcoat * BRDF_Specular_GGX_Environment( geometry.viewDir, geometry.clearcoatNormal, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearcoatRoughness );\n\n\t\tfloat ccDotNL = ccDotNV;\n\t\tfloat clearcoatDHR = material.clearcoat * clearcoatDHRApprox( material.clearcoatRoughness, ccDotNL );\n\n\t#else\n\n\t\tfloat clearcoatDHR = 0.0;\n\n\t#endif\n\n\tfloat clearcoatInv = 1.0 - clearcoatDHR;\n\n\t// Both indirect specular and indirect diffuse light accumulate here\n\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\n\tBRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );\n\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );\n\n\treflectedLight.indirectSpecular += clearcoatInv * radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n\n}\n\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n\n// ref: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n\n}\n`;\n","export default /* glsl */`\n/**\n * This is a template that can be used to light a material, it uses pluggable\n * RenderEquations (RE)for specific lighting scenarios.\n *\n * Instructions for use:\n * - Ensure that both RE_Direct, RE_IndirectDiffuse and RE_IndirectSpecular are defined\n * - If you have defined an RE_IndirectSpecular, you need to also provide a Material_LightProbeLOD. <---- ???\n * - Create a material parameter that is to be passed as the third parameter to your lighting functions.\n *\n * TODO:\n * - Add area light support.\n * - Add sphere light support.\n * - Add diffuse light probe (irradiance cubemap) support.\n */\n\nGeometricContext geometry;\n\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\n\n#ifdef CLEARCOAT\n\n\tgeometry.clearcoatNormal = clearcoatNormal;\n\n#endif\n\nIncidentLight directLight;\n\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\n\t\tpointLight = pointLights[ i ];\n\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\n\tSpotLight spotLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\n\t\tspotLight = spotLights[ i ];\n\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\n\t\tdirectionalLight = directionalLights[ i ];\n\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= all( bvec2( directLight.visible, receiveShadow ) ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\n\tRectAreaLight rectAreaLight;\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\n\t}\n\t#pragma unroll_loop_end\n\n#endif\n\n#if defined( RE_IndirectDiffuse )\n\n\tvec3 iblIrradiance = vec3( 0.0 );\n\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\n\tirradiance += getLightProbeIrradiance( lightProbe, geometry );\n\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\n\t\t}\n\t\t#pragma unroll_loop_end\n\n\t#endif\n\n#endif\n\n#if defined( RE_IndirectSpecular )\n\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( RE_IndirectDiffuse )\n\n\t#ifdef USE_LIGHTMAP\n\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\tvec3 lightMapIrradiance = lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\n\t\t\tlightMapIrradiance *= PI; // factor of PI should not be present; included here to prevent breakage\n\n\t\t#endif\n\n\t\tirradiance += lightMapIrradiance;\n\n\t#endif\n\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\n\t\tiblIrradiance += getLightProbeIndirectIrradiance( /*lightProbe,*/ geometry, maxMipLevel );\n\n\t#endif\n\n#endif\n\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\n\tradiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry.viewDir, geometry.normal, material.specularRoughness, maxMipLevel );\n\n\t#ifdef CLEARCOAT\n\n\t\tclearcoatRadiance += getLightProbeIndirectRadiance( /*specularLightProbe,*/ geometry.viewDir, geometry.clearcoatNormal, material.clearcoatRoughness, maxMipLevel );\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( RE_IndirectDiffuse )\n\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n\n#endif\n\n#if defined( RE_IndirectSpecular )\n\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometry, material, reflectedLight );\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\n\t// Doing a strict comparison with == 1.0 can cause noise artifacts\n\t// on some platforms. See issue #17623.\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_LOGDEPTHBUF\n\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\n\t#else\n\n\t\tuniform float logDepthBufFC;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_LOGDEPTHBUF\n\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\n\t#else\n\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\n\t\t\tgl_Position.z *= gl_Position.w;\n\n\t\t}\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_MAP\n\n\tvec4 texelColor = texture2D( map, vUv );\n\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_MAP\n\n\tuniform sampler2D map;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\n#endif\n\n#ifdef USE_MAP\n\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n\n#endif\n\n#ifdef USE_ALPHAMAP\n\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\n\tuniform mat3 uvTransform;\n\n#endif\n\n#ifdef USE_MAP\n\n\tuniform sampler2D map;\n\n#endif\n\n#ifdef USE_ALPHAMAP\n\n\tuniform sampler2D alphaMap;\n\n#endif\n`;\n","export default /* glsl */`\nfloat metalnessFactor = metalness;\n\n#ifdef USE_METALNESSMAP\n\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\n\t// reads channel B, compatible with a combined OcclusionRoughnessMetallic (RGB) texture\n\tmetalnessFactor *= texelMetalness.b;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_METALNESSMAP\n\n\tuniform sampler2D metalnessMap;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_MORPHNORMALS\n\n\t// morphTargetBaseInfluence is set based on BufferGeometry.morphTargetsRelative value:\n\t// When morphTargetsRelative is false, this is set to 1 - sum(influences); this results in normal = sum((target - base) * influence)\n\t// When morphTargetsRelative is true, this is set to 1; as a result, all morph targets are simply added to the base after weighting\n\tobjectNormal *= morphTargetBaseInfluence;\n\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_MORPHTARGETS\n\n\tuniform float morphTargetBaseInfluence;\n\n\t#ifndef USE_MORPHNORMALS\n\n\tuniform float morphTargetInfluences[ 8 ];\n\n\t#else\n\n\tuniform float morphTargetInfluences[ 4 ];\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_MORPHTARGETS\n\n\t// morphTargetBaseInfluence is set based on BufferGeometry.morphTargetsRelative value:\n\t// When morphTargetsRelative is false, this is set to 1 - sum(influences); this results in position = sum((target - base) * influence)\n\t// When morphTargetsRelative is true, this is set to 1; as a result, all morph targets are simply added to the base after weighting\n\ttransformed *= morphTargetBaseInfluence;\n\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\n\t#ifndef USE_MORPHNORMALS\n\n\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef FLAT_SHADED\n\n\t// Workaround for Adreno/Nexus5 not able able to do dFdx( vViewPosition ) ...\n\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n\n#else\n\n\tvec3 normal = normalize( vNormal );\n\n\t#ifdef DOUBLE_SIDED\n\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n\t#endif\n\n\t#ifdef USE_TANGENT\n\n\t\tvec3 tangent = normalize( vTangent );\n\t\tvec3 bitangent = normalize( vBitangent );\n\n\t\t#ifdef DOUBLE_SIDED\n\n\t\t\ttangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\t\tbitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n\t\t#endif\n\n\t\t#if defined( TANGENTSPACE_NORMALMAP ) || defined( USE_CLEARCOAT_NORMALMAP )\n\n\t\t\tmat3 vTBN = mat3( tangent, bitangent, normal );\n\n\t\t#endif\n\n\t#endif\n\n#endif\n\n// non perturbed normal for clearcoat among others\n\nvec3 geometryNormal = normal;\n\n`;\n","export default /* glsl */`\n\n#ifdef OBJECTSPACE_NORMALMAP\n\n\tnormal = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0; // overrides both flatShading and attribute normals\n\n\t#ifdef FLIP_SIDED\n\n\t\tnormal = - normal;\n\n\t#endif\n\n\t#ifdef DOUBLE_SIDED\n\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n\t#endif\n\n\tnormal = normalize( normalMatrix * normal );\n\n#elif defined( TANGENTSPACE_NORMALMAP )\n\n\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\n\t#ifdef USE_TANGENT\n\n\t\tnormal = normalize( vTBN * mapN );\n\n\t#else\n\n\t\tnormal = perturbNormal2Arb( -vViewPosition, normal, mapN );\n\n\t#endif\n\n#elif defined( USE_BUMPMAP )\n\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_NORMALMAP\n\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\n#endif\n\n#ifdef OBJECTSPACE_NORMALMAP\n\n\tuniform mat3 normalMatrix;\n\n#endif\n\n#if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )\n\n\t// Per-Pixel Tangent Space Normal Mapping\n\t// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html\n\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {\n\n\t\t// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988\n\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s ); // we do not care about the magnitude\n\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\n\t\tmat3 tsn = mat3( S, T, N );\n\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\n\t\treturn normalize( tsn * mapN );\n\n\t}\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef CLEARCOAT\n\n\tvec3 clearcoatNormal = geometryNormal;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_CLEARCOAT_NORMALMAP\n\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\n\t#ifdef USE_TANGENT\n\n\t\tclearcoatNormal = normalize( vTBN * clearcoatMapN );\n\n\t#else\n\n\t\tclearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN );\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n\n#ifdef USE_CLEARCOATMAP\n\n\tuniform sampler2D clearcoatMap;\n\n#endif\n\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\n\tuniform sampler2D clearcoatRoughnessMap;\n\n#endif\n\n#ifdef USE_CLEARCOAT_NORMALMAP\n\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n\n#endif\n`;\n","export default /* glsl */`\nvec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\n\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\n\nconst float PackUpscale = 256. / 255.; // fraction -> 0..1 (including 1)\nconst float UnpackDownscale = 255. / 256.; // 0..1 -> fraction (excluding 1)\n\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\n\nconst float ShiftRight8 = 1. / 256.;\n\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8; // tidy overflow\n\treturn r * PackUpscale;\n}\n\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\n\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ));\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w);\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\n\n// NOTE: viewZ/eyeZ is < 0 when in front of the camera per OpenGL conventions\n\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\n\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n`;\n","export default /* glsl */`\n#ifdef PREMULTIPLIED_ALPHA\n\n\t// Get get normal blending with premultipled, use with CustomBlending, OneFactor, OneMinusSrcAlphaFactor, AddEquation.\n\tgl_FragColor.rgb *= gl_FragColor.a;\n\n#endif\n`;\n","export default /* glsl */`\nvec4 mvPosition = vec4( transformed, 1.0 );\n\n#ifdef USE_INSTANCING\n\n\tmvPosition = instanceMatrix * mvPosition;\n\n#endif\n\nmvPosition = modelViewMatrix * mvPosition;\n\ngl_Position = projectionMatrix * mvPosition;\n`;\n","export default /* glsl */`\n#ifdef DITHERING\n\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef DITHERING\n\n\t// based on https://www.shadertoy.com/view/MslGR8\n\tvec3 dithering( vec3 color ) {\n\t\t//Calculate grid position\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\n\t\t//Shift the individual colors differently, thus making it even harder to see the dithering pattern\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\n\t\t//modify shift acording to grid position.\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\n\t\t//shift the color by dither_shift\n\t\treturn color + dither_shift_RGB;\n\t}\n\n#endif\n`;\n","export default /* glsl */`\nfloat roughnessFactor = roughness;\n\n#ifdef USE_ROUGHNESSMAP\n\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\n\t// reads channel G, compatible with a combined OcclusionRoughnessMetallic (RGB) texture\n\troughnessFactor *= texelRoughness.g;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_ROUGHNESSMAP\n\n\tuniform sampler2D roughnessMap;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SHADOWMAP\n\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t/*\n\t#if NUM_RECT_AREA_LIGHTS > 0\n\n\t\t// TODO (abelnation): create uniforms for area light shadows\n\n\t#endif\n\t*/\n\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\n\t}\n\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\n\t}\n\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\n\t\tfloat occlusion = 1.0;\n\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\n\t\tfloat hard_shadow = step( compare , distribution.x ); // Hard Shadow\n\n\t\tif (hard_shadow != 1.0 ) {\n\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance ); // Chebeyshevs inequality\n\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 ); // 0.3 reduces light bleed\n\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\n\t\t}\n\t\treturn occlusion;\n\n\t}\n\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\n\t\tfloat shadow = 1.0;\n\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\n\t\t// if ( something && something ) breaks ATI OpenGL shader compiler\n\t\t// if ( all( something, something ) ) using this instead\n\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\n\t\tbool frustumTest = all( frustumTestVec );\n\n\t\tif ( frustumTest ) {\n\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ), \n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ), \n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\n\t\t#else // no percentage-closer filtering:\n\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\n\t\t#endif\n\n\t\t}\n\n\t\treturn shadow;\n\n\t}\n\n\t// cubeToUV() maps a 3D direction vector suitable for cube texture mapping to a 2D\n\t// vector suitable for 2D texture mapping. This code uses the following layout for the\n\t// 2D texture:\n\t//\n\t// xzXZ\n\t// y Y\n\t//\n\t// Y - Positive y direction\n\t// y - Negative y direction\n\t// X - Positive x direction\n\t// x - Negative x direction\n\t// Z - Positive z direction\n\t// z - Negative z direction\n\t//\n\t// Source and test bed:\n\t// https://gist.github.com/tschw/da10c43c467ce8afd0c4\n\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\n\t\t// Number of texels to avoid at the edge of each square\n\n\t\tvec3 absV = abs( v );\n\n\t\t// Intersect unit cube\n\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\n\t\t// Apply scale to avoid seams\n\n\t\t// two texels less per square (one texel will do for NEAREST)\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\n\t\t// Unwrap\n\n\t\t// space: -1 ... 1 range for each square\n\t\t//\n\t\t// #X##\t\tdim := ( 4 , 2 )\n\t\t// # #\t\tcenter := ( 1 , 1 )\n\n\t\tvec2 planar = v.xy;\n\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\n\t\tif ( absV.z >= almostOne ) {\n\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\n\t\t} else if ( absV.x >= almostOne ) {\n\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\n\t\t} else if ( absV.y >= almostOne ) {\n\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\n\t\t}\n\n\t\t// Transform to UV space\n\n\t\t// scale := 0.5 / dim\n\t\t// translate := ( center + 0.5 ) / dim\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\n\t}\n\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\n\t\t// for point lights, the uniform @vShadowCoord is re-purposed to hold\n\t\t// the vector from the light to the world-space position of the fragment.\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\n\t\t// dp = normalized distance from light to fragment position\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear ); // need to clamp?\n\t\tdp += shadowBias;\n\n\t\t// bd3D = base direction 3D\n\t\tvec3 bd3D = normalize( lightToPosition );\n\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\n\t\t#else // no percentage-closer filtering\n\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\n\t\t#endif\n\n\t}\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SHADOWMAP\n\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\n\t#endif\n\n\t/*\n\t#if NUM_RECT_AREA_LIGHTS > 0\n\n\t\t// TODO (abelnation): uniforms for area light shadows\n\n\t#endif\n\t*/\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SHADOWMAP\n\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t/*\n\t#if NUM_RECT_AREA_LIGHTS > 0\n\n\t\t// TODO (abelnation): update vAreaShadowCoord with area light info\n\n\t#endif\n\t*/\n\n#endif\n`;\n","export default /* glsl */`\nfloat getShadowMask() {\n\n\tfloat shadow = 1.0;\n\n\t#ifdef USE_SHADOWMAP\n\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\n\tDirectionalLightShadow directionalLight;\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\n\tSpotLightShadow spotLight;\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\n\tPointLightShadow pointLight;\n\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\n\t}\n\t#pragma unroll_loop_end\n\n\t#endif\n\n\t/*\n\t#if NUM_RECT_AREA_LIGHTS > 0\n\n\t\t// TODO (abelnation): update shadow for Area light\n\n\t#endif\n\t*/\n\n\t#endif\n\n\treturn shadow;\n\n}\n`;\n","export default /* glsl */`\n#ifdef USE_SKINNING\n\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SKINNING\n\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\n\t#ifdef BONE_TEXTURE\n\n\t\tuniform highp sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\n\t\tmat4 getBoneMatrix( const in float i ) {\n\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\n\t\t\ty = dy * ( y + 0.5 );\n\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\n\t\t\treturn bone;\n\n\t\t}\n\n\t#else\n\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\n\t\tmat4 getBoneMatrix( const in float i ) {\n\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\n\t\t}\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SKINNING\n\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SKINNING\n\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\n\t#ifdef USE_TANGENT\n\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\n\t#endif\n\n#endif\n`;\n","export default /* glsl */`\nfloat specularStrength;\n\n#ifdef USE_SPECULARMAP\n\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n\n#else\n\n\tspecularStrength = 1.0;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_SPECULARMAP\n\n\tuniform sampler2D specularMap;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( TONE_MAPPING )\n\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n\n#endif\n`;\n","export default /* glsl */`\n#ifndef saturate\n// may have defined saturate() already\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\n\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\n\n// exposure only\nvec3 LinearToneMapping( vec3 color ) {\n\n\treturn toneMappingExposure * color;\n\n}\n\n// source: https://www.cs.utah.edu/~reinhard/cdrom/\nvec3 ReinhardToneMapping( vec3 color ) {\n\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n\n}\n\n// source: http://filmicgames.com/archives/75\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\n\t// John Hable's filmic operator from Uncharted 2 video game\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n\n}\n\n// source: http://filmicgames.com/archives/75\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\n\t// optimized filmic operator by Jim Hejl and Richard Burgess-Dawson\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n\n}\n\n// source: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\n\tcolor *= toneMappingExposure;\n\treturn saturate( ( color * ( 2.51 * color + 0.03 ) ) / ( color * ( 2.43 * color + 0.59 ) + 0.14 ) );\n\n}\n`;\n","export default /* glsl */`\n#if ( defined( USE_UV ) && ! defined( UVS_VERTEX_ONLY ) )\n\n\tvarying vec2 vUv;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_UV\n\n\t#ifdef UVS_VERTEX_ONLY\n\n\t\tvec2 vUv;\n\n\t#else\n\n\t\tvarying vec2 vUv;\n\n\t#endif\n\n\tuniform mat3 uvTransform;\n\n#endif\n`;\n","export default /* glsl */`\n#ifdef USE_UV\n\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\n\tvarying vec2 vUv2;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n\n\tuniform mat3 uv2Transform;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\n\tvUv2 = ( uv2Transform * vec3( uv2, 1 ) ).xy;\n\n#endif\n`;\n","export default /* glsl */`\n#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\n\t#ifdef USE_INSTANCING\n\n\t\tworldPosition = instanceMatrix * worldPosition;\n\n\t#endif\n\n\tworldPosition = modelMatrix * worldPosition;\n\n#endif\n`;\n","export default /* glsl */`\nuniform sampler2D t2D;\n\nvarying vec2 vUv;\n\nvoid main() {\n\n\tvec4 texColor = texture2D( t2D, vUv );\n\n\tgl_FragColor = mapTexelToLinear( texColor );\n\n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nvarying vec2 vUv;\nuniform mat3 uvTransform;\n\nvoid main() {\n\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n\n}\n`;\n","export default /* glsl */`\n\n#include \nuniform float opacity;\n\nvarying vec3 vWorldDirection;\n\n#include \n\nvoid main() {\n\n\tvec3 vReflect = vWorldDirection;\n\t#include \n\n\tgl_FragColor = envColor;\n\tgl_FragColor.a *= opacity;\n\n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nvarying vec3 vWorldDirection;\n\n#include \n\nvoid main() {\n\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t#include \n\t#include \n\n\tgl_Position.z = gl_Position.w; // set z to camera.far\n\n}\n`;\n","export default /* glsl */`\n#if DEPTH_PACKING == 3200\n\n\tuniform float opacity;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tdiffuseColor.a = opacity;\n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\n\t#include \n\n\t// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\n\t#if DEPTH_PACKING == 3200\n\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\n\t#elif DEPTH_PACKING == 3201\n\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\n\t#endif\n\n}\n`;\n","export default /* glsl */`\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\n// This is used for computing an equivalent of gl_FragCoord.z that is as high precision as possible.\n// Some platforms compute gl_FragCoord at a lower precision which makes the manually computed value better for\n// depth-based postprocessing effects. Reproduced on iPad with A10 processor / iPadOS 13.3.1.\nvarying vec2 vHighPrecisionZW;\n\nvoid main() {\n\n\t#include \n\n\t#include \n\n\t#ifdef USE_DISPLACEMENTMAP\n\n\t\t#include \n\t\t#include \n\t\t#include \n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvHighPrecisionZW = gl_Position.zw;\n\n}\n`;\n","export default /* glsl */`\n#define DISTANCE\n\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main () {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( 1.0 );\n\n\t#include \n\t#include \n\t#include \n\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist ); // clamp to [ 0, 1 ]\n\n\tgl_FragColor = packDepthToRGBA( dist );\n\n}\n`;\n","export default /* glsl */`\n#define DISTANCE\n\nvarying vec3 vWorldPosition;\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\t#include \n\n\t#ifdef USE_DISPLACEMENTMAP\n\n\t\t#include \n\t\t#include \n\t\t#include \n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvWorldPosition = worldPosition.xyz;\n\n}\n`;\n","export default /* glsl */`\nuniform sampler2D tEquirect;\n\nvarying vec3 vWorldDirection;\n\n#include \n\nvoid main() {\n\n\tvec3 direction = normalize( vWorldDirection );\n\n\tvec2 sampleUV = equirectUv( direction );\n\n\tvec4 texColor = texture2D( tEquirect, sampleUV );\n\n\tgl_FragColor = mapTexelToLinear( texColor );\n\n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nvarying vec3 vWorldDirection;\n\n#include \n\nvoid main() {\n\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform vec3 diffuse;\nuniform float opacity;\n\nuniform float dashSize;\nuniform float totalSize;\n\nvarying float vLineDistance;\n\n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\n\t\tdiscard;\n\n\t}\n\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include \n\t#include \n\n\toutgoingLight = diffuseColor.rgb; // simple shader\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform float scale;\nattribute float lineDistance;\n\nvarying float vLineDistance;\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\tvLineDistance = scale * lineDistance;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform vec3 diffuse;\nuniform float opacity;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\n\t// accumulation (baked indirect lighting only)\n\t#ifdef USE_LIGHTMAP\n\t\n\t\tvec4 lightMapTexel= texture2D( lightMap, vUv2 );\n\t\treflectedLight.indirectDiffuse += lightMapTexelToLinear( lightMapTexel ).rgb * lightMapIntensity;\n\n\t#else\n\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\n\t#endif\n\n\t// modulation\n\t#include \n\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\n\t#include \n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#ifdef USE_ENVMAP\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// accumulation\n\n\t#ifdef DOUBLE_SIDED\n\n\t\treflectedLight.indirectDiffuse += ( gl_FrontFacing ) ? vIndirectFront : vIndirectBack;\n\n\t#else\n\n\t\treflectedLight.indirectDiffuse += vIndirectFront;\n\n\t#endif\n\n\t#include \n\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\n\t#ifdef DOUBLE_SIDED\n\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\n\t#else\n\n\t\treflectedLight.directDiffuse = vLightFront;\n\n\t#endif\n\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\n\t// modulation\n\n\t#include \n\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\n\t#include \n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n`;\n","export default /* glsl */`\n#define LAMBERT\n\nvarying vec3 vLightFront;\nvarying vec3 vIndirectFront;\n\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n\tvarying vec3 vIndirectBack;\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n`;\n","export default /* glsl */`\n#define MATCAP\n\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n\n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5; // 0.495 to remove artifacts caused by undersized matcap disks\n\n\t#ifdef USE_MATCAP\n\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t\tmatcapColor = matcapTexelToLinear( matcapColor );\n\n\t#else\n\n\t\tvec4 matcapColor = vec4( 1.0 );\n\n\t#endif\n\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define MATCAP\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n\n\t\tvNormal = normalize( transformedNormal );\n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\n\tvViewPosition = - mvPosition.xyz;\n\n}\n`;\n","export default /* glsl */`\n#define TOON\n\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// accumulation\n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// modulation\n\t#include \n\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define TOON\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n\n\tvNormal = normalize( transformedNormal );\n\n#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvViewPosition = - mvPosition.xyz;\n\n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define PHONG\n\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// accumulation\n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// modulation\n\t#include \n\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\n\t#include \n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define PHONG\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n\n\tvNormal = normalize( transformedNormal );\n\n#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvViewPosition = - mvPosition.xyz;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define STANDARD\n\n#ifdef PHYSICAL\n\t#define REFLECTIVITY\n\t#define CLEARCOAT\n\t#define TRANSPARENCY\n#endif\n\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n\n#ifdef TRANSPARENCY\n\tuniform float transparency;\n#endif\n\n#ifdef REFLECTIVITY\n\tuniform float reflectivity;\n#endif\n\n#ifdef CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n\n#ifdef USE_SHEEN\n\tuniform vec3 sheen;\n#endif\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n\t#ifdef USE_TANGENT\n\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\n\t#endif\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// accumulation\n\t#include \n\t#include \n\t#include \n\t#include \n\n\t// modulation\n\t#include \n\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\n\t// this is a stub for the transparency model\n\t#ifdef TRANSPARENCY\n\t\tdiffuseColor.a *= saturate( 1. - transparency + linearToRelativeLuminance( reflectedLight.directSpecular + reflectedLight.indirectSpecular ) );\n\t#endif\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define STANDARD\n\nvarying vec3 vViewPosition;\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n\t#ifdef USE_TANGENT\n\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\n\t#endif\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n\n\tvNormal = normalize( transformedNormal );\n\n\t#ifdef USE_TANGENT\n\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\n\t#endif\n\n#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n\tvViewPosition = - mvPosition.xyz;\n\n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#define NORMAL\n\nuniform float opacity;\n\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\n\tvarying vec3 vViewPosition;\n\n#endif\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n\t#ifdef USE_TANGENT\n\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\n\t#endif\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\n}\n`;\n","export default /* glsl */`\n#define NORMAL\n\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\n\tvarying vec3 vViewPosition;\n\n#endif\n\n#ifndef FLAT_SHADED\n\n\tvarying vec3 vNormal;\n\n\t#ifdef USE_TANGENT\n\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\n\t#endif\n\n#endif\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n#ifndef FLAT_SHADED // Normal computed with derivatives when FLAT_SHADED\n\n\tvNormal = normalize( transformedNormal );\n\n\t#ifdef USE_TANGENT\n\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\n\t#endif\n\n#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( TANGENTSPACE_NORMALMAP )\n\n\tvViewPosition = - mvPosition.xyz;\n\n#endif\n\n}\n`;\n","export default /* glsl */`\nuniform vec3 diffuse;\nuniform float opacity;\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\toutgoingLight = diffuseColor.rgb;\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform float size;\nuniform float scale;\n\n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\tgl_PointSize = size;\n\n\t#ifdef USE_SIZEATTENUATION\n\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\n\t#endif\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform vec3 color;\nuniform float opacity;\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\n#include \n#include \n\nvoid main() {\n\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform vec3 diffuse;\nuniform float opacity;\n\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\n\t#include \n\t#include \n\t#include \n\t#include \n\n\toutgoingLight = diffuseColor.rgb;\n\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\n\t#include \n\t#include \n\t#include \n\n}\n`;\n","export default /* glsl */`\nuniform float rotation;\nuniform vec2 center;\n\n#include \n#include \n#include \n#include \n#include \n\nvoid main() {\n\n\t#include \n\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\n\t#ifndef USE_SIZEATTENUATION\n\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\n\t#endif\n\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\n\tmvPosition.xy += rotatedPosition;\n\n\tgl_Position = projectionMatrix * mvPosition;\n\n\t#include \n\t#include \n\t#include \n\n}\n`;\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { BackSide, FrontSide, CubeUVReflectionMapping } from '../../constants.js';\nimport { BoxBufferGeometry } from '../../geometries/BoxGeometry.js';\nimport { PlaneBufferGeometry } from '../../geometries/PlaneGeometry.js';\nimport { ShaderMaterial } from '../../materials/ShaderMaterial.js';\nimport { Color } from '../../math/Color.js';\nimport { Mesh } from '../../objects/Mesh.js';\nimport { ShaderLib } from '../shaders/ShaderLib.js';\nimport { cloneUniforms } from '../shaders/UniformsUtils.js';\n\nfunction WebGLBackground( renderer, state, objects, premultipliedAlpha ) {\n\n\tvar clearColor = new Color( 0x000000 );\n\tvar clearAlpha = 0;\n\n\tvar planeMesh;\n\tvar boxMesh;\n\n\tvar currentBackground = null;\n\tvar currentBackgroundVersion = 0;\n\tvar currentTonemapping = null;\n\n\tfunction render( renderList, scene, camera, forceClear ) {\n\n\t\tvar background = scene.background;\n\n\t\t// Ignore background in AR\n\t\t// TODO: Reconsider this.\n\n\t\tvar xr = renderer.xr;\n\t\tvar session = xr.getSession && xr.getSession();\n\n\t\tif ( session && session.environmentBlendMode === 'additive' ) {\n\n\t\t\tbackground = null;\n\n\t\t}\n\n\t\tif ( background === null ) {\n\n\t\t\tsetClear( clearColor, clearAlpha );\n\n\t\t} else if ( background && background.isColor ) {\n\n\t\t\tsetClear( background, 1 );\n\t\t\tforceClear = true;\n\n\t\t}\n\n\t\tif ( renderer.autoClear || forceClear ) {\n\n\t\t\trenderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );\n\n\t\t}\n\n\t\tif ( background && ( background.isCubeTexture || background.isWebGLCubeRenderTarget || background.mapping === CubeUVReflectionMapping ) ) {\n\n\t\t\tif ( boxMesh === undefined ) {\n\n\t\t\t\tboxMesh = new Mesh(\n\t\t\t\t\tnew BoxBufferGeometry( 1, 1, 1 ),\n\t\t\t\t\tnew ShaderMaterial( {\n\t\t\t\t\t\ttype: 'BackgroundCubeMaterial',\n\t\t\t\t\t\tuniforms: cloneUniforms( ShaderLib.cube.uniforms ),\n\t\t\t\t\t\tvertexShader: ShaderLib.cube.vertexShader,\n\t\t\t\t\t\tfragmentShader: ShaderLib.cube.fragmentShader,\n\t\t\t\t\t\tside: BackSide,\n\t\t\t\t\t\tdepthTest: false,\n\t\t\t\t\t\tdepthWrite: false,\n\t\t\t\t\t\tfog: false\n\t\t\t\t\t} )\n\t\t\t\t);\n\n\t\t\t\tboxMesh.geometry.deleteAttribute( 'normal' );\n\t\t\t\tboxMesh.geometry.deleteAttribute( 'uv' );\n\n\t\t\t\tboxMesh.onBeforeRender = function ( renderer, scene, camera ) {\n\n\t\t\t\t\tthis.matrixWorld.copyPosition( camera.matrixWorld );\n\n\t\t\t\t};\n\n\t\t\t\t// enable code injection for non-built-in material\n\t\t\t\tObject.defineProperty( boxMesh.material, 'envMap', {\n\n\t\t\t\t\tget: function () {\n\n\t\t\t\t\t\treturn this.uniforms.envMap.value;\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t\tobjects.update( boxMesh );\n\n\t\t\t}\n\n\t\t\tvar texture = background.isWebGLCubeRenderTarget ? background.texture : background;\n\n\t\t\tboxMesh.material.uniforms.envMap.value = texture;\n\t\t\tboxMesh.material.uniforms.flipEnvMap.value = texture.isCubeTexture ? - 1 : 1;\n\n\t\t\tif ( currentBackground !== background ||\n\t\t\t\tcurrentBackgroundVersion !== texture.version ||\n\t\t\t\tcurrentTonemapping !== renderer.toneMapping ) {\n\n\t\t\t\tboxMesh.material.needsUpdate = true;\n\n\t\t\t\tcurrentBackground = background;\n\t\t\t\tcurrentBackgroundVersion = texture.version;\n\t\t\t\tcurrentTonemapping = renderer.toneMapping;\n\n\t\t\t}\n\n\t\t\t// push to the pre-sorted opaque render list\n\t\t\trenderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0, null );\n\n\t\t} else if ( background && background.isTexture ) {\n\n\t\t\tif ( planeMesh === undefined ) {\n\n\t\t\t\tplaneMesh = new Mesh(\n\t\t\t\t\tnew PlaneBufferGeometry( 2, 2 ),\n\t\t\t\t\tnew ShaderMaterial( {\n\t\t\t\t\t\ttype: 'BackgroundMaterial',\n\t\t\t\t\t\tuniforms: cloneUniforms( ShaderLib.background.uniforms ),\n\t\t\t\t\t\tvertexShader: ShaderLib.background.vertexShader,\n\t\t\t\t\t\tfragmentShader: ShaderLib.background.fragmentShader,\n\t\t\t\t\t\tside: FrontSide,\n\t\t\t\t\t\tdepthTest: false,\n\t\t\t\t\t\tdepthWrite: false,\n\t\t\t\t\t\tfog: false\n\t\t\t\t\t} )\n\t\t\t\t);\n\n\t\t\t\tplaneMesh.geometry.deleteAttribute( 'normal' );\n\n\t\t\t\t// enable code injection for non-built-in material\n\t\t\t\tObject.defineProperty( planeMesh.material, 'map', {\n\n\t\t\t\t\tget: function () {\n\n\t\t\t\t\t\treturn this.uniforms.t2D.value;\n\n\t\t\t\t\t}\n\n\t\t\t\t} );\n\n\t\t\t\tobjects.update( planeMesh );\n\n\t\t\t}\n\n\t\t\tplaneMesh.material.uniforms.t2D.value = background;\n\n\t\t\tif ( background.matrixAutoUpdate === true ) {\n\n\t\t\t\tbackground.updateMatrix();\n\n\t\t\t}\n\n\t\t\tplaneMesh.material.uniforms.uvTransform.value.copy( background.matrix );\n\n\t\t\tif ( currentBackground !== background ||\n\t\t\t\tcurrentBackgroundVersion !== background.version ||\n\t\t\t\tcurrentTonemapping !== renderer.toneMapping ) {\n\n\t\t\t\tplaneMesh.material.needsUpdate = true;\n\n\t\t\t\tcurrentBackground = background;\n\t\t\t\tcurrentBackgroundVersion = background.version;\n\t\t\t\tcurrentTonemapping = renderer.toneMapping;\n\n\t\t\t}\n\n\n\t\t\t// push to the pre-sorted opaque render list\n\t\t\trenderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0, null );\n\n\t\t}\n\n\t}\n\n\tfunction setClear( color, alpha ) {\n\n\t\tstate.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha );\n\n\t}\n\n\treturn {\n\n\t\tgetClearColor: function () {\n\n\t\t\treturn clearColor;\n\n\t\t},\n\t\tsetClearColor: function ( color, alpha ) {\n\n\t\t\tclearColor.set( color );\n\t\t\tclearAlpha = alpha !== undefined ? alpha : 1;\n\t\t\tsetClear( clearColor, clearAlpha );\n\n\t\t},\n\t\tgetClearAlpha: function () {\n\n\t\t\treturn clearAlpha;\n\n\t\t},\n\t\tsetClearAlpha: function ( alpha ) {\n\n\t\t\tclearAlpha = alpha;\n\t\t\tsetClear( clearColor, clearAlpha );\n\n\t\t},\n\t\trender: render\n\n\t};\n\n}\n\n\nexport { WebGLBackground };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLBufferRenderer( gl, extensions, info, capabilities ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\n\tvar mode;\n\n\tfunction setMode( value ) {\n\n\t\tmode = value;\n\n\t}\n\n\tfunction render( start, count ) {\n\n\t\tgl.drawArrays( mode, start, count );\n\n\t\tinfo.update( count, mode );\n\n\t}\n\n\tfunction renderInstances( geometry, start, count, primcount ) {\n\n\t\tif ( primcount === 0 ) return;\n\n\t\tvar extension, methodName;\n\n\t\tif ( isWebGL2 ) {\n\n\t\t\textension = gl;\n\t\t\tmethodName = 'drawArraysInstanced';\n\n\t\t} else {\n\n\t\t\textension = extensions.get( 'ANGLE_instanced_arrays' );\n\t\t\tmethodName = 'drawArraysInstancedANGLE';\n\n\t\t\tif ( extension === null ) {\n\n\t\t\t\tconsole.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t}\n\n\t\textension[ methodName ]( mode, start, count, primcount );\n\n\t\tinfo.update( count, mode, primcount );\n\n\t}\n\n\t//\n\n\tthis.setMode = setMode;\n\tthis.render = render;\n\tthis.renderInstances = renderInstances;\n\n}\n\n\nexport { WebGLBufferRenderer };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLCapabilities( gl, extensions, parameters ) {\n\n\tvar maxAnisotropy;\n\n\tfunction getMaxAnisotropy() {\n\n\t\tif ( maxAnisotropy !== undefined ) return maxAnisotropy;\n\n\t\tvar extension = extensions.get( 'EXT_texture_filter_anisotropic' );\n\n\t\tif ( extension !== null ) {\n\n\t\t\tmaxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );\n\n\t\t} else {\n\n\t\t\tmaxAnisotropy = 0;\n\n\t\t}\n\n\t\treturn maxAnisotropy;\n\n\t}\n\n\tfunction getMaxPrecision( precision ) {\n\n\t\tif ( precision === 'highp' ) {\n\n\t\t\tif ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&\n\t\t\t\tgl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {\n\n\t\t\t\treturn 'highp';\n\n\t\t\t}\n\n\t\t\tprecision = 'mediump';\n\n\t\t}\n\n\t\tif ( precision === 'mediump' ) {\n\n\t\t\tif ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&\n\t\t\t\tgl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {\n\n\t\t\t\treturn 'mediump';\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn 'lowp';\n\n\t}\n\n\t/* eslint-disable no-undef */\n\tvar isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && gl instanceof WebGL2RenderingContext ) ||\n\t\t( typeof WebGL2ComputeRenderingContext !== 'undefined' && gl instanceof WebGL2ComputeRenderingContext );\n\t/* eslint-enable no-undef */\n\n\tvar precision = parameters.precision !== undefined ? parameters.precision : 'highp';\n\tvar maxPrecision = getMaxPrecision( precision );\n\n\tif ( maxPrecision !== precision ) {\n\n\t\tconsole.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' );\n\t\tprecision = maxPrecision;\n\n\t}\n\n\tvar logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;\n\n\tvar maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );\n\tvar maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );\n\tvar maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );\n\tvar maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );\n\n\tvar maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );\n\tvar maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );\n\tvar maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );\n\tvar maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );\n\n\tvar vertexTextures = maxVertexTextures > 0;\n\tvar floatFragmentTextures = isWebGL2 || !! extensions.get( 'OES_texture_float' );\n\tvar floatVertexTextures = vertexTextures && floatFragmentTextures;\n\n\tvar maxSamples = isWebGL2 ? gl.getParameter( gl.MAX_SAMPLES ) : 0;\n\n\treturn {\n\n\t\tisWebGL2: isWebGL2,\n\n\t\tgetMaxAnisotropy: getMaxAnisotropy,\n\t\tgetMaxPrecision: getMaxPrecision,\n\n\t\tprecision: precision,\n\t\tlogarithmicDepthBuffer: logarithmicDepthBuffer,\n\n\t\tmaxTextures: maxTextures,\n\t\tmaxVertexTextures: maxVertexTextures,\n\t\tmaxTextureSize: maxTextureSize,\n\t\tmaxCubemapSize: maxCubemapSize,\n\n\t\tmaxAttributes: maxAttributes,\n\t\tmaxVertexUniforms: maxVertexUniforms,\n\t\tmaxVaryings: maxVaryings,\n\t\tmaxFragmentUniforms: maxFragmentUniforms,\n\n\t\tvertexTextures: vertexTextures,\n\t\tfloatFragmentTextures: floatFragmentTextures,\n\t\tfloatVertexTextures: floatVertexTextures,\n\n\t\tmaxSamples: maxSamples\n\n\t};\n\n}\n\n\nexport { WebGLCapabilities };\n","/**\n * @author tschw\n */\n\nimport { Matrix3 } from '../../math/Matrix3.js';\nimport { Plane } from '../../math/Plane.js';\n\nfunction WebGLClipping() {\n\n\tvar scope = this,\n\n\t\tglobalState = null,\n\t\tnumGlobalPlanes = 0,\n\t\tlocalClippingEnabled = false,\n\t\trenderingShadows = false,\n\n\t\tplane = new Plane(),\n\t\tviewNormalMatrix = new Matrix3(),\n\n\t\tuniform = { value: null, needsUpdate: false };\n\n\tthis.uniform = uniform;\n\tthis.numPlanes = 0;\n\tthis.numIntersection = 0;\n\n\tthis.init = function ( planes, enableLocalClipping, camera ) {\n\n\t\tvar enabled =\n\t\t\tplanes.length !== 0 ||\n\t\t\tenableLocalClipping ||\n\t\t\t// enable state of previous frame - the clipping code has to\n\t\t\t// run another frame in order to reset the state:\n\t\t\tnumGlobalPlanes !== 0 ||\n\t\t\tlocalClippingEnabled;\n\n\t\tlocalClippingEnabled = enableLocalClipping;\n\n\t\tglobalState = projectPlanes( planes, camera, 0 );\n\t\tnumGlobalPlanes = planes.length;\n\n\t\treturn enabled;\n\n\t};\n\n\tthis.beginShadows = function () {\n\n\t\trenderingShadows = true;\n\t\tprojectPlanes( null );\n\n\t};\n\n\tthis.endShadows = function () {\n\n\t\trenderingShadows = false;\n\t\tresetGlobalState();\n\n\t};\n\n\tthis.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) {\n\n\t\tif ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) {\n\n\t\t\t// there's no local clipping\n\n\t\t\tif ( renderingShadows ) {\n\n\t\t\t\t// there's no global clipping\n\n\t\t\t\tprojectPlanes( null );\n\n\t\t\t} else {\n\n\t\t\t\tresetGlobalState();\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tvar nGlobal = renderingShadows ? 0 : numGlobalPlanes,\n\t\t\t\tlGlobal = nGlobal * 4,\n\n\t\t\t\tdstArray = cache.clippingState || null;\n\n\t\t\tuniform.value = dstArray; // ensure unique state\n\n\t\t\tdstArray = projectPlanes( planes, camera, lGlobal, fromCache );\n\n\t\t\tfor ( var i = 0; i !== lGlobal; ++ i ) {\n\n\t\t\t\tdstArray[ i ] = globalState[ i ];\n\n\t\t\t}\n\n\t\t\tcache.clippingState = dstArray;\n\t\t\tthis.numIntersection = clipIntersection ? this.numPlanes : 0;\n\t\t\tthis.numPlanes += nGlobal;\n\n\t\t}\n\n\n\t};\n\n\tfunction resetGlobalState() {\n\n\t\tif ( uniform.value !== globalState ) {\n\n\t\t\tuniform.value = globalState;\n\t\t\tuniform.needsUpdate = numGlobalPlanes > 0;\n\n\t\t}\n\n\t\tscope.numPlanes = numGlobalPlanes;\n\t\tscope.numIntersection = 0;\n\n\t}\n\n\tfunction projectPlanes( planes, camera, dstOffset, skipTransform ) {\n\n\t\tvar nPlanes = planes !== null ? planes.length : 0,\n\t\t\tdstArray = null;\n\n\t\tif ( nPlanes !== 0 ) {\n\n\t\t\tdstArray = uniform.value;\n\n\t\t\tif ( skipTransform !== true || dstArray === null ) {\n\n\t\t\t\tvar flatSize = dstOffset + nPlanes * 4,\n\t\t\t\t\tviewMatrix = camera.matrixWorldInverse;\n\n\t\t\t\tviewNormalMatrix.getNormalMatrix( viewMatrix );\n\n\t\t\t\tif ( dstArray === null || dstArray.length < flatSize ) {\n\n\t\t\t\t\tdstArray = new Float32Array( flatSize );\n\n\t\t\t\t}\n\n\t\t\t\tfor ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) {\n\n\t\t\t\t\tplane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );\n\n\t\t\t\t\tplane.normal.toArray( dstArray, i4 );\n\t\t\t\t\tdstArray[ i4 + 3 ] = plane.constant;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tuniform.value = dstArray;\n\t\t\tuniform.needsUpdate = true;\n\n\t\t}\n\n\t\tscope.numPlanes = nPlanes;\n\t\tscope.numIntersection = 0;\n\n\t\treturn dstArray;\n\n\t}\n\n}\n\n\nexport { WebGLClipping };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLExtensions( gl ) {\n\n\tvar extensions = {};\n\n\treturn {\n\n\t\tget: function ( name ) {\n\n\t\t\tif ( extensions[ name ] !== undefined ) {\n\n\t\t\t\treturn extensions[ name ];\n\n\t\t\t}\n\n\t\t\tvar extension;\n\n\t\t\tswitch ( name ) {\n\n\t\t\t\tcase 'WEBGL_depth_texture':\n\t\t\t\t\textension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'EXT_texture_filter_anisotropic':\n\t\t\t\t\textension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'WEBGL_compressed_texture_s3tc':\n\t\t\t\t\textension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'WEBGL_compressed_texture_pvrtc':\n\t\t\t\t\textension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' );\n\t\t\t\t\tbreak;\n\n\t\t\t\tdefault:\n\t\t\t\t\textension = gl.getExtension( name );\n\n\t\t\t}\n\n\t\t\tif ( extension === null ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' );\n\n\t\t\t}\n\n\t\t\textensions[ name ] = extension;\n\n\t\t\treturn extension;\n\n\t\t}\n\n\t};\n\n}\n\n\nexport { WebGLExtensions };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute.js';\nimport { BufferGeometry } from '../../core/BufferGeometry.js';\nimport { arrayMax } from '../../utils.js';\n\nfunction WebGLGeometries( gl, attributes, info ) {\n\n\tvar geometries = new WeakMap();\n\tvar wireframeAttributes = new WeakMap();\n\n\tfunction onGeometryDispose( event ) {\n\n\t\tvar geometry = event.target;\n\t\tvar buffergeometry = geometries.get( geometry );\n\n\t\tif ( buffergeometry.index !== null ) {\n\n\t\t\tattributes.remove( buffergeometry.index );\n\n\t\t}\n\n\t\tfor ( var name in buffergeometry.attributes ) {\n\n\t\t\tattributes.remove( buffergeometry.attributes[ name ] );\n\n\t\t}\n\n\t\tgeometry.removeEventListener( 'dispose', onGeometryDispose );\n\n\t\tgeometries.delete( geometry );\n\n\t\tvar attribute = wireframeAttributes.get( buffergeometry );\n\n\t\tif ( attribute ) {\n\n\t\t\tattributes.remove( attribute );\n\t\t\twireframeAttributes.delete( buffergeometry );\n\n\t\t}\n\n\t\t//\n\n\t\tinfo.memory.geometries --;\n\n\t}\n\n\tfunction get( object, geometry ) {\n\n\t\tvar buffergeometry = geometries.get( geometry );\n\n\t\tif ( buffergeometry ) return buffergeometry;\n\n\t\tgeometry.addEventListener( 'dispose', onGeometryDispose );\n\n\t\tif ( geometry.isBufferGeometry ) {\n\n\t\t\tbuffergeometry = geometry;\n\n\t\t} else if ( geometry.isGeometry ) {\n\n\t\t\tif ( geometry._bufferGeometry === undefined ) {\n\n\t\t\t\tgeometry._bufferGeometry = new BufferGeometry().setFromObject( object );\n\n\t\t\t}\n\n\t\t\tbuffergeometry = geometry._bufferGeometry;\n\n\t\t}\n\n\t\tgeometries.set( geometry, buffergeometry );\n\n\t\tinfo.memory.geometries ++;\n\n\t\treturn buffergeometry;\n\n\t}\n\n\tfunction update( geometry ) {\n\n\t\tvar index = geometry.index;\n\t\tvar geometryAttributes = geometry.attributes;\n\n\t\tif ( index !== null ) {\n\n\t\t\tattributes.update( index, gl.ELEMENT_ARRAY_BUFFER );\n\n\t\t}\n\n\t\tfor ( var name in geometryAttributes ) {\n\n\t\t\tattributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );\n\n\t\t}\n\n\t\t// morph targets\n\n\t\tvar morphAttributes = geometry.morphAttributes;\n\n\t\tfor ( var name in morphAttributes ) {\n\n\t\t\tvar array = morphAttributes[ name ];\n\n\t\t\tfor ( var i = 0, l = array.length; i < l; i ++ ) {\n\n\t\t\t\tattributes.update( array[ i ], gl.ARRAY_BUFFER );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tfunction updateWireframeAttribute( geometry ) {\n\n\t\tvar indices = [];\n\n\t\tvar geometryIndex = geometry.index;\n\t\tvar geometryPosition = geometry.attributes.position;\n\t\tvar version = 0;\n\n\t\tif ( geometryIndex !== null ) {\n\n\t\t\tvar array = geometryIndex.array;\n\t\t\tversion = geometryIndex.version;\n\n\t\t\tfor ( var i = 0, l = array.length; i < l; i += 3 ) {\n\n\t\t\t\tvar a = array[ i + 0 ];\n\t\t\t\tvar b = array[ i + 1 ];\n\t\t\t\tvar c = array[ i + 2 ];\n\n\t\t\t\tindices.push( a, b, b, c, c, a );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tvar array = geometryPosition.array;\n\t\t\tversion = geometryPosition.version;\n\n\t\t\tfor ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {\n\n\t\t\t\tvar a = i + 0;\n\t\t\t\tvar b = i + 1;\n\t\t\t\tvar c = i + 2;\n\n\t\t\t\tindices.push( a, b, b, c, c, a );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );\n\t\tattribute.version = version;\n\n\t\tattributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER );\n\n\t\t//\n\n\t\tvar previousAttribute = wireframeAttributes.get( geometry );\n\n\t\tif ( previousAttribute ) attributes.remove( previousAttribute );\n\n\t\t//\n\n\t\twireframeAttributes.set( geometry, attribute );\n\n\t}\n\n\tfunction getWireframeAttribute( geometry ) {\n\n\t\tvar currentAttribute = wireframeAttributes.get( geometry );\n\n\t\tif ( currentAttribute ) {\n\n\t\t\tvar geometryIndex = geometry.index;\n\n\t\t\tif ( geometryIndex !== null ) {\n\n\t\t\t\t// if the attribute is obsolete, create a new one\n\n\t\t\t\tif ( currentAttribute.version < geometryIndex.version ) {\n\n\t\t\t\t\tupdateWireframeAttribute( geometry );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tupdateWireframeAttribute( geometry );\n\n\t\t}\n\n\t\treturn wireframeAttributes.get( geometry );\n\n\t}\n\n\treturn {\n\n\t\tget: get,\n\t\tupdate: update,\n\n\t\tgetWireframeAttribute: getWireframeAttribute\n\n\t};\n\n}\n\n\nexport { WebGLGeometries };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\n\tvar mode;\n\n\tfunction setMode( value ) {\n\n\t\tmode = value;\n\n\t}\n\n\tvar type, bytesPerElement;\n\n\tfunction setIndex( value ) {\n\n\t\ttype = value.type;\n\t\tbytesPerElement = value.bytesPerElement;\n\n\t}\n\n\tfunction render( start, count ) {\n\n\t\tgl.drawElements( mode, count, type, start * bytesPerElement );\n\n\t\tinfo.update( count, mode );\n\n\t}\n\n\tfunction renderInstances( geometry, start, count, primcount ) {\n\n\t\tif ( primcount === 0 ) return;\n\n\t\tvar extension, methodName;\n\n\t\tif ( isWebGL2 ) {\n\n\t\t\textension = gl;\n\t\t\tmethodName = 'drawElementsInstanced';\n\n\t\t} else {\n\n\t\t\textension = extensions.get( 'ANGLE_instanced_arrays' );\n\t\t\tmethodName = 'drawElementsInstancedANGLE';\n\n\t\t\tif ( extension === null ) {\n\n\t\t\t\tconsole.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t}\n\n\t\textension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );\n\n\t\tinfo.update( count, mode, primcount );\n\n\t}\n\n\t//\n\n\tthis.setMode = setMode;\n\tthis.setIndex = setIndex;\n\tthis.render = render;\n\tthis.renderInstances = renderInstances;\n\n}\n\n\nexport { WebGLIndexedBufferRenderer };\n","/**\n * @author Mugen87 / https://github.com/Mugen87\n */\n\nfunction WebGLInfo( gl ) {\n\n\tvar memory = {\n\t\tgeometries: 0,\n\t\ttextures: 0\n\t};\n\n\tvar render = {\n\t\tframe: 0,\n\t\tcalls: 0,\n\t\ttriangles: 0,\n\t\tpoints: 0,\n\t\tlines: 0\n\t};\n\n\tfunction update( count, mode, instanceCount ) {\n\n\t\tinstanceCount = instanceCount || 1;\n\n\t\trender.calls ++;\n\n\t\tswitch ( mode ) {\n\n\t\t\tcase gl.TRIANGLES:\n\t\t\t\trender.triangles += instanceCount * ( count / 3 );\n\t\t\t\tbreak;\n\n\t\t\tcase gl.LINES:\n\t\t\t\trender.lines += instanceCount * ( count / 2 );\n\t\t\t\tbreak;\n\n\t\t\tcase gl.LINE_STRIP:\n\t\t\t\trender.lines += instanceCount * ( count - 1 );\n\t\t\t\tbreak;\n\n\t\t\tcase gl.LINE_LOOP:\n\t\t\t\trender.lines += instanceCount * count;\n\t\t\t\tbreak;\n\n\t\t\tcase gl.POINTS:\n\t\t\t\trender.points += instanceCount * count;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tconsole.error( 'THREE.WebGLInfo: Unknown draw mode:', mode );\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\tfunction reset() {\n\n\t\trender.frame ++;\n\t\trender.calls = 0;\n\t\trender.triangles = 0;\n\t\trender.points = 0;\n\t\trender.lines = 0;\n\n\t}\n\n\treturn {\n\t\tmemory: memory,\n\t\trender: render,\n\t\tprograms: null,\n\t\tautoReset: true,\n\t\treset: reset,\n\t\tupdate: update\n\t};\n\n}\n\n\nexport { WebGLInfo };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction absNumericalSort( a, b ) {\n\n\treturn Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] );\n\n}\n\nfunction WebGLMorphtargets( gl ) {\n\n\tvar influencesList = {};\n\tvar morphInfluences = new Float32Array( 8 );\n\n\tfunction update( object, geometry, material, program ) {\n\n\t\tvar objectInfluences = object.morphTargetInfluences;\n\n\t\t// When object doesn't have morph target influences defined, we treat it as a 0-length array\n\t\t// This is important to make sure we set up morphTargetBaseInfluence / morphTargetInfluences\n\n\t\tvar length = objectInfluences === undefined ? 0 : objectInfluences.length;\n\n\t\tvar influences = influencesList[ geometry.id ];\n\n\t\tif ( influences === undefined ) {\n\n\t\t\t// initialise list\n\n\t\t\tinfluences = [];\n\n\t\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\t\tinfluences[ i ] = [ i, 0 ];\n\n\t\t\t}\n\n\t\t\tinfluencesList[ geometry.id ] = influences;\n\n\t\t}\n\n\t\tvar morphTargets = material.morphTargets && geometry.morphAttributes.position;\n\t\tvar morphNormals = material.morphNormals && geometry.morphAttributes.normal;\n\n\t\t// Remove current morphAttributes\n\n\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\tvar influence = influences[ i ];\n\n\t\t\tif ( influence[ 1 ] !== 0 ) {\n\n\t\t\t\tif ( morphTargets ) geometry.deleteAttribute( 'morphTarget' + i );\n\t\t\t\tif ( morphNormals ) geometry.deleteAttribute( 'morphNormal' + i );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Collect influences\n\n\t\tfor ( var i = 0; i < length; i ++ ) {\n\n\t\t\tvar influence = influences[ i ];\n\n\t\t\tinfluence[ 0 ] = i;\n\t\t\tinfluence[ 1 ] = objectInfluences[ i ];\n\n\t\t}\n\n\t\tinfluences.sort( absNumericalSort );\n\n\t\t// Add morphAttributes\n\n\t\tvar morphInfluencesSum = 0;\n\n\t\tfor ( var i = 0; i < 8; i ++ ) {\n\n\t\t\tvar influence = influences[ i ];\n\n\t\t\tif ( influence ) {\n\n\t\t\t\tvar index = influence[ 0 ];\n\t\t\t\tvar value = influence[ 1 ];\n\n\t\t\t\tif ( value ) {\n\n\t\t\t\t\tif ( morphTargets ) geometry.setAttribute( 'morphTarget' + i, morphTargets[ index ] );\n\t\t\t\t\tif ( morphNormals ) geometry.setAttribute( 'morphNormal' + i, morphNormals[ index ] );\n\n\t\t\t\t\tmorphInfluences[ i ] = value;\n\t\t\t\t\tmorphInfluencesSum += value;\n\t\t\t\t\tcontinue;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tmorphInfluences[ i ] = 0;\n\n\t\t}\n\n\t\t// GLSL shader uses formula baseinfluence * base + sum(target * influence)\n\t\t// This allows us to switch between absolute morphs and relative morphs without changing shader code\n\t\t// When baseinfluence = 1 - sum(influence), the above is equivalent to sum((target - base) * influence)\n\t\tvar morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;\n\n\t\tprogram.getUniforms().setValue( gl, 'morphTargetBaseInfluence', morphBaseInfluence );\n\t\tprogram.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences );\n\n\t}\n\n\treturn {\n\n\t\tupdate: update\n\n\t};\n\n}\n\n\nexport { WebGLMorphtargets };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLObjects( gl, geometries, attributes, info ) {\n\n\tvar updateMap = new WeakMap();\n\n\tfunction update( object ) {\n\n\t\tvar frame = info.render.frame;\n\n\t\tvar geometry = object.geometry;\n\t\tvar buffergeometry = geometries.get( object, geometry );\n\n\t\t// Update once per frame\n\n\t\tif ( updateMap.get( buffergeometry ) !== frame ) {\n\n\t\t\tif ( geometry.isGeometry ) {\n\n\t\t\t\tbuffergeometry.updateFromObject( object );\n\n\t\t\t}\n\n\t\t\tgeometries.update( buffergeometry );\n\n\t\t\tupdateMap.set( buffergeometry, frame );\n\n\t\t}\n\n\t\tif ( object.isInstancedMesh ) {\n\n\t\t\tattributes.update( object.instanceMatrix, gl.ARRAY_BUFFER );\n\n\t\t}\n\n\t\treturn buffergeometry;\n\n\t}\n\n\tfunction dispose() {\n\n\t\tupdateMap = new WeakMap();\n\n\t}\n\n\treturn {\n\n\t\tupdate: update,\n\t\tdispose: dispose\n\n\t};\n\n}\n\n\nexport { WebGLObjects };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { Texture } from './Texture.js';\nimport { CubeReflectionMapping, RGBFormat } from '../constants.js';\n\nfunction CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) {\n\n\timages = images !== undefined ? images : [];\n\tmapping = mapping !== undefined ? mapping : CubeReflectionMapping;\n\tformat = format !== undefined ? format : RGBFormat;\n\n\tTexture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding );\n\n\tthis.flipY = false;\n\n}\n\nCubeTexture.prototype = Object.create( Texture.prototype );\nCubeTexture.prototype.constructor = CubeTexture;\n\nCubeTexture.prototype.isCubeTexture = true;\n\nObject.defineProperty( CubeTexture.prototype, 'images', {\n\n\tget: function () {\n\n\t\treturn this.image;\n\n\t},\n\n\tset: function ( value ) {\n\n\t\tthis.image = value;\n\n\t}\n\n} );\n\n\nexport { CubeTexture };\n","/**\n * @author Takahiro https://github.com/takahirox\n */\n\nimport { Texture } from './Texture.js';\nimport { ClampToEdgeWrapping, NearestFilter } from '../constants.js';\n\nfunction DataTexture2DArray( data, width, height, depth ) {\n\n\tTexture.call( this, null );\n\n\tthis.image = { data: data || null, width: width || 1, height: height || 1, depth: depth || 1 };\n\n\tthis.magFilter = NearestFilter;\n\tthis.minFilter = NearestFilter;\n\n\tthis.wrapR = ClampToEdgeWrapping;\n\n\tthis.generateMipmaps = false;\n\tthis.flipY = false;\n\n\tthis.needsUpdate = true;\n\n}\n\nDataTexture2DArray.prototype = Object.create( Texture.prototype );\nDataTexture2DArray.prototype.constructor = DataTexture2DArray;\nDataTexture2DArray.prototype.isDataTexture2DArray = true;\n\nexport { DataTexture2DArray };\n","/**\n * @author Artur Trzesiok\n */\n\nimport { Texture } from './Texture.js';\nimport { ClampToEdgeWrapping, NearestFilter } from '../constants.js';\n\nfunction DataTexture3D( data, width, height, depth ) {\n\n\t// We're going to add .setXXX() methods for setting properties later.\n\t// Users can still set in DataTexture3D directly.\n\t//\n\t//\tvar texture = new THREE.DataTexture3D( data, width, height, depth );\n\t// \ttexture.anisotropy = 16;\n\t//\n\t// See #14839\n\n\tTexture.call( this, null );\n\n\tthis.image = { data: data || null, width: width || 1, height: height || 1, depth: depth || 1 };\n\n\tthis.magFilter = NearestFilter;\n\tthis.minFilter = NearestFilter;\n\n\tthis.wrapR = ClampToEdgeWrapping;\n\n\tthis.generateMipmaps = false;\n\tthis.flipY = false;\n\n\tthis.needsUpdate = true;\n\n\n}\n\nDataTexture3D.prototype = Object.create( Texture.prototype );\nDataTexture3D.prototype.constructor = DataTexture3D;\nDataTexture3D.prototype.isDataTexture3D = true;\n\nexport { DataTexture3D };\n","import { ShaderChunk } from './ShaderChunk.js';\nimport { mergeUniforms } from './UniformsUtils.js';\nimport { Vector2 } from '../../math/Vector2.js';\nimport { Vector3 } from '../../math/Vector3.js';\nimport { UniformsLib } from './UniformsLib.js';\nimport { Color } from '../../math/Color.js';\nimport { Matrix3 } from '../../math/Matrix3.js';\n\n/**\n * @author alteredq / http://alteredqualia.com/\n * @author mrdoob / http://mrdoob.com/\n * @author mikael emtinger / http://gomo.se/\n */\n\nvar ShaderLib = {\n\n\tbasic: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.specularmap,\n\t\t\tUniformsLib.envmap,\n\t\t\tUniformsLib.aomap,\n\t\t\tUniformsLib.lightmap,\n\t\t\tUniformsLib.fog\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshbasic_vert,\n\t\tfragmentShader: ShaderChunk.meshbasic_frag\n\n\t},\n\n\tlambert: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.specularmap,\n\t\t\tUniformsLib.envmap,\n\t\t\tUniformsLib.aomap,\n\t\t\tUniformsLib.lightmap,\n\t\t\tUniformsLib.emissivemap,\n\t\t\tUniformsLib.fog,\n\t\t\tUniformsLib.lights,\n\t\t\t{\n\t\t\t\temissive: { value: new Color( 0x000000 ) }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshlambert_vert,\n\t\tfragmentShader: ShaderChunk.meshlambert_frag\n\n\t},\n\n\tphong: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.specularmap,\n\t\t\tUniformsLib.envmap,\n\t\t\tUniformsLib.aomap,\n\t\t\tUniformsLib.lightmap,\n\t\t\tUniformsLib.emissivemap,\n\t\t\tUniformsLib.bumpmap,\n\t\t\tUniformsLib.normalmap,\n\t\t\tUniformsLib.displacementmap,\n\t\t\tUniformsLib.fog,\n\t\t\tUniformsLib.lights,\n\t\t\t{\n\t\t\t\temissive: { value: new Color( 0x000000 ) },\n\t\t\t\tspecular: { value: new Color( 0x111111 ) },\n\t\t\t\tshininess: { value: 30 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshphong_vert,\n\t\tfragmentShader: ShaderChunk.meshphong_frag\n\n\t},\n\n\tstandard: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.envmap,\n\t\t\tUniformsLib.aomap,\n\t\t\tUniformsLib.lightmap,\n\t\t\tUniformsLib.emissivemap,\n\t\t\tUniformsLib.bumpmap,\n\t\t\tUniformsLib.normalmap,\n\t\t\tUniformsLib.displacementmap,\n\t\t\tUniformsLib.roughnessmap,\n\t\t\tUniformsLib.metalnessmap,\n\t\t\tUniformsLib.fog,\n\t\t\tUniformsLib.lights,\n\t\t\t{\n\t\t\t\temissive: { value: new Color( 0x000000 ) },\n\t\t\t\troughness: { value: 1.0 },\n\t\t\t\tmetalness: { value: 0.0 },\n\t\t\t\tenvMapIntensity: { value: 1 } // temporary\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshphysical_vert,\n\t\tfragmentShader: ShaderChunk.meshphysical_frag\n\n\t},\n\n\ttoon: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.specularmap,\n\t\t\tUniformsLib.aomap,\n\t\t\tUniformsLib.lightmap,\n\t\t\tUniformsLib.emissivemap,\n\t\t\tUniformsLib.bumpmap,\n\t\t\tUniformsLib.normalmap,\n\t\t\tUniformsLib.displacementmap,\n\t\t\tUniformsLib.gradientmap,\n\t\t\tUniformsLib.fog,\n\t\t\tUniformsLib.lights,\n\t\t\t{\n\t\t\t\temissive: { value: new Color( 0x000000 ) },\n\t\t\t\tspecular: { value: new Color( 0x111111 ) },\n\t\t\t\tshininess: { value: 30 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshtoon_vert,\n\t\tfragmentShader: ShaderChunk.meshtoon_frag\n\n\t},\n\n\tmatcap: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.bumpmap,\n\t\t\tUniformsLib.normalmap,\n\t\t\tUniformsLib.displacementmap,\n\t\t\tUniformsLib.fog,\n\t\t\t{\n\t\t\t\tmatcap: { value: null }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.meshmatcap_vert,\n\t\tfragmentShader: ShaderChunk.meshmatcap_frag\n\n\t},\n\n\tpoints: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.points,\n\t\t\tUniformsLib.fog\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.points_vert,\n\t\tfragmentShader: ShaderChunk.points_frag\n\n\t},\n\n\tdashed: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.fog,\n\t\t\t{\n\t\t\t\tscale: { value: 1 },\n\t\t\t\tdashSize: { value: 1 },\n\t\t\t\ttotalSize: { value: 2 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.linedashed_vert,\n\t\tfragmentShader: ShaderChunk.linedashed_frag\n\n\t},\n\n\tdepth: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.displacementmap\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.depth_vert,\n\t\tfragmentShader: ShaderChunk.depth_frag\n\n\t},\n\n\tnormal: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.bumpmap,\n\t\t\tUniformsLib.normalmap,\n\t\t\tUniformsLib.displacementmap,\n\t\t\t{\n\t\t\t\topacity: { value: 1.0 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.normal_vert,\n\t\tfragmentShader: ShaderChunk.normal_frag\n\n\t},\n\n\tsprite: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.sprite,\n\t\t\tUniformsLib.fog\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.sprite_vert,\n\t\tfragmentShader: ShaderChunk.sprite_frag\n\n\t},\n\n\tbackground: {\n\n\t\tuniforms: {\n\t\t\tuvTransform: { value: new Matrix3() },\n\t\t\tt2D: { value: null },\n\t\t},\n\n\t\tvertexShader: ShaderChunk.background_vert,\n\t\tfragmentShader: ShaderChunk.background_frag\n\n\t},\n\t/* -------------------------------------------------------------------------\n\t//\tCube map shader\n\t ------------------------------------------------------------------------- */\n\n\tcube: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.envmap,\n\t\t\t{\n\t\t\t\topacity: { value: 1.0 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.cube_vert,\n\t\tfragmentShader: ShaderChunk.cube_frag\n\n\t},\n\n\tequirect: {\n\n\t\tuniforms: {\n\t\t\ttEquirect: { value: null },\n\t\t},\n\n\t\tvertexShader: ShaderChunk.equirect_vert,\n\t\tfragmentShader: ShaderChunk.equirect_frag\n\n\t},\n\n\tdistanceRGBA: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.common,\n\t\t\tUniformsLib.displacementmap,\n\t\t\t{\n\t\t\t\treferencePosition: { value: new Vector3() },\n\t\t\t\tnearDistance: { value: 1 },\n\t\t\t\tfarDistance: { value: 1000 }\n\t\t\t}\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.distanceRGBA_vert,\n\t\tfragmentShader: ShaderChunk.distanceRGBA_frag\n\n\t},\n\n\tshadow: {\n\n\t\tuniforms: mergeUniforms( [\n\t\t\tUniformsLib.lights,\n\t\t\tUniformsLib.fog,\n\t\t\t{\n\t\t\t\tcolor: { value: new Color( 0x00000 ) },\n\t\t\t\topacity: { value: 1.0 }\n\t\t\t},\n\t\t] ),\n\n\t\tvertexShader: ShaderChunk.shadow_vert,\n\t\tfragmentShader: ShaderChunk.shadow_frag\n\n\t}\n\n};\n\nShaderLib.physical = {\n\n\tuniforms: mergeUniforms( [\n\t\tShaderLib.standard.uniforms,\n\t\t{\n\t\t\tclearcoat: { value: 0 },\n\t\t\tclearcoatMap: { value: null },\n\t\t\tclearcoatRoughness: { value: 0 },\n\t\t\tclearcoatRoughnessMap: { value: null },\n\t\t\tclearcoatNormalScale: { value: new Vector2( 1, 1 ) },\n\t\t\tclearcoatNormalMap: { value: null },\n\t\t\tsheen: { value: new Color( 0x000000 ) },\n\t\t\ttransparency: { value: 0 },\n\t\t}\n\t] ),\n\n\tvertexShader: ShaderChunk.meshphysical_vert,\n\tfragmentShader: ShaderChunk.meshphysical_frag\n\n};\n\n\nexport { ShaderLib };\n","/**\n * @author tschw\n * @author Mugen87 / https://github.com/Mugen87\n * @author mrdoob / http://mrdoob.com/\n *\n * Uniforms of a program.\n * Those form a tree structure with a special top-level container for the root,\n * which you get by calling 'new WebGLUniforms( gl, program )'.\n *\n *\n * Properties of inner nodes including the top-level container:\n *\n * .seq - array of nested uniforms\n * .map - nested uniforms by name\n *\n *\n * Methods of all nodes except the top-level container:\n *\n * .setValue( gl, value, [textures] )\n *\n * \t\tuploads a uniform value(s)\n * \tthe 'textures' parameter is needed for sampler uniforms\n *\n *\n * Static methods of the top-level container (textures factorizations):\n *\n * .upload( gl, seq, values, textures )\n *\n * \t\tsets uniforms in 'seq' to 'values[id].value'\n *\n * .seqWithValue( seq, values ) : filteredSeq\n *\n * \t\tfilters 'seq' entries with corresponding entry in values\n *\n *\n * Methods of the top-level container (textures factorizations):\n *\n * .setValue( gl, name, value, textures )\n *\n * \t\tsets uniform with name 'name' to 'value'\n *\n * .setOptional( gl, obj, prop )\n *\n * \t\tlike .set for an optional property of the object\n *\n */\n\nimport { CubeTexture } from '../../textures/CubeTexture.js';\nimport { Texture } from '../../textures/Texture.js';\nimport { DataTexture2DArray } from '../../textures/DataTexture2DArray.js';\nimport { DataTexture3D } from '../../textures/DataTexture3D.js';\n\nvar emptyTexture = new Texture();\nvar emptyTexture2dArray = new DataTexture2DArray();\nvar emptyTexture3d = new DataTexture3D();\nvar emptyCubeTexture = new CubeTexture();\n\n// --- Utilities ---\n\n// Array Caches (provide typed arrays for temporary by size)\n\nvar arrayCacheF32 = [];\nvar arrayCacheI32 = [];\n\n// Float32Array caches used for uploading Matrix uniforms\n\nvar mat4array = new Float32Array( 16 );\nvar mat3array = new Float32Array( 9 );\nvar mat2array = new Float32Array( 4 );\n\n// Flattening for arrays of vectors and matrices\n\nfunction flatten( array, nBlocks, blockSize ) {\n\n\tvar firstElem = array[ 0 ];\n\n\tif ( firstElem <= 0 || firstElem > 0 ) return array;\n\t// unoptimized: ! isNaN( firstElem )\n\t// see http://jacksondunstan.com/articles/983\n\n\tvar n = nBlocks * blockSize,\n\t\tr = arrayCacheF32[ n ];\n\n\tif ( r === undefined ) {\n\n\t\tr = new Float32Array( n );\n\t\tarrayCacheF32[ n ] = r;\n\n\t}\n\n\tif ( nBlocks !== 0 ) {\n\n\t\tfirstElem.toArray( r, 0 );\n\n\t\tfor ( var i = 1, offset = 0; i !== nBlocks; ++ i ) {\n\n\t\t\toffset += blockSize;\n\t\t\tarray[ i ].toArray( r, offset );\n\n\t\t}\n\n\t}\n\n\treturn r;\n\n}\n\nfunction arraysEqual( a, b ) {\n\n\tif ( a.length !== b.length ) return false;\n\n\tfor ( var i = 0, l = a.length; i < l; i ++ ) {\n\n\t\tif ( a[ i ] !== b[ i ] ) return false;\n\n\t}\n\n\treturn true;\n\n}\n\nfunction copyArray( a, b ) {\n\n\tfor ( var i = 0, l = b.length; i < l; i ++ ) {\n\n\t\ta[ i ] = b[ i ];\n\n\t}\n\n}\n\n// Texture unit allocation\n\nfunction allocTexUnits( textures, n ) {\n\n\tvar r = arrayCacheI32[ n ];\n\n\tif ( r === undefined ) {\n\n\t\tr = new Int32Array( n );\n\t\tarrayCacheI32[ n ] = r;\n\n\t}\n\n\tfor ( var i = 0; i !== n; ++ i )\n\t\tr[ i ] = textures.allocateTextureUnit();\n\n\treturn r;\n\n}\n\n// --- Setters ---\n\n// Note: Defining these methods externally, because they come in a bunch\n// and this way their names minify.\n\n// Single scalar\n\nfunction setValueV1f( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( cache[ 0 ] === v ) return;\n\n\tgl.uniform1f( this.addr, v );\n\n\tcache[ 0 ] = v;\n\n}\n\n// Single float vector (from flat array or THREE.VectorN)\n\nfunction setValueV2f( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( v.x !== undefined ) {\n\n\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) {\n\n\t\t\tgl.uniform2f( this.addr, v.x, v.y );\n\n\t\t\tcache[ 0 ] = v.x;\n\t\t\tcache[ 1 ] = v.y;\n\n\t\t}\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniform2fv( this.addr, v );\n\n\t\tcopyArray( cache, v );\n\n\t}\n\n}\n\nfunction setValueV3f( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( v.x !== undefined ) {\n\n\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) {\n\n\t\t\tgl.uniform3f( this.addr, v.x, v.y, v.z );\n\n\t\t\tcache[ 0 ] = v.x;\n\t\t\tcache[ 1 ] = v.y;\n\t\t\tcache[ 2 ] = v.z;\n\n\t\t}\n\n\t} else if ( v.r !== undefined ) {\n\n\t\tif ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) {\n\n\t\t\tgl.uniform3f( this.addr, v.r, v.g, v.b );\n\n\t\t\tcache[ 0 ] = v.r;\n\t\t\tcache[ 1 ] = v.g;\n\t\t\tcache[ 2 ] = v.b;\n\n\t\t}\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniform3fv( this.addr, v );\n\n\t\tcopyArray( cache, v );\n\n\t}\n\n}\n\nfunction setValueV4f( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( v.x !== undefined ) {\n\n\t\tif ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) {\n\n\t\t\tgl.uniform4f( this.addr, v.x, v.y, v.z, v.w );\n\n\t\t\tcache[ 0 ] = v.x;\n\t\t\tcache[ 1 ] = v.y;\n\t\t\tcache[ 2 ] = v.z;\n\t\t\tcache[ 3 ] = v.w;\n\n\t\t}\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniform4fv( this.addr, v );\n\n\t\tcopyArray( cache, v );\n\n\t}\n\n}\n\n// Single matrix (from flat array or MatrixN)\n\nfunction setValueM2( gl, v ) {\n\n\tvar cache = this.cache;\n\tvar elements = v.elements;\n\n\tif ( elements === undefined ) {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniformMatrix2fv( this.addr, false, v );\n\n\t\tcopyArray( cache, v );\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, elements ) ) return;\n\n\t\tmat2array.set( elements );\n\n\t\tgl.uniformMatrix2fv( this.addr, false, mat2array );\n\n\t\tcopyArray( cache, elements );\n\n\t}\n\n}\n\nfunction setValueM3( gl, v ) {\n\n\tvar cache = this.cache;\n\tvar elements = v.elements;\n\n\tif ( elements === undefined ) {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniformMatrix3fv( this.addr, false, v );\n\n\t\tcopyArray( cache, v );\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, elements ) ) return;\n\n\t\tmat3array.set( elements );\n\n\t\tgl.uniformMatrix3fv( this.addr, false, mat3array );\n\n\t\tcopyArray( cache, elements );\n\n\t}\n\n}\n\nfunction setValueM4( gl, v ) {\n\n\tvar cache = this.cache;\n\tvar elements = v.elements;\n\n\tif ( elements === undefined ) {\n\n\t\tif ( arraysEqual( cache, v ) ) return;\n\n\t\tgl.uniformMatrix4fv( this.addr, false, v );\n\n\t\tcopyArray( cache, v );\n\n\t} else {\n\n\t\tif ( arraysEqual( cache, elements ) ) return;\n\n\t\tmat4array.set( elements );\n\n\t\tgl.uniformMatrix4fv( this.addr, false, mat4array );\n\n\t\tcopyArray( cache, elements );\n\n\t}\n\n}\n\n// Single texture (2D / Cube)\n\nfunction setValueT1( gl, v, textures ) {\n\n\tvar cache = this.cache;\n\tvar unit = textures.allocateTextureUnit();\n\n\tif ( cache[ 0 ] !== unit ) {\n\n\t\tgl.uniform1i( this.addr, unit );\n\t\tcache[ 0 ] = unit;\n\n\t}\n\n\ttextures.safeSetTexture2D( v || emptyTexture, unit );\n\n}\n\nfunction setValueT2DArray1( gl, v, textures ) {\n\n\tvar cache = this.cache;\n\tvar unit = textures.allocateTextureUnit();\n\n\tif ( cache[ 0 ] !== unit ) {\n\n\t\tgl.uniform1i( this.addr, unit );\n\t\tcache[ 0 ] = unit;\n\n\t}\n\n\ttextures.setTexture2DArray( v || emptyTexture2dArray, unit );\n\n}\n\nfunction setValueT3D1( gl, v, textures ) {\n\n\tvar cache = this.cache;\n\tvar unit = textures.allocateTextureUnit();\n\n\tif ( cache[ 0 ] !== unit ) {\n\n\t\tgl.uniform1i( this.addr, unit );\n\t\tcache[ 0 ] = unit;\n\n\t}\n\n\ttextures.setTexture3D( v || emptyTexture3d, unit );\n\n}\n\nfunction setValueT6( gl, v, textures ) {\n\n\tvar cache = this.cache;\n\tvar unit = textures.allocateTextureUnit();\n\n\tif ( cache[ 0 ] !== unit ) {\n\n\t\tgl.uniform1i( this.addr, unit );\n\t\tcache[ 0 ] = unit;\n\n\t}\n\n\ttextures.safeSetTextureCube( v || emptyCubeTexture, unit );\n\n}\n\n// Integer / Boolean vectors or arrays thereof (always flat arrays)\n\nfunction setValueV1i( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( cache[ 0 ] === v ) return;\n\n\tgl.uniform1i( this.addr, v );\n\n\tcache[ 0 ] = v;\n\n}\n\nfunction setValueV2i( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( arraysEqual( cache, v ) ) return;\n\n\tgl.uniform2iv( this.addr, v );\n\n\tcopyArray( cache, v );\n\n}\n\nfunction setValueV3i( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( arraysEqual( cache, v ) ) return;\n\n\tgl.uniform3iv( this.addr, v );\n\n\tcopyArray( cache, v );\n\n}\n\nfunction setValueV4i( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( arraysEqual( cache, v ) ) return;\n\n\tgl.uniform4iv( this.addr, v );\n\n\tcopyArray( cache, v );\n\n}\n\n// uint\n\nfunction setValueV1ui( gl, v ) {\n\n\tvar cache = this.cache;\n\n\tif ( cache[ 0 ] === v ) return;\n\n\tgl.uniform1ui( this.addr, v );\n\n\tcache[ 0 ] = v;\n\n}\n\n// Helper to pick the right setter for the singular case\n\nfunction getSingularSetter( type ) {\n\n\tswitch ( type ) {\n\n\t\tcase 0x1406: return setValueV1f; // FLOAT\n\t\tcase 0x8b50: return setValueV2f; // _VEC2\n\t\tcase 0x8b51: return setValueV3f; // _VEC3\n\t\tcase 0x8b52: return setValueV4f; // _VEC4\n\n\t\tcase 0x8b5a: return setValueM2; // _MAT2\n\t\tcase 0x8b5b: return setValueM3; // _MAT3\n\t\tcase 0x8b5c: return setValueM4; // _MAT4\n\n\t\tcase 0x1404: case 0x8b56: return setValueV1i; // INT, BOOL\n\t\tcase 0x8b53: case 0x8b57: return setValueV2i; // _VEC2\n\t\tcase 0x8b54: case 0x8b58: return setValueV3i; // _VEC3\n\t\tcase 0x8b55: case 0x8b59: return setValueV4i; // _VEC4\n\n\t\tcase 0x1405: return setValueV1ui; // UINT\n\n\t\tcase 0x8b5e: // SAMPLER_2D\n\t\tcase 0x8d66: // SAMPLER_EXTERNAL_OES\n\t\tcase 0x8dca: // INT_SAMPLER_2D\n\t\tcase 0x8dd2: // UNSIGNED_INT_SAMPLER_2D\n\t\tcase 0x8b62: // SAMPLER_2D_SHADOW\n\t\t\treturn setValueT1;\n\n\t\tcase 0x8b5f: // SAMPLER_3D\n\t\tcase 0x8dcb: // INT_SAMPLER_3D\n\t\tcase 0x8dd3: // UNSIGNED_INT_SAMPLER_3D\n\t\t\treturn setValueT3D1;\n\n\t\tcase 0x8b60: // SAMPLER_CUBE\n\t\tcase 0x8dcc: // INT_SAMPLER_CUBE\n\t\tcase 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE\n\t\tcase 0x8dc5: // SAMPLER_CUBE_SHADOW\n\t\t\treturn setValueT6;\n\n\t\tcase 0x8dc1: // SAMPLER_2D_ARRAY\n\t\tcase 0x8dcf: // INT_SAMPLER_2D_ARRAY\n\t\tcase 0x8dd7: // UNSIGNED_INT_SAMPLER_2D_ARRAY\n\t\tcase 0x8dc4: // SAMPLER_2D_ARRAY_SHADOW\n\t\t\treturn setValueT2DArray1;\n\n\t}\n\n}\n\n// Array of scalars\nfunction setValueV1fArray( gl, v ) {\n\n\tgl.uniform1fv( this.addr, v );\n\n}\n\n// Integer / Boolean vectors or arrays thereof (always flat arrays)\nfunction setValueV1iArray( gl, v ) {\n\n\tgl.uniform1iv( this.addr, v );\n\n}\n\nfunction setValueV2iArray( gl, v ) {\n\n\tgl.uniform2iv( this.addr, v );\n\n}\n\nfunction setValueV3iArray( gl, v ) {\n\n\tgl.uniform3iv( this.addr, v );\n\n}\n\nfunction setValueV4iArray( gl, v ) {\n\n\tgl.uniform4iv( this.addr, v );\n\n}\n\n\n// Array of vectors (flat or from THREE classes)\n\nfunction setValueV2fArray( gl, v ) {\n\n\tvar data = flatten( v, this.size, 2 );\n\n\tgl.uniform2fv( this.addr, data );\n\n}\n\nfunction setValueV3fArray( gl, v ) {\n\n\tvar data = flatten( v, this.size, 3 );\n\n\tgl.uniform3fv( this.addr, data );\n\n}\n\nfunction setValueV4fArray( gl, v ) {\n\n\tvar data = flatten( v, this.size, 4 );\n\n\tgl.uniform4fv( this.addr, data );\n\n}\n\n// Array of matrices (flat or from THREE clases)\n\nfunction setValueM2Array( gl, v ) {\n\n\tvar data = flatten( v, this.size, 4 );\n\n\tgl.uniformMatrix2fv( this.addr, false, data );\n\n}\n\nfunction setValueM3Array( gl, v ) {\n\n\tvar data = flatten( v, this.size, 9 );\n\n\tgl.uniformMatrix3fv( this.addr, false, data );\n\n}\n\nfunction setValueM4Array( gl, v ) {\n\n\tvar data = flatten( v, this.size, 16 );\n\n\tgl.uniformMatrix4fv( this.addr, false, data );\n\n}\n\n// Array of textures (2D / Cube)\n\nfunction setValueT1Array( gl, v, textures ) {\n\n\tvar n = v.length;\n\n\tvar units = allocTexUnits( textures, n );\n\n\tgl.uniform1iv( this.addr, units );\n\n\tfor ( var i = 0; i !== n; ++ i ) {\n\n\t\ttextures.safeSetTexture2D( v[ i ] || emptyTexture, units[ i ] );\n\n\t}\n\n}\n\nfunction setValueT6Array( gl, v, textures ) {\n\n\tvar n = v.length;\n\n\tvar units = allocTexUnits( textures, n );\n\n\tgl.uniform1iv( this.addr, units );\n\n\tfor ( var i = 0; i !== n; ++ i ) {\n\n\t\ttextures.safeSetTextureCube( v[ i ] || emptyCubeTexture, units[ i ] );\n\n\t}\n\n}\n\n// Helper to pick the right setter for a pure (bottom-level) array\n\nfunction getPureArraySetter( type ) {\n\n\tswitch ( type ) {\n\n\t\tcase 0x1406: return setValueV1fArray; // FLOAT\n\t\tcase 0x8b50: return setValueV2fArray; // _VEC2\n\t\tcase 0x8b51: return setValueV3fArray; // _VEC3\n\t\tcase 0x8b52: return setValueV4fArray; // _VEC4\n\n\t\tcase 0x8b5a: return setValueM2Array; // _MAT2\n\t\tcase 0x8b5b: return setValueM3Array; // _MAT3\n\t\tcase 0x8b5c: return setValueM4Array; // _MAT4\n\n\t\tcase 0x1404: case 0x8b56: return setValueV1iArray; // INT, BOOL\n\t\tcase 0x8b53: case 0x8b57: return setValueV2iArray; // _VEC2\n\t\tcase 0x8b54: case 0x8b58: return setValueV3iArray; // _VEC3\n\t\tcase 0x8b55: case 0x8b59: return setValueV4iArray; // _VEC4\n\n\t\tcase 0x8b5e: // SAMPLER_2D\n\t\tcase 0x8d66: // SAMPLER_EXTERNAL_OES\n\t\tcase 0x8dca: // INT_SAMPLER_2D\n\t\tcase 0x8dd2: // UNSIGNED_INT_SAMPLER_2D\n\t\tcase 0x8b62: // SAMPLER_2D_SHADOW\n\t\t\treturn setValueT1Array;\n\n\t\tcase 0x8b60: // SAMPLER_CUBE\n\t\tcase 0x8dcc: // INT_SAMPLER_CUBE\n\t\tcase 0x8dd4: // UNSIGNED_INT_SAMPLER_CUBE\n\t\tcase 0x8dc5: // SAMPLER_CUBE_SHADOW\n\t\t\treturn setValueT6Array;\n\n\t}\n\n}\n\n// --- Uniform Classes ---\n\nfunction SingleUniform( id, activeInfo, addr ) {\n\n\tthis.id = id;\n\tthis.addr = addr;\n\tthis.cache = [];\n\tthis.setValue = getSingularSetter( activeInfo.type );\n\n\t// this.path = activeInfo.name; // DEBUG\n\n}\n\nfunction PureArrayUniform( id, activeInfo, addr ) {\n\n\tthis.id = id;\n\tthis.addr = addr;\n\tthis.cache = [];\n\tthis.size = activeInfo.size;\n\tthis.setValue = getPureArraySetter( activeInfo.type );\n\n\t// this.path = activeInfo.name; // DEBUG\n\n}\n\nPureArrayUniform.prototype.updateCache = function ( data ) {\n\n\tvar cache = this.cache;\n\n\tif ( data instanceof Float32Array && cache.length !== data.length ) {\n\n\t\tthis.cache = new Float32Array( data.length );\n\n\t}\n\n\tcopyArray( cache, data );\n\n};\n\nfunction StructuredUniform( id ) {\n\n\tthis.id = id;\n\n\tthis.seq = [];\n\tthis.map = {};\n\n}\n\nStructuredUniform.prototype.setValue = function ( gl, value, textures ) {\n\n\tvar seq = this.seq;\n\n\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\n\n\t\tvar u = seq[ i ];\n\t\tu.setValue( gl, value[ u.id ], textures );\n\n\t}\n\n};\n\n// --- Top-level ---\n\n// Parser - builds up the property tree from the path strings\n\nvar RePathPart = /([\\w\\d_]+)(\\])?(\\[|\\.)?/g;\n\n// extracts\n// \t- the identifier (member name or array index)\n// - followed by an optional right bracket (found when array index)\n// - followed by an optional left bracket or dot (type of subscript)\n//\n// Note: These portions can be read in a non-overlapping fashion and\n// allow straightforward parsing of the hierarchy that WebGL encodes\n// in the uniform names.\n\nfunction addUniform( container, uniformObject ) {\n\n\tcontainer.seq.push( uniformObject );\n\tcontainer.map[ uniformObject.id ] = uniformObject;\n\n}\n\nfunction parseUniform( activeInfo, addr, container ) {\n\n\tvar path = activeInfo.name,\n\t\tpathLength = path.length;\n\n\t// reset RegExp object, because of the early exit of a previous run\n\tRePathPart.lastIndex = 0;\n\n\twhile ( true ) {\n\n\t\tvar match = RePathPart.exec( path ),\n\t\t\tmatchEnd = RePathPart.lastIndex,\n\n\t\t\tid = match[ 1 ],\n\t\t\tidIsIndex = match[ 2 ] === ']',\n\t\t\tsubscript = match[ 3 ];\n\n\t\tif ( idIsIndex ) id = id | 0; // convert to integer\n\n\t\tif ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) {\n\n\t\t\t// bare name or \"pure\" bottom-level array \"[0]\" suffix\n\n\t\t\taddUniform( container, subscript === undefined ?\n\t\t\t\tnew SingleUniform( id, activeInfo, addr ) :\n\t\t\t\tnew PureArrayUniform( id, activeInfo, addr ) );\n\n\t\t\tbreak;\n\n\t\t} else {\n\n\t\t\t// step into inner node / create it in case it doesn't exist\n\n\t\t\tvar map = container.map, next = map[ id ];\n\n\t\t\tif ( next === undefined ) {\n\n\t\t\t\tnext = new StructuredUniform( id );\n\t\t\t\taddUniform( container, next );\n\n\t\t\t}\n\n\t\t\tcontainer = next;\n\n\t\t}\n\n\t}\n\n}\n\n// Root Container\n\nfunction WebGLUniforms( gl, program ) {\n\n\tthis.seq = [];\n\tthis.map = {};\n\n\tvar n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );\n\n\tfor ( var i = 0; i < n; ++ i ) {\n\n\t\tvar info = gl.getActiveUniform( program, i ),\n\t\t\taddr = gl.getUniformLocation( program, info.name );\n\n\t\tparseUniform( info, addr, this );\n\n\t}\n\n}\n\nWebGLUniforms.prototype.setValue = function ( gl, name, value, textures ) {\n\n\tvar u = this.map[ name ];\n\n\tif ( u !== undefined ) u.setValue( gl, value, textures );\n\n};\n\nWebGLUniforms.prototype.setOptional = function ( gl, object, name ) {\n\n\tvar v = object[ name ];\n\n\tif ( v !== undefined ) this.setValue( gl, name, v );\n\n};\n\n\n// Static interface\n\nWebGLUniforms.upload = function ( gl, seq, values, textures ) {\n\n\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\n\n\t\tvar u = seq[ i ],\n\t\t\tv = values[ u.id ];\n\n\t\tif ( v.needsUpdate !== false ) {\n\n\t\t\t// note: always updating when .needsUpdate is undefined\n\t\t\tu.setValue( gl, v.value, textures );\n\n\t\t}\n\n\t}\n\n};\n\nWebGLUniforms.seqWithValue = function ( seq, values ) {\n\n\tvar r = [];\n\n\tfor ( var i = 0, n = seq.length; i !== n; ++ i ) {\n\n\t\tvar u = seq[ i ];\n\t\tif ( u.id in values ) r.push( u );\n\n\t}\n\n\treturn r;\n\n};\n\nexport { WebGLUniforms };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction WebGLShader( gl, type, string ) {\n\n\tvar shader = gl.createShader( type );\n\n\tgl.shaderSource( shader, string );\n\tgl.compileShader( shader );\n\n\treturn shader;\n\n}\n\nexport { WebGLShader };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { WebGLUniforms } from './WebGLUniforms.js';\nimport { WebGLShader } from './WebGLShader.js';\nimport { ShaderChunk } from '../shaders/ShaderChunk.js';\nimport { NoToneMapping, AddOperation, MixOperation, MultiplyOperation, EquirectangularRefractionMapping, CubeRefractionMapping, SphericalReflectionMapping, EquirectangularReflectionMapping, CubeUVRefractionMapping, CubeUVReflectionMapping, CubeReflectionMapping, PCFSoftShadowMap, PCFShadowMap, VSMShadowMap, ACESFilmicToneMapping, CineonToneMapping, Uncharted2ToneMapping, ReinhardToneMapping, LinearToneMapping, GammaEncoding, RGBDEncoding, RGBM16Encoding, RGBM7Encoding, RGBEEncoding, sRGBEncoding, LinearEncoding, LogLuvEncoding } from '../../constants.js';\n\nvar programIdCount = 0;\n\nfunction addLineNumbers( string ) {\n\n\tvar lines = string.split( '\\n' );\n\n\tfor ( var i = 0; i < lines.length; i ++ ) {\n\n\t\tlines[ i ] = ( i + 1 ) + ': ' + lines[ i ];\n\n\t}\n\n\treturn lines.join( '\\n' );\n\n}\n\nfunction getEncodingComponents( encoding ) {\n\n\tswitch ( encoding ) {\n\n\t\tcase LinearEncoding:\n\t\t\treturn [ 'Linear', '( value )' ];\n\t\tcase sRGBEncoding:\n\t\t\treturn [ 'sRGB', '( value )' ];\n\t\tcase RGBEEncoding:\n\t\t\treturn [ 'RGBE', '( value )' ];\n\t\tcase RGBM7Encoding:\n\t\t\treturn [ 'RGBM', '( value, 7.0 )' ];\n\t\tcase RGBM16Encoding:\n\t\t\treturn [ 'RGBM', '( value, 16.0 )' ];\n\t\tcase RGBDEncoding:\n\t\t\treturn [ 'RGBD', '( value, 256.0 )' ];\n\t\tcase GammaEncoding:\n\t\t\treturn [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ];\n\t\tcase LogLuvEncoding:\n\t\t\treturn [ 'LogLuv', '( value )' ];\n\t\tdefault:\n\t\t\tthrow new Error( 'unsupported encoding: ' + encoding );\n\n\t}\n\n}\n\nfunction getShaderErrors( gl, shader, type ) {\n\n\tvar status = gl.getShaderParameter( shader, gl.COMPILE_STATUS );\n\tvar log = gl.getShaderInfoLog( shader ).trim();\n\n\tif ( status && log === '' ) return '';\n\n\t// --enable-privileged-webgl-extension\n\t// console.log( '**' + type + '**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) );\n\n\tvar source = gl.getShaderSource( shader );\n\n\treturn 'THREE.WebGLShader: gl.getShaderInfoLog() ' + type + '\\n' + log + addLineNumbers( source );\n\n}\n\nfunction getTexelDecodingFunction( functionName, encoding ) {\n\n\tvar components = getEncodingComponents( encoding );\n\treturn 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }';\n\n}\n\nfunction getTexelEncodingFunction( functionName, encoding ) {\n\n\tvar components = getEncodingComponents( encoding );\n\treturn 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }';\n\n}\n\nfunction getToneMappingFunction( functionName, toneMapping ) {\n\n\tvar toneMappingName;\n\n\tswitch ( toneMapping ) {\n\n\t\tcase LinearToneMapping:\n\t\t\ttoneMappingName = 'Linear';\n\t\t\tbreak;\n\n\t\tcase ReinhardToneMapping:\n\t\t\ttoneMappingName = 'Reinhard';\n\t\t\tbreak;\n\n\t\tcase Uncharted2ToneMapping:\n\t\t\ttoneMappingName = 'Uncharted2';\n\t\t\tbreak;\n\n\t\tcase CineonToneMapping:\n\t\t\ttoneMappingName = 'OptimizedCineon';\n\t\t\tbreak;\n\n\t\tcase ACESFilmicToneMapping:\n\t\t\ttoneMappingName = 'ACESFilmic';\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tthrow new Error( 'unsupported toneMapping: ' + toneMapping );\n\n\t}\n\n\treturn 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }';\n\n}\n\nfunction generateExtensions( parameters ) {\n\n\tvar chunks = [\n\t\t( parameters.extensionDerivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.tangentSpaceNormalMap || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID === 'physical' ) ? '#extension GL_OES_standard_derivatives : enable' : '',\n\t\t( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ? '#extension GL_EXT_frag_depth : enable' : '',\n\t\t( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ? '#extension GL_EXT_draw_buffers : require' : '',\n\t\t( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ? '#extension GL_EXT_shader_texture_lod : enable' : ''\n\t];\n\n\treturn chunks.filter( filterEmptyLine ).join( '\\n' );\n\n}\n\nfunction generateDefines( defines ) {\n\n\tvar chunks = [];\n\n\tfor ( var name in defines ) {\n\n\t\tvar value = defines[ name ];\n\n\t\tif ( value === false ) continue;\n\n\t\tchunks.push( '#define ' + name + ' ' + value );\n\n\t}\n\n\treturn chunks.join( '\\n' );\n\n}\n\nfunction fetchAttributeLocations( gl, program ) {\n\n\tvar attributes = {};\n\n\tvar n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );\n\n\tfor ( var i = 0; i < n; i ++ ) {\n\n\t\tvar info = gl.getActiveAttrib( program, i );\n\t\tvar name = info.name;\n\n\t\t// console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i );\n\n\t\tattributes[ name ] = gl.getAttribLocation( program, name );\n\n\t}\n\n\treturn attributes;\n\n}\n\nfunction filterEmptyLine( string ) {\n\n\treturn string !== '';\n\n}\n\nfunction replaceLightNums( string, parameters ) {\n\n\treturn string\n\t\t.replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )\n\t\t.replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights )\n\t\t.replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights )\n\t\t.replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights )\n\t\t.replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights )\n\t\t.replace( /NUM_DIR_LIGHT_SHADOWS/g, parameters.numDirLightShadows )\n\t\t.replace( /NUM_SPOT_LIGHT_SHADOWS/g, parameters.numSpotLightShadows )\n\t\t.replace( /NUM_POINT_LIGHT_SHADOWS/g, parameters.numPointLightShadows );\n\n}\n\nfunction replaceClippingPlaneNums( string, parameters ) {\n\n\treturn string\n\t\t.replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes )\n\t\t.replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );\n\n}\n\n// Resolve Includes\n\nvar includePattern = /^[ \\t]*#include +<([\\w\\d./]+)>/gm;\n\nfunction resolveIncludes( string ) {\n\n\treturn string.replace( includePattern, includeReplacer );\n\n}\n\nfunction includeReplacer( match, include ) {\n\n\tvar string = ShaderChunk[ include ];\n\n\tif ( string === undefined ) {\n\n\t\tthrow new Error( 'Can not resolve #include <' + include + '>' );\n\n\t}\n\n\treturn resolveIncludes( string );\n\n}\n\n// Unroll Loops\n\nvar deprecatedUnrollLoopPattern = /#pragma unroll_loop[\\s]+?for \\( int i \\= (\\d+)\\; i < (\\d+)\\; i \\+\\+ \\) \\{([\\s\\S]+?)(?=\\})\\}/g;\nvar unrollLoopPattern = /#pragma unroll_loop_start[\\s]+?for \\( int i \\= (\\d+)\\; i < (\\d+)\\; i \\+\\+ \\) \\{([\\s\\S]+?)(?=\\})\\}[\\s]+?#pragma unroll_loop_end/g;\n\nfunction unrollLoops( string ) {\n\n\treturn string\n\t\t.replace( unrollLoopPattern, loopReplacer )\n\t\t.replace( deprecatedUnrollLoopPattern, deprecatedLoopReplacer );\n\n}\n\nfunction deprecatedLoopReplacer( match, start, end, snippet ) {\n\n\tconsole.warn( 'WebGLProgram: #pragma unroll_loop shader syntax is deprecated. Please use #pragma unroll_loop_start syntax instead.' );\n\treturn loopReplacer( match, start, end, snippet );\n\n}\n\nfunction loopReplacer( match, start, end, snippet ) {\n\n\tvar string = '';\n\n\tfor ( var i = parseInt( start ); i < parseInt( end ); i ++ ) {\n\n\t\tstring += snippet\n\t\t\t.replace( /\\[ i \\]/g, '[ ' + i + ' ]' )\n\t\t\t.replace( /UNROLLED_LOOP_INDEX/g, i );\n\n\t}\n\n\treturn string;\n\n}\n\n//\n\nfunction generatePrecision( parameters ) {\n\n\tvar precisionstring = \"precision \" + parameters.precision + \" float;\\nprecision \" + parameters.precision + \" int;\";\n\n\tif ( parameters.precision === \"highp\" ) {\n\n\t\tprecisionstring += \"\\n#define HIGH_PRECISION\";\n\n\t} else if ( parameters.precision === \"mediump\" ) {\n\n\t\tprecisionstring += \"\\n#define MEDIUM_PRECISION\";\n\n\t} else if ( parameters.precision === \"lowp\" ) {\n\n\t\tprecisionstring += \"\\n#define LOW_PRECISION\";\n\n\t}\n\n\treturn precisionstring;\n\n}\n\nfunction generateShadowMapTypeDefine( parameters ) {\n\n\tvar shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC';\n\n\tif ( parameters.shadowMapType === PCFShadowMap ) {\n\n\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF';\n\n\t} else if ( parameters.shadowMapType === PCFSoftShadowMap ) {\n\n\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT';\n\n\t} else if ( parameters.shadowMapType === VSMShadowMap ) {\n\n\t\tshadowMapTypeDefine = 'SHADOWMAP_TYPE_VSM';\n\n\t}\n\n\treturn shadowMapTypeDefine;\n\n}\n\nfunction generateEnvMapTypeDefine( parameters ) {\n\n\tvar envMapTypeDefine = 'ENVMAP_TYPE_CUBE';\n\n\tif ( parameters.envMap ) {\n\n\t\tswitch ( parameters.envMapMode ) {\n\n\t\t\tcase CubeReflectionMapping:\n\t\t\tcase CubeRefractionMapping:\n\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_CUBE';\n\t\t\t\tbreak;\n\n\t\t\tcase CubeUVReflectionMapping:\n\t\t\tcase CubeUVRefractionMapping:\n\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV';\n\t\t\t\tbreak;\n\n\t\t\tcase EquirectangularReflectionMapping:\n\t\t\tcase EquirectangularRefractionMapping:\n\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_EQUIREC';\n\t\t\t\tbreak;\n\n\t\t\tcase SphericalReflectionMapping:\n\t\t\t\tenvMapTypeDefine = 'ENVMAP_TYPE_SPHERE';\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\treturn envMapTypeDefine;\n\n}\n\nfunction generateEnvMapModeDefine( parameters ) {\n\n\tvar envMapModeDefine = 'ENVMAP_MODE_REFLECTION';\n\n\tif ( parameters.envMap ) {\n\n\t\tswitch ( parameters.envMapMode ) {\n\n\t\t\tcase CubeRefractionMapping:\n\t\t\tcase EquirectangularRefractionMapping:\n\t\t\t\tenvMapModeDefine = 'ENVMAP_MODE_REFRACTION';\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\treturn envMapModeDefine;\n\n}\n\nfunction generateEnvMapBlendingDefine( parameters ) {\n\n\tvar envMapBlendingDefine = 'ENVMAP_BLENDING_NONE';\n\n\tif ( parameters.envMap ) {\n\n\t\tswitch ( parameters.combine ) {\n\n\t\t\tcase MultiplyOperation:\n\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY';\n\t\t\t\tbreak;\n\n\t\t\tcase MixOperation:\n\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_MIX';\n\t\t\t\tbreak;\n\n\t\t\tcase AddOperation:\n\t\t\t\tenvMapBlendingDefine = 'ENVMAP_BLENDING_ADD';\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\treturn envMapBlendingDefine;\n\n}\n\nfunction WebGLProgram( renderer, cacheKey, parameters ) {\n\n\tvar gl = renderer.getContext();\n\n\tvar defines = parameters.defines;\n\n\tvar vertexShader = parameters.vertexShader;\n\tvar fragmentShader = parameters.fragmentShader;\n\tvar shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );\n\tvar envMapTypeDefine = generateEnvMapTypeDefine( parameters );\n\tvar envMapModeDefine = generateEnvMapModeDefine( parameters );\n\tvar envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );\n\n\n\tvar gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0;\n\n\tvar customExtensions = parameters.isWebGL2 ? '' : generateExtensions( parameters );\n\n\tvar customDefines = generateDefines( defines );\n\n\tvar program = gl.createProgram();\n\n\tvar prefixVertex, prefixFragment;\n\n\tif ( parameters.isRawShaderMaterial ) {\n\n\t\tprefixVertex = [\n\n\t\t\tcustomDefines\n\n\t\t].filter( filterEmptyLine ).join( '\\n' );\n\n\t\tif ( prefixVertex.length > 0 ) {\n\n\t\t\tprefixVertex += '\\n';\n\n\t\t}\n\n\t\tprefixFragment = [\n\n\t\t\tcustomExtensions,\n\t\t\tcustomDefines\n\n\t\t].filter( filterEmptyLine ).join( '\\n' );\n\n\t\tif ( prefixFragment.length > 0 ) {\n\n\t\t\tprefixFragment += '\\n';\n\n\t\t}\n\n\t} else {\n\n\t\tprefixVertex = [\n\n\t\t\tgeneratePrecision( parameters ),\n\n\t\t\t'#define SHADER_NAME ' + parameters.shaderName,\n\n\t\t\tcustomDefines,\n\n\t\t\tparameters.instancing ? '#define USE_INSTANCING' : '',\n\t\t\tparameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '',\n\n\t\t\t'#define GAMMA_FACTOR ' + gammaFactorDefine,\n\n\t\t\t'#define MAX_BONES ' + parameters.maxBones,\n\t\t\t( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',\n\t\t\t( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',\n\n\t\t\tparameters.map ? '#define USE_MAP' : '',\n\t\t\tparameters.envMap ? '#define USE_ENVMAP' : '',\n\t\t\tparameters.envMap ? '#define ' + envMapModeDefine : '',\n\t\t\tparameters.lightMap ? '#define USE_LIGHTMAP' : '',\n\t\t\tparameters.aoMap ? '#define USE_AOMAP' : '',\n\t\t\tparameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',\n\t\t\tparameters.bumpMap ? '#define USE_BUMPMAP' : '',\n\t\t\tparameters.normalMap ? '#define USE_NORMALMAP' : '',\n\t\t\t( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',\n\t\t\t( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',\n\n\t\t\tparameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',\n\t\t\tparameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',\n\t\t\tparameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',\n\t\t\tparameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '',\n\t\t\tparameters.specularMap ? '#define USE_SPECULARMAP' : '',\n\t\t\tparameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',\n\t\t\tparameters.metalnessMap ? '#define USE_METALNESSMAP' : '',\n\t\t\tparameters.alphaMap ? '#define USE_ALPHAMAP' : '',\n\n\t\t\tparameters.vertexTangents ? '#define USE_TANGENT' : '',\n\t\t\tparameters.vertexColors ? '#define USE_COLOR' : '',\n\t\t\tparameters.vertexUvs ? '#define USE_UV' : '',\n\t\t\tparameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',\n\n\t\t\tparameters.flatShading ? '#define FLAT_SHADED' : '',\n\n\t\t\tparameters.skinning ? '#define USE_SKINNING' : '',\n\t\t\tparameters.useVertexTexture ? '#define BONE_TEXTURE' : '',\n\n\t\t\tparameters.morphTargets ? '#define USE_MORPHTARGETS' : '',\n\t\t\tparameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '',\n\t\t\tparameters.doubleSided ? '#define DOUBLE_SIDED' : '',\n\t\t\tparameters.flipSided ? '#define FLIP_SIDED' : '',\n\n\t\t\tparameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',\n\t\t\tparameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',\n\n\t\t\tparameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '',\n\n\t\t\tparameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',\n\t\t\t( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',\n\n\t\t\t'uniform mat4 modelMatrix;',\n\t\t\t'uniform mat4 modelViewMatrix;',\n\t\t\t'uniform mat4 projectionMatrix;',\n\t\t\t'uniform mat4 viewMatrix;',\n\t\t\t'uniform mat3 normalMatrix;',\n\t\t\t'uniform vec3 cameraPosition;',\n\t\t\t'uniform bool isOrthographic;',\n\n\t\t\t'#ifdef USE_INSTANCING',\n\n\t\t\t' attribute mat4 instanceMatrix;',\n\n\t\t\t'#endif',\n\n\t\t\t'attribute vec3 position;',\n\t\t\t'attribute vec3 normal;',\n\t\t\t'attribute vec2 uv;',\n\n\t\t\t'#ifdef USE_TANGENT',\n\n\t\t\t'\tattribute vec4 tangent;',\n\n\t\t\t'#endif',\n\n\t\t\t'#ifdef USE_COLOR',\n\n\t\t\t'\tattribute vec3 color;',\n\n\t\t\t'#endif',\n\n\t\t\t'#ifdef USE_MORPHTARGETS',\n\n\t\t\t'\tattribute vec3 morphTarget0;',\n\t\t\t'\tattribute vec3 morphTarget1;',\n\t\t\t'\tattribute vec3 morphTarget2;',\n\t\t\t'\tattribute vec3 morphTarget3;',\n\n\t\t\t'\t#ifdef USE_MORPHNORMALS',\n\n\t\t\t'\t\tattribute vec3 morphNormal0;',\n\t\t\t'\t\tattribute vec3 morphNormal1;',\n\t\t\t'\t\tattribute vec3 morphNormal2;',\n\t\t\t'\t\tattribute vec3 morphNormal3;',\n\n\t\t\t'\t#else',\n\n\t\t\t'\t\tattribute vec3 morphTarget4;',\n\t\t\t'\t\tattribute vec3 morphTarget5;',\n\t\t\t'\t\tattribute vec3 morphTarget6;',\n\t\t\t'\t\tattribute vec3 morphTarget7;',\n\n\t\t\t'\t#endif',\n\n\t\t\t'#endif',\n\n\t\t\t'#ifdef USE_SKINNING',\n\n\t\t\t'\tattribute vec4 skinIndex;',\n\t\t\t'\tattribute vec4 skinWeight;',\n\n\t\t\t'#endif',\n\n\t\t\t'\\n'\n\n\t\t].filter( filterEmptyLine ).join( '\\n' );\n\n\t\tprefixFragment = [\n\n\t\t\tcustomExtensions,\n\n\t\t\tgeneratePrecision( parameters ),\n\n\t\t\t'#define SHADER_NAME ' + parameters.shaderName,\n\n\t\t\tcustomDefines,\n\n\t\t\tparameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer\n\n\t\t\t'#define GAMMA_FACTOR ' + gammaFactorDefine,\n\n\t\t\t( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '',\n\t\t\t( parameters.useFog && parameters.fogExp2 ) ? '#define FOG_EXP2' : '',\n\n\t\t\tparameters.map ? '#define USE_MAP' : '',\n\t\t\tparameters.matcap ? '#define USE_MATCAP' : '',\n\t\t\tparameters.envMap ? '#define USE_ENVMAP' : '',\n\t\t\tparameters.envMap ? '#define ' + envMapTypeDefine : '',\n\t\t\tparameters.envMap ? '#define ' + envMapModeDefine : '',\n\t\t\tparameters.envMap ? '#define ' + envMapBlendingDefine : '',\n\t\t\tparameters.lightMap ? '#define USE_LIGHTMAP' : '',\n\t\t\tparameters.aoMap ? '#define USE_AOMAP' : '',\n\t\t\tparameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '',\n\t\t\tparameters.bumpMap ? '#define USE_BUMPMAP' : '',\n\t\t\tparameters.normalMap ? '#define USE_NORMALMAP' : '',\n\t\t\t( parameters.normalMap && parameters.objectSpaceNormalMap ) ? '#define OBJECTSPACE_NORMALMAP' : '',\n\t\t\t( parameters.normalMap && parameters.tangentSpaceNormalMap ) ? '#define TANGENTSPACE_NORMALMAP' : '',\n\t\t\tparameters.clearcoatMap ? '#define USE_CLEARCOATMAP' : '',\n\t\t\tparameters.clearcoatRoughnessMap ? '#define USE_CLEARCOAT_ROUGHNESSMAP' : '',\n\t\t\tparameters.clearcoatNormalMap ? '#define USE_CLEARCOAT_NORMALMAP' : '',\n\t\t\tparameters.specularMap ? '#define USE_SPECULARMAP' : '',\n\t\t\tparameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '',\n\t\t\tparameters.metalnessMap ? '#define USE_METALNESSMAP' : '',\n\t\t\tparameters.alphaMap ? '#define USE_ALPHAMAP' : '',\n\n\t\t\tparameters.sheen ? '#define USE_SHEEN' : '',\n\n\t\t\tparameters.vertexTangents ? '#define USE_TANGENT' : '',\n\t\t\tparameters.vertexColors ? '#define USE_COLOR' : '',\n\t\t\tparameters.vertexUvs ? '#define USE_UV' : '',\n\t\t\tparameters.uvsVertexOnly ? '#define UVS_VERTEX_ONLY' : '',\n\n\t\t\tparameters.gradientMap ? '#define USE_GRADIENTMAP' : '',\n\n\t\t\tparameters.flatShading ? '#define FLAT_SHADED' : '',\n\n\t\t\tparameters.doubleSided ? '#define DOUBLE_SIDED' : '',\n\t\t\tparameters.flipSided ? '#define FLIP_SIDED' : '',\n\n\t\t\tparameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '',\n\t\t\tparameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '',\n\n\t\t\tparameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '',\n\n\t\t\tparameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '',\n\n\t\t\tparameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',\n\t\t\t( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ? '#define USE_LOGDEPTHBUF_EXT' : '',\n\n\t\t\t( ( parameters.extensionShaderTextureLOD || parameters.envMap ) && parameters.rendererExtensionShaderTextureLod ) ? '#define TEXTURE_LOD_EXT' : '',\n\n\t\t\t'uniform mat4 viewMatrix;',\n\t\t\t'uniform vec3 cameraPosition;',\n\t\t\t'uniform bool isOrthographic;',\n\n\t\t\t( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',\n\t\t\t( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below\n\t\t\t( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',\n\n\t\t\tparameters.dithering ? '#define DITHERING' : '',\n\n\t\t\t( parameters.outputEncoding || parameters.mapEncoding || parameters.matcapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding || parameters.lightMapEncoding ) ?\n\t\t\t\tShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below\n\t\t\tparameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',\n\t\t\tparameters.matcapEncoding ? getTexelDecodingFunction( 'matcapTexelToLinear', parameters.matcapEncoding ) : '',\n\t\t\tparameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '',\n\t\t\tparameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '',\n\t\t\tparameters.lightMapEncoding ? getTexelDecodingFunction( 'lightMapTexelToLinear', parameters.lightMapEncoding ) : '',\n\t\t\tparameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '',\n\n\t\t\tparameters.depthPacking ? '#define DEPTH_PACKING ' + parameters.depthPacking : '',\n\n\t\t\t'\\n'\n\n\t\t].filter( filterEmptyLine ).join( '\\n' );\n\n\t}\n\n\tvertexShader = resolveIncludes( vertexShader );\n\tvertexShader = replaceLightNums( vertexShader, parameters );\n\tvertexShader = replaceClippingPlaneNums( vertexShader, parameters );\n\n\tfragmentShader = resolveIncludes( fragmentShader );\n\tfragmentShader = replaceLightNums( fragmentShader, parameters );\n\tfragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );\n\n\tvertexShader = unrollLoops( vertexShader );\n\tfragmentShader = unrollLoops( fragmentShader );\n\n\tif ( parameters.isWebGL2 && ! parameters.isRawShaderMaterial ) {\n\n\t\tvar isGLSL3ShaderMaterial = false;\n\n\t\tvar versionRegex = /^\\s*#version\\s+300\\s+es\\s*\\n/;\n\n\t\tif ( parameters.isShaderMaterial &&\n\t\t\tvertexShader.match( versionRegex ) !== null &&\n\t\t\tfragmentShader.match( versionRegex ) !== null ) {\n\n\t\t\tisGLSL3ShaderMaterial = true;\n\n\t\t\tvertexShader = vertexShader.replace( versionRegex, '' );\n\t\t\tfragmentShader = fragmentShader.replace( versionRegex, '' );\n\n\t\t}\n\n\t\t// GLSL 3.0 conversion\n\n\t\tprefixVertex = [\n\t\t\t'#version 300 es\\n',\n\t\t\t'#define attribute in',\n\t\t\t'#define varying out',\n\t\t\t'#define texture2D texture'\n\t\t].join( '\\n' ) + '\\n' + prefixVertex;\n\n\t\tprefixFragment = [\n\t\t\t'#version 300 es\\n',\n\t\t\t'#define varying in',\n\t\t\tisGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',\n\t\t\tisGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',\n\t\t\t'#define gl_FragDepthEXT gl_FragDepth',\n\t\t\t'#define texture2D texture',\n\t\t\t'#define textureCube texture',\n\t\t\t'#define texture2DProj textureProj',\n\t\t\t'#define texture2DLodEXT textureLod',\n\t\t\t'#define texture2DProjLodEXT textureProjLod',\n\t\t\t'#define textureCubeLodEXT textureLod',\n\t\t\t'#define texture2DGradEXT textureGrad',\n\t\t\t'#define texture2DProjGradEXT textureProjGrad',\n\t\t\t'#define textureCubeGradEXT textureGrad'\n\t\t].join( '\\n' ) + '\\n' + prefixFragment;\n\n\t}\n\n\tvar vertexGlsl = prefixVertex + vertexShader;\n\tvar fragmentGlsl = prefixFragment + fragmentShader;\n\n\t// console.log( '*VERTEX*', vertexGlsl );\n\t// console.log( '*FRAGMENT*', fragmentGlsl );\n\n\tvar glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );\n\tvar glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );\n\n\tgl.attachShader( program, glVertexShader );\n\tgl.attachShader( program, glFragmentShader );\n\n\t// Force a particular attribute to index 0.\n\n\tif ( parameters.index0AttributeName !== undefined ) {\n\n\t\tgl.bindAttribLocation( program, 0, parameters.index0AttributeName );\n\n\t} else if ( parameters.morphTargets === true ) {\n\n\t\t// programs with morphTargets displace position out of attribute 0\n\t\tgl.bindAttribLocation( program, 0, 'position' );\n\n\t}\n\n\tgl.linkProgram( program );\n\n\t// check for link errors\n\tif ( renderer.debug.checkShaderErrors ) {\n\n\t\tvar programLog = gl.getProgramInfoLog( program ).trim();\n\t\tvar vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();\n\t\tvar fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();\n\n\t\tvar runnable = true;\n\t\tvar haveDiagnostics = true;\n\n\t\tif ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) {\n\n\t\t\trunnable = false;\n\n\t\t\tvar vertexErrors = getShaderErrors( gl, glVertexShader, 'vertex' );\n\t\t\tvar fragmentErrors = getShaderErrors( gl, glFragmentShader, 'fragment' );\n\n\t\t\tconsole.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexErrors, fragmentErrors );\n\n\t\t} else if ( programLog !== '' ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog );\n\n\t\t} else if ( vertexLog === '' || fragmentLog === '' ) {\n\n\t\t\thaveDiagnostics = false;\n\n\t\t}\n\n\t\tif ( haveDiagnostics ) {\n\n\t\t\tthis.diagnostics = {\n\n\t\t\t\trunnable: runnable,\n\n\t\t\t\tprogramLog: programLog,\n\n\t\t\t\tvertexShader: {\n\n\t\t\t\t\tlog: vertexLog,\n\t\t\t\t\tprefix: prefixVertex\n\n\t\t\t\t},\n\n\t\t\t\tfragmentShader: {\n\n\t\t\t\t\tlog: fragmentLog,\n\t\t\t\t\tprefix: prefixFragment\n\n\t\t\t\t}\n\n\t\t\t};\n\n\t\t}\n\n\t}\n\n\t// Clean up\n\n\t// Crashes in iOS9 and iOS10. #18402\n\t// gl.detachShader( program, glVertexShader );\n\t// gl.detachShader( program, glFragmentShader );\n\n\tgl.deleteShader( glVertexShader );\n\tgl.deleteShader( glFragmentShader );\n\n\t// set up caching for uniform locations\n\n\tvar cachedUniforms;\n\n\tthis.getUniforms = function () {\n\n\t\tif ( cachedUniforms === undefined ) {\n\n\t\t\tcachedUniforms = new WebGLUniforms( gl, program );\n\n\t\t}\n\n\t\treturn cachedUniforms;\n\n\t};\n\n\t// set up caching for attribute locations\n\n\tvar cachedAttributes;\n\n\tthis.getAttributes = function () {\n\n\t\tif ( cachedAttributes === undefined ) {\n\n\t\t\tcachedAttributes = fetchAttributeLocations( gl, program );\n\n\t\t}\n\n\t\treturn cachedAttributes;\n\n\t};\n\n\t// free resource\n\n\tthis.destroy = function () {\n\n\t\tgl.deleteProgram( program );\n\t\tthis.program = undefined;\n\n\t};\n\n\t//\n\n\tthis.name = parameters.shaderName;\n\tthis.id = programIdCount ++;\n\tthis.cacheKey = cacheKey;\n\tthis.usedTimes = 1;\n\tthis.program = program;\n\tthis.vertexShader = glVertexShader;\n\tthis.fragmentShader = glFragmentShader;\n\n\treturn this;\n\n}\n\nexport { WebGLProgram };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { BackSide, DoubleSide, CubeUVRefractionMapping, CubeUVReflectionMapping, LinearEncoding, ObjectSpaceNormalMap, TangentSpaceNormalMap, NoToneMapping } from '../../constants.js';\nimport { WebGLProgram } from './WebGLProgram.js';\nimport { ShaderLib } from '../shaders/ShaderLib.js';\nimport { UniformsUtils } from '../shaders/UniformsUtils.js';\n\nfunction WebGLPrograms( renderer, extensions, capabilities ) {\n\n\tvar programs = [];\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\tvar logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;\n\tvar floatVertexTextures = capabilities.floatVertexTextures;\n\tvar precision = capabilities.precision;\n\tvar maxVertexUniforms = capabilities.maxVertexUniforms;\n\tvar vertexTextures = capabilities.vertexTextures;\n\n\tvar shaderIDs = {\n\t\tMeshDepthMaterial: 'depth',\n\t\tMeshDistanceMaterial: 'distanceRGBA',\n\t\tMeshNormalMaterial: 'normal',\n\t\tMeshBasicMaterial: 'basic',\n\t\tMeshLambertMaterial: 'lambert',\n\t\tMeshPhongMaterial: 'phong',\n\t\tMeshToonMaterial: 'toon',\n\t\tMeshStandardMaterial: 'physical',\n\t\tMeshPhysicalMaterial: 'physical',\n\t\tMeshMatcapMaterial: 'matcap',\n\t\tLineBasicMaterial: 'basic',\n\t\tLineDashedMaterial: 'dashed',\n\t\tPointsMaterial: 'points',\n\t\tShadowMaterial: 'shadow',\n\t\tSpriteMaterial: 'sprite'\n\t};\n\n\tvar parameterNames = [\n\t\t\"precision\", \"isWebGL2\", \"supportsVertexTextures\", \"outputEncoding\", \"instancing\",\n\t\t\"map\", \"mapEncoding\", \"matcap\", \"matcapEncoding\", \"envMap\", \"envMapMode\", \"envMapEncoding\", \"envMapCubeUV\",\n\t\t\"lightMap\", \"lightMapEncoding\", \"aoMap\", \"emissiveMap\", \"emissiveMapEncoding\", \"bumpMap\", \"normalMap\", \"objectSpaceNormalMap\", \"tangentSpaceNormalMap\", \"clearcoatMap\", \"clearcoatRoughnessMap\", \"clearcoatNormalMap\", \"displacementMap\", \"specularMap\",\n\t\t\"roughnessMap\", \"metalnessMap\", \"gradientMap\",\n\t\t\"alphaMap\", \"combine\", \"vertexColors\", \"vertexTangents\", \"vertexUvs\", \"uvsVertexOnly\", \"fog\", \"useFog\", \"fogExp2\",\n\t\t\"flatShading\", \"sizeAttenuation\", \"logarithmicDepthBuffer\", \"skinning\",\n\t\t\"maxBones\", \"useVertexTexture\", \"morphTargets\", \"morphNormals\",\n\t\t\"maxMorphTargets\", \"maxMorphNormals\", \"premultipliedAlpha\",\n\t\t\"numDirLights\", \"numPointLights\", \"numSpotLights\", \"numHemiLights\", \"numRectAreaLights\",\n\t\t\"numDirLightShadows\", \"numPointLightShadows\", \"numSpotLightShadows\",\n\t\t\"shadowMapEnabled\", \"shadowMapType\", \"toneMapping\", 'physicallyCorrectLights',\n\t\t\"alphaTest\", \"doubleSided\", \"flipSided\", \"numClippingPlanes\", \"numClipIntersection\", \"depthPacking\", \"dithering\",\n\t\t\"sheen\"\n\t];\n\n\tfunction getShaderObject( material, shaderID ) {\n\n\t\tvar shaderobject;\n\n\t\tif ( shaderID ) {\n\n\t\t\tvar shader = ShaderLib[ shaderID ];\n\n\t\t\tshaderobject = {\n\t\t\t\tname: material.type,\n\t\t\t\tuniforms: UniformsUtils.clone( shader.uniforms ),\n\t\t\t\tvertexShader: shader.vertexShader,\n\t\t\t\tfragmentShader: shader.fragmentShader\n\t\t\t};\n\n\t\t} else {\n\n\t\t\tshaderobject = {\n\t\t\t\tname: material.type,\n\t\t\t\tuniforms: material.uniforms,\n\t\t\t\tvertexShader: material.vertexShader,\n\t\t\t\tfragmentShader: material.fragmentShader\n\t\t\t};\n\n\t\t}\n\n\t\treturn shaderobject;\n\n\t}\n\n\tfunction allocateBones( object ) {\n\n\t\tvar skeleton = object.skeleton;\n\t\tvar bones = skeleton.bones;\n\n\t\tif ( floatVertexTextures ) {\n\n\t\t\treturn 1024;\n\n\t\t} else {\n\n\t\t\t// default for when object is not specified\n\t\t\t// ( for example when prebuilding shader to be used with multiple objects )\n\t\t\t//\n\t\t\t// - leave some extra space for other uniforms\n\t\t\t// - limit here is ANGLE's 254 max uniform vectors\n\t\t\t// (up to 54 should be safe)\n\n\t\t\tvar nVertexUniforms = maxVertexUniforms;\n\t\t\tvar nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );\n\n\t\t\tvar maxBones = Math.min( nVertexMatrices, bones.length );\n\n\t\t\tif ( maxBones < bones.length ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' );\n\t\t\t\treturn 0;\n\n\t\t\t}\n\n\t\t\treturn maxBones;\n\n\t\t}\n\n\t}\n\n\tfunction getTextureEncodingFromMap( map ) {\n\n\t\tvar encoding;\n\n\t\tif ( ! map ) {\n\n\t\t\tencoding = LinearEncoding;\n\n\t\t} else if ( map.isTexture ) {\n\n\t\t\tencoding = map.encoding;\n\n\t\t} else if ( map.isWebGLRenderTarget ) {\n\n\t\t\tconsole.warn( \"THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead.\" );\n\t\t\tencoding = map.texture.encoding;\n\n\t\t}\n\n\t\treturn encoding;\n\n\t}\n\n\tthis.getParameters = function ( material, lights, shadows, scene, nClipPlanes, nClipIntersection, object ) {\n\n\t\tvar fog = scene.fog;\n\t\tvar environment = material.isMeshStandardMaterial ? scene.environment : null;\n\n\t\tvar envMap = material.envMap || environment;\n\n\t\tvar shaderID = shaderIDs[ material.type ];\n\n\t\t// heuristics to create shader parameters according to lights in the scene\n\t\t// (not to blow over maxLights budget)\n\n\t\tvar maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0;\n\n\t\tif ( material.precision !== null ) {\n\n\t\t\tprecision = capabilities.getMaxPrecision( material.precision );\n\n\t\t\tif ( precision !== material.precision ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar shaderobject = getShaderObject( material, shaderID );\n\t\tmaterial.onBeforeCompile( shaderobject, renderer );\n\n\t\tvar currentRenderTarget = renderer.getRenderTarget();\n\n\t\tvar parameters = {\n\n\t\t\tisWebGL2: isWebGL2,\n\n\t\t\tshaderID: shaderID,\n\t\t\tshaderName: shaderobject.name,\n\n\t\t\tuniforms: shaderobject.uniforms,\n\t\t\tvertexShader: shaderobject.vertexShader,\n\t\t\tfragmentShader: shaderobject.fragmentShader,\n\t\t\tdefines: material.defines,\n\n\t\t\tisRawShaderMaterial: material.isRawShaderMaterial,\n\t\t\tisShaderMaterial: material.isShaderMaterial,\n\n\t\t\tprecision: precision,\n\n\t\t\tinstancing: object.isInstancedMesh === true,\n\n\t\t\tsupportsVertexTextures: vertexTextures,\n\t\t\toutputEncoding: ( currentRenderTarget !== null ) ? getTextureEncodingFromMap( currentRenderTarget.texture ) : renderer.outputEncoding,\n\t\t\tmap: !! material.map,\n\t\t\tmapEncoding: getTextureEncodingFromMap( material.map ),\n\t\t\tmatcap: !! material.matcap,\n\t\t\tmatcapEncoding: getTextureEncodingFromMap( material.matcap ),\n\t\t\tenvMap: !! envMap,\n\t\t\tenvMapMode: envMap && envMap.mapping,\n\t\t\tenvMapEncoding: getTextureEncodingFromMap( envMap ),\n\t\t\tenvMapCubeUV: ( !! envMap ) && ( ( envMap.mapping === CubeUVReflectionMapping ) || ( envMap.mapping === CubeUVRefractionMapping ) ),\n\t\t\tlightMap: !! material.lightMap,\n\t\t\tlightMapEncoding: getTextureEncodingFromMap( material.lightMap ),\n\t\t\taoMap: !! material.aoMap,\n\t\t\temissiveMap: !! material.emissiveMap,\n\t\t\temissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap ),\n\t\t\tbumpMap: !! material.bumpMap,\n\t\t\tnormalMap: !! material.normalMap,\n\t\t\tobjectSpaceNormalMap: material.normalMapType === ObjectSpaceNormalMap,\n\t\t\ttangentSpaceNormalMap: material.normalMapType === TangentSpaceNormalMap,\n\t\t\tclearcoatMap: !! material.clearcoatMap,\n\t\t\tclearcoatRoughnessMap: !! material.clearcoatRoughnessMap,\n\t\t\tclearcoatNormalMap: !! material.clearcoatNormalMap,\n\t\t\tdisplacementMap: !! material.displacementMap,\n\t\t\troughnessMap: !! material.roughnessMap,\n\t\t\tmetalnessMap: !! material.metalnessMap,\n\t\t\tspecularMap: !! material.specularMap,\n\t\t\talphaMap: !! material.alphaMap,\n\n\t\t\tgradientMap: !! material.gradientMap,\n\n\t\t\tsheen: !! material.sheen,\n\n\t\t\tcombine: material.combine,\n\n\t\t\tvertexTangents: ( material.normalMap && material.vertexTangents ),\n\t\t\tvertexColors: material.vertexColors,\n\t\t\tvertexUvs: !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatMap || !! material.clearcoatRoughnessMap || !! material.clearcoatNormalMap || !! material.displacementMap,\n\t\t\tuvsVertexOnly: ! ( !! material.map || !! material.bumpMap || !! material.normalMap || !! material.specularMap || !! material.alphaMap || !! material.emissiveMap || !! material.roughnessMap || !! material.metalnessMap || !! material.clearcoatNormalMap ) && !! material.displacementMap,\n\n\t\t\tfog: !! fog,\n\t\t\tuseFog: material.fog,\n\t\t\tfogExp2: ( fog && fog.isFogExp2 ),\n\n\t\t\tflatShading: material.flatShading,\n\n\t\t\tsizeAttenuation: material.sizeAttenuation,\n\t\t\tlogarithmicDepthBuffer: logarithmicDepthBuffer,\n\n\t\t\tskinning: material.skinning && maxBones > 0,\n\t\t\tmaxBones: maxBones,\n\t\t\tuseVertexTexture: floatVertexTextures,\n\n\t\t\tmorphTargets: material.morphTargets,\n\t\t\tmorphNormals: material.morphNormals,\n\t\t\tmaxMorphTargets: renderer.maxMorphTargets,\n\t\t\tmaxMorphNormals: renderer.maxMorphNormals,\n\n\t\t\tnumDirLights: lights.directional.length,\n\t\t\tnumPointLights: lights.point.length,\n\t\t\tnumSpotLights: lights.spot.length,\n\t\t\tnumRectAreaLights: lights.rectArea.length,\n\t\t\tnumHemiLights: lights.hemi.length,\n\n\t\t\tnumDirLightShadows: lights.directionalShadowMap.length,\n\t\t\tnumPointLightShadows: lights.pointShadowMap.length,\n\t\t\tnumSpotLightShadows: lights.spotShadowMap.length,\n\n\t\t\tnumClippingPlanes: nClipPlanes,\n\t\t\tnumClipIntersection: nClipIntersection,\n\n\t\t\tdithering: material.dithering,\n\n\t\t\tshadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,\n\t\t\tshadowMapType: renderer.shadowMap.type,\n\n\t\t\ttoneMapping: material.toneMapped ? renderer.toneMapping : NoToneMapping,\n\t\t\tphysicallyCorrectLights: renderer.physicallyCorrectLights,\n\n\t\t\tpremultipliedAlpha: material.premultipliedAlpha,\n\n\t\t\talphaTest: material.alphaTest,\n\t\t\tdoubleSided: material.side === DoubleSide,\n\t\t\tflipSided: material.side === BackSide,\n\n\t\t\tdepthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false,\n\n\t\t\tindex0AttributeName: material.index0AttributeName,\n\n\t\t\textensionDerivatives: material.extensions && material.extensions.derivatives,\n\t\t\textensionFragDepth: material.extensions && material.extensions.fragDepth,\n\t\t\textensionDrawBuffers: material.extensions && material.extensions.drawBuffers,\n\t\t\textensionShaderTextureLOD: material.extensions && material.extensions.shaderTextureLOD,\n\n\t\t\trendererExtensionFragDepth: isWebGL2 || extensions.get( 'EXT_frag_depth' ) !== null,\n\t\t\trendererExtensionDrawBuffers: isWebGL2 || extensions.get( 'WEBGL_draw_buffers' ) !== null,\n\t\t\trendererExtensionShaderTextureLod: isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) !== null,\n\n\t\t\tonBeforeCompile: material.onBeforeCompile\n\n\t\t};\n\n\t\treturn parameters;\n\n\t};\n\n\tthis.getProgramCacheKey = function ( parameters ) {\n\n\t\tvar array = [];\n\n\t\tif ( parameters.shaderID ) {\n\n\t\t\tarray.push( parameters.shaderID );\n\n\t\t} else {\n\n\t\t\tarray.push( parameters.fragmentShader );\n\t\t\tarray.push( parameters.vertexShader );\n\n\t\t}\n\n\t\tif ( parameters.defines !== undefined ) {\n\n\t\t\tfor ( var name in parameters.defines ) {\n\n\t\t\t\tarray.push( name );\n\t\t\t\tarray.push( parameters.defines[ name ] );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( parameters.isRawShaderMaterial === undefined ) {\n\n\t\t\tfor ( var i = 0; i < parameterNames.length; i ++ ) {\n\n\t\t\t\tarray.push( parameters[ parameterNames[ i ] ] );\n\n\t\t\t}\n\n\t\t\tarray.push( renderer.outputEncoding );\n\t\t\tarray.push( renderer.gammaFactor );\n\n\t\t}\n\n\t\tarray.push( parameters.onBeforeCompile.toString() );\n\n\t\treturn array.join();\n\n\t};\n\n\tthis.acquireProgram = function ( parameters, cacheKey ) {\n\n\t\tvar program;\n\n\t\t// Check if code has been already compiled\n\t\tfor ( var p = 0, pl = programs.length; p < pl; p ++ ) {\n\n\t\t\tvar preexistingProgram = programs[ p ];\n\n\t\t\tif ( preexistingProgram.cacheKey === cacheKey ) {\n\n\t\t\t\tprogram = preexistingProgram;\n\t\t\t\t++ program.usedTimes;\n\n\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( program === undefined ) {\n\n\t\t\tprogram = new WebGLProgram( renderer, cacheKey, parameters );\n\t\t\tprograms.push( program );\n\n\t\t}\n\n\t\treturn program;\n\n\t};\n\n\tthis.releaseProgram = function ( program ) {\n\n\t\tif ( -- program.usedTimes === 0 ) {\n\n\t\t\t// Remove from unordered set\n\t\t\tvar i = programs.indexOf( program );\n\t\t\tprograms[ i ] = programs[ programs.length - 1 ];\n\t\t\tprograms.pop();\n\n\t\t\t// Free WebGL resources\n\t\t\tprogram.destroy();\n\n\t\t}\n\n\t};\n\n\t// Exposed for resource monitoring & error feedback via renderer.info:\n\tthis.programs = programs;\n\n}\n\n\nexport { WebGLPrograms };\n","/**\n * @author fordacious / fordacious.github.io\n */\n\nfunction WebGLProperties() {\n\n\tvar properties = new WeakMap();\n\n\tfunction get( object ) {\n\n\t\tvar map = properties.get( object );\n\n\t\tif ( map === undefined ) {\n\n\t\t\tmap = {};\n\t\t\tproperties.set( object, map );\n\n\t\t}\n\n\t\treturn map;\n\n\t}\n\n\tfunction remove( object ) {\n\n\t\tproperties.delete( object );\n\n\t}\n\n\tfunction update( object, key, value ) {\n\n\t\tproperties.get( object )[ key ] = value;\n\n\t}\n\n\tfunction dispose() {\n\n\t\tproperties = new WeakMap();\n\n\t}\n\n\treturn {\n\t\tget: get,\n\t\tremove: remove,\n\t\tupdate: update,\n\t\tdispose: dispose\n\t};\n\n}\n\n\nexport { WebGLProperties };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction painterSortStable( a, b ) {\n\n\tif ( a.groupOrder !== b.groupOrder ) {\n\n\t\treturn a.groupOrder - b.groupOrder;\n\n\t} else if ( a.renderOrder !== b.renderOrder ) {\n\n\t\treturn a.renderOrder - b.renderOrder;\n\n\t} else if ( a.program !== b.program ) {\n\n\t\treturn a.program.id - b.program.id;\n\n\t} else if ( a.material.id !== b.material.id ) {\n\n\t\treturn a.material.id - b.material.id;\n\n\t} else if ( a.z !== b.z ) {\n\n\t\treturn a.z - b.z;\n\n\t} else {\n\n\t\treturn a.id - b.id;\n\n\t}\n\n}\n\nfunction reversePainterSortStable( a, b ) {\n\n\tif ( a.groupOrder !== b.groupOrder ) {\n\n\t\treturn a.groupOrder - b.groupOrder;\n\n\t} else if ( a.renderOrder !== b.renderOrder ) {\n\n\t\treturn a.renderOrder - b.renderOrder;\n\n\t} else if ( a.z !== b.z ) {\n\n\t\treturn b.z - a.z;\n\n\t} else {\n\n\t\treturn a.id - b.id;\n\n\t}\n\n}\n\n\nfunction WebGLRenderList() {\n\n\tvar renderItems = [];\n\tvar renderItemsIndex = 0;\n\n\tvar opaque = [];\n\tvar transparent = [];\n\n\tvar defaultProgram = { id: - 1 };\n\n\tfunction init() {\n\n\t\trenderItemsIndex = 0;\n\n\t\topaque.length = 0;\n\t\ttransparent.length = 0;\n\n\t}\n\n\tfunction getNextRenderItem( object, geometry, material, groupOrder, z, group ) {\n\n\t\tvar renderItem = renderItems[ renderItemsIndex ];\n\n\t\tif ( renderItem === undefined ) {\n\n\t\t\trenderItem = {\n\t\t\t\tid: object.id,\n\t\t\t\tobject: object,\n\t\t\t\tgeometry: geometry,\n\t\t\t\tmaterial: material,\n\t\t\t\tprogram: material.program || defaultProgram,\n\t\t\t\tgroupOrder: groupOrder,\n\t\t\t\trenderOrder: object.renderOrder,\n\t\t\t\tz: z,\n\t\t\t\tgroup: group\n\t\t\t};\n\n\t\t\trenderItems[ renderItemsIndex ] = renderItem;\n\n\t\t} else {\n\n\t\t\trenderItem.id = object.id;\n\t\t\trenderItem.object = object;\n\t\t\trenderItem.geometry = geometry;\n\t\t\trenderItem.material = material;\n\t\t\trenderItem.program = material.program || defaultProgram;\n\t\t\trenderItem.groupOrder = groupOrder;\n\t\t\trenderItem.renderOrder = object.renderOrder;\n\t\t\trenderItem.z = z;\n\t\t\trenderItem.group = group;\n\n\t\t}\n\n\t\trenderItemsIndex ++;\n\n\t\treturn renderItem;\n\n\t}\n\n\tfunction push( object, geometry, material, groupOrder, z, group ) {\n\n\t\tvar renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );\n\n\t\t( material.transparent === true ? transparent : opaque ).push( renderItem );\n\n\t}\n\n\tfunction unshift( object, geometry, material, groupOrder, z, group ) {\n\n\t\tvar renderItem = getNextRenderItem( object, geometry, material, groupOrder, z, group );\n\n\t\t( material.transparent === true ? transparent : opaque ).unshift( renderItem );\n\n\t}\n\n\tfunction sort( customOpaqueSort, customTransparentSort ) {\n\n\t\tif ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );\n\t\tif ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );\n\n\t}\n\n\tfunction finish() {\n\n\t\t// Clear references from inactive renderItems in the list\n\n\t\tfor ( var i = renderItemsIndex, il = renderItems.length; i < il; i ++ ) {\n\n\t\t\tvar renderItem = renderItems[ i ];\n\n\t\t\tif ( renderItem.id === null ) break;\n\n\t\t\trenderItem.id = null;\n\t\t\trenderItem.object = null;\n\t\t\trenderItem.geometry = null;\n\t\t\trenderItem.material = null;\n\t\t\trenderItem.program = null;\n\t\t\trenderItem.group = null;\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\topaque: opaque,\n\t\ttransparent: transparent,\n\n\t\tinit: init,\n\t\tpush: push,\n\t\tunshift: unshift,\n\t\tfinish: finish,\n\n\t\tsort: sort\n\t};\n\n}\n\nfunction WebGLRenderLists() {\n\n\tvar lists = new WeakMap();\n\n\tfunction onSceneDispose( event ) {\n\n\t\tvar scene = event.target;\n\n\t\tscene.removeEventListener( 'dispose', onSceneDispose );\n\n\t\tlists.delete( scene );\n\n\t}\n\n\tfunction get( scene, camera ) {\n\n\t\tvar cameras = lists.get( scene );\n\t\tvar list;\n\t\tif ( cameras === undefined ) {\n\n\t\t\tlist = new WebGLRenderList();\n\t\t\tlists.set( scene, new WeakMap() );\n\t\t\tlists.get( scene ).set( camera, list );\n\n\t\t\tscene.addEventListener( 'dispose', onSceneDispose );\n\n\t\t} else {\n\n\t\t\tlist = cameras.get( camera );\n\t\t\tif ( list === undefined ) {\n\n\t\t\t\tlist = new WebGLRenderList();\n\t\t\t\tcameras.set( camera, list );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn list;\n\n\t}\n\n\tfunction dispose() {\n\n\t\tlists = new WeakMap();\n\n\t}\n\n\treturn {\n\t\tget: get,\n\t\tdispose: dispose\n\t};\n\n}\n\n\nexport { WebGLRenderLists };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { Color } from '../../math/Color.js';\nimport { Matrix4 } from '../../math/Matrix4.js';\nimport { Vector2 } from '../../math/Vector2.js';\nimport { Vector3 } from '../../math/Vector3.js';\n\nfunction UniformsCache() {\n\n\tvar lights = {};\n\n\treturn {\n\n\t\tget: function ( light ) {\n\n\t\t\tif ( lights[ light.id ] !== undefined ) {\n\n\t\t\t\treturn lights[ light.id ];\n\n\t\t\t}\n\n\t\t\tvar uniforms;\n\n\t\t\tswitch ( light.type ) {\n\n\t\t\t\tcase 'DirectionalLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tdirection: new Vector3(),\n\t\t\t\t\t\tcolor: new Color()\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'SpotLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tposition: new Vector3(),\n\t\t\t\t\t\tdirection: new Vector3(),\n\t\t\t\t\t\tcolor: new Color(),\n\t\t\t\t\t\tdistance: 0,\n\t\t\t\t\t\tconeCos: 0,\n\t\t\t\t\t\tpenumbraCos: 0,\n\t\t\t\t\t\tdecay: 0\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'PointLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tposition: new Vector3(),\n\t\t\t\t\t\tcolor: new Color(),\n\t\t\t\t\t\tdistance: 0,\n\t\t\t\t\t\tdecay: 0\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'HemisphereLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tdirection: new Vector3(),\n\t\t\t\t\t\tskyColor: new Color(),\n\t\t\t\t\t\tgroundColor: new Color()\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'RectAreaLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tcolor: new Color(),\n\t\t\t\t\t\tposition: new Vector3(),\n\t\t\t\t\t\thalfWidth: new Vector3(),\n\t\t\t\t\t\thalfHeight: new Vector3()\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t}\n\n\t\t\tlights[ light.id ] = uniforms;\n\n\t\t\treturn uniforms;\n\n\t\t}\n\n\t};\n\n}\n\nfunction ShadowUniformsCache() {\n\n\tvar lights = {};\n\n\treturn {\n\n\t\tget: function ( light ) {\n\n\t\t\tif ( lights[ light.id ] !== undefined ) {\n\n\t\t\t\treturn lights[ light.id ];\n\n\t\t\t}\n\n\t\t\tvar uniforms;\n\n\t\t\tswitch ( light.type ) {\n\n\t\t\t\tcase 'DirectionalLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tshadowBias: 0,\n\t\t\t\t\t\tshadowRadius: 1,\n\t\t\t\t\t\tshadowMapSize: new Vector2()\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'SpotLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tshadowBias: 0,\n\t\t\t\t\t\tshadowRadius: 1,\n\t\t\t\t\t\tshadowMapSize: new Vector2()\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'PointLight':\n\t\t\t\t\tuniforms = {\n\t\t\t\t\t\tshadowBias: 0,\n\t\t\t\t\t\tshadowRadius: 1,\n\t\t\t\t\t\tshadowMapSize: new Vector2(),\n\t\t\t\t\t\tshadowCameraNear: 1,\n\t\t\t\t\t\tshadowCameraFar: 1000\n\t\t\t\t\t};\n\t\t\t\t\tbreak;\n\n\t\t\t\t// TODO (abelnation): set RectAreaLight shadow uniforms\n\n\t\t\t}\n\n\t\t\tlights[ light.id ] = uniforms;\n\n\t\t\treturn uniforms;\n\n\t\t}\n\n\t};\n\n}\n\n\n\nvar nextVersion = 0;\n\nfunction shadowCastingLightsFirst( lightA, lightB ) {\n\n\treturn ( lightB.castShadow ? 1 : 0 ) - ( lightA.castShadow ? 1 : 0 );\n\n}\n\nfunction WebGLLights() {\n\n\tvar cache = new UniformsCache();\n\n\tvar shadowCache = ShadowUniformsCache();\n\n\tvar state = {\n\n\t\tversion: 0,\n\n\t\thash: {\n\t\t\tdirectionalLength: - 1,\n\t\t\tpointLength: - 1,\n\t\t\tspotLength: - 1,\n\t\t\trectAreaLength: - 1,\n\t\t\themiLength: - 1,\n\n\t\t\tnumDirectionalShadows: - 1,\n\t\t\tnumPointShadows: - 1,\n\t\t\tnumSpotShadows: - 1\n\t\t},\n\n\t\tambient: [ 0, 0, 0 ],\n\t\tprobe: [],\n\t\tdirectional: [],\n\t\tdirectionalShadow: [],\n\t\tdirectionalShadowMap: [],\n\t\tdirectionalShadowMatrix: [],\n\t\tspot: [],\n\t\tspotShadow: [],\n\t\tspotShadowMap: [],\n\t\tspotShadowMatrix: [],\n\t\trectArea: [],\n\t\tpoint: [],\n\t\tpointShadow: [],\n\t\tpointShadowMap: [],\n\t\tpointShadowMatrix: [],\n\t\themi: []\n\n\t};\n\n\tfor ( var i = 0; i < 9; i ++ ) state.probe.push( new Vector3() );\n\n\tvar vector3 = new Vector3();\n\tvar matrix4 = new Matrix4();\n\tvar matrix42 = new Matrix4();\n\n\tfunction setup( lights, shadows, camera ) {\n\n\t\tvar r = 0, g = 0, b = 0;\n\n\t\tfor ( var i = 0; i < 9; i ++ ) state.probe[ i ].set( 0, 0, 0 );\n\n\t\tvar directionalLength = 0;\n\t\tvar pointLength = 0;\n\t\tvar spotLength = 0;\n\t\tvar rectAreaLength = 0;\n\t\tvar hemiLength = 0;\n\n\t\tvar numDirectionalShadows = 0;\n\t\tvar numPointShadows = 0;\n\t\tvar numSpotShadows = 0;\n\n\t\tvar viewMatrix = camera.matrixWorldInverse;\n\n\t\tlights.sort( shadowCastingLightsFirst );\n\n\t\tfor ( var i = 0, l = lights.length; i < l; i ++ ) {\n\n\t\t\tvar light = lights[ i ];\n\n\t\t\tvar color = light.color;\n\t\t\tvar intensity = light.intensity;\n\t\t\tvar distance = light.distance;\n\n\t\t\tvar shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;\n\n\t\t\tif ( light.isAmbientLight ) {\n\n\t\t\t\tr += color.r * intensity;\n\t\t\t\tg += color.g * intensity;\n\t\t\t\tb += color.b * intensity;\n\n\t\t\t} else if ( light.isLightProbe ) {\n\n\t\t\t\tfor ( var j = 0; j < 9; j ++ ) {\n\n\t\t\t\t\tstate.probe[ j ].addScaledVector( light.sh.coefficients[ j ], intensity );\n\n\t\t\t\t}\n\n\t\t\t} else if ( light.isDirectionalLight ) {\n\n\t\t\t\tvar uniforms = cache.get( light );\n\n\t\t\t\tuniforms.color.copy( light.color ).multiplyScalar( light.intensity );\n\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tvector3.setFromMatrixPosition( light.target.matrixWorld );\n\t\t\t\tuniforms.direction.sub( vector3 );\n\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\n\n\t\t\t\tif ( light.castShadow ) {\n\n\t\t\t\t\tvar shadow = light.shadow;\n\n\t\t\t\t\tvar shadowUniforms = shadowCache.get( light );\n\n\t\t\t\t\tshadowUniforms.shadowBias = shadow.bias;\n\t\t\t\t\tshadowUniforms.shadowRadius = shadow.radius;\n\t\t\t\t\tshadowUniforms.shadowMapSize = shadow.mapSize;\n\n\t\t\t\t\tstate.directionalShadow[ directionalLength ] = shadowUniforms;\n\t\t\t\t\tstate.directionalShadowMap[ directionalLength ] = shadowMap;\n\t\t\t\t\tstate.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;\n\n\t\t\t\t\tnumDirectionalShadows ++;\n\n\t\t\t\t}\n\n\t\t\t\tstate.directional[ directionalLength ] = uniforms;\n\n\t\t\t\tdirectionalLength ++;\n\n\t\t\t} else if ( light.isSpotLight ) {\n\n\t\t\t\tvar uniforms = cache.get( light );\n\n\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\n\n\t\t\t\tuniforms.color.copy( color ).multiplyScalar( intensity );\n\t\t\t\tuniforms.distance = distance;\n\n\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tvector3.setFromMatrixPosition( light.target.matrixWorld );\n\t\t\t\tuniforms.direction.sub( vector3 );\n\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\n\n\t\t\t\tuniforms.coneCos = Math.cos( light.angle );\n\t\t\t\tuniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) );\n\t\t\t\tuniforms.decay = light.decay;\n\n\t\t\t\tif ( light.castShadow ) {\n\n\t\t\t\t\tvar shadow = light.shadow;\n\n\t\t\t\t\tvar shadowUniforms = shadowCache.get( light );\n\n\t\t\t\t\tshadowUniforms.shadowBias = shadow.bias;\n\t\t\t\t\tshadowUniforms.shadowRadius = shadow.radius;\n\t\t\t\t\tshadowUniforms.shadowMapSize = shadow.mapSize;\n\n\t\t\t\t\tstate.spotShadow[ spotLength ] = shadowUniforms;\n\t\t\t\t\tstate.spotShadowMap[ spotLength ] = shadowMap;\n\t\t\t\t\tstate.spotShadowMatrix[ spotLength ] = light.shadow.matrix;\n\n\t\t\t\t\tnumSpotShadows ++;\n\n\t\t\t\t}\n\n\t\t\t\tstate.spot[ spotLength ] = uniforms;\n\n\t\t\t\tspotLength ++;\n\n\t\t\t} else if ( light.isRectAreaLight ) {\n\n\t\t\t\tvar uniforms = cache.get( light );\n\n\t\t\t\t// (a) intensity is the total visible light emitted\n\t\t\t\t//uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) );\n\n\t\t\t\t// (b) intensity is the brightness of the light\n\t\t\t\tuniforms.color.copy( color ).multiplyScalar( intensity );\n\n\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\n\n\t\t\t\t// extract local rotation of light to derive width/height half vectors\n\t\t\t\tmatrix42.identity();\n\t\t\t\tmatrix4.copy( light.matrixWorld );\n\t\t\t\tmatrix4.premultiply( viewMatrix );\n\t\t\t\tmatrix42.extractRotation( matrix4 );\n\n\t\t\t\tuniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );\n\t\t\t\tuniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );\n\n\t\t\t\tuniforms.halfWidth.applyMatrix4( matrix42 );\n\t\t\t\tuniforms.halfHeight.applyMatrix4( matrix42 );\n\n\t\t\t\t// TODO (abelnation): RectAreaLight distance?\n\t\t\t\t// uniforms.distance = distance;\n\n\t\t\t\tstate.rectArea[ rectAreaLength ] = uniforms;\n\n\t\t\t\trectAreaLength ++;\n\n\t\t\t} else if ( light.isPointLight ) {\n\n\t\t\t\tvar uniforms = cache.get( light );\n\n\t\t\t\tuniforms.position.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tuniforms.position.applyMatrix4( viewMatrix );\n\n\t\t\t\tuniforms.color.copy( light.color ).multiplyScalar( light.intensity );\n\t\t\t\tuniforms.distance = light.distance;\n\t\t\t\tuniforms.decay = light.decay;\n\n\t\t\t\tif ( light.castShadow ) {\n\n\t\t\t\t\tvar shadow = light.shadow;\n\n\t\t\t\t\tvar shadowUniforms = shadowCache.get( light );\n\n\t\t\t\t\tshadowUniforms.shadowBias = shadow.bias;\n\t\t\t\t\tshadowUniforms.shadowRadius = shadow.radius;\n\t\t\t\t\tshadowUniforms.shadowMapSize = shadow.mapSize;\n\t\t\t\t\tshadowUniforms.shadowCameraNear = shadow.camera.near;\n\t\t\t\t\tshadowUniforms.shadowCameraFar = shadow.camera.far;\n\n\t\t\t\t\tstate.pointShadow[ pointLength ] = shadowUniforms;\n\t\t\t\t\tstate.pointShadowMap[ pointLength ] = shadowMap;\n\t\t\t\t\tstate.pointShadowMatrix[ pointLength ] = light.shadow.matrix;\n\n\t\t\t\t\tnumPointShadows ++;\n\n\t\t\t\t}\n\n\t\t\t\tstate.point[ pointLength ] = uniforms;\n\n\t\t\t\tpointLength ++;\n\n\t\t\t} else if ( light.isHemisphereLight ) {\n\n\t\t\t\tvar uniforms = cache.get( light );\n\n\t\t\t\tuniforms.direction.setFromMatrixPosition( light.matrixWorld );\n\t\t\t\tuniforms.direction.transformDirection( viewMatrix );\n\t\t\t\tuniforms.direction.normalize();\n\n\t\t\t\tuniforms.skyColor.copy( light.color ).multiplyScalar( intensity );\n\t\t\t\tuniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );\n\n\t\t\t\tstate.hemi[ hemiLength ] = uniforms;\n\n\t\t\t\themiLength ++;\n\n\t\t\t}\n\n\t\t}\n\n\t\tstate.ambient[ 0 ] = r;\n\t\tstate.ambient[ 1 ] = g;\n\t\tstate.ambient[ 2 ] = b;\n\n\t\tvar hash = state.hash;\n\n\t\tif ( hash.directionalLength !== directionalLength ||\n\t\t\thash.pointLength !== pointLength ||\n\t\t\thash.spotLength !== spotLength ||\n\t\t\thash.rectAreaLength !== rectAreaLength ||\n\t\t\thash.hemiLength !== hemiLength ||\n\t\t\thash.numDirectionalShadows !== numDirectionalShadows ||\n\t\t\thash.numPointShadows !== numPointShadows ||\n\t\t\thash.numSpotShadows !== numSpotShadows ) {\n\n\t\t\tstate.directional.length = directionalLength;\n\t\t\tstate.spot.length = spotLength;\n\t\t\tstate.rectArea.length = rectAreaLength;\n\t\t\tstate.point.length = pointLength;\n\t\t\tstate.hemi.length = hemiLength;\n\n\t\t\tstate.directionalShadow.length = numDirectionalShadows;\n\t\t\tstate.directionalShadowMap.length = numDirectionalShadows;\n\t\t\tstate.pointShadow.length = numPointShadows;\n\t\t\tstate.pointShadowMap.length = numPointShadows;\n\t\t\tstate.spotShadow.length = numSpotShadows;\n\t\t\tstate.spotShadowMap.length = numSpotShadows;\n\t\t\tstate.directionalShadowMatrix.length = numDirectionalShadows;\n\t\t\tstate.pointShadowMatrix.length = numPointShadows;\n\t\t\tstate.spotShadowMatrix.length = numSpotShadows;\n\n\t\t\thash.directionalLength = directionalLength;\n\t\t\thash.pointLength = pointLength;\n\t\t\thash.spotLength = spotLength;\n\t\t\thash.rectAreaLength = rectAreaLength;\n\t\t\thash.hemiLength = hemiLength;\n\n\t\t\thash.numDirectionalShadows = numDirectionalShadows;\n\t\t\thash.numPointShadows = numPointShadows;\n\t\t\thash.numSpotShadows = numSpotShadows;\n\n\t\t\tstate.version = nextVersion ++;\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\tsetup: setup,\n\t\tstate: state\n\t};\n\n}\n\n\nexport { WebGLLights };\n","/**\n * @author Mugen87 / https://github.com/Mugen87\n */\n\nimport { WebGLLights } from './WebGLLights.js';\n\nfunction WebGLRenderState() {\n\n\tvar lights = new WebGLLights();\n\n\tvar lightsArray = [];\n\tvar shadowsArray = [];\n\n\tfunction init() {\n\n\t\tlightsArray.length = 0;\n\t\tshadowsArray.length = 0;\n\n\t}\n\n\tfunction pushLight( light ) {\n\n\t\tlightsArray.push( light );\n\n\t}\n\n\tfunction pushShadow( shadowLight ) {\n\n\t\tshadowsArray.push( shadowLight );\n\n\t}\n\n\tfunction setupLights( camera ) {\n\n\t\tlights.setup( lightsArray, shadowsArray, camera );\n\n\t}\n\n\tvar state = {\n\t\tlightsArray: lightsArray,\n\t\tshadowsArray: shadowsArray,\n\n\t\tlights: lights\n\t};\n\n\treturn {\n\t\tinit: init,\n\t\tstate: state,\n\t\tsetupLights: setupLights,\n\n\t\tpushLight: pushLight,\n\t\tpushShadow: pushShadow\n\t};\n\n}\n\nfunction WebGLRenderStates() {\n\n\tvar renderStates = new WeakMap();\n\n\tfunction onSceneDispose( event ) {\n\n\t\tvar scene = event.target;\n\n\t\tscene.removeEventListener( 'dispose', onSceneDispose );\n\n\t\trenderStates.delete( scene );\n\n\t}\n\n\tfunction get( scene, camera ) {\n\n\t\tvar renderState;\n\n\t\tif ( renderStates.has( scene ) === false ) {\n\n\t\t\trenderState = new WebGLRenderState();\n\t\t\trenderStates.set( scene, new WeakMap() );\n\t\t\trenderStates.get( scene ).set( camera, renderState );\n\n\t\t\tscene.addEventListener( 'dispose', onSceneDispose );\n\n\t\t} else {\n\n\t\t\tif ( renderStates.get( scene ).has( camera ) === false ) {\n\n\t\t\t\trenderState = new WebGLRenderState();\n\t\t\t\trenderStates.get( scene ).set( camera, renderState );\n\n\t\t\t} else {\n\n\t\t\t\trenderState = renderStates.get( scene ).get( camera );\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn renderState;\n\n\t}\n\n\tfunction dispose() {\n\n\t\trenderStates = new WeakMap();\n\n\t}\n\n\treturn {\n\t\tget: get,\n\t\tdispose: dispose\n\t};\n\n}\n\n\nexport { WebGLRenderStates };\n","import { Material } from './Material.js';\nimport { BasicDepthPacking } from '../constants.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author bhouston / https://clara.io\n * @author WestLangley / http://github.com/WestLangley\n *\n * parameters = {\n *\n * opacity: ,\n *\n * map: new THREE.Texture( ),\n *\n * alphaMap: new THREE.Texture( ),\n *\n * displacementMap: new THREE.Texture( ),\n * displacementScale: ,\n * displacementBias: ,\n *\n * wireframe: ,\n * wireframeLinewidth: \n * }\n */\n\nfunction MeshDepthMaterial( parameters ) {\n\n\tMaterial.call( this );\n\n\tthis.type = 'MeshDepthMaterial';\n\n\tthis.depthPacking = BasicDepthPacking;\n\n\tthis.skinning = false;\n\tthis.morphTargets = false;\n\n\tthis.map = null;\n\n\tthis.alphaMap = null;\n\n\tthis.displacementMap = null;\n\tthis.displacementScale = 1;\n\tthis.displacementBias = 0;\n\n\tthis.wireframe = false;\n\tthis.wireframeLinewidth = 1;\n\n\tthis.fog = false;\n\n\tthis.setValues( parameters );\n\n}\n\nMeshDepthMaterial.prototype = Object.create( Material.prototype );\nMeshDepthMaterial.prototype.constructor = MeshDepthMaterial;\n\nMeshDepthMaterial.prototype.isMeshDepthMaterial = true;\n\nMeshDepthMaterial.prototype.copy = function ( source ) {\n\n\tMaterial.prototype.copy.call( this, source );\n\n\tthis.depthPacking = source.depthPacking;\n\n\tthis.skinning = source.skinning;\n\tthis.morphTargets = source.morphTargets;\n\n\tthis.map = source.map;\n\n\tthis.alphaMap = source.alphaMap;\n\n\tthis.displacementMap = source.displacementMap;\n\tthis.displacementScale = source.displacementScale;\n\tthis.displacementBias = source.displacementBias;\n\n\tthis.wireframe = source.wireframe;\n\tthis.wireframeLinewidth = source.wireframeLinewidth;\n\n\treturn this;\n\n};\n\n\nexport { MeshDepthMaterial };\n","import { Material } from './Material.js';\nimport { Vector3 } from '../math/Vector3.js';\n\n/**\n * @author WestLangley / http://github.com/WestLangley\n *\n * parameters = {\n *\n * referencePosition: ,\n * nearDistance: ,\n * farDistance: ,\n *\n * skinning: ,\n * morphTargets: ,\n *\n * map: new THREE.Texture( ),\n *\n * alphaMap: new THREE.Texture( ),\n *\n * displacementMap: new THREE.Texture( ),\n * displacementScale: ,\n * displacementBias: \n *\n * }\n */\n\nfunction MeshDistanceMaterial( parameters ) {\n\n\tMaterial.call( this );\n\n\tthis.type = 'MeshDistanceMaterial';\n\n\tthis.referencePosition = new Vector3();\n\tthis.nearDistance = 1;\n\tthis.farDistance = 1000;\n\n\tthis.skinning = false;\n\tthis.morphTargets = false;\n\n\tthis.map = null;\n\n\tthis.alphaMap = null;\n\n\tthis.displacementMap = null;\n\tthis.displacementScale = 1;\n\tthis.displacementBias = 0;\n\n\tthis.fog = false;\n\n\tthis.setValues( parameters );\n\n}\n\nMeshDistanceMaterial.prototype = Object.create( Material.prototype );\nMeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial;\n\nMeshDistanceMaterial.prototype.isMeshDistanceMaterial = true;\n\nMeshDistanceMaterial.prototype.copy = function ( source ) {\n\n\tMaterial.prototype.copy.call( this, source );\n\n\tthis.referencePosition.copy( source.referencePosition );\n\tthis.nearDistance = source.nearDistance;\n\tthis.farDistance = source.farDistance;\n\n\tthis.skinning = source.skinning;\n\tthis.morphTargets = source.morphTargets;\n\n\tthis.map = source.map;\n\n\tthis.alphaMap = source.alphaMap;\n\n\tthis.displacementMap = source.displacementMap;\n\tthis.displacementScale = source.displacementScale;\n\tthis.displacementBias = source.displacementBias;\n\n\treturn this;\n\n};\n\n\nexport { MeshDistanceMaterial };\n","/**\n * @author alteredq / http://alteredqualia.com/\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { FrontSide, BackSide, DoubleSide, RGBAFormat, NearestFilter, LinearFilter, PCFShadowMap, VSMShadowMap, RGBADepthPacking, NoBlending } from '../../constants.js';\nimport { WebGLRenderTarget } from '../WebGLRenderTarget.js';\nimport { MeshDepthMaterial } from '../../materials/MeshDepthMaterial.js';\nimport { MeshDistanceMaterial } from '../../materials/MeshDistanceMaterial.js';\nimport { ShaderMaterial } from '../../materials/ShaderMaterial.js';\nimport { BufferAttribute } from '../../core/BufferAttribute.js';\nimport { BufferGeometry } from '../../core/BufferGeometry.js';\nimport { Mesh } from '../../objects/Mesh.js';\nimport { Vector4 } from '../../math/Vector4.js';\nimport { Vector2 } from '../../math/Vector2.js';\nimport { Frustum } from '../../math/Frustum.js';\n\nimport vsm_frag from '../shaders/ShaderLib/vsm_frag.glsl.js';\nimport vsm_vert from '../shaders/ShaderLib/vsm_vert.glsl.js';\n\nfunction WebGLShadowMap( _renderer, _objects, maxTextureSize ) {\n\n\tvar _frustum = new Frustum(),\n\n\t\t_shadowMapSize = new Vector2(),\n\t\t_viewportSize = new Vector2(),\n\n\t\t_viewport = new Vector4(),\n\n\t\t_depthMaterials = [],\n\t\t_distanceMaterials = [],\n\n\t\t_materialCache = {};\n\n\tvar shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide };\n\n\tvar shadowMaterialVertical = new ShaderMaterial( {\n\n\t\tdefines: {\n\t\t\tSAMPLE_RATE: 2.0 / 8.0,\n\t\t\tHALF_SAMPLE_RATE: 1.0 / 8.0\n\t\t},\n\n\t\tuniforms: {\n\t\t\tshadow_pass: { value: null },\n\t\t\tresolution: { value: new Vector2() },\n\t\t\tradius: { value: 4.0 }\n\t\t},\n\n\t\tvertexShader: vsm_vert,\n\n\t\tfragmentShader: vsm_frag\n\n\t} );\n\n\tvar shadowMaterialHorizonal = shadowMaterialVertical.clone();\n\tshadowMaterialHorizonal.defines.HORIZONAL_PASS = 1;\n\n\tvar fullScreenTri = new BufferGeometry();\n\tfullScreenTri.setAttribute(\n\t\t\"position\",\n\t\tnew BufferAttribute(\n\t\t\tnew Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),\n\t\t\t3\n\t\t)\n\t);\n\n\tvar fullScreenMesh = new Mesh( fullScreenTri, shadowMaterialVertical );\n\n\tvar scope = this;\n\n\tthis.enabled = false;\n\n\tthis.autoUpdate = true;\n\tthis.needsUpdate = false;\n\n\tthis.type = PCFShadowMap;\n\n\tthis.render = function ( lights, scene, camera ) {\n\n\t\tif ( scope.enabled === false ) return;\n\t\tif ( scope.autoUpdate === false && scope.needsUpdate === false ) return;\n\n\t\tif ( lights.length === 0 ) return;\n\n\t\tvar currentRenderTarget = _renderer.getRenderTarget();\n\t\tvar activeCubeFace = _renderer.getActiveCubeFace();\n\t\tvar activeMipmapLevel = _renderer.getActiveMipmapLevel();\n\n\t\tvar _state = _renderer.state;\n\n\t\t// Set GL state for depth map.\n\t\t_state.setBlending( NoBlending );\n\t\t_state.buffers.color.setClear( 1, 1, 1, 1 );\n\t\t_state.buffers.depth.setTest( true );\n\t\t_state.setScissorTest( false );\n\n\t\t// render depth map\n\n\t\tfor ( var i = 0, il = lights.length; i < il; i ++ ) {\n\n\t\t\tvar light = lights[ i ];\n\t\t\tvar shadow = light.shadow;\n\n\t\t\tif ( shadow === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' );\n\t\t\t\tcontinue;\n\n\t\t\t}\n\n\t\t\t_shadowMapSize.copy( shadow.mapSize );\n\n\t\t\tvar shadowFrameExtents = shadow.getFrameExtents();\n\n\t\t\t_shadowMapSize.multiply( shadowFrameExtents );\n\n\t\t\t_viewportSize.copy( shadow.mapSize );\n\n\t\t\tif ( _shadowMapSize.x > maxTextureSize || _shadowMapSize.y > maxTextureSize ) {\n\n\t\t\t\tif ( _shadowMapSize.x > maxTextureSize ) {\n\n\t\t\t\t\t_viewportSize.x = Math.floor( maxTextureSize / shadowFrameExtents.x );\n\t\t\t\t\t_shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;\n\t\t\t\t\tshadow.mapSize.x = _viewportSize.x;\n\n\t\t\t\t}\n\n\t\t\t\tif ( _shadowMapSize.y > maxTextureSize ) {\n\n\t\t\t\t\t_viewportSize.y = Math.floor( maxTextureSize / shadowFrameExtents.y );\n\t\t\t\t\t_shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;\n\t\t\t\t\tshadow.mapSize.y = _viewportSize.y;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( shadow.map === null && ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {\n\n\t\t\t\tvar pars = { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat };\n\n\t\t\t\tshadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\n\t\t\t\tshadow.map.texture.name = light.name + \".shadowMap\";\n\n\t\t\t\tshadow.mapPass = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\n\n\t\t\t\tshadow.camera.updateProjectionMatrix();\n\n\t\t\t}\n\n\t\t\tif ( shadow.map === null ) {\n\n\t\t\t\tvar pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat };\n\n\t\t\t\tshadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );\n\t\t\t\tshadow.map.texture.name = light.name + \".shadowMap\";\n\n\t\t\t\tshadow.camera.updateProjectionMatrix();\n\n\t\t\t}\n\n\t\t\t_renderer.setRenderTarget( shadow.map );\n\t\t\t_renderer.clear();\n\n\t\t\tvar viewportCount = shadow.getViewportCount();\n\n\t\t\tfor ( var vp = 0; vp < viewportCount; vp ++ ) {\n\n\t\t\t\tvar viewport = shadow.getViewport( vp );\n\n\t\t\t\t_viewport.set(\n\t\t\t\t\t_viewportSize.x * viewport.x,\n\t\t\t\t\t_viewportSize.y * viewport.y,\n\t\t\t\t\t_viewportSize.x * viewport.z,\n\t\t\t\t\t_viewportSize.y * viewport.w\n\t\t\t\t);\n\n\t\t\t\t_state.viewport( _viewport );\n\n\t\t\t\tshadow.updateMatrices( light, vp );\n\n\t\t\t\t_frustum = shadow.getFrustum();\n\n\t\t\t\trenderObject( scene, camera, shadow.camera, light, this.type );\n\n\t\t\t}\n\n\t\t\t// do blur pass for VSM\n\n\t\t\tif ( ! shadow.isPointLightShadow && this.type === VSMShadowMap ) {\n\n\t\t\t\tVSMPass( shadow, camera );\n\n\t\t\t}\n\n\t\t}\n\n\t\tscope.needsUpdate = false;\n\n\t\t_renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );\n\n\t};\n\n\tfunction VSMPass( shadow, camera ) {\n\n\t\tvar geometry = _objects.update( fullScreenMesh );\n\n\t\t// vertical pass\n\n\t\tshadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;\n\t\tshadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;\n\t\tshadowMaterialVertical.uniforms.radius.value = shadow.radius;\n\t\t_renderer.setRenderTarget( shadow.mapPass );\n\t\t_renderer.clear();\n\t\t_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialVertical, fullScreenMesh, null );\n\n\t\t// horizonal pass\n\n\t\tshadowMaterialHorizonal.uniforms.shadow_pass.value = shadow.mapPass.texture;\n\t\tshadowMaterialHorizonal.uniforms.resolution.value = shadow.mapSize;\n\t\tshadowMaterialHorizonal.uniforms.radius.value = shadow.radius;\n\t\t_renderer.setRenderTarget( shadow.map );\n\t\t_renderer.clear();\n\t\t_renderer.renderBufferDirect( camera, null, geometry, shadowMaterialHorizonal, fullScreenMesh, null );\n\n\t}\n\n\tfunction getDepthMaterialVariant( useMorphing, useSkinning, useInstancing ) {\n\n\t\tvar index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;\n\n\t\tvar material = _depthMaterials[ index ];\n\n\t\tif ( material === undefined ) {\n\n\t\t\tmaterial = new MeshDepthMaterial( {\n\n\t\t\t\tdepthPacking: RGBADepthPacking,\n\n\t\t\t\tmorphTargets: useMorphing,\n\t\t\t\tskinning: useSkinning\n\n\t\t\t} );\n\n\t\t\t_depthMaterials[ index ] = material;\n\n\t\t}\n\n\t\treturn material;\n\n\t}\n\n\tfunction getDistanceMaterialVariant( useMorphing, useSkinning, useInstancing ) {\n\n\t\tvar index = useMorphing << 0 | useSkinning << 1 | useInstancing << 2;\n\n\t\tvar material = _distanceMaterials[ index ];\n\n\t\tif ( material === undefined ) {\n\n\t\t\tmaterial = new MeshDistanceMaterial( {\n\n\t\t\t\tmorphTargets: useMorphing,\n\t\t\t\tskinning: useSkinning\n\n\t\t\t} );\n\n\t\t\t_distanceMaterials[ index ] = material;\n\n\t\t}\n\n\t\treturn material;\n\n\t}\n\n\tfunction getDepthMaterial( object, geometry, material, light, shadowCameraNear, shadowCameraFar, type ) {\n\n\t\tvar result = null;\n\n\t\tvar getMaterialVariant = getDepthMaterialVariant;\n\t\tvar customMaterial = object.customDepthMaterial;\n\n\t\tif ( light.isPointLight === true ) {\n\n\t\t\tgetMaterialVariant = getDistanceMaterialVariant;\n\t\t\tcustomMaterial = object.customDistanceMaterial;\n\n\t\t}\n\n\t\tif ( customMaterial === undefined ) {\n\n\t\t\tvar useMorphing = false;\n\n\t\t\tif ( material.morphTargets === true ) {\n\n\t\t\t\tuseMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0;\n\n\t\t\t}\n\n\t\t\tvar useSkinning = false;\n\n\t\t\tif ( object.isSkinnedMesh === true ) {\n\n\t\t\t\tif ( material.skinning === true ) {\n\n\t\t\t\t\tuseSkinning = true;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar useInstancing = object.isInstancedMesh === true;\n\n\t\t\tresult = getMaterialVariant( useMorphing, useSkinning, useInstancing );\n\n\t\t} else {\n\n\t\t\tresult = customMaterial;\n\n\t\t}\n\n\t\tif ( _renderer.localClippingEnabled &&\n\t\t\t\tmaterial.clipShadows === true &&\n\t\t\t\tmaterial.clippingPlanes.length !== 0 ) {\n\n\t\t\t// in this case we need a unique material instance reflecting the\n\t\t\t// appropriate state\n\n\t\t\tvar keyA = result.uuid, keyB = material.uuid;\n\n\t\t\tvar materialsForVariant = _materialCache[ keyA ];\n\n\t\t\tif ( materialsForVariant === undefined ) {\n\n\t\t\t\tmaterialsForVariant = {};\n\t\t\t\t_materialCache[ keyA ] = materialsForVariant;\n\n\t\t\t}\n\n\t\t\tvar cachedMaterial = materialsForVariant[ keyB ];\n\n\t\t\tif ( cachedMaterial === undefined ) {\n\n\t\t\t\tcachedMaterial = result.clone();\n\t\t\t\tmaterialsForVariant[ keyB ] = cachedMaterial;\n\n\t\t\t}\n\n\t\t\tresult = cachedMaterial;\n\n\t\t}\n\n\t\tresult.visible = material.visible;\n\t\tresult.wireframe = material.wireframe;\n\n\t\tif ( type === VSMShadowMap ) {\n\n\t\t\tresult.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;\n\n\t\t} else {\n\n\t\t\tresult.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];\n\n\t\t}\n\n\t\tresult.clipShadows = material.clipShadows;\n\t\tresult.clippingPlanes = material.clippingPlanes;\n\t\tresult.clipIntersection = material.clipIntersection;\n\n\t\tresult.wireframeLinewidth = material.wireframeLinewidth;\n\t\tresult.linewidth = material.linewidth;\n\n\t\tif ( light.isPointLight === true && result.isMeshDistanceMaterial === true ) {\n\n\t\t\tresult.referencePosition.setFromMatrixPosition( light.matrixWorld );\n\t\t\tresult.nearDistance = shadowCameraNear;\n\t\t\tresult.farDistance = shadowCameraFar;\n\n\t\t}\n\n\t\treturn result;\n\n\t}\n\n\tfunction renderObject( object, camera, shadowCamera, light, type ) {\n\n\t\tif ( object.visible === false ) return;\n\n\t\tvar visible = object.layers.test( camera.layers );\n\n\t\tif ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {\n\n\t\t\tif ( ( object.castShadow || ( object.receiveShadow && type === VSMShadowMap ) ) && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {\n\n\t\t\t\tobject.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );\n\n\t\t\t\tvar geometry = _objects.update( object );\n\t\t\t\tvar material = object.material;\n\n\t\t\t\tif ( Array.isArray( material ) ) {\n\n\t\t\t\t\tvar groups = geometry.groups;\n\n\t\t\t\t\tfor ( var k = 0, kl = groups.length; k < kl; k ++ ) {\n\n\t\t\t\t\t\tvar group = groups[ k ];\n\t\t\t\t\t\tvar groupMaterial = material[ group.materialIndex ];\n\n\t\t\t\t\t\tif ( groupMaterial && groupMaterial.visible ) {\n\n\t\t\t\t\t\t\tvar depthMaterial = getDepthMaterial( object, geometry, groupMaterial, light, shadowCamera.near, shadowCamera.far, type );\n\n\t\t\t\t\t\t\t_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( material.visible ) {\n\n\t\t\t\t\tvar depthMaterial = getDepthMaterial( object, geometry, material, light, shadowCamera.near, shadowCamera.far, type );\n\n\t\t\t\t\t_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar children = object.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\trenderObject( children[ i ], camera, shadowCamera, light, type );\n\n\t\t}\n\n\t}\n\n}\n\n\nexport { WebGLShadowMap };\n","export default /* glsl */`\n\nvoid main() {\n\n\tgl_Position = vec4( position, 1.0 );\n\n}\n\n`;\n","export default /* glsl */`\nuniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n\n#include \n\nvoid main() {\n\n float mean = 0.0;\n float squared_mean = 0.0;\n\n\t// This seems totally useless but it's a crazy work around for a Adreno compiler bug\n\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy ) / resolution ) );\n\n for ( float i = -1.0; i < 1.0 ; i += SAMPLE_RATE) {\n\n #ifdef HORIZONAL_PASS\n\n vec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( i, 0.0 ) * radius ) / resolution ) );\n mean += distribution.x;\n squared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\n #else\n\n float depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, i ) * radius ) / resolution ) );\n mean += depth;\n squared_mean += depth * depth;\n\n #endif\n\n }\n\n mean = mean * HALF_SAMPLE_RATE;\n squared_mean = squared_mean * HALF_SAMPLE_RATE;\n\n float std_dev = sqrt( squared_mean - mean * mean );\n\n gl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n\n}\n`;\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceFront, CullFaceBack, CullFaceNone, DoubleSide, BackSide, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NoBlending, NormalBlending, AddEquation, SubtractEquation, ReverseSubtractEquation, MinEquation, MaxEquation, ZeroFactor, OneFactor, SrcColorFactor, SrcAlphaFactor, SrcAlphaSaturateFactor, DstColorFactor, DstAlphaFactor, OneMinusSrcColorFactor, OneMinusSrcAlphaFactor, OneMinusDstColorFactor, OneMinusDstAlphaFactor } from '../../constants.js';\nimport { Vector4 } from '../../math/Vector4.js';\n\nfunction WebGLState( gl, extensions, capabilities ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\n\tfunction ColorBuffer() {\n\n\t\tvar locked = false;\n\n\t\tvar color = new Vector4();\n\t\tvar currentColorMask = null;\n\t\tvar currentColorClear = new Vector4( 0, 0, 0, 0 );\n\n\t\treturn {\n\n\t\t\tsetMask: function ( colorMask ) {\n\n\t\t\t\tif ( currentColorMask !== colorMask && ! locked ) {\n\n\t\t\t\t\tgl.colorMask( colorMask, colorMask, colorMask, colorMask );\n\t\t\t\t\tcurrentColorMask = colorMask;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetLocked: function ( lock ) {\n\n\t\t\t\tlocked = lock;\n\n\t\t\t},\n\n\t\t\tsetClear: function ( r, g, b, a, premultipliedAlpha ) {\n\n\t\t\t\tif ( premultipliedAlpha === true ) {\n\n\t\t\t\t\tr *= a; g *= a; b *= a;\n\n\t\t\t\t}\n\n\t\t\t\tcolor.set( r, g, b, a );\n\n\t\t\t\tif ( currentColorClear.equals( color ) === false ) {\n\n\t\t\t\t\tgl.clearColor( r, g, b, a );\n\t\t\t\t\tcurrentColorClear.copy( color );\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\treset: function () {\n\n\t\t\t\tlocked = false;\n\n\t\t\t\tcurrentColorMask = null;\n\t\t\t\tcurrentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state\n\n\t\t\t}\n\n\t\t};\n\n\t}\n\n\tfunction DepthBuffer() {\n\n\t\tvar locked = false;\n\n\t\tvar currentDepthMask = null;\n\t\tvar currentDepthFunc = null;\n\t\tvar currentDepthClear = null;\n\n\t\treturn {\n\n\t\t\tsetTest: function ( depthTest ) {\n\n\t\t\t\tif ( depthTest ) {\n\n\t\t\t\t\tenable( gl.DEPTH_TEST );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tdisable( gl.DEPTH_TEST );\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetMask: function ( depthMask ) {\n\n\t\t\t\tif ( currentDepthMask !== depthMask && ! locked ) {\n\n\t\t\t\t\tgl.depthMask( depthMask );\n\t\t\t\t\tcurrentDepthMask = depthMask;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetFunc: function ( depthFunc ) {\n\n\t\t\t\tif ( currentDepthFunc !== depthFunc ) {\n\n\t\t\t\t\tif ( depthFunc ) {\n\n\t\t\t\t\t\tswitch ( depthFunc ) {\n\n\t\t\t\t\t\t\tcase NeverDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.NEVER );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase AlwaysDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.ALWAYS );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase LessDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.LESS );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase LessEqualDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.LEQUAL );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase EqualDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.EQUAL );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase GreaterEqualDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.GEQUAL );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase GreaterDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.GREATER );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase NotEqualDepth:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.NOTEQUAL );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\n\t\t\t\t\t\t\t\tgl.depthFunc( gl.LEQUAL );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tgl.depthFunc( gl.LEQUAL );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tcurrentDepthFunc = depthFunc;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetLocked: function ( lock ) {\n\n\t\t\t\tlocked = lock;\n\n\t\t\t},\n\n\t\t\tsetClear: function ( depth ) {\n\n\t\t\t\tif ( currentDepthClear !== depth ) {\n\n\t\t\t\t\tgl.clearDepth( depth );\n\t\t\t\t\tcurrentDepthClear = depth;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\treset: function () {\n\n\t\t\t\tlocked = false;\n\n\t\t\t\tcurrentDepthMask = null;\n\t\t\t\tcurrentDepthFunc = null;\n\t\t\t\tcurrentDepthClear = null;\n\n\t\t\t}\n\n\t\t};\n\n\t}\n\n\tfunction StencilBuffer() {\n\n\t\tvar locked = false;\n\n\t\tvar currentStencilMask = null;\n\t\tvar currentStencilFunc = null;\n\t\tvar currentStencilRef = null;\n\t\tvar currentStencilFuncMask = null;\n\t\tvar currentStencilFail = null;\n\t\tvar currentStencilZFail = null;\n\t\tvar currentStencilZPass = null;\n\t\tvar currentStencilClear = null;\n\n\t\treturn {\n\n\t\t\tsetTest: function ( stencilTest ) {\n\n\t\t\t\tif ( ! locked ) {\n\n\t\t\t\t\tif ( stencilTest ) {\n\n\t\t\t\t\t\tenable( gl.STENCIL_TEST );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tdisable( gl.STENCIL_TEST );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetMask: function ( stencilMask ) {\n\n\t\t\t\tif ( currentStencilMask !== stencilMask && ! locked ) {\n\n\t\t\t\t\tgl.stencilMask( stencilMask );\n\t\t\t\t\tcurrentStencilMask = stencilMask;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetFunc: function ( stencilFunc, stencilRef, stencilMask ) {\n\n\t\t\t\tif ( currentStencilFunc !== stencilFunc ||\n\t\t\t\t currentStencilRef \t!== stencilRef \t||\n\t\t\t\t currentStencilFuncMask !== stencilMask ) {\n\n\t\t\t\t\tgl.stencilFunc( stencilFunc, stencilRef, stencilMask );\n\n\t\t\t\t\tcurrentStencilFunc = stencilFunc;\n\t\t\t\t\tcurrentStencilRef = stencilRef;\n\t\t\t\t\tcurrentStencilFuncMask = stencilMask;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetOp: function ( stencilFail, stencilZFail, stencilZPass ) {\n\n\t\t\t\tif ( currentStencilFail\t !== stencilFail \t||\n\t\t\t\t currentStencilZFail !== stencilZFail ||\n\t\t\t\t currentStencilZPass !== stencilZPass ) {\n\n\t\t\t\t\tgl.stencilOp( stencilFail, stencilZFail, stencilZPass );\n\n\t\t\t\t\tcurrentStencilFail = stencilFail;\n\t\t\t\t\tcurrentStencilZFail = stencilZFail;\n\t\t\t\t\tcurrentStencilZPass = stencilZPass;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\tsetLocked: function ( lock ) {\n\n\t\t\t\tlocked = lock;\n\n\t\t\t},\n\n\t\t\tsetClear: function ( stencil ) {\n\n\t\t\t\tif ( currentStencilClear !== stencil ) {\n\n\t\t\t\t\tgl.clearStencil( stencil );\n\t\t\t\t\tcurrentStencilClear = stencil;\n\n\t\t\t\t}\n\n\t\t\t},\n\n\t\t\treset: function () {\n\n\t\t\t\tlocked = false;\n\n\t\t\t\tcurrentStencilMask = null;\n\t\t\t\tcurrentStencilFunc = null;\n\t\t\t\tcurrentStencilRef = null;\n\t\t\t\tcurrentStencilFuncMask = null;\n\t\t\t\tcurrentStencilFail = null;\n\t\t\t\tcurrentStencilZFail = null;\n\t\t\t\tcurrentStencilZPass = null;\n\t\t\t\tcurrentStencilClear = null;\n\n\t\t\t}\n\n\t\t};\n\n\t}\n\n\t//\n\n\tvar colorBuffer = new ColorBuffer();\n\tvar depthBuffer = new DepthBuffer();\n\tvar stencilBuffer = new StencilBuffer();\n\n\tvar maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );\n\tvar newAttributes = new Uint8Array( maxVertexAttributes );\n\tvar enabledAttributes = new Uint8Array( maxVertexAttributes );\n\tvar attributeDivisors = new Uint8Array( maxVertexAttributes );\n\n\tvar enabledCapabilities = {};\n\n\tvar currentProgram = null;\n\n\tvar currentBlendingEnabled = null;\n\tvar currentBlending = null;\n\tvar currentBlendEquation = null;\n\tvar currentBlendSrc = null;\n\tvar currentBlendDst = null;\n\tvar currentBlendEquationAlpha = null;\n\tvar currentBlendSrcAlpha = null;\n\tvar currentBlendDstAlpha = null;\n\tvar currentPremultipledAlpha = false;\n\n\tvar currentFlipSided = null;\n\tvar currentCullFace = null;\n\n\tvar currentLineWidth = null;\n\n\tvar currentPolygonOffsetFactor = null;\n\tvar currentPolygonOffsetUnits = null;\n\n\tvar maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS );\n\n\tvar lineWidthAvailable = false;\n\tvar version = 0;\n\tvar glVersion = gl.getParameter( gl.VERSION );\n\n\tif ( glVersion.indexOf( 'WebGL' ) !== - 1 ) {\n\n\t\tversion = parseFloat( /^WebGL\\ ([0-9])/.exec( glVersion )[ 1 ] );\n\t\tlineWidthAvailable = ( version >= 1.0 );\n\n\t} else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) {\n\n\t\tversion = parseFloat( /^OpenGL\\ ES\\ ([0-9])/.exec( glVersion )[ 1 ] );\n\t\tlineWidthAvailable = ( version >= 2.0 );\n\n\t}\n\n\tvar currentTextureSlot = null;\n\tvar currentBoundTextures = {};\n\n\tvar currentScissor = new Vector4();\n\tvar currentViewport = new Vector4();\n\n\tfunction createTexture( type, target, count ) {\n\n\t\tvar data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4.\n\t\tvar texture = gl.createTexture();\n\n\t\tgl.bindTexture( type, texture );\n\t\tgl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST );\n\t\tgl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST );\n\n\t\tfor ( var i = 0; i < count; i ++ ) {\n\n\t\t\tgl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );\n\n\t\t}\n\n\t\treturn texture;\n\n\t}\n\n\tvar emptyTextures = {};\n\temptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 );\n\temptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 );\n\n\t// init\n\n\tcolorBuffer.setClear( 0, 0, 0, 1 );\n\tdepthBuffer.setClear( 1 );\n\tstencilBuffer.setClear( 0 );\n\n\tenable( gl.DEPTH_TEST );\n\tdepthBuffer.setFunc( LessEqualDepth );\n\n\tsetFlipSided( false );\n\tsetCullFace( CullFaceBack );\n\tenable( gl.CULL_FACE );\n\n\tsetBlending( NoBlending );\n\n\t//\n\n\tfunction initAttributes() {\n\n\t\tfor ( var i = 0, l = newAttributes.length; i < l; i ++ ) {\n\n\t\t\tnewAttributes[ i ] = 0;\n\n\t\t}\n\n\t}\n\n\tfunction enableAttribute( attribute ) {\n\n\t\tenableAttributeAndDivisor( attribute, 0 );\n\n\t}\n\n\tfunction enableAttributeAndDivisor( attribute, meshPerAttribute ) {\n\n\t\tnewAttributes[ attribute ] = 1;\n\n\t\tif ( enabledAttributes[ attribute ] === 0 ) {\n\n\t\t\tgl.enableVertexAttribArray( attribute );\n\t\t\tenabledAttributes[ attribute ] = 1;\n\n\t\t}\n\n\t\tif ( attributeDivisors[ attribute ] !== meshPerAttribute ) {\n\n\t\t\tvar extension = isWebGL2 ? gl : extensions.get( 'ANGLE_instanced_arrays' );\n\n\t\t\textension[ isWebGL2 ? 'vertexAttribDivisor' : 'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );\n\t\t\tattributeDivisors[ attribute ] = meshPerAttribute;\n\n\t\t}\n\n\t}\n\n\tfunction disableUnusedAttributes() {\n\n\t\tfor ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) {\n\n\t\t\tif ( enabledAttributes[ i ] !== newAttributes[ i ] ) {\n\n\t\t\t\tgl.disableVertexAttribArray( i );\n\t\t\t\tenabledAttributes[ i ] = 0;\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tfunction vertexAttribPointer( index, size, type, normalized, stride, offset ) {\n\n\t\tif ( isWebGL2 === true && ( type === gl.INT || type === gl.UNSIGNED_INT ) ) {\n\n\t\t\tgl.vertexAttribIPointer( index, size, type, normalized, stride, offset );\n\n\t\t} else {\n\n\t\t\tgl.vertexAttribPointer( index, size, type, normalized, stride, offset );\n\n\t\t}\n\n\t}\n\n\tfunction enable( id ) {\n\n\t\tif ( enabledCapabilities[ id ] !== true ) {\n\n\t\t\tgl.enable( id );\n\t\t\tenabledCapabilities[ id ] = true;\n\n\t\t}\n\n\t}\n\n\tfunction disable( id ) {\n\n\t\tif ( enabledCapabilities[ id ] !== false ) {\n\n\t\t\tgl.disable( id );\n\t\t\tenabledCapabilities[ id ] = false;\n\n\t\t}\n\n\t}\n\n\tfunction useProgram( program ) {\n\n\t\tif ( currentProgram !== program ) {\n\n\t\t\tgl.useProgram( program );\n\n\t\t\tcurrentProgram = program;\n\n\t\t\treturn true;\n\n\t\t}\n\n\t\treturn false;\n\n\t}\n\n\tvar equationToGL = {\n\t\t[ AddEquation ]: gl.FUNC_ADD,\n\t\t[ SubtractEquation ]: gl.FUNC_SUBTRACT,\n\t\t[ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT\n\t};\n\n\tif ( isWebGL2 ) {\n\n\t\tequationToGL[ MinEquation ] = gl.MIN;\n\t\tequationToGL[ MaxEquation ] = gl.MAX;\n\n\t} else {\n\n\t\tvar extension = extensions.get( 'EXT_blend_minmax' );\n\n\t\tif ( extension !== null ) {\n\n\t\t\tequationToGL[ MinEquation ] = extension.MIN_EXT;\n\t\t\tequationToGL[ MaxEquation ] = extension.MAX_EXT;\n\n\t\t}\n\n\t}\n\n\tvar factorToGL = {\n\t\t[ ZeroFactor ]: gl.ZERO,\n\t\t[ OneFactor ]: gl.ONE,\n\t\t[ SrcColorFactor ]: gl.SRC_COLOR,\n\t\t[ SrcAlphaFactor ]: gl.SRC_ALPHA,\n\t\t[ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE,\n\t\t[ DstColorFactor ]: gl.DST_COLOR,\n\t\t[ DstAlphaFactor ]: gl.DST_ALPHA,\n\t\t[ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR,\n\t\t[ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA,\n\t\t[ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR,\n\t\t[ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA\n\t};\n\n\tfunction setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) {\n\n\t\tif ( blending === NoBlending ) {\n\n\t\t\tif ( currentBlendingEnabled ) {\n\n\t\t\t\tdisable( gl.BLEND );\n\t\t\t\tcurrentBlendingEnabled = false;\n\n\t\t\t}\n\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( ! currentBlendingEnabled ) {\n\n\t\t\tenable( gl.BLEND );\n\t\t\tcurrentBlendingEnabled = true;\n\n\t\t}\n\n\t\tif ( blending !== CustomBlending ) {\n\n\t\t\tif ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {\n\n\t\t\t\tif ( currentBlendEquation !== AddEquation || currentBlendEquationAlpha !== AddEquation ) {\n\n\t\t\t\t\tgl.blendEquation( gl.FUNC_ADD );\n\n\t\t\t\t\tcurrentBlendEquation = AddEquation;\n\t\t\t\t\tcurrentBlendEquationAlpha = AddEquation;\n\n\t\t\t\t}\n\n\t\t\t\tif ( premultipliedAlpha ) {\n\n\t\t\t\t\tswitch ( blending ) {\n\n\t\t\t\t\t\tcase NormalBlending:\n\t\t\t\t\t\t\tgl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase AdditiveBlending:\n\t\t\t\t\t\t\tgl.blendFunc( gl.ONE, gl.ONE );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase SubtractiveBlending:\n\t\t\t\t\t\t\tgl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase MultiplyBlending:\n\t\t\t\t\t\t\tgl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tconsole.error( 'THREE.WebGLState: Invalid blending: ', blending );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tswitch ( blending ) {\n\n\t\t\t\t\t\tcase NormalBlending:\n\t\t\t\t\t\t\tgl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase AdditiveBlending:\n\t\t\t\t\t\t\tgl.blendFunc( gl.SRC_ALPHA, gl.ONE );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase SubtractiveBlending:\n\t\t\t\t\t\t\tgl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tcase MultiplyBlending:\n\t\t\t\t\t\t\tgl.blendFunc( gl.ZERO, gl.SRC_COLOR );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\tconsole.error( 'THREE.WebGLState: Invalid blending: ', blending );\n\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tcurrentBlendSrc = null;\n\t\t\t\tcurrentBlendDst = null;\n\t\t\t\tcurrentBlendSrcAlpha = null;\n\t\t\t\tcurrentBlendDstAlpha = null;\n\n\t\t\t\tcurrentBlending = blending;\n\t\t\t\tcurrentPremultipledAlpha = premultipliedAlpha;\n\n\t\t\t}\n\n\t\t\treturn;\n\n\t\t}\n\n\t\t// custom blending\n\n\t\tblendEquationAlpha = blendEquationAlpha || blendEquation;\n\t\tblendSrcAlpha = blendSrcAlpha || blendSrc;\n\t\tblendDstAlpha = blendDstAlpha || blendDst;\n\n\t\tif ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {\n\n\t\t\tgl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );\n\n\t\t\tcurrentBlendEquation = blendEquation;\n\t\t\tcurrentBlendEquationAlpha = blendEquationAlpha;\n\n\t\t}\n\n\t\tif ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {\n\n\t\t\tgl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );\n\n\t\t\tcurrentBlendSrc = blendSrc;\n\t\t\tcurrentBlendDst = blendDst;\n\t\t\tcurrentBlendSrcAlpha = blendSrcAlpha;\n\t\t\tcurrentBlendDstAlpha = blendDstAlpha;\n\n\t\t}\n\n\t\tcurrentBlending = blending;\n\t\tcurrentPremultipledAlpha = null;\n\n\t}\n\n\tfunction setMaterial( material, frontFaceCW ) {\n\n\t\tmaterial.side === DoubleSide\n\t\t\t? disable( gl.CULL_FACE )\n\t\t\t: enable( gl.CULL_FACE );\n\n\t\tvar flipSided = ( material.side === BackSide );\n\t\tif ( frontFaceCW ) flipSided = ! flipSided;\n\n\t\tsetFlipSided( flipSided );\n\n\t\t( material.blending === NormalBlending && material.transparent === false )\n\t\t\t? setBlending( NoBlending )\n\t\t\t: setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha );\n\n\t\tdepthBuffer.setFunc( material.depthFunc );\n\t\tdepthBuffer.setTest( material.depthTest );\n\t\tdepthBuffer.setMask( material.depthWrite );\n\t\tcolorBuffer.setMask( material.colorWrite );\n\n\t\tvar stencilWrite = material.stencilWrite;\n\t\tstencilBuffer.setTest( stencilWrite );\n\t\tif ( stencilWrite ) {\n\n\t\t\tstencilBuffer.setMask( material.stencilWriteMask );\n\t\t\tstencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );\n\t\t\tstencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );\n\n\t\t}\n\n\t\tsetPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );\n\n\t}\n\n\t//\n\n\tfunction setFlipSided( flipSided ) {\n\n\t\tif ( currentFlipSided !== flipSided ) {\n\n\t\t\tif ( flipSided ) {\n\n\t\t\t\tgl.frontFace( gl.CW );\n\n\t\t\t} else {\n\n\t\t\t\tgl.frontFace( gl.CCW );\n\n\t\t\t}\n\n\t\t\tcurrentFlipSided = flipSided;\n\n\t\t}\n\n\t}\n\n\tfunction setCullFace( cullFace ) {\n\n\t\tif ( cullFace !== CullFaceNone ) {\n\n\t\t\tenable( gl.CULL_FACE );\n\n\t\t\tif ( cullFace !== currentCullFace ) {\n\n\t\t\t\tif ( cullFace === CullFaceBack ) {\n\n\t\t\t\t\tgl.cullFace( gl.BACK );\n\n\t\t\t\t} else if ( cullFace === CullFaceFront ) {\n\n\t\t\t\t\tgl.cullFace( gl.FRONT );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tgl.cullFace( gl.FRONT_AND_BACK );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tdisable( gl.CULL_FACE );\n\n\t\t}\n\n\t\tcurrentCullFace = cullFace;\n\n\t}\n\n\tfunction setLineWidth( width ) {\n\n\t\tif ( width !== currentLineWidth ) {\n\n\t\t\tif ( lineWidthAvailable ) gl.lineWidth( width );\n\n\t\t\tcurrentLineWidth = width;\n\n\t\t}\n\n\t}\n\n\tfunction setPolygonOffset( polygonOffset, factor, units ) {\n\n\t\tif ( polygonOffset ) {\n\n\t\t\tenable( gl.POLYGON_OFFSET_FILL );\n\n\t\t\tif ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {\n\n\t\t\t\tgl.polygonOffset( factor, units );\n\n\t\t\t\tcurrentPolygonOffsetFactor = factor;\n\t\t\t\tcurrentPolygonOffsetUnits = units;\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tdisable( gl.POLYGON_OFFSET_FILL );\n\n\t\t}\n\n\t}\n\n\tfunction setScissorTest( scissorTest ) {\n\n\t\tif ( scissorTest ) {\n\n\t\t\tenable( gl.SCISSOR_TEST );\n\n\t\t} else {\n\n\t\t\tdisable( gl.SCISSOR_TEST );\n\n\t\t}\n\n\t}\n\n\t// texture\n\n\tfunction activeTexture( webglSlot ) {\n\n\t\tif ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;\n\n\t\tif ( currentTextureSlot !== webglSlot ) {\n\n\t\t\tgl.activeTexture( webglSlot );\n\t\t\tcurrentTextureSlot = webglSlot;\n\n\t\t}\n\n\t}\n\n\tfunction bindTexture( webglType, webglTexture ) {\n\n\t\tif ( currentTextureSlot === null ) {\n\n\t\t\tactiveTexture();\n\n\t\t}\n\n\t\tvar boundTexture = currentBoundTextures[ currentTextureSlot ];\n\n\t\tif ( boundTexture === undefined ) {\n\n\t\t\tboundTexture = { type: undefined, texture: undefined };\n\t\t\tcurrentBoundTextures[ currentTextureSlot ] = boundTexture;\n\n\t\t}\n\n\t\tif ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {\n\n\t\t\tgl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );\n\n\t\t\tboundTexture.type = webglType;\n\t\t\tboundTexture.texture = webglTexture;\n\n\t\t}\n\n\t}\n\n\tfunction unbindTexture() {\n\n\t\tvar boundTexture = currentBoundTextures[ currentTextureSlot ];\n\n\t\tif ( boundTexture !== undefined && boundTexture.type !== undefined ) {\n\n\t\t\tgl.bindTexture( boundTexture.type, null );\n\n\t\t\tboundTexture.type = undefined;\n\t\t\tboundTexture.texture = undefined;\n\n\t\t}\n\n\t}\n\n\tfunction compressedTexImage2D() {\n\n\t\ttry {\n\n\t\t\tgl.compressedTexImage2D.apply( gl, arguments );\n\n\t\t} catch ( error ) {\n\n\t\t\tconsole.error( 'THREE.WebGLState:', error );\n\n\t\t}\n\n\t}\n\n\tfunction texImage2D() {\n\n\t\ttry {\n\n\t\t\tgl.texImage2D.apply( gl, arguments );\n\n\t\t} catch ( error ) {\n\n\t\t\tconsole.error( 'THREE.WebGLState:', error );\n\n\t\t}\n\n\t}\n\n\tfunction texImage3D() {\n\n\t\ttry {\n\n\t\t\tgl.texImage3D.apply( gl, arguments );\n\n\t\t} catch ( error ) {\n\n\t\t\tconsole.error( 'THREE.WebGLState:', error );\n\n\t\t}\n\n\t}\n\n\t//\n\n\tfunction scissor( scissor ) {\n\n\t\tif ( currentScissor.equals( scissor ) === false ) {\n\n\t\t\tgl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );\n\t\t\tcurrentScissor.copy( scissor );\n\n\t\t}\n\n\t}\n\n\tfunction viewport( viewport ) {\n\n\t\tif ( currentViewport.equals( viewport ) === false ) {\n\n\t\t\tgl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );\n\t\t\tcurrentViewport.copy( viewport );\n\n\t\t}\n\n\t}\n\n\t//\n\n\tfunction reset() {\n\n\t\tfor ( var i = 0; i < enabledAttributes.length; i ++ ) {\n\n\t\t\tif ( enabledAttributes[ i ] === 1 ) {\n\n\t\t\t\tgl.disableVertexAttribArray( i );\n\t\t\t\tenabledAttributes[ i ] = 0;\n\n\t\t\t}\n\n\t\t}\n\n\t\tenabledCapabilities = {};\n\n\t\tcurrentTextureSlot = null;\n\t\tcurrentBoundTextures = {};\n\n\t\tcurrentProgram = null;\n\n\t\tcurrentBlending = null;\n\n\t\tcurrentFlipSided = null;\n\t\tcurrentCullFace = null;\n\n\t\tcolorBuffer.reset();\n\t\tdepthBuffer.reset();\n\t\tstencilBuffer.reset();\n\n\t}\n\n\treturn {\n\n\t\tbuffers: {\n\t\t\tcolor: colorBuffer,\n\t\t\tdepth: depthBuffer,\n\t\t\tstencil: stencilBuffer\n\t\t},\n\n\t\tinitAttributes: initAttributes,\n\t\tenableAttribute: enableAttribute,\n\t\tenableAttributeAndDivisor: enableAttributeAndDivisor,\n\t\tdisableUnusedAttributes: disableUnusedAttributes,\n\t\tvertexAttribPointer: vertexAttribPointer,\n\t\tenable: enable,\n\t\tdisable: disable,\n\n\t\tuseProgram: useProgram,\n\n\t\tsetBlending: setBlending,\n\t\tsetMaterial: setMaterial,\n\n\t\tsetFlipSided: setFlipSided,\n\t\tsetCullFace: setCullFace,\n\n\t\tsetLineWidth: setLineWidth,\n\t\tsetPolygonOffset: setPolygonOffset,\n\n\t\tsetScissorTest: setScissorTest,\n\n\t\tactiveTexture: activeTexture,\n\t\tbindTexture: bindTexture,\n\t\tunbindTexture: unbindTexture,\n\t\tcompressedTexImage2D: compressedTexImage2D,\n\t\ttexImage2D: texImage2D,\n\t\ttexImage3D: texImage3D,\n\n\t\tscissor: scissor,\n\t\tviewport: viewport,\n\n\t\treset: reset\n\n\t};\n\n}\n\nexport { WebGLState };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { LinearFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping } from '../../constants.js';\nimport { MathUtils } from '../../math/MathUtils.js';\n\nfunction WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\tvar maxTextures = capabilities.maxTextures;\n\tvar maxCubemapSize = capabilities.maxCubemapSize;\n\tvar maxTextureSize = capabilities.maxTextureSize;\n\tvar maxSamples = capabilities.maxSamples;\n\n\tvar _videoTextures = new WeakMap();\n\tvar _canvas;\n\n\t// cordova iOS (as of 5.0) still uses UIWebView, which provides OffscreenCanvas,\n\t// also OffscreenCanvas.getContext(\"webgl\"), but not OffscreenCanvas.getContext(\"2d\")!\n\t// Some implementations may only implement OffscreenCanvas partially (e.g. lacking 2d).\n\n\tvar useOffscreenCanvas = false;\n\n\ttry {\n\n\t\tuseOffscreenCanvas = typeof OffscreenCanvas !== 'undefined'\n\t\t\t&& ( new OffscreenCanvas( 1, 1 ).getContext( \"2d\" ) ) !== null;\n\n\t} catch ( err ) {\n\n\t\t// Ignore any errors\n\n\t}\n\n\tfunction createCanvas( width, height ) {\n\n\t\t// Use OffscreenCanvas when available. Specially needed in web workers\n\n\t\treturn useOffscreenCanvas ?\n\t\t\tnew OffscreenCanvas( width, height ) :\n\t\t\tdocument.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' );\n\n\t}\n\n\tfunction resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {\n\n\t\tvar scale = 1;\n\n\t\t// handle case if texture exceeds max size\n\n\t\tif ( image.width > maxSize || image.height > maxSize ) {\n\n\t\t\tscale = maxSize / Math.max( image.width, image.height );\n\n\t\t}\n\n\t\t// only perform resize if necessary\n\n\t\tif ( scale < 1 || needsPowerOfTwo === true ) {\n\n\t\t\t// only perform resize for certain image types\n\n\t\t\tif ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) ||\n\t\t\t\t( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) ||\n\t\t\t\t( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) {\n\n\t\t\t\tvar floor = needsPowerOfTwo ? MathUtils.floorPowerOfTwo : Math.floor;\n\n\t\t\t\tvar width = floor( scale * image.width );\n\t\t\t\tvar height = floor( scale * image.height );\n\n\t\t\t\tif ( _canvas === undefined ) _canvas = createCanvas( width, height );\n\n\t\t\t\t// cube textures can't reuse the same canvas\n\n\t\t\t\tvar canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;\n\n\t\t\t\tcanvas.width = width;\n\t\t\t\tcanvas.height = height;\n\n\t\t\t\tvar context = canvas.getContext( '2d' );\n\t\t\t\tcontext.drawImage( image, 0, 0, width, height );\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture has been resized from (' + image.width + 'x' + image.height + ') to (' + width + 'x' + height + ').' );\n\n\t\t\t\treturn canvas;\n\n\t\t\t} else {\n\n\t\t\t\tif ( 'data' in image ) {\n\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width + 'x' + image.height + ').' );\n\n\t\t\t\t}\n\n\t\t\t\treturn image;\n\n\t\t\t}\n\n\t\t}\n\n\t\treturn image;\n\n\t}\n\n\tfunction isPowerOfTwo( image ) {\n\n\t\treturn MathUtils.isPowerOfTwo( image.width ) && MathUtils.isPowerOfTwo( image.height );\n\n\t}\n\n\tfunction textureNeedsPowerOfTwo( texture ) {\n\n\t\tif ( isWebGL2 ) return false;\n\n\t\treturn ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) ||\n\t\t\t( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter );\n\n\t}\n\n\tfunction textureNeedsGenerateMipmaps( texture, supportsMips ) {\n\n\t\treturn texture.generateMipmaps && supportsMips &&\n\t\t\ttexture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter;\n\n\t}\n\n\tfunction generateMipmap( target, texture, width, height ) {\n\n\t\t_gl.generateMipmap( target );\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\t// Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11\n\t\ttextureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E;\n\n\t}\n\n\tfunction getInternalFormat( internalFormatName, glFormat, glType ) {\n\n\t\tif ( isWebGL2 === false ) return glFormat;\n\n\t\tif ( internalFormatName !== null ) {\n\n\t\t\tif ( _gl[ internalFormatName ] !== undefined ) return _gl[ internalFormatName ];\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \\'' + internalFormatName + '\\'' );\n\n\t\t}\n\n\t\tvar internalFormat = glFormat;\n\n\t\tif ( glFormat === _gl.RED ) {\n\n\t\t\tif ( glType === _gl.FLOAT ) internalFormat = _gl.R32F;\n\t\t\tif ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F;\n\t\t\tif ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8;\n\n\t\t}\n\n\t\tif ( glFormat === _gl.RGB ) {\n\n\t\t\tif ( glType === _gl.FLOAT ) internalFormat = _gl.RGB32F;\n\t\t\tif ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGB16F;\n\t\t\tif ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RGB8;\n\n\t\t}\n\n\t\tif ( glFormat === _gl.RGBA ) {\n\n\t\t\tif ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F;\n\t\t\tif ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F;\n\t\t\tif ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RGBA8;\n\n\t\t}\n\n\t\tif ( internalFormat === _gl.R16F || internalFormat === _gl.R32F ||\n\t\t\tinternalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) {\n\n\t\t\textensions.get( 'EXT_color_buffer_float' );\n\n\t\t}\n\n\t\treturn internalFormat;\n\n\t}\n\n\t// Fallback filters for non-power-of-2 textures\n\n\tfunction filterFallback( f ) {\n\n\t\tif ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) {\n\n\t\t\treturn _gl.NEAREST;\n\n\t\t}\n\n\t\treturn _gl.LINEAR;\n\n\t}\n\n\t//\n\n\tfunction onTextureDispose( event ) {\n\n\t\tvar texture = event.target;\n\n\t\ttexture.removeEventListener( 'dispose', onTextureDispose );\n\n\t\tdeallocateTexture( texture );\n\n\t\tif ( texture.isVideoTexture ) {\n\n\t\t\t_videoTextures.delete( texture );\n\n\t\t}\n\n\t\tinfo.memory.textures --;\n\n\t}\n\n\tfunction onRenderTargetDispose( event ) {\n\n\t\tvar renderTarget = event.target;\n\n\t\trenderTarget.removeEventListener( 'dispose', onRenderTargetDispose );\n\n\t\tdeallocateRenderTarget( renderTarget );\n\n\t\tinfo.memory.textures --;\n\n\t}\n\n\t//\n\n\tfunction deallocateTexture( texture ) {\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\tif ( textureProperties.__webglInit === undefined ) return;\n\n\t\t_gl.deleteTexture( textureProperties.__webglTexture );\n\n\t\tproperties.remove( texture );\n\n\t}\n\n\tfunction deallocateRenderTarget( renderTarget ) {\n\n\t\tvar renderTargetProperties = properties.get( renderTarget );\n\t\tvar textureProperties = properties.get( renderTarget.texture );\n\n\t\tif ( ! renderTarget ) return;\n\n\t\tif ( textureProperties.__webglTexture !== undefined ) {\n\n\t\t\t_gl.deleteTexture( textureProperties.__webglTexture );\n\n\t\t}\n\n\t\tif ( renderTarget.depthTexture ) {\n\n\t\t\trenderTarget.depthTexture.dispose();\n\n\t\t}\n\n\t\tif ( renderTarget.isWebGLCubeRenderTarget ) {\n\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\t_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] );\n\t\t\t\tif ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t_gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );\n\t\t\tif ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );\n\t\t\tif ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );\n\t\t\tif ( renderTargetProperties.__webglColorRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer );\n\t\t\tif ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );\n\n\t\t}\n\n\t\tproperties.remove( renderTarget.texture );\n\t\tproperties.remove( renderTarget );\n\n\t}\n\n\t//\n\n\tvar textureUnits = 0;\n\n\tfunction resetTextureUnits() {\n\n\t\ttextureUnits = 0;\n\n\t}\n\n\tfunction allocateTextureUnit() {\n\n\t\tvar textureUnit = textureUnits;\n\n\t\tif ( textureUnit >= maxTextures ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLTextures: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + maxTextures );\n\n\t\t}\n\n\t\ttextureUnits += 1;\n\n\t\treturn textureUnit;\n\n\t}\n\n\t//\n\n\tfunction setTexture2D( texture, slot ) {\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\tif ( texture.isVideoTexture ) updateVideoTexture( texture );\n\n\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\n\n\t\t\tvar image = texture.image;\n\n\t\t\tif ( image === undefined ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined' );\n\n\t\t\t} else if ( image.complete === false ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );\n\n\t\t\t} else {\n\n\t\t\t\tuploadTexture( textureProperties, texture, slot );\n\t\t\t\treturn;\n\n\t\t\t}\n\n\t\t}\n\n\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\tstate.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );\n\n\t}\n\n\tfunction setTexture2DArray( texture, slot ) {\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\n\n\t\t\tuploadTexture( textureProperties, texture, slot );\n\t\t\treturn;\n\n\t\t}\n\n\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\tstate.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture );\n\n\t}\n\n\tfunction setTexture3D( texture, slot ) {\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\n\n\t\t\tuploadTexture( textureProperties, texture, slot );\n\t\t\treturn;\n\n\t\t}\n\n\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\tstate.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture );\n\n\t}\n\n\tfunction setTextureCube( texture, slot ) {\n\n\t\tif ( texture.image.length !== 6 ) return;\n\n\t\tvar textureProperties = properties.get( texture );\n\n\t\tif ( texture.version > 0 && textureProperties.__version !== texture.version ) {\n\n\t\t\tinitTexture( textureProperties, texture );\n\n\t\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\t\tstate.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );\n\n\t\t\t_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );\n\n\t\t\tvar isCompressed = ( texture && ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture ) );\n\t\t\tvar isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );\n\n\t\t\tvar cubeImage = [];\n\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\tif ( ! isCompressed && ! isDataTexture ) {\n\n\t\t\t\t\tcubeImage[ i ] = resizeImage( texture.image[ i ], false, true, maxCubemapSize );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tcubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ];\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tvar image = cubeImage[ 0 ],\n\t\t\t\tsupportsMips = isPowerOfTwo( image ) || isWebGL2,\n\t\t\t\tglFormat = utils.convert( texture.format ),\n\t\t\t\tglType = utils.convert( texture.type ),\n\t\t\t\tglInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );\n\n\t\t\tsetTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips );\n\n\t\t\tvar mipmaps;\n\n\t\t\tif ( isCompressed ) {\n\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\t\tmipmaps = cubeImage[ i ].mipmaps;\n\n\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\n\n\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\n\n\t\t\t\t\t\tif ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {\n\n\t\t\t\t\t\t\tif ( glFormat !== null ) {\n\n\t\t\t\t\t\t\t\tstate.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );\n\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\n\n\t\t\t} else {\n\n\t\t\t\tmipmaps = texture.mipmaps;\n\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\t\tif ( isDataTexture ) {\n\n\t\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data );\n\n\t\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\n\n\t\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\n\t\t\t\t\t\t\tvar mipmapImage = mipmap.image[ i ].image;\n\n\t\t\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glInternalFormat, glFormat, glType, cubeImage[ i ] );\n\n\t\t\t\t\t\tfor ( var j = 0; j < mipmaps.length; j ++ ) {\n\n\t\t\t\t\t\t\tvar mipmap = mipmaps[ j ];\n\n\t\t\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j + 1, glInternalFormat, glFormat, glType, mipmap.image[ i ] );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length;\n\n\t\t\t}\n\n\t\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\n\n\t\t\t\t// We assume images for cube map have the same size.\n\t\t\t\tgenerateMipmap( _gl.TEXTURE_CUBE_MAP, texture, image.width, image.height );\n\n\t\t\t}\n\n\t\t\ttextureProperties.__version = texture.version;\n\n\t\t\tif ( texture.onUpdate ) texture.onUpdate( texture );\n\n\t\t} else {\n\n\t\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\t\tstate.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );\n\n\t\t}\n\n\t}\n\n\tfunction setTextureCubeDynamic( texture, slot ) {\n\n\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\tstate.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture );\n\n\t}\n\n\tvar wrappingToGL = {\n\t\t[ RepeatWrapping ]: _gl.REPEAT,\n\t\t[ ClampToEdgeWrapping ]: _gl.CLAMP_TO_EDGE,\n\t\t[ MirroredRepeatWrapping ]: _gl.MIRRORED_REPEAT\n\t};\n\n\tvar filterToGL = {\n\t\t[ NearestFilter ]: _gl.NEAREST,\n\t\t[ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST,\n\t\t[ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR,\n\n\t\t[ LinearFilter ]: _gl.LINEAR,\n\t\t[ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST,\n\t\t[ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR\n\t};\n\n\tfunction setTextureParameters( textureType, texture, supportsMips ) {\n\n\t\tif ( supportsMips ) {\n\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] );\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] );\n\n\t\t\tif ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) {\n\n\t\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] );\n\n\t\t\t}\n\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] );\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] );\n\n\t\t} else {\n\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );\n\n\t\t\tif ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) {\n\n\t\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, _gl.CLAMP_TO_EDGE );\n\n\t\t\t}\n\n\t\t\tif ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );\n\n\t\t\t}\n\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );\n\t\t\t_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );\n\n\t\t\tif ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar extension = extensions.get( 'EXT_texture_filter_anisotropic' );\n\n\t\tif ( extension ) {\n\n\t\t\tif ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return;\n\t\t\tif ( texture.type === HalfFloatType && ( isWebGL2 || extensions.get( 'OES_texture_half_float_linear' ) ) === null ) return;\n\n\t\t\tif ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {\n\n\t\t\t\t_gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );\n\t\t\t\tproperties.get( texture ).__currentAnisotropy = texture.anisotropy;\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tfunction initTexture( textureProperties, texture ) {\n\n\t\tif ( textureProperties.__webglInit === undefined ) {\n\n\t\t\ttextureProperties.__webglInit = true;\n\n\t\t\ttexture.addEventListener( 'dispose', onTextureDispose );\n\n\t\t\ttextureProperties.__webglTexture = _gl.createTexture();\n\n\t\t\tinfo.memory.textures ++;\n\n\t\t}\n\n\t}\n\n\tfunction uploadTexture( textureProperties, texture, slot ) {\n\n\t\tvar textureType = _gl.TEXTURE_2D;\n\n\t\tif ( texture.isDataTexture2DArray ) textureType = _gl.TEXTURE_2D_ARRAY;\n\t\tif ( texture.isDataTexture3D ) textureType = _gl.TEXTURE_3D;\n\n\t\tinitTexture( textureProperties, texture );\n\n\t\tstate.activeTexture( _gl.TEXTURE0 + slot );\n\t\tstate.bindTexture( textureType, textureProperties.__webglTexture );\n\n\t\t_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );\n\t\t_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );\n\t\t_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );\n\n\t\tvar needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( texture.image ) === false;\n\t\tvar image = resizeImage( texture.image, needsPowerOfTwo, false, maxTextureSize );\n\n\t\tvar supportsMips = isPowerOfTwo( image ) || isWebGL2,\n\t\t\tglFormat = utils.convert( texture.format ),\n\t\t\tglType = utils.convert( texture.type ),\n\t\t\tglInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType );\n\n\t\tsetTextureParameters( textureType, texture, supportsMips );\n\n\t\tvar mipmap, mipmaps = texture.mipmaps;\n\n\t\tif ( texture.isDepthTexture ) {\n\n\t\t\t// populate depth texture with dummy data\n\n\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT;\n\n\t\t\tif ( isWebGL2 ) {\n\n\t\t\t\tif ( texture.type === FloatType ) {\n\n\t\t\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT32F;\n\n\t\t\t\t} else if ( texture.type === UnsignedIntType ) {\n\n\t\t\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT24;\n\n\t\t\t\t} else if ( texture.type === UnsignedInt248Type ) {\n\n\t\t\t\t\tglInternalFormat = _gl.DEPTH24_STENCIL8;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT16; // WebGL2 requires sized internalformat for glTexImage2D\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\tif ( texture.type === FloatType ) {\n\n\t\t\t\t\tconsole.error( 'WebGLRenderer: Floating point depth texture requires WebGL2.' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t// validation checks for WebGL 1\n\n\t\t\tif ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {\n\n\t\t\t\t// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are\n\t\t\t\t// DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT\n\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\n\t\t\t\tif ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) {\n\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );\n\n\t\t\t\t\ttexture.type = UnsignedShortType;\n\t\t\t\t\tglType = utils.convert( texture.type );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( texture.format === DepthStencilFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {\n\n\t\t\t\t// Depth stencil textures need the DEPTH_STENCIL internal format\n\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\n\t\t\t\tglInternalFormat = _gl.DEPTH_STENCIL;\n\n\t\t\t\t// The error INVALID_OPERATION is generated by texImage2D if format and internalformat are\n\t\t\t\t// DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL.\n\t\t\t\t// (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/)\n\t\t\t\tif ( texture.type !== UnsignedInt248Type ) {\n\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );\n\n\t\t\t\t\ttexture.type = UnsignedInt248Type;\n\t\t\t\t\tglType = utils.convert( texture.type );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\t//\n\n\t\t\tstate.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, null );\n\n\t\t} else if ( texture.isDataTexture ) {\n\n\t\t\t// use manually created mipmaps if available\n\t\t\t// if there are no manual mipmaps\n\t\t\t// set 0 level mipmap and then use GL to generate other mipmap levels\n\n\t\t\tif ( mipmaps.length > 0 && supportsMips ) {\n\n\t\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\n\n\t\t\t\t\tmipmap = mipmaps[ i ];\n\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\n\n\t\t\t\t}\n\n\t\t\t\ttexture.generateMipmaps = false;\n\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\n\n\t\t\t} else {\n\n\t\t\t\tstate.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );\n\t\t\t\ttextureProperties.__maxMipLevel = 0;\n\n\t\t\t}\n\n\t\t} else if ( texture.isCompressedTexture ) {\n\n\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\n\n\t\t\t\tmipmap = mipmaps[ i ];\n\n\t\t\t\tif ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) {\n\n\t\t\t\t\tif ( glFormat !== null ) {\n\n\t\t\t\t\t\tstate.compressedTexImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\n\n\t\t} else if ( texture.isDataTexture2DArray ) {\n\n\t\t\tstate.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );\n\t\t\ttextureProperties.__maxMipLevel = 0;\n\n\t\t} else if ( texture.isDataTexture3D ) {\n\n\t\t\tstate.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );\n\t\t\ttextureProperties.__maxMipLevel = 0;\n\n\t\t} else {\n\n\t\t\t// regular Texture (image, video, canvas)\n\n\t\t\t// use manually created mipmaps if available\n\t\t\t// if there are no manual mipmaps\n\t\t\t// set 0 level mipmap and then use GL to generate other mipmap levels\n\n\t\t\tif ( mipmaps.length > 0 && supportsMips ) {\n\n\t\t\t\tfor ( var i = 0, il = mipmaps.length; i < il; i ++ ) {\n\n\t\t\t\t\tmipmap = mipmaps[ i ];\n\t\t\t\t\tstate.texImage2D( _gl.TEXTURE_2D, i, glInternalFormat, glFormat, glType, mipmap );\n\n\t\t\t\t}\n\n\t\t\t\ttexture.generateMipmaps = false;\n\t\t\t\ttextureProperties.__maxMipLevel = mipmaps.length - 1;\n\n\t\t\t} else {\n\n\t\t\t\tstate.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );\n\t\t\t\ttextureProperties.__maxMipLevel = 0;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\n\n\t\t\tgenerateMipmap( textureType, texture, image.width, image.height );\n\n\t\t}\n\n\t\ttextureProperties.__version = texture.version;\n\n\t\tif ( texture.onUpdate ) texture.onUpdate( texture );\n\n\t}\n\n\t// Render targets\n\n\t// Setup storage for target texture and bind it to correct framebuffer\n\tfunction setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) {\n\n\t\tvar glFormat = utils.convert( renderTarget.texture.format );\n\t\tvar glType = utils.convert( renderTarget.texture.type );\n\t\tvar glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );\n\t\tstate.texImage2D( textureTarget, 0, glInternalFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );\n\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );\n\t\t_gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 );\n\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );\n\n\t}\n\n\t// Setup storage for internal depth/stencil buffers and bind to correct framebuffer\n\tfunction setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {\n\n\t\t_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );\n\n\t\tif ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {\n\n\t\t\tvar glInternalFormat = _gl.DEPTH_COMPONENT16;\n\n\t\t\tif ( isMultisample ) {\n\n\t\t\t\tvar depthTexture = renderTarget.depthTexture;\n\n\t\t\t\tif ( depthTexture && depthTexture.isDepthTexture ) {\n\n\t\t\t\t\tif ( depthTexture.type === FloatType ) {\n\n\t\t\t\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT32F;\n\n\t\t\t\t\t} else if ( depthTexture.type === UnsignedIntType ) {\n\n\t\t\t\t\t\tglInternalFormat = _gl.DEPTH_COMPONENT24;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\n\n\t\t\t\t_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );\n\n\t\t\t} else {\n\n\t\t\t\t_gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );\n\n\t\t\t}\n\n\t\t\t_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );\n\n\t\t} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {\n\n\t\t\tif ( isMultisample ) {\n\n\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\n\n\t\t\t\t_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height );\n\n\t\t\t} else {\n\n\t\t\t\t_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );\n\n\t\t\t}\n\n\n\t\t\t_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );\n\n\t\t} else {\n\n\t\t\tvar glFormat = utils.convert( renderTarget.texture.format );\n\t\t\tvar glType = utils.convert( renderTarget.texture.type );\n\t\t\tvar glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );\n\n\t\t\tif ( isMultisample ) {\n\n\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\n\n\t\t\t\t_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );\n\n\t\t\t} else {\n\n\t\t\t\t_gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );\n\n\t\t\t}\n\n\t\t}\n\n\t\t_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );\n\n\t}\n\n\t// Setup resources for a Depth Texture for a FBO (needs an extension)\n\tfunction setupDepthTexture( framebuffer, renderTarget ) {\n\n\t\tvar isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );\n\t\tif ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' );\n\n\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );\n\n\t\tif ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {\n\n\t\t\tthrow new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );\n\n\t\t}\n\n\t\t// upload an empty depth texture with framebuffer size\n\t\tif ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||\n\t\t\t\trenderTarget.depthTexture.image.width !== renderTarget.width ||\n\t\t\t\trenderTarget.depthTexture.image.height !== renderTarget.height ) {\n\n\t\t\trenderTarget.depthTexture.image.width = renderTarget.width;\n\t\t\trenderTarget.depthTexture.image.height = renderTarget.height;\n\t\t\trenderTarget.depthTexture.needsUpdate = true;\n\n\t\t}\n\n\t\tsetTexture2D( renderTarget.depthTexture, 0 );\n\n\t\tvar webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;\n\n\t\tif ( renderTarget.depthTexture.format === DepthFormat ) {\n\n\t\t\t_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );\n\n\t\t} else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {\n\n\t\t\t_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );\n\n\t\t} else {\n\n\t\t\tthrow new Error( 'Unknown depthTexture format' );\n\n\t\t}\n\n\t}\n\n\t// Setup GL resources for a non-texture depth buffer\n\tfunction setupDepthRenderbuffer( renderTarget ) {\n\n\t\tvar renderTargetProperties = properties.get( renderTarget );\n\n\t\tvar isCube = ( renderTarget.isWebGLCubeRenderTarget === true );\n\n\t\tif ( renderTarget.depthTexture ) {\n\n\t\t\tif ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' );\n\n\t\t\tsetupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );\n\n\t\t} else {\n\n\t\t\tif ( isCube ) {\n\n\t\t\t\trenderTargetProperties.__webglDepthbuffer = [];\n\n\t\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] );\n\t\t\t\t\trenderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer();\n\t\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget, false );\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );\n\t\t\t\trenderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();\n\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget, false );\n\n\t\t\t}\n\n\t\t}\n\n\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );\n\n\t}\n\n\t// Set up GL resources for the render target\n\tfunction setupRenderTarget( renderTarget ) {\n\n\t\tvar renderTargetProperties = properties.get( renderTarget );\n\t\tvar textureProperties = properties.get( renderTarget.texture );\n\n\t\trenderTarget.addEventListener( 'dispose', onRenderTargetDispose );\n\n\t\ttextureProperties.__webglTexture = _gl.createTexture();\n\n\t\tinfo.memory.textures ++;\n\n\t\tvar isCube = ( renderTarget.isWebGLCubeRenderTarget === true );\n\t\tvar isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );\n\t\tvar supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;\n\n\t\t// Handles WebGL2 RGBFormat fallback - #18858\n\n\t\tif ( isWebGL2 && renderTarget.texture.format === RGBFormat && ( renderTarget.texture.type === FloatType || renderTarget.texture.type === HalfFloatType ) ) {\n\n\t\t\trenderTarget.texture.format = RGBAFormat;\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: Rendering to textures with RGB format is not supported. Using RGBA format instead.' );\n\n\t\t}\n\n\t\t// Setup framebuffer\n\n\t\tif ( isCube ) {\n\n\t\t\trenderTargetProperties.__webglFramebuffer = [];\n\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\trenderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer();\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\trenderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();\n\n\t\t\tif ( isMultisample ) {\n\n\t\t\t\tif ( isWebGL2 ) {\n\n\t\t\t\t\trenderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();\n\t\t\t\t\trenderTargetProperties.__webglColorRenderbuffer = _gl.createRenderbuffer();\n\n\t\t\t\t\t_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer );\n\n\t\t\t\t\tvar glFormat = utils.convert( renderTarget.texture.format );\n\t\t\t\t\tvar glType = utils.convert( renderTarget.texture.type );\n\t\t\t\t\tvar glInternalFormat = getInternalFormat( renderTarget.texture.internalFormat, glFormat, glType );\n\t\t\t\t\tvar samples = getRenderTargetSamples( renderTarget );\n\t\t\t\t\t_gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );\n\n\t\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );\n\t\t\t\t\t_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer );\n\t\t\t\t\t_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );\n\n\t\t\t\t\tif ( renderTarget.depthBuffer ) {\n\n\t\t\t\t\t\trenderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();\n\t\t\t\t\t\tsetupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget, true );\n\n\t\t\t\t\t}\n\n\t\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );\n\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Setup color buffer\n\n\t\tif ( isCube ) {\n\n\t\t\tstate.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );\n\t\t\tsetTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, supportsMips );\n\n\t\t\tfor ( var i = 0; i < 6; i ++ ) {\n\n\t\t\t\tsetupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );\n\n\t\t\t}\n\n\t\t\tif ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {\n\n\t\t\t\tgenerateMipmap( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, renderTarget.width, renderTarget.height );\n\n\t\t\t}\n\n\t\t\tstate.bindTexture( _gl.TEXTURE_CUBE_MAP, null );\n\n\t\t} else {\n\n\t\t\tstate.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );\n\t\t\tsetTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, supportsMips );\n\t\t\tsetupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D );\n\n\t\t\tif ( textureNeedsGenerateMipmaps( renderTarget.texture, supportsMips ) ) {\n\n\t\t\t\tgenerateMipmap( _gl.TEXTURE_2D, renderTarget.texture, renderTarget.width, renderTarget.height );\n\n\t\t\t}\n\n\t\t\tstate.bindTexture( _gl.TEXTURE_2D, null );\n\n\t\t}\n\n\t\t// Setup depth and stencil buffers\n\n\t\tif ( renderTarget.depthBuffer ) {\n\n\t\t\tsetupDepthRenderbuffer( renderTarget );\n\n\t\t}\n\n\t}\n\n\tfunction updateRenderTargetMipmap( renderTarget ) {\n\n\t\tvar texture = renderTarget.texture;\n\t\tvar supportsMips = isPowerOfTwo( renderTarget ) || isWebGL2;\n\n\t\tif ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {\n\n\t\t\tvar target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;\n\t\t\tvar webglTexture = properties.get( texture ).__webglTexture;\n\n\t\t\tstate.bindTexture( target, webglTexture );\n\t\t\tgenerateMipmap( target, texture, renderTarget.width, renderTarget.height );\n\t\t\tstate.bindTexture( target, null );\n\n\t\t}\n\n\t}\n\n\tfunction updateMultisampleRenderTarget( renderTarget ) {\n\n\t\tif ( renderTarget.isWebGLMultisampleRenderTarget ) {\n\n\t\t\tif ( isWebGL2 ) {\n\n\t\t\t\tvar renderTargetProperties = properties.get( renderTarget );\n\n\t\t\t\t_gl.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );\n\t\t\t\t_gl.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );\n\n\t\t\t\tvar width = renderTarget.width;\n\t\t\t\tvar height = renderTarget.height;\n\t\t\t\tvar mask = _gl.COLOR_BUFFER_BIT;\n\n\t\t\t\tif ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT;\n\t\t\t\tif ( renderTarget.stencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT;\n\n\t\t\t\t_gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST );\n\n\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer ); // see #18905\n\n\t\t\t} else {\n\n\t\t\t\tconsole.warn( 'THREE.WebGLRenderer: WebGLMultisampleRenderTarget can only be used with WebGL2.' );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tfunction getRenderTargetSamples( renderTarget ) {\n\n\t\treturn ( isWebGL2 && renderTarget.isWebGLMultisampleRenderTarget ) ?\n\t\t\tMath.min( maxSamples, renderTarget.samples ) : 0;\n\n\t}\n\n\tfunction updateVideoTexture( texture ) {\n\n\t\tvar frame = info.render.frame;\n\n\t\t// Check the last frame we updated the VideoTexture\n\n\t\tif ( _videoTextures.get( texture ) !== frame ) {\n\n\t\t\t_videoTextures.set( texture, frame );\n\t\t\ttexture.update();\n\n\t\t}\n\n\t}\n\n\t// backwards compatibility\n\n\tvar warnedTexture2D = false;\n\tvar warnedTextureCube = false;\n\n\tfunction safeSetTexture2D( texture, slot ) {\n\n\t\tif ( texture && texture.isWebGLRenderTarget ) {\n\n\t\t\tif ( warnedTexture2D === false ) {\n\n\t\t\t\tconsole.warn( \"THREE.WebGLTextures.safeSetTexture2D: don't use render targets as textures. Use their .texture property instead.\" );\n\t\t\t\twarnedTexture2D = true;\n\n\t\t\t}\n\n\t\t\ttexture = texture.texture;\n\n\t\t}\n\n\t\tsetTexture2D( texture, slot );\n\n\t}\n\n\tfunction safeSetTextureCube( texture, slot ) {\n\n\t\tif ( texture && texture.isWebGLCubeRenderTarget ) {\n\n\t\t\tif ( warnedTextureCube === false ) {\n\n\t\t\t\tconsole.warn( \"THREE.WebGLTextures.safeSetTextureCube: don't use cube render targets as textures. Use their .texture property instead.\" );\n\t\t\t\twarnedTextureCube = true;\n\n\t\t\t}\n\n\t\t\ttexture = texture.texture;\n\n\t\t}\n\n\t\t// currently relying on the fact that WebGLCubeRenderTarget.texture is a Texture and NOT a CubeTexture\n\t\t// TODO: unify these code paths\n\t\tif ( ( texture && texture.isCubeTexture ) ||\n\t\t\t( Array.isArray( texture.image ) && texture.image.length === 6 ) ) {\n\n\t\t\t// CompressedTexture can have Array in image :/\n\n\t\t\t// this function alone should take care of cube textures\n\t\t\tsetTextureCube( texture, slot );\n\n\t\t} else {\n\n\t\t\t// assumed: texture property of THREE.WebGLCubeRenderTarget\n\t\t\tsetTextureCubeDynamic( texture, slot );\n\n\t\t}\n\n\t}\n\n\t//\n\n\tthis.allocateTextureUnit = allocateTextureUnit;\n\tthis.resetTextureUnits = resetTextureUnits;\n\n\tthis.setTexture2D = setTexture2D;\n\tthis.setTexture2DArray = setTexture2DArray;\n\tthis.setTexture3D = setTexture3D;\n\tthis.setTextureCube = setTextureCube;\n\tthis.setTextureCubeDynamic = setTextureCubeDynamic;\n\tthis.setupRenderTarget = setupRenderTarget;\n\tthis.updateRenderTargetMipmap = updateRenderTargetMipmap;\n\tthis.updateMultisampleRenderTarget = updateMultisampleRenderTarget;\n\n\tthis.safeSetTexture2D = safeSetTexture2D;\n\tthis.safeSetTextureCube = safeSetTextureCube;\n\n}\n\nexport { WebGLTextures };\n","/**\n * @author thespite / http://www.twitter.com/thespite\n */\n\nimport { RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_10x10_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RedFormat, RGBAFormat, RGBFormat, AlphaFormat, RedIntegerFormat, RGFormat, RGIntegerFormat, RGBIntegerFormat, RGBAIntegerFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedShort565Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, SRGB8_ALPHA8_ASTC_4x4_Format, SRGB8_ALPHA8_ASTC_5x4_Format, SRGB8_ALPHA8_ASTC_5x5_Format, SRGB8_ALPHA8_ASTC_6x5_Format, SRGB8_ALPHA8_ASTC_6x6_Format, SRGB8_ALPHA8_ASTC_8x5_Format, SRGB8_ALPHA8_ASTC_8x6_Format, SRGB8_ALPHA8_ASTC_8x8_Format, SRGB8_ALPHA8_ASTC_10x5_Format, SRGB8_ALPHA8_ASTC_10x6_Format, SRGB8_ALPHA8_ASTC_10x8_Format, SRGB8_ALPHA8_ASTC_10x10_Format, SRGB8_ALPHA8_ASTC_12x10_Format, SRGB8_ALPHA8_ASTC_12x12_Format, RGBA_BPTC_Format } from '../../constants.js';\n\nfunction WebGLUtils( gl, extensions, capabilities ) {\n\n\tvar isWebGL2 = capabilities.isWebGL2;\n\n\tfunction convert( p ) {\n\n\t\tvar extension;\n\n\t\tif ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE;\n\t\tif ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4;\n\t\tif ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1;\n\t\tif ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5;\n\n\t\tif ( p === ByteType ) return gl.BYTE;\n\t\tif ( p === ShortType ) return gl.SHORT;\n\t\tif ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT;\n\t\tif ( p === IntType ) return gl.INT;\n\t\tif ( p === UnsignedIntType ) return gl.UNSIGNED_INT;\n\t\tif ( p === FloatType ) return gl.FLOAT;\n\n\t\tif ( p === HalfFloatType ) {\n\n\t\t\tif ( isWebGL2 ) return gl.HALF_FLOAT;\n\n\t\t\textension = extensions.get( 'OES_texture_half_float' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\treturn extension.HALF_FLOAT_OES;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === AlphaFormat ) return gl.ALPHA;\n\t\tif ( p === RGBFormat ) return gl.RGB;\n\t\tif ( p === RGBAFormat ) return gl.RGBA;\n\t\tif ( p === LuminanceFormat ) return gl.LUMINANCE;\n\t\tif ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA;\n\t\tif ( p === DepthFormat ) return gl.DEPTH_COMPONENT;\n\t\tif ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL;\n\t\tif ( p === RedFormat ) return gl.RED;\n\n\t\t// WebGL2 formats.\n\n\t\tif ( p === RedIntegerFormat ) return gl.RED_INTEGER;\n\t\tif ( p === RGFormat ) return gl.RG;\n\t\tif ( p === RGIntegerFormat ) return gl.RG_INTEGER;\n\t\tif ( p === RGBIntegerFormat ) return gl.RGB_INTEGER;\n\t\tif ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER;\n\n\t\tif ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format ||\n\t\t\tp === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) {\n\n\t\t\textension = extensions.get( 'WEBGL_compressed_texture_s3tc' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\tif ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT;\n\t\t\t\tif ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT;\n\t\t\t\tif ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT;\n\t\t\t\tif ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format ||\n\t\t\tp === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) {\n\n\t\t\textension = extensions.get( 'WEBGL_compressed_texture_pvrtc' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\tif ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;\n\t\t\t\tif ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;\n\t\t\t\tif ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;\n\t\t\t\tif ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === RGB_ETC1_Format ) {\n\n\t\t\textension = extensions.get( 'WEBGL_compressed_texture_etc1' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\treturn extension.COMPRESSED_RGB_ETC1_WEBGL;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) {\n\n\t\t\textension = extensions.get( 'WEBGL_compressed_texture_etc' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\tif ( p === RGB_ETC2_Format ) return extension.COMPRESSED_RGB8_ETC2;\n\t\t\t\tif ( p === RGBA_ETC2_EAC_Format ) return extension.COMPRESSED_RGBA8_ETC2_EAC;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format ||\n\t\t\tp === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format ||\n\t\t\tp === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format ||\n\t\t\tp === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format ||\n\t\t\tp === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ||\n\t\t\tp === SRGB8_ALPHA8_ASTC_4x4_Format || p === SRGB8_ALPHA8_ASTC_5x4_Format || p === SRGB8_ALPHA8_ASTC_5x5_Format ||\n\t\t\tp === SRGB8_ALPHA8_ASTC_6x5_Format || p === SRGB8_ALPHA8_ASTC_6x6_Format || p === SRGB8_ALPHA8_ASTC_8x5_Format ||\n\t\t\tp === SRGB8_ALPHA8_ASTC_8x6_Format || p === SRGB8_ALPHA8_ASTC_8x8_Format || p === SRGB8_ALPHA8_ASTC_10x5_Format ||\n\t\t\tp === SRGB8_ALPHA8_ASTC_10x6_Format || p === SRGB8_ALPHA8_ASTC_10x8_Format || p === SRGB8_ALPHA8_ASTC_10x10_Format ||\n\t\t\tp === SRGB8_ALPHA8_ASTC_12x10_Format || p === SRGB8_ALPHA8_ASTC_12x12_Format ) {\n\n\t\t\textension = extensions.get( 'WEBGL_compressed_texture_astc' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\t// TODO Complete?\n\n\t\t\t\treturn p;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === RGBA_BPTC_Format ) {\n\n\t\t\textension = extensions.get( 'EXT_texture_compression_bptc' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\t// TODO Complete?\n\n\t\t\t\treturn p;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( p === UnsignedInt248Type ) {\n\n\t\t\tif ( isWebGL2 ) return gl.UNSIGNED_INT_24_8;\n\n\t\t\textension = extensions.get( 'WEBGL_depth_texture' );\n\n\t\t\tif ( extension !== null ) {\n\n\t\t\t\treturn extension.UNSIGNED_INT_24_8_WEBGL;\n\n\t\t\t} else {\n\n\t\t\t\treturn null;\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\treturn { convert: convert };\n\n}\n\n\nexport { WebGLUtils };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { PerspectiveCamera } from './PerspectiveCamera.js';\n\nfunction ArrayCamera( array ) {\n\n\tPerspectiveCamera.call( this );\n\n\tthis.cameras = array || [];\n\n}\n\nArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), {\n\n\tconstructor: ArrayCamera,\n\n\tisArrayCamera: true\n\n} );\n\n\nexport { ArrayCamera };\n","import { Object3D } from '../core/Object3D.js';\n\n/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nfunction Group() {\n\n\tObject3D.call( this );\n\n\tthis.type = 'Group';\n\n}\n\nGroup.prototype = Object.assign( Object.create( Object3D.prototype ), {\n\n\tconstructor: Group,\n\n\tisGroup: true\n\n} );\n\n\nexport { Group };\n","import { Group } from '../../objects/Group.js';\n\n/**\n * @author Mugen87 / https://github.com/Mugen87\n */\n\nfunction WebXRController() {\n\n\tthis._targetRay = null;\n\tthis._grip = null;\n\n}\n\nObject.assign( WebXRController.prototype, {\n\n\tconstructor: WebXRController,\n\n\tgetTargetRaySpace: function () {\n\n\t\tif ( this._targetRay === null ) {\n\n\t\t\tthis._targetRay = new Group();\n\t\t\tthis._targetRay.matrixAutoUpdate = false;\n\t\t\tthis._targetRay.visible = false;\n\n\t\t}\n\n\t\treturn this._targetRay;\n\n\t},\n\n\tgetGripSpace: function () {\n\n\t\tif ( this._grip === null ) {\n\n\t\t\tthis._grip = new Group();\n\t\t\tthis._grip.matrixAutoUpdate = false;\n\t\t\tthis._grip.visible = false;\n\n\t\t}\n\n\t\treturn this._grip;\n\n\t},\n\n\tdispatchEvent: function ( event ) {\n\n\t\tif ( this._targetRay !== null ) {\n\n\t\t\tthis._targetRay.dispatchEvent( event );\n\n\t\t}\n\n\t\tif ( this._grip !== null ) {\n\n\t\t\tthis._grip.dispatchEvent( event );\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tdisconnect: function ( inputSource ) {\n\n\t\tthis.dispatchEvent( { type: 'disconnected', data: inputSource } );\n\n\t\tif ( this._targetRay !== null ) {\n\n\t\t\tthis._targetRay.visible = false;\n\n\t\t}\n\n\t\tif ( this._grip !== null ) {\n\n\t\t\tthis._grip.visible = false;\n\n\t\t}\n\n\t\treturn this;\n\n\t},\n\n\tupdate: function ( inputSource, frame, referenceSpace ) {\n\n\t\tvar inputPose = null;\n\t\tvar gripPose = null;\n\n\t\tvar targetRay = this._targetRay;\n\t\tvar grip = this._grip;\n\n\t\tif ( inputSource ) {\n\n\t\t\tif ( targetRay !== null ) {\n\n\t\t\t\tinputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );\n\n\t\t\t\tif ( inputPose !== null ) {\n\n\t\t\t\t\ttargetRay.matrix.fromArray( inputPose.transform.matrix );\n\t\t\t\t\ttargetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( grip !== null && inputSource.gripSpace ) {\n\n\t\t\t\tgripPose = frame.getPose( inputSource.gripSpace, referenceSpace );\n\n\t\t\t\tif ( gripPose !== null ) {\n\n\t\t\t\t\tgrip.matrix.fromArray( gripPose.transform.matrix );\n\t\t\t\t\tgrip.matrix.decompose( grip.position, grip.rotation, grip.scale );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( targetRay !== null ) {\n\n\t\t\ttargetRay.visible = ( inputPose !== null );\n\n\t\t}\n\n\t\tif ( grip !== null ) {\n\n\t\t\tgrip.visible = ( gripPose !== null );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { WebXRController };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { ArrayCamera } from '../../cameras/ArrayCamera.js';\nimport { EventDispatcher } from '../../core/EventDispatcher.js';\nimport { PerspectiveCamera } from '../../cameras/PerspectiveCamera.js';\nimport { Vector3 } from '../../math/Vector3.js';\nimport { Vector4 } from '../../math/Vector4.js';\nimport { WebGLAnimation } from '../webgl/WebGLAnimation.js';\nimport { WebXRController } from './WebXRController.js';\n\nfunction WebXRManager( renderer, gl ) {\n\n\tvar scope = this;\n\n\tvar session = null;\n\n\tvar framebufferScaleFactor = 1.0;\n\n\tvar referenceSpace = null;\n\tvar referenceSpaceType = 'local-floor';\n\n\tvar pose = null;\n\n\tvar controllers = [];\n\tvar inputSourcesMap = new Map();\n\n\t//\n\n\tvar cameraL = new PerspectiveCamera();\n\tcameraL.layers.enable( 1 );\n\tcameraL.viewport = new Vector4();\n\n\tvar cameraR = new PerspectiveCamera();\n\tcameraR.layers.enable( 2 );\n\tcameraR.viewport = new Vector4();\n\n\tvar cameras = [ cameraL, cameraR ];\n\n\tvar cameraVR = new ArrayCamera();\n\tcameraVR.layers.enable( 1 );\n\tcameraVR.layers.enable( 2 );\n\n\tvar _currentDepthNear = null;\n\tvar _currentDepthFar = null;\n\n\t//\n\n\tthis.enabled = false;\n\n\tthis.isPresenting = false;\n\n\tthis.getController = function ( index ) {\n\n\t\tvar controller = controllers[ index ];\n\n\t\tif ( controller === undefined ) {\n\n\t\t\tcontroller = new WebXRController();\n\t\t\tcontrollers[ index ] = controller;\n\n\t\t}\n\n\t\treturn controller.getTargetRaySpace();\n\n\t};\n\n\tthis.getControllerGrip = function ( index ) {\n\n\t\tvar controller = controllers[ index ];\n\n\t\tif ( controller === undefined ) {\n\n\t\t\tcontroller = new WebXRController();\n\t\t\tcontrollers[ index ] = controller;\n\n\t\t}\n\n\t\treturn controller.getGripSpace();\n\n\t};\n\n\t//\n\n\tfunction onSessionEvent( event ) {\n\n\t\tvar controller = inputSourcesMap.get( event.inputSource );\n\n\t\tif ( controller ) {\n\n\t\t\tcontroller.dispatchEvent( { type: event.type } );\n\n\t\t}\n\n\t}\n\n\tfunction onSessionEnd() {\n\n\t\tinputSourcesMap.forEach( function ( controller, inputSource ) {\n\n\t\t\tcontroller.disconnect( inputSource );\n\n\t\t} );\n\n\t\tinputSourcesMap.clear();\n\n\t\t//\n\n\t\trenderer.setFramebuffer( null );\n\t\trenderer.setRenderTarget( renderer.getRenderTarget() ); // Hack #15830\n\t\tanimation.stop();\n\n\t\tscope.isPresenting = false;\n\n\t\tscope.dispatchEvent( { type: 'sessionend' } );\n\n\t}\n\n\tfunction onRequestReferenceSpace( value ) {\n\n\t\treferenceSpace = value;\n\n\t\tanimation.setContext( session );\n\t\tanimation.start();\n\n\t\tscope.isPresenting = true;\n\n\t\tscope.dispatchEvent( { type: 'sessionstart' } );\n\n\t}\n\n\tthis.setFramebufferScaleFactor = function ( value ) {\n\n\t\tframebufferScaleFactor = value;\n\n\t\tif ( scope.isPresenting === true ) {\n\n\t\t\tconsole.warn( 'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );\n\n\t\t}\n\n\t};\n\n\tthis.setReferenceSpaceType = function ( value ) {\n\n\t\treferenceSpaceType = value;\n\n\t\tif ( scope.isPresenting === true ) {\n\n\t\t\tconsole.warn( 'THREE.WebXRManager: Cannot change reference space type while presenting.' );\n\n\t\t}\n\n\t};\n\n\tthis.getReferenceSpace = function () {\n\n\t\treturn referenceSpace;\n\n\t};\n\n\tthis.getSession = function () {\n\n\t\treturn session;\n\n\t};\n\n\tthis.setSession = function ( value ) {\n\n\t\tsession = value;\n\n\t\tif ( session !== null ) {\n\n\t\t\tsession.addEventListener( 'select', onSessionEvent );\n\t\t\tsession.addEventListener( 'selectstart', onSessionEvent );\n\t\t\tsession.addEventListener( 'selectend', onSessionEvent );\n\t\t\tsession.addEventListener( 'squeeze', onSessionEvent );\n\t\t\tsession.addEventListener( 'squeezestart', onSessionEvent );\n\t\t\tsession.addEventListener( 'squeezeend', onSessionEvent );\n\t\t\tsession.addEventListener( 'end', onSessionEnd );\n\n\t\t\tvar attributes = gl.getContextAttributes();\n\n\t\t\tif ( attributes.xrCompatible !== true ) {\n\n\t\t\t\tgl.makeXRCompatible();\n\n\t\t\t}\n\n\t\t\tvar layerInit = {\n\t\t\t\tantialias: attributes.antialias,\n\t\t\t\talpha: attributes.alpha,\n\t\t\t\tdepth: attributes.depth,\n\t\t\t\tstencil: attributes.stencil,\n\t\t\t\tframebufferScaleFactor: framebufferScaleFactor\n\t\t\t};\n\n\t\t\t// eslint-disable-next-line no-undef\n\t\t\tvar baseLayer = new XRWebGLLayer( session, gl, layerInit );\n\n\t\t\tsession.updateRenderState( { baseLayer: baseLayer } );\n\n\t\t\tsession.requestReferenceSpace( referenceSpaceType ).then( onRequestReferenceSpace );\n\n\t\t\t//\n\n\t\t\tsession.addEventListener( 'inputsourceschange', updateInputSources );\n\n\t\t}\n\n\t};\n\n\tfunction updateInputSources( event ) {\n\n\t\tvar inputSources = session.inputSources;\n\n\t\t// Assign inputSources to available controllers\n\n\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\n\n\t\t\tinputSourcesMap.set( inputSources[ i ], controllers[ i ] );\n\n\t\t}\n\n\t\t// Notify disconnected\n\n\t\tfor ( var i = 0; i < event.removed.length; i ++ ) {\n\n\t\t\tvar inputSource = event.removed[ i ];\n\t\t\tvar controller = inputSourcesMap.get( inputSource );\n\n\t\t\tif ( controller ) {\n\n\t\t\t\tcontroller.dispatchEvent( { type: 'disconnected', data: inputSource } );\n\t\t\t\tinputSourcesMap.delete( inputSource );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Notify connected\n\n\t\tfor ( var i = 0; i < event.added.length; i ++ ) {\n\n\t\t\tvar inputSource = event.added[ i ];\n\t\t\tvar controller = inputSourcesMap.get( inputSource );\n\n\t\t\tif ( controller ) {\n\n\t\t\t\tcontroller.dispatchEvent( { type: 'connected', data: inputSource } );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\t//\n\n\tvar cameraLPos = new Vector3();\n\tvar cameraRPos = new Vector3();\n\n\t/**\n\t * @author jsantell / https://www.jsantell.com/\n\t *\n\t * Assumes 2 cameras that are parallel and share an X-axis, and that\n\t * the cameras' projection and world matrices have already been set.\n\t * And that near and far planes are identical for both cameras.\n\t * Visualization of this technique: https://computergraphics.stackexchange.com/a/4765\n\t */\n\tfunction setProjectionFromUnion( camera, cameraL, cameraR ) {\n\n\t\tcameraLPos.setFromMatrixPosition( cameraL.matrixWorld );\n\t\tcameraRPos.setFromMatrixPosition( cameraR.matrixWorld );\n\n\t\tvar ipd = cameraLPos.distanceTo( cameraRPos );\n\n\t\tvar projL = cameraL.projectionMatrix.elements;\n\t\tvar projR = cameraR.projectionMatrix.elements;\n\n\t\t// VR systems will have identical far and near planes, and\n\t\t// most likely identical top and bottom frustum extents.\n\t\t// Use the left camera for these values.\n\t\tvar near = projL[ 14 ] / ( projL[ 10 ] - 1 );\n\t\tvar far = projL[ 14 ] / ( projL[ 10 ] + 1 );\n\t\tvar topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];\n\t\tvar bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];\n\n\t\tvar leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];\n\t\tvar rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];\n\t\tvar left = near * leftFov;\n\t\tvar right = near * rightFov;\n\n\t\t// Calculate the new camera's position offset from the\n\t\t// left camera. xOffset should be roughly half `ipd`.\n\t\tvar zOffset = ipd / ( - leftFov + rightFov );\n\t\tvar xOffset = zOffset * - leftFov;\n\n\t\t// TODO: Better way to apply this offset?\n\t\tcameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );\n\t\tcamera.translateX( xOffset );\n\t\tcamera.translateZ( zOffset );\n\t\tcamera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );\n\t\tcamera.matrixWorldInverse.getInverse( camera.matrixWorld );\n\n\t\t// Find the union of the frustum values of the cameras and scale\n\t\t// the values so that the near plane's position does not change in world space,\n\t\t// although must now be relative to the new union camera.\n\t\tvar near2 = near + zOffset;\n\t\tvar far2 = far + zOffset;\n\t\tvar left2 = left - xOffset;\n\t\tvar right2 = right + ( ipd - xOffset );\n\t\tvar top2 = topFov * far / far2 * near2;\n\t\tvar bottom2 = bottomFov * far / far2 * near2;\n\n\t\tcamera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );\n\n\t}\n\n\tfunction updateCamera( camera, parent ) {\n\n\t\tif ( parent === null ) {\n\n\t\t\tcamera.matrixWorld.copy( camera.matrix );\n\n\t\t} else {\n\n\t\t\tcamera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );\n\n\t\t}\n\n\t\tcamera.matrixWorldInverse.getInverse( camera.matrixWorld );\n\n\t}\n\n\tthis.getCamera = function ( camera ) {\n\n\t\tcameraVR.near = cameraR.near = cameraL.near = camera.near;\n\t\tcameraVR.far = cameraR.far = cameraL.far = camera.far;\n\n\t\tif ( _currentDepthNear !== cameraVR.near || _currentDepthFar !== cameraVR.far ) {\n\n\t\t\t// Note that the new renderState won't apply until the next frame. See #18320\n\n\t\t\tsession.updateRenderState( {\n\t\t\t\tdepthNear: cameraVR.near,\n\t\t\t\tdepthFar: cameraVR.far\n\t\t\t} );\n\n\t\t\t_currentDepthNear = cameraVR.near;\n\t\t\t_currentDepthFar = cameraVR.far;\n\n\t\t}\n\n\t\tvar parent = camera.parent;\n\t\tvar cameras = cameraVR.cameras;\n\n\t\tupdateCamera( cameraVR, parent );\n\n\t\tfor ( var i = 0; i < cameras.length; i ++ ) {\n\n\t\t\tupdateCamera( cameras[ i ], parent );\n\n\t\t}\n\n\t\t// update camera and its children\n\n\t\tcamera.matrixWorld.copy( cameraVR.matrixWorld );\n\n\t\tvar children = camera.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tchildren[ i ].updateMatrixWorld( true );\n\n\t\t}\n\n\t\t// update projection matrix for proper view frustum culling\n\n\t\tif ( cameras.length === 2 ) {\n\n\t\t\tsetProjectionFromUnion( cameraVR, cameraL, cameraR );\n\n\t\t} else {\n\n\t\t\t// assume single camera setup (AR)\n\n\t\t\tcameraVR.projectionMatrix.copy( cameraL.projectionMatrix );\n\n\t\t}\n\n\t\treturn cameraVR;\n\n\t};\n\n\t// Animation Loop\n\n\tvar onAnimationFrameCallback = null;\n\n\tfunction onAnimationFrame( time, frame ) {\n\n\t\tpose = frame.getViewerPose( referenceSpace );\n\n\t\tif ( pose !== null ) {\n\n\t\t\tvar views = pose.views;\n\t\t\tvar baseLayer = session.renderState.baseLayer;\n\n\t\t\trenderer.setFramebuffer( baseLayer.framebuffer );\n\n\t\t\tvar cameraVRNeedsUpdate = false;\n\n\t\t\t// check if it's necessary to rebuild cameraVR's camera list\n\n\t\t\tif ( views.length !== cameraVR.cameras.length ) {\n\n\t\t\t\tcameraVR.cameras.length = 0;\n\t\t\t\tcameraVRNeedsUpdate = true;\n\n\t\t\t}\n\n\t\t\tfor ( var i = 0; i < views.length; i ++ ) {\n\n\t\t\t\tvar view = views[ i ];\n\t\t\t\tvar viewport = baseLayer.getViewport( view );\n\n\t\t\t\tvar camera = cameras[ i ];\n\t\t\t\tcamera.matrix.fromArray( view.transform.matrix );\n\t\t\t\tcamera.projectionMatrix.fromArray( view.projectionMatrix );\n\t\t\t\tcamera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );\n\n\t\t\t\tif ( i === 0 ) {\n\n\t\t\t\t\tcameraVR.matrix.copy( camera.matrix );\n\n\t\t\t\t}\n\n\t\t\t\tif ( cameraVRNeedsUpdate === true ) {\n\n\t\t\t\t\tcameraVR.cameras.push( camera );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\t//\n\n\t\tvar inputSources = session.inputSources;\n\n\t\tfor ( var i = 0; i < controllers.length; i ++ ) {\n\n\t\t\tvar controller = controllers[ i ];\n\t\t\tvar inputSource = inputSources[ i ];\n\n\t\t\tcontroller.update( inputSource, frame, referenceSpace );\n\n\t\t}\n\n\t\tif ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );\n\n\t}\n\n\tvar animation = new WebGLAnimation();\n\tanimation.setAnimationLoop( onAnimationFrame );\n\n\tthis.setAnimationLoop = function ( callback ) {\n\n\t\tonAnimationFrameCallback = callback;\n\n\t};\n\n\tthis.dispose = function () {};\n\n}\n\nObject.assign( WebXRManager.prototype, EventDispatcher.prototype );\n\nexport { WebXRManager };\n","/**\n * @author mrdoob / http://mrdoob.com/\n */\n\nimport { BackSide } from \"../../constants.js\";\n\nfunction WebGLMaterials( properties ) {\n\n\tfunction refreshFogUniforms( uniforms, fog ) {\n\n\t\tuniforms.fogColor.value.copy( fog.color );\n\n\t\tif ( fog.isFog ) {\n\n\t\t\tuniforms.fogNear.value = fog.near;\n\t\t\tuniforms.fogFar.value = fog.far;\n\n\t\t} else if ( fog.isFogExp2 ) {\n\n\t\t\tuniforms.fogDensity.value = fog.density;\n\n\t\t}\n\n\t}\n\n\tfunction refreshMaterialUniforms( uniforms, material, environment, pixelRatio, height ) {\n\n\t\tif ( material.isMeshBasicMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\n\t\t} else if ( material.isMeshLambertMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsLambert( uniforms, material );\n\n\t\t} else if ( material.isMeshToonMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsToon( uniforms, material );\n\n\t\t} else if ( material.isMeshPhongMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsPhong( uniforms, material );\n\n\t\t} else if ( material.isMeshStandardMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material, environment );\n\n\t\t\tif ( material.isMeshPhysicalMaterial ) {\n\n\t\t\t\trefreshUniformsPhysical( uniforms, material, environment );\n\n\t\t\t} else {\n\n\t\t\t\trefreshUniformsStandard( uniforms, material, environment );\n\n\t\t\t}\n\n\t\t} else if ( material.isMeshMatcapMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsMatcap( uniforms, material );\n\n\t\t} else if ( material.isMeshDepthMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsDepth( uniforms, material );\n\n\t\t} else if ( material.isMeshDistanceMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsDistance( uniforms, material );\n\n\t\t} else if ( material.isMeshNormalMaterial ) {\n\n\t\t\trefreshUniformsCommon( uniforms, material );\n\t\t\trefreshUniformsNormal( uniforms, material );\n\n\t\t} else if ( material.isLineBasicMaterial ) {\n\n\t\t\trefreshUniformsLine( uniforms, material );\n\n\t\t\tif ( material.isLineDashedMaterial ) {\n\n\t\t\t\trefreshUniformsDash( uniforms, material );\n\n\t\t\t}\n\n\t\t} else if ( material.isPointsMaterial ) {\n\n\t\t\trefreshUniformsPoints( uniforms, material, pixelRatio, height );\n\n\t\t} else if ( material.isSpriteMaterial ) {\n\n\t\t\trefreshUniformsSprites( uniforms, material );\n\n\t\t} else if ( material.isShadowMaterial ) {\n\n\t\t\tuniforms.color.value.copy( material.color );\n\t\t\tuniforms.opacity.value = material.opacity;\n\n\t\t} else if ( material.isShaderMaterial ) {\n\n\t\t\tmaterial.uniformsNeedUpdate = false; // #15581\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsCommon( uniforms, material, environment ) {\n\n\t\tuniforms.opacity.value = material.opacity;\n\n\t\tif ( material.color ) {\n\n\t\t\tuniforms.diffuse.value.copy( material.color );\n\n\t\t}\n\n\t\tif ( material.emissive ) {\n\n\t\t\tuniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );\n\n\t\t}\n\n\t\tif ( material.map ) {\n\n\t\t\tuniforms.map.value = material.map;\n\n\t\t}\n\n\t\tif ( material.alphaMap ) {\n\n\t\t\tuniforms.alphaMap.value = material.alphaMap;\n\n\t\t}\n\n\t\tif ( material.specularMap ) {\n\n\t\t\tuniforms.specularMap.value = material.specularMap;\n\n\t\t}\n\n\t\tvar envMap = material.envMap || environment;\n\n\t\tif ( envMap ) {\n\n\t\t\tuniforms.envMap.value = envMap;\n\n\t\t\tuniforms.flipEnvMap.value = envMap.isCubeTexture ? - 1 : 1;\n\n\t\t\tuniforms.reflectivity.value = material.reflectivity;\n\t\t\tuniforms.refractionRatio.value = material.refractionRatio;\n\n\t\t\tuniforms.maxMipLevel.value = properties.get( envMap ).__maxMipLevel;\n\n\t\t}\n\n\t\tif ( material.lightMap ) {\n\n\t\t\tuniforms.lightMap.value = material.lightMap;\n\t\t\tuniforms.lightMapIntensity.value = material.lightMapIntensity;\n\n\t\t}\n\n\t\tif ( material.aoMap ) {\n\n\t\t\tuniforms.aoMap.value = material.aoMap;\n\t\t\tuniforms.aoMapIntensity.value = material.aoMapIntensity;\n\n\t\t}\n\n\t\t// uv repeat and offset setting priorities\n\t\t// 1. color map\n\t\t// 2. specular map\n\t\t// 3. normal map\n\t\t// 4. bump map\n\t\t// 5. alpha map\n\t\t// 6. emissive map\n\n\t\tvar uvScaleMap;\n\n\t\tif ( material.map ) {\n\n\t\t\tuvScaleMap = material.map;\n\n\t\t} else if ( material.specularMap ) {\n\n\t\t\tuvScaleMap = material.specularMap;\n\n\t\t} else if ( material.displacementMap ) {\n\n\t\t\tuvScaleMap = material.displacementMap;\n\n\t\t} else if ( material.normalMap ) {\n\n\t\t\tuvScaleMap = material.normalMap;\n\n\t\t} else if ( material.bumpMap ) {\n\n\t\t\tuvScaleMap = material.bumpMap;\n\n\t\t} else if ( material.roughnessMap ) {\n\n\t\t\tuvScaleMap = material.roughnessMap;\n\n\t\t} else if ( material.metalnessMap ) {\n\n\t\t\tuvScaleMap = material.metalnessMap;\n\n\t\t} else if ( material.alphaMap ) {\n\n\t\t\tuvScaleMap = material.alphaMap;\n\n\t\t} else if ( material.emissiveMap ) {\n\n\t\t\tuvScaleMap = material.emissiveMap;\n\n\t\t}\n\n\t\tif ( uvScaleMap !== undefined ) {\n\n\t\t\t// backwards compatibility\n\t\t\tif ( uvScaleMap.isWebGLRenderTarget ) {\n\n\t\t\t\tuvScaleMap = uvScaleMap.texture;\n\n\t\t\t}\n\n\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\n\n\t\t\t\tuvScaleMap.updateMatrix();\n\n\t\t\t}\n\n\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\n\n\t\t}\n\n\t\t// uv repeat and offset setting priorities for uv2\n\t\t// 1. ao map\n\t\t// 2. light map\n\n\t\tvar uv2ScaleMap;\n\n\t\tif ( material.aoMap ) {\n\n\t\t\tuv2ScaleMap = material.aoMap;\n\n\t\t} else if ( material.lightMap ) {\n\n\t\t\tuv2ScaleMap = material.lightMap;\n\n\t\t}\n\n\t\tif ( uv2ScaleMap !== undefined ) {\n\n\t\t\t// backwards compatibility\n\t\t\tif ( uv2ScaleMap.isWebGLRenderTarget ) {\n\n\t\t\t\tuv2ScaleMap = uv2ScaleMap.texture;\n\n\t\t\t}\n\n\t\t\tif ( uv2ScaleMap.matrixAutoUpdate === true ) {\n\n\t\t\t\tuv2ScaleMap.updateMatrix();\n\n\t\t\t}\n\n\t\t\tuniforms.uv2Transform.value.copy( uv2ScaleMap.matrix );\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsLine( uniforms, material ) {\n\n\t\tuniforms.diffuse.value.copy( material.color );\n\t\tuniforms.opacity.value = material.opacity;\n\n\t}\n\n\tfunction refreshUniformsDash( uniforms, material ) {\n\n\t\tuniforms.dashSize.value = material.dashSize;\n\t\tuniforms.totalSize.value = material.dashSize + material.gapSize;\n\t\tuniforms.scale.value = material.scale;\n\n\t}\n\n\tfunction refreshUniformsPoints( uniforms, material, pixelRatio, height ) {\n\n\t\tuniforms.diffuse.value.copy( material.color );\n\t\tuniforms.opacity.value = material.opacity;\n\t\tuniforms.size.value = material.size * pixelRatio;\n\t\tuniforms.scale.value = height * 0.5;\n\n\t\tif ( material.map ) {\n\n\t\t\tuniforms.map.value = material.map;\n\n\t\t}\n\n\t\tif ( material.alphaMap ) {\n\n\t\t\tuniforms.alphaMap.value = material.alphaMap;\n\n\t\t}\n\n\t\t// uv repeat and offset setting priorities\n\t\t// 1. color map\n\t\t// 2. alpha map\n\n\t\tvar uvScaleMap;\n\n\t\tif ( material.map ) {\n\n\t\t\tuvScaleMap = material.map;\n\n\t\t} else if ( material.alphaMap ) {\n\n\t\t\tuvScaleMap = material.alphaMap;\n\n\t\t}\n\n\t\tif ( uvScaleMap !== undefined ) {\n\n\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\n\n\t\t\t\tuvScaleMap.updateMatrix();\n\n\t\t\t}\n\n\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsSprites( uniforms, material ) {\n\n\t\tuniforms.diffuse.value.copy( material.color );\n\t\tuniforms.opacity.value = material.opacity;\n\t\tuniforms.rotation.value = material.rotation;\n\n\t\tif ( material.map ) {\n\n\t\t\tuniforms.map.value = material.map;\n\n\t\t}\n\n\t\tif ( material.alphaMap ) {\n\n\t\t\tuniforms.alphaMap.value = material.alphaMap;\n\n\t\t}\n\n\t\t// uv repeat and offset setting priorities\n\t\t// 1. color map\n\t\t// 2. alpha map\n\n\t\tvar uvScaleMap;\n\n\t\tif ( material.map ) {\n\n\t\t\tuvScaleMap = material.map;\n\n\t\t} else if ( material.alphaMap ) {\n\n\t\t\tuvScaleMap = material.alphaMap;\n\n\t\t}\n\n\t\tif ( uvScaleMap !== undefined ) {\n\n\t\t\tif ( uvScaleMap.matrixAutoUpdate === true ) {\n\n\t\t\t\tuvScaleMap.updateMatrix();\n\n\t\t\t}\n\n\t\t\tuniforms.uvTransform.value.copy( uvScaleMap.matrix );\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsLambert( uniforms, material ) {\n\n\t\tif ( material.emissiveMap ) {\n\n\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsPhong( uniforms, material ) {\n\n\t\tuniforms.specular.value.copy( material.specular );\n\t\tuniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )\n\n\t\tif ( material.emissiveMap ) {\n\n\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\n\n\t\t}\n\n\t\tif ( material.bumpMap ) {\n\n\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\tuniforms.bumpScale.value = material.bumpScale;\n\t\t\tif ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;\n\n\t\t}\n\n\t\tif ( material.normalMap ) {\n\n\t\t\tuniforms.normalMap.value = material.normalMap;\n\t\t\tuniforms.normalScale.value.copy( material.normalScale );\n\t\t\tif ( material.side === BackSide ) uniforms.normalScale.value.negate();\n\n\t\t}\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsToon( uniforms, material ) {\n\n\t\tuniforms.specular.value.copy( material.specular );\n\t\tuniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 )\n\n\t\tif ( material.gradientMap ) {\n\n\t\t\tuniforms.gradientMap.value = material.gradientMap;\n\n\t\t}\n\n\t\tif ( material.emissiveMap ) {\n\n\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\n\n\t\t}\n\n\t\tif ( material.bumpMap ) {\n\n\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\tuniforms.bumpScale.value = material.bumpScale;\n\t\t\tif ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;\n\n\t\t}\n\n\t\tif ( material.normalMap ) {\n\n\t\t\tuniforms.normalMap.value = material.normalMap;\n\t\t\tuniforms.normalScale.value.copy( material.normalScale );\n\t\t\tif ( material.side === BackSide ) uniforms.normalScale.value.negate();\n\n\t\t}\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsStandard( uniforms, material, environment ) {\n\n\t\tuniforms.roughness.value = material.roughness;\n\t\tuniforms.metalness.value = material.metalness;\n\n\t\tif ( material.roughnessMap ) {\n\n\t\t\tuniforms.roughnessMap.value = material.roughnessMap;\n\n\t\t}\n\n\t\tif ( material.metalnessMap ) {\n\n\t\t\tuniforms.metalnessMap.value = material.metalnessMap;\n\n\t\t}\n\n\t\tif ( material.emissiveMap ) {\n\n\t\t\tuniforms.emissiveMap.value = material.emissiveMap;\n\n\t\t}\n\n\t\tif ( material.bumpMap ) {\n\n\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\tuniforms.bumpScale.value = material.bumpScale;\n\t\t\tif ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;\n\n\t\t}\n\n\t\tif ( material.normalMap ) {\n\n\t\t\tuniforms.normalMap.value = material.normalMap;\n\t\t\tuniforms.normalScale.value.copy( material.normalScale );\n\t\t\tif ( material.side === BackSide ) uniforms.normalScale.value.negate();\n\n\t\t}\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t\tif ( material.envMap || environment ) {\n\n\t\t\t//uniforms.envMap.value = material.envMap; // part of uniforms common\n\t\t\tuniforms.envMapIntensity.value = material.envMapIntensity;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsPhysical( uniforms, material, environment ) {\n\n\t\trefreshUniformsStandard( uniforms, material, environment );\n\n\t\tuniforms.reflectivity.value = material.reflectivity; // also part of uniforms common\n\n\t\tuniforms.clearcoat.value = material.clearcoat;\n\t\tuniforms.clearcoatRoughness.value = material.clearcoatRoughness;\n\t\tif ( material.sheen ) uniforms.sheen.value.copy( material.sheen );\n\n\t\tif ( material.clearcoatMap ) {\n\n\t\t\tuniforms.clearcoatMap.value = material.clearcoatMap;\n\n\t\t}\n\n\t\tif ( material.clearcoatRoughnessMap ) {\n\n\t\t\tuniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;\n\n\t\t}\n\n\t\tif ( material.clearcoatNormalMap ) {\n\n\t\t\tuniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );\n\t\t\tuniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;\n\n\t\t\tif ( material.side === BackSide ) {\n\n\t\t\t\tuniforms.clearcoatNormalScale.value.negate();\n\n\t\t\t}\n\n\t\t}\n\n\t\tuniforms.transparency.value = material.transparency;\n\n\t}\n\n\tfunction refreshUniformsMatcap( uniforms, material ) {\n\n\t\tif ( material.matcap ) {\n\n\t\t\tuniforms.matcap.value = material.matcap;\n\n\t\t}\n\n\t\tif ( material.bumpMap ) {\n\n\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\tuniforms.bumpScale.value = material.bumpScale;\n\t\t\tif ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;\n\n\t\t}\n\n\t\tif ( material.normalMap ) {\n\n\t\t\tuniforms.normalMap.value = material.normalMap;\n\t\t\tuniforms.normalScale.value.copy( material.normalScale );\n\t\t\tif ( material.side === BackSide ) uniforms.normalScale.value.negate();\n\n\t\t}\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsDepth( uniforms, material ) {\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t}\n\n\tfunction refreshUniformsDistance( uniforms, material ) {\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t\tuniforms.referencePosition.value.copy( material.referencePosition );\n\t\tuniforms.nearDistance.value = material.nearDistance;\n\t\tuniforms.farDistance.value = material.farDistance;\n\n\t}\n\n\tfunction refreshUniformsNormal( uniforms, material ) {\n\n\t\tif ( material.bumpMap ) {\n\n\t\t\tuniforms.bumpMap.value = material.bumpMap;\n\t\t\tuniforms.bumpScale.value = material.bumpScale;\n\t\t\tif ( material.side === BackSide ) uniforms.bumpScale.value *= - 1;\n\n\t\t}\n\n\t\tif ( material.normalMap ) {\n\n\t\t\tuniforms.normalMap.value = material.normalMap;\n\t\t\tuniforms.normalScale.value.copy( material.normalScale );\n\t\t\tif ( material.side === BackSide ) uniforms.normalScale.value.negate();\n\n\t\t}\n\n\t\tif ( material.displacementMap ) {\n\n\t\t\tuniforms.displacementMap.value = material.displacementMap;\n\t\t\tuniforms.displacementScale.value = material.displacementScale;\n\t\t\tuniforms.displacementBias.value = material.displacementBias;\n\n\t\t}\n\n\t}\n\n\treturn {\n\t\trefreshFogUniforms: refreshFogUniforms,\n\t\trefreshMaterialUniforms: refreshMaterialUniforms\n\t};\n\n}\n\nexport { WebGLMaterials };\n","/**\n * @author supereggbert / http://www.paulbrunt.co.uk/\n * @author mrdoob / http://mrdoob.com/\n * @author alteredq / http://alteredqualia.com/\n * @author szimek / https://github.com/szimek/\n * @author tschw\n */\n\nimport {\n\tRGBAFormat,\n\tHalfFloatType,\n\tFloatType,\n\tUnsignedByteType,\n\tLinearEncoding,\n\tNoToneMapping\n} from '../constants.js';\nimport { MathUtils } from '../math/MathUtils.js';\nimport { DataTexture } from '../textures/DataTexture.js';\nimport { Frustum } from '../math/Frustum.js';\nimport { Matrix4 } from '../math/Matrix4.js';\nimport { UniformsLib } from './shaders/UniformsLib.js';\nimport { Vector2 } from '../math/Vector2.js';\nimport { Vector3 } from '../math/Vector3.js';\nimport { Vector4 } from '../math/Vector4.js';\nimport { Scene } from '../scenes/Scene.js';\nimport { WebGLAnimation } from './webgl/WebGLAnimation.js';\nimport { WebGLAttributes } from './webgl/WebGLAttributes.js';\nimport { WebGLBackground } from './webgl/WebGLBackground.js';\nimport { WebGLBufferRenderer } from './webgl/WebGLBufferRenderer.js';\nimport { WebGLCapabilities } from './webgl/WebGLCapabilities.js';\nimport { WebGLClipping } from './webgl/WebGLClipping.js';\nimport { WebGLExtensions } from './webgl/WebGLExtensions.js';\nimport { WebGLGeometries } from './webgl/WebGLGeometries.js';\nimport { WebGLIndexedBufferRenderer } from './webgl/WebGLIndexedBufferRenderer.js';\nimport { WebGLInfo } from './webgl/WebGLInfo.js';\nimport { WebGLMorphtargets } from './webgl/WebGLMorphtargets.js';\nimport { WebGLObjects } from './webgl/WebGLObjects.js';\nimport { WebGLPrograms } from './webgl/WebGLPrograms.js';\nimport { WebGLProperties } from './webgl/WebGLProperties.js';\nimport { WebGLRenderLists } from './webgl/WebGLRenderLists.js';\nimport { WebGLRenderStates } from './webgl/WebGLRenderStates.js';\nimport { WebGLShadowMap } from './webgl/WebGLShadowMap.js';\nimport { WebGLState } from './webgl/WebGLState.js';\nimport { WebGLTextures } from './webgl/WebGLTextures.js';\nimport { WebGLUniforms } from './webgl/WebGLUniforms.js';\nimport { WebGLUtils } from './webgl/WebGLUtils.js';\nimport { WebXRManager } from './webxr/WebXRManager.js';\nimport { WebGLMaterials } from \"./webgl/WebGLMaterials.js\";\n\nfunction WebGLRenderer( parameters ) {\n\n\tparameters = parameters || {};\n\n\tvar _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ),\n\t\t_context = parameters.context !== undefined ? parameters.context : null,\n\n\t\t_alpha = parameters.alpha !== undefined ? parameters.alpha : false,\n\t\t_depth = parameters.depth !== undefined ? parameters.depth : true,\n\t\t_stencil = parameters.stencil !== undefined ? parameters.stencil : true,\n\t\t_antialias = parameters.antialias !== undefined ? parameters.antialias : false,\n\t\t_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,\n\t\t_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,\n\t\t_powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default',\n\t\t_failIfMajorPerformanceCaveat = parameters.failIfMajorPerformanceCaveat !== undefined ? parameters.failIfMajorPerformanceCaveat : false;\n\n\tvar currentRenderList = null;\n\tvar currentRenderState = null;\n\n\t// public properties\n\n\tthis.domElement = _canvas;\n\n\t// Debug configuration container\n\tthis.debug = {\n\n\t\t/**\n\t\t * Enables error checking and reporting when shader programs are being compiled\n\t\t * @type {boolean}\n\t\t */\n\t\tcheckShaderErrors: true\n\t};\n\n\t// clearing\n\n\tthis.autoClear = true;\n\tthis.autoClearColor = true;\n\tthis.autoClearDepth = true;\n\tthis.autoClearStencil = true;\n\n\t// scene graph\n\n\tthis.sortObjects = true;\n\n\t// user-defined clipping\n\n\tthis.clippingPlanes = [];\n\tthis.localClippingEnabled = false;\n\n\t// physically based shading\n\n\tthis.gammaFactor = 2.0;\t// for backwards compatibility\n\tthis.outputEncoding = LinearEncoding;\n\n\t// physical lights\n\n\tthis.physicallyCorrectLights = false;\n\n\t// tone mapping\n\n\tthis.toneMapping = NoToneMapping;\n\tthis.toneMappingExposure = 1.0;\n\tthis.toneMappingWhitePoint = 1.0;\n\n\t// morphs\n\n\tthis.maxMorphTargets = 8;\n\tthis.maxMorphNormals = 4;\n\n\t// internal properties\n\n\tvar _this = this,\n\n\t\t_isContextLost = false,\n\n\t\t// internal state cache\n\n\t\t_framebuffer = null,\n\n\t\t_currentActiveCubeFace = 0,\n\t\t_currentActiveMipmapLevel = 0,\n\t\t_currentRenderTarget = null,\n\t\t_currentFramebuffer = null,\n\t\t_currentMaterialId = - 1,\n\n\t\t// geometry and program caching\n\n\t\t_currentGeometryProgram = {\n\t\t\tgeometry: null,\n\t\t\tprogram: null,\n\t\t\twireframe: false\n\t\t},\n\n\t\t_currentCamera = null,\n\t\t_currentArrayCamera = null,\n\n\t\t_currentViewport = new Vector4(),\n\t\t_currentScissor = new Vector4(),\n\t\t_currentScissorTest = null,\n\n\t\t//\n\n\t\t_width = _canvas.width,\n\t\t_height = _canvas.height,\n\n\t\t_pixelRatio = 1,\n\t\t_opaqueSort = null,\n\t\t_transparentSort = null,\n\n\t\t_viewport = new Vector4( 0, 0, _width, _height ),\n\t\t_scissor = new Vector4( 0, 0, _width, _height ),\n\t\t_scissorTest = false,\n\n\t\t// frustum\n\n\t\t_frustum = new Frustum(),\n\n\t\t// clipping\n\n\t\t_clipping = new WebGLClipping(),\n\t\t_clippingEnabled = false,\n\t\t_localClippingEnabled = false,\n\n\t\t// camera matrices cache\n\n\t\t_projScreenMatrix = new Matrix4(),\n\n\t\t_vector3 = new Vector3();\n\n\tfunction getTargetPixelRatio() {\n\n\t\treturn _currentRenderTarget === null ? _pixelRatio : 1;\n\n\t}\n\n\t// initialize\n\n\tvar _gl;\n\n\ttry {\n\n\t\tvar contextAttributes = {\n\t\t\talpha: _alpha,\n\t\t\tdepth: _depth,\n\t\t\tstencil: _stencil,\n\t\t\tantialias: _antialias,\n\t\t\tpremultipliedAlpha: _premultipliedAlpha,\n\t\t\tpreserveDrawingBuffer: _preserveDrawingBuffer,\n\t\t\tpowerPreference: _powerPreference,\n\t\t\tfailIfMajorPerformanceCaveat: _failIfMajorPerformanceCaveat\n\t\t};\n\n\t\t// event listeners must be registered before WebGL context is created, see #12753\n\n\t\t_canvas.addEventListener( 'webglcontextlost', onContextLost, false );\n\t\t_canvas.addEventListener( 'webglcontextrestored', onContextRestore, false );\n\n\t\t_gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );\n\n\t\tif ( _gl === null ) {\n\n\t\t\tif ( _canvas.getContext( 'webgl' ) !== null ) {\n\n\t\t\t\tthrow new Error( 'Error creating WebGL context with your selected attributes.' );\n\n\t\t\t} else {\n\n\t\t\t\tthrow new Error( 'Error creating WebGL context.' );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Some experimental-webgl implementations do not have getShaderPrecisionFormat\n\n\t\tif ( _gl.getShaderPrecisionFormat === undefined ) {\n\n\t\t\t_gl.getShaderPrecisionFormat = function () {\n\n\t\t\t\treturn { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 };\n\n\t\t\t};\n\n\t\t}\n\n\t} catch ( error ) {\n\n\t\tconsole.error( 'THREE.WebGLRenderer: ' + error.message );\n\t\tthrow error;\n\n\t}\n\n\tvar extensions, capabilities, state, info;\n\tvar properties, textures, attributes, geometries, objects;\n\tvar programCache, materials, renderLists, renderStates;\n\n\tvar background, morphtargets, bufferRenderer, indexedBufferRenderer;\n\n\tvar utils;\n\n\tfunction initGLContext() {\n\n\t\textensions = new WebGLExtensions( _gl );\n\n\t\tcapabilities = new WebGLCapabilities( _gl, extensions, parameters );\n\n\t\tif ( capabilities.isWebGL2 === false ) {\n\n\t\t\textensions.get( 'WEBGL_depth_texture' );\n\t\t\textensions.get( 'OES_texture_float' );\n\t\t\textensions.get( 'OES_texture_half_float' );\n\t\t\textensions.get( 'OES_texture_half_float_linear' );\n\t\t\textensions.get( 'OES_standard_derivatives' );\n\t\t\textensions.get( 'OES_element_index_uint' );\n\t\t\textensions.get( 'ANGLE_instanced_arrays' );\n\n\t\t}\n\n\t\textensions.get( 'OES_texture_float_linear' );\n\n\t\tutils = new WebGLUtils( _gl, extensions, capabilities );\n\n\t\tstate = new WebGLState( _gl, extensions, capabilities );\n\t\tstate.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );\n\t\tstate.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );\n\n\t\tinfo = new WebGLInfo( _gl );\n\t\tproperties = new WebGLProperties();\n\t\ttextures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );\n\t\tattributes = new WebGLAttributes( _gl, capabilities );\n\t\tgeometries = new WebGLGeometries( _gl, attributes, info );\n\t\tobjects = new WebGLObjects( _gl, geometries, attributes, info );\n\t\tmorphtargets = new WebGLMorphtargets( _gl );\n\t\tprogramCache = new WebGLPrograms( _this, extensions, capabilities );\n\t\tmaterials = new WebGLMaterials( properties );\n\t\trenderLists = new WebGLRenderLists();\n\t\trenderStates = new WebGLRenderStates();\n\n\t\tbackground = new WebGLBackground( _this, state, objects, _premultipliedAlpha );\n\n\t\tbufferRenderer = new WebGLBufferRenderer( _gl, extensions, info, capabilities );\n\t\tindexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );\n\n\t\tinfo.programs = programCache.programs;\n\n\t\t_this.capabilities = capabilities;\n\t\t_this.extensions = extensions;\n\t\t_this.properties = properties;\n\t\t_this.renderLists = renderLists;\n\t\t_this.state = state;\n\t\t_this.info = info;\n\n\t}\n\n\tinitGLContext();\n\n\t// xr\n\n\tvar xr = new WebXRManager( _this, _gl );\n\n\tthis.xr = xr;\n\n\t// shadow map\n\n\tvar shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );\n\n\tthis.shadowMap = shadowMap;\n\n\t// API\n\n\tthis.getContext = function () {\n\n\t\treturn _gl;\n\n\t};\n\n\tthis.getContextAttributes = function () {\n\n\t\treturn _gl.getContextAttributes();\n\n\t};\n\n\tthis.forceContextLoss = function () {\n\n\t\tvar extension = extensions.get( 'WEBGL_lose_context' );\n\t\tif ( extension ) extension.loseContext();\n\n\t};\n\n\tthis.forceContextRestore = function () {\n\n\t\tvar extension = extensions.get( 'WEBGL_lose_context' );\n\t\tif ( extension ) extension.restoreContext();\n\n\t};\n\n\tthis.getPixelRatio = function () {\n\n\t\treturn _pixelRatio;\n\n\t};\n\n\tthis.setPixelRatio = function ( value ) {\n\n\t\tif ( value === undefined ) return;\n\n\t\t_pixelRatio = value;\n\n\t\tthis.setSize( _width, _height, false );\n\n\t};\n\n\tthis.getSize = function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'WebGLRenderer: .getsize() now requires a Vector2 as an argument' );\n\n\t\t\ttarget = new Vector2();\n\n\t\t}\n\n\t\treturn target.set( _width, _height );\n\n\t};\n\n\tthis.setSize = function ( width, height, updateStyle ) {\n\n\t\tif ( xr.isPresenting ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer: Can\\'t change size while VR device is presenting.' );\n\t\t\treturn;\n\n\t\t}\n\n\t\t_width = width;\n\t\t_height = height;\n\n\t\t_canvas.width = Math.floor( width * _pixelRatio );\n\t\t_canvas.height = Math.floor( height * _pixelRatio );\n\n\t\tif ( updateStyle !== false ) {\n\n\t\t\t_canvas.style.width = width + 'px';\n\t\t\t_canvas.style.height = height + 'px';\n\n\t\t}\n\n\t\tthis.setViewport( 0, 0, width, height );\n\n\t};\n\n\tthis.getDrawingBufferSize = function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'WebGLRenderer: .getdrawingBufferSize() now requires a Vector2 as an argument' );\n\n\t\t\ttarget = new Vector2();\n\n\t\t}\n\n\t\treturn target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();\n\n\t};\n\n\tthis.setDrawingBufferSize = function ( width, height, pixelRatio ) {\n\n\t\t_width = width;\n\t\t_height = height;\n\n\t\t_pixelRatio = pixelRatio;\n\n\t\t_canvas.width = Math.floor( width * pixelRatio );\n\t\t_canvas.height = Math.floor( height * pixelRatio );\n\n\t\tthis.setViewport( 0, 0, width, height );\n\n\t};\n\n\tthis.getCurrentViewport = function ( target ) {\n\n\t\tif ( target === undefined ) {\n\n\t\t\tconsole.warn( 'WebGLRenderer: .getCurrentViewport() now requires a Vector4 as an argument' );\n\n\t\t\ttarget = new Vector4();\n\n\t\t}\n\n\t\treturn target.copy( _currentViewport );\n\n\t};\n\n\tthis.getViewport = function ( target ) {\n\n\t\treturn target.copy( _viewport );\n\n\t};\n\n\tthis.setViewport = function ( x, y, width, height ) {\n\n\t\tif ( x.isVector4 ) {\n\n\t\t\t_viewport.set( x.x, x.y, x.z, x.w );\n\n\t\t} else {\n\n\t\t\t_viewport.set( x, y, width, height );\n\n\t\t}\n\n\t\tstate.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );\n\n\t};\n\n\tthis.getScissor = function ( target ) {\n\n\t\treturn target.copy( _scissor );\n\n\t};\n\n\tthis.setScissor = function ( x, y, width, height ) {\n\n\t\tif ( x.isVector4 ) {\n\n\t\t\t_scissor.set( x.x, x.y, x.z, x.w );\n\n\t\t} else {\n\n\t\t\t_scissor.set( x, y, width, height );\n\n\t\t}\n\n\t\tstate.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );\n\n\t};\n\n\tthis.getScissorTest = function () {\n\n\t\treturn _scissorTest;\n\n\t};\n\n\tthis.setScissorTest = function ( boolean ) {\n\n\t\tstate.setScissorTest( _scissorTest = boolean );\n\n\t};\n\n\tthis.setOpaqueSort = function ( method ) {\n\n\t\t_opaqueSort = method;\n\n\t};\n\n\tthis.setTransparentSort = function ( method ) {\n\n\t\t_transparentSort = method;\n\n\t};\n\n\t// Clearing\n\n\tthis.getClearColor = function () {\n\n\t\treturn background.getClearColor();\n\n\t};\n\n\tthis.setClearColor = function () {\n\n\t\tbackground.setClearColor.apply( background, arguments );\n\n\t};\n\n\tthis.getClearAlpha = function () {\n\n\t\treturn background.getClearAlpha();\n\n\t};\n\n\tthis.setClearAlpha = function () {\n\n\t\tbackground.setClearAlpha.apply( background, arguments );\n\n\t};\n\n\tthis.clear = function ( color, depth, stencil ) {\n\n\t\tvar bits = 0;\n\n\t\tif ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;\n\t\tif ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;\n\t\tif ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;\n\n\t\t_gl.clear( bits );\n\n\t};\n\n\tthis.clearColor = function () {\n\n\t\tthis.clear( true, false, false );\n\n\t};\n\n\tthis.clearDepth = function () {\n\n\t\tthis.clear( false, true, false );\n\n\t};\n\n\tthis.clearStencil = function () {\n\n\t\tthis.clear( false, false, true );\n\n\t};\n\n\t//\n\n\tthis.dispose = function () {\n\n\t\t_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );\n\t\t_canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false );\n\n\t\trenderLists.dispose();\n\t\trenderStates.dispose();\n\t\tproperties.dispose();\n\t\tobjects.dispose();\n\n\t\txr.dispose();\n\n\t\tanimation.stop();\n\n\t};\n\n\t// Events\n\n\tfunction onContextLost( event ) {\n\n\t\tevent.preventDefault();\n\n\t\tconsole.log( 'THREE.WebGLRenderer: Context Lost.' );\n\n\t\t_isContextLost = true;\n\n\t}\n\n\tfunction onContextRestore( /* event */ ) {\n\n\t\tconsole.log( 'THREE.WebGLRenderer: Context Restored.' );\n\n\t\t_isContextLost = false;\n\n\t\tinitGLContext();\n\n\t}\n\n\tfunction onMaterialDispose( event ) {\n\n\t\tvar material = event.target;\n\n\t\tmaterial.removeEventListener( 'dispose', onMaterialDispose );\n\n\t\tdeallocateMaterial( material );\n\n\t}\n\n\t// Buffer deallocation\n\n\tfunction deallocateMaterial( material ) {\n\n\t\treleaseMaterialProgramReference( material );\n\n\t\tproperties.remove( material );\n\n\t}\n\n\n\tfunction releaseMaterialProgramReference( material ) {\n\n\t\tvar programInfo = properties.get( material ).program;\n\n\t\tmaterial.program = undefined;\n\n\t\tif ( programInfo !== undefined ) {\n\n\t\t\tprogramCache.releaseProgram( programInfo );\n\n\t\t}\n\n\t}\n\n\t// Buffer rendering\n\n\tfunction renderObjectImmediate( object, program ) {\n\n\t\tobject.render( function ( object ) {\n\n\t\t\t_this.renderBufferImmediate( object, program );\n\n\t\t} );\n\n\t}\n\n\tthis.renderBufferImmediate = function ( object, program ) {\n\n\t\tstate.initAttributes();\n\n\t\tvar buffers = properties.get( object );\n\n\t\tif ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer();\n\t\tif ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer();\n\t\tif ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();\n\t\tif ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();\n\n\t\tvar programAttributes = program.getAttributes();\n\n\t\tif ( object.hasPositions ) {\n\n\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );\n\t\t\t_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );\n\n\t\t\tstate.enableAttribute( programAttributes.position );\n\t\t\t_gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 );\n\n\t\t}\n\n\t\tif ( object.hasNormals ) {\n\n\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal );\n\t\t\t_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );\n\n\t\t\tstate.enableAttribute( programAttributes.normal );\n\t\t\t_gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 );\n\n\t\t}\n\n\t\tif ( object.hasUvs ) {\n\n\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );\n\t\t\t_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );\n\n\t\t\tstate.enableAttribute( programAttributes.uv );\n\t\t\t_gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 );\n\n\t\t}\n\n\t\tif ( object.hasColors ) {\n\n\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );\n\t\t\t_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );\n\n\t\t\tstate.enableAttribute( programAttributes.color );\n\t\t\t_gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 );\n\n\t\t}\n\n\t\tstate.disableUnusedAttributes();\n\n\t\t_gl.drawArrays( _gl.TRIANGLES, 0, object.count );\n\n\t\tobject.count = 0;\n\n\t};\n\n\tvar tempScene = new Scene();\n\n\tthis.renderBufferDirect = function ( camera, scene, geometry, material, object, group ) {\n\n\t\tif ( scene === null ) scene = tempScene; // renderBufferDirect second parameter used to be fog (could be null)\n\n\t\tvar frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 );\n\n\t\tvar program = setProgram( camera, scene, material, object );\n\n\t\tstate.setMaterial( material, frontFaceCW );\n\n\t\tvar updateBuffers = false;\n\n\t\tif ( _currentGeometryProgram.geometry !== geometry.id ||\n\t\t\t_currentGeometryProgram.program !== program.id ||\n\t\t\t_currentGeometryProgram.wireframe !== ( material.wireframe === true ) ) {\n\n\t\t\t_currentGeometryProgram.geometry = geometry.id;\n\t\t\t_currentGeometryProgram.program = program.id;\n\t\t\t_currentGeometryProgram.wireframe = material.wireframe === true;\n\t\t\tupdateBuffers = true;\n\n\t\t}\n\n\t\tif ( material.morphTargets || material.morphNormals ) {\n\n\t\t\tmorphtargets.update( object, geometry, material, program );\n\n\t\t\tupdateBuffers = true;\n\n\t\t}\n\n\t\tif ( object.isInstancedMesh === true ) {\n\n\t\t\tupdateBuffers = true;\n\n\t\t}\n\n\t\t//\n\n\t\tvar index = geometry.index;\n\t\tvar position = geometry.attributes.position;\n\n\t\t//\n\n\t\tif ( index === null ) {\n\n\t\t\tif ( position === undefined || position.count === 0 ) return;\n\n\t\t} else if ( index.count === 0 ) {\n\n\t\t\treturn;\n\n\t\t}\n\n\t\t//\n\n\t\tvar rangeFactor = 1;\n\n\t\tif ( material.wireframe === true ) {\n\n\t\t\tindex = geometries.getWireframeAttribute( geometry );\n\t\t\trangeFactor = 2;\n\n\t\t}\n\n\t\tvar attribute;\n\t\tvar renderer = bufferRenderer;\n\n\t\tif ( index !== null ) {\n\n\t\t\tattribute = attributes.get( index );\n\n\t\t\trenderer = indexedBufferRenderer;\n\t\t\trenderer.setIndex( attribute );\n\n\t\t}\n\n\t\tif ( updateBuffers ) {\n\n\t\t\tsetupVertexAttributes( object, geometry, material, program );\n\n\t\t\tif ( index !== null ) {\n\n\t\t\t\t_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer );\n\n\t\t\t}\n\n\t\t}\n\n\t\t//\n\n\t\tvar dataCount = ( index !== null ) ? index.count : position.count;\n\n\t\tvar rangeStart = geometry.drawRange.start * rangeFactor;\n\t\tvar rangeCount = geometry.drawRange.count * rangeFactor;\n\n\t\tvar groupStart = group !== null ? group.start * rangeFactor : 0;\n\t\tvar groupCount = group !== null ? group.count * rangeFactor : Infinity;\n\n\t\tvar drawStart = Math.max( rangeStart, groupStart );\n\t\tvar drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1;\n\n\t\tvar drawCount = Math.max( 0, drawEnd - drawStart + 1 );\n\n\t\tif ( drawCount === 0 ) return;\n\n\t\t//\n\n\t\tif ( object.isMesh ) {\n\n\t\t\tif ( material.wireframe === true ) {\n\n\t\t\t\tstate.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );\n\t\t\t\trenderer.setMode( _gl.LINES );\n\n\t\t\t} else {\n\n\t\t\t\trenderer.setMode( _gl.TRIANGLES );\n\n\t\t\t}\n\n\t\t} else if ( object.isLine ) {\n\n\t\t\tvar lineWidth = material.linewidth;\n\n\t\t\tif ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material\n\n\t\t\tstate.setLineWidth( lineWidth * getTargetPixelRatio() );\n\n\t\t\tif ( object.isLineSegments ) {\n\n\t\t\t\trenderer.setMode( _gl.LINES );\n\n\t\t\t} else if ( object.isLineLoop ) {\n\n\t\t\t\trenderer.setMode( _gl.LINE_LOOP );\n\n\t\t\t} else {\n\n\t\t\t\trenderer.setMode( _gl.LINE_STRIP );\n\n\t\t\t}\n\n\t\t} else if ( object.isPoints ) {\n\n\t\t\trenderer.setMode( _gl.POINTS );\n\n\t\t} else if ( object.isSprite ) {\n\n\t\t\trenderer.setMode( _gl.TRIANGLES );\n\n\t\t}\n\n\t\tif ( object.isInstancedMesh ) {\n\n\t\t\trenderer.renderInstances( geometry, drawStart, drawCount, object.count );\n\n\t\t} else if ( geometry.isInstancedBufferGeometry ) {\n\n\t\t\tvar instanceCount = Math.min( geometry.instanceCount, geometry._maxInstanceCount );\n\n\t\t\trenderer.renderInstances( geometry, drawStart, drawCount, instanceCount );\n\n\t\t} else {\n\n\t\t\trenderer.render( drawStart, drawCount );\n\n\t\t}\n\n\t};\n\n\tfunction setupVertexAttributes( object, geometry, material, program ) {\n\n\t\tif ( capabilities.isWebGL2 === false && ( object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {\n\n\t\t\tif ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) return;\n\n\t\t}\n\n\t\tstate.initAttributes();\n\n\t\tvar geometryAttributes = geometry.attributes;\n\n\t\tvar programAttributes = program.getAttributes();\n\n\t\tvar materialDefaultAttributeValues = material.defaultAttributeValues;\n\n\t\tfor ( var name in programAttributes ) {\n\n\t\t\tvar programAttribute = programAttributes[ name ];\n\n\t\t\tif ( programAttribute >= 0 ) {\n\n\t\t\t\tvar geometryAttribute = geometryAttributes[ name ];\n\n\t\t\t\tif ( geometryAttribute !== undefined ) {\n\n\t\t\t\t\tvar normalized = geometryAttribute.normalized;\n\t\t\t\t\tvar size = geometryAttribute.itemSize;\n\n\t\t\t\t\tvar attribute = attributes.get( geometryAttribute );\n\n\t\t\t\t\t// TODO Attribute may not be available on context restore\n\n\t\t\t\t\tif ( attribute === undefined ) continue;\n\n\t\t\t\t\tvar buffer = attribute.buffer;\n\t\t\t\t\tvar type = attribute.type;\n\t\t\t\t\tvar bytesPerElement = attribute.bytesPerElement;\n\n\t\t\t\t\tif ( geometryAttribute.isInterleavedBufferAttribute ) {\n\n\t\t\t\t\t\tvar data = geometryAttribute.data;\n\t\t\t\t\t\tvar stride = data.stride;\n\t\t\t\t\t\tvar offset = geometryAttribute.offset;\n\n\t\t\t\t\t\tif ( data && data.isInstancedInterleavedBuffer ) {\n\n\t\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );\n\n\t\t\t\t\t\t\tif ( geometry._maxInstanceCount === undefined ) {\n\n\t\t\t\t\t\t\t\tgeometry._maxInstanceCount = data.meshPerAttribute * data.count;\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tstate.enableAttribute( programAttribute );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );\n\t\t\t\t\t\tstate.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( geometryAttribute.isInstancedBufferAttribute ) {\n\n\t\t\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );\n\n\t\t\t\t\t\t\tif ( geometry._maxInstanceCount === undefined ) {\n\n\t\t\t\t\t\t\t\tgeometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\tstate.enableAttribute( programAttribute );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );\n\t\t\t\t\t\tstate.vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( name === 'instanceMatrix' ) {\n\n\t\t\t\t\tvar attribute = attributes.get( object.instanceMatrix );\n\n\t\t\t\t\t// TODO Attribute may not be available on context restore\n\n\t\t\t\t\tif ( attribute === undefined ) continue;\n\n\t\t\t\t\tvar buffer = attribute.buffer;\n\t\t\t\t\tvar type = attribute.type;\n\n\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 0, 1 );\n\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 1, 1 );\n\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 2, 1 );\n\t\t\t\t\tstate.enableAttributeAndDivisor( programAttribute + 3, 1 );\n\n\t\t\t\t\t_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );\n\n\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 0, 4, type, false, 64, 0 );\n\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 1, 4, type, false, 64, 16 );\n\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 2, 4, type, false, 64, 32 );\n\t\t\t\t\t_gl.vertexAttribPointer( programAttribute + 3, 4, type, false, 64, 48 );\n\n\t\t\t\t} else if ( materialDefaultAttributeValues !== undefined ) {\n\n\t\t\t\t\tvar value = materialDefaultAttributeValues[ name ];\n\n\t\t\t\t\tif ( value !== undefined ) {\n\n\t\t\t\t\t\tswitch ( value.length ) {\n\n\t\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\t\t_gl.vertexAttrib2fv( programAttribute, value );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\t\t\t_gl.vertexAttrib3fv( programAttribute, value );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\t\t_gl.vertexAttrib4fv( programAttribute, value );\n\t\t\t\t\t\t\t\tbreak;\n\n\t\t\t\t\t\t\tdefault:\n\t\t\t\t\t\t\t\t_gl.vertexAttrib1fv( programAttribute, value );\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tstate.disableUnusedAttributes();\n\n\t}\n\n\t// Compile\n\n\tthis.compile = function ( scene, camera ) {\n\n\t\tcurrentRenderState = renderStates.get( scene, camera );\n\t\tcurrentRenderState.init();\n\n\t\tscene.traverse( function ( object ) {\n\n\t\t\tif ( object.isLight ) {\n\n\t\t\t\tcurrentRenderState.pushLight( object );\n\n\t\t\t\tif ( object.castShadow ) {\n\n\t\t\t\t\tcurrentRenderState.pushShadow( object );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} );\n\n\t\tcurrentRenderState.setupLights( camera );\n\n\t\tconst compiled = {};\n\n\t\tscene.traverse( function ( object ) {\n\n\t\t\tlet material = object.material;\n\n\t\t\tif ( material ) {\n\n\t\t\t\tif ( Array.isArray( material ) ) {\n\n\t\t\t\t\tfor ( let i = 0; i < material.length; i ++ ) {\n\n\t\t\t\t\t\tlet material2 = material[ i ];\n\n\t\t\t\t\t\tif ( material2.uuid in compiled === false ) {\n\n\t\t\t\t\t\t\tinitMaterial( material2, scene, object );\n\t\t\t\t\t\t\tcompiled[ material2.uuid ] = true;\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n\n\t\t\t\t} else if ( material.uuid in compiled === false ) {\n\n\t\t\t\t\tinitMaterial( material, scene, object );\n\t\t\t\t\tcompiled[ material.uuid ] = true;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t} );\n\n\t};\n\n\t// Animation Loop\n\n\tvar onAnimationFrameCallback = null;\n\n\tfunction onAnimationFrame( time ) {\n\n\t\tif ( xr.isPresenting ) return;\n\t\tif ( onAnimationFrameCallback ) onAnimationFrameCallback( time );\n\n\t}\n\n\tvar animation = new WebGLAnimation();\n\tanimation.setAnimationLoop( onAnimationFrame );\n\n\tif ( typeof window !== 'undefined' ) animation.setContext( window );\n\n\tthis.setAnimationLoop = function ( callback ) {\n\n\t\tonAnimationFrameCallback = callback;\n\t\txr.setAnimationLoop( callback );\n\n\t\tanimation.start();\n\n\t};\n\n\t// Rendering\n\n\tthis.render = function ( scene, camera ) {\n\n\t\tvar renderTarget, forceClear;\n\n\t\tif ( arguments[ 2 ] !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );\n\t\t\trenderTarget = arguments[ 2 ];\n\n\t\t}\n\n\t\tif ( arguments[ 3 ] !== undefined ) {\n\n\t\t\tconsole.warn( 'THREE.WebGLRenderer.render(): the forceClear argument has been removed. Use .clear() instead.' );\n\t\t\tforceClear = arguments[ 3 ];\n\n\t\t}\n\n\t\tif ( ! ( camera && camera.isCamera ) ) {\n\n\t\t\tconsole.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );\n\t\t\treturn;\n\n\t\t}\n\n\t\tif ( _isContextLost ) return;\n\n\t\t// reset caching for this frame\n\n\t\t_currentGeometryProgram.geometry = null;\n\t\t_currentGeometryProgram.program = null;\n\t\t_currentGeometryProgram.wireframe = false;\n\t\t_currentMaterialId = - 1;\n\t\t_currentCamera = null;\n\n\t\t// update scene graph\n\n\t\tif ( scene.autoUpdate === true ) scene.updateMatrixWorld();\n\n\t\t// update camera matrices and frustum\n\n\t\tif ( camera.parent === null ) camera.updateMatrixWorld();\n\n\t\tif ( xr.enabled && xr.isPresenting ) {\n\n\t\t\tcamera = xr.getCamera( camera );\n\n\t\t}\n\n\t\t//\n\t\tscene.onBeforeRender( _this, scene, camera, renderTarget || _currentRenderTarget );\n\n\t\tcurrentRenderState = renderStates.get( scene, camera );\n\t\tcurrentRenderState.init();\n\n\t\t_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );\n\t\t_frustum.setFromProjectionMatrix( _projScreenMatrix );\n\n\t\t_localClippingEnabled = this.localClippingEnabled;\n\t\t_clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );\n\n\t\tcurrentRenderList = renderLists.get( scene, camera );\n\t\tcurrentRenderList.init();\n\n\t\tprojectObject( scene, camera, 0, _this.sortObjects );\n\n\t\tcurrentRenderList.finish();\n\n\t\tif ( _this.sortObjects === true ) {\n\n\t\t\tcurrentRenderList.sort( _opaqueSort, _transparentSort );\n\n\t\t}\n\n\t\t//\n\n\t\tif ( _clippingEnabled ) _clipping.beginShadows();\n\n\t\tvar shadowsArray = currentRenderState.state.shadowsArray;\n\n\t\tshadowMap.render( shadowsArray, scene, camera );\n\n\t\tcurrentRenderState.setupLights( camera );\n\n\t\tif ( _clippingEnabled ) _clipping.endShadows();\n\n\t\t//\n\n\t\tif ( this.info.autoReset ) this.info.reset();\n\n\t\tif ( renderTarget !== undefined ) {\n\n\t\t\tthis.setRenderTarget( renderTarget );\n\n\t\t}\n\n\t\t//\n\n\t\tbackground.render( currentRenderList, scene, camera, forceClear );\n\n\t\t// render scene\n\n\t\tvar opaqueObjects = currentRenderList.opaque;\n\t\tvar transparentObjects = currentRenderList.transparent;\n\n\t\tif ( scene.overrideMaterial ) {\n\n\t\t\tvar overrideMaterial = scene.overrideMaterial;\n\n\t\t\tif ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial );\n\t\t\tif ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial );\n\n\t\t} else {\n\n\t\t\t// opaque pass (front-to-back order)\n\n\t\t\tif ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera );\n\n\t\t\t// transparent pass (back-to-front order)\n\n\t\t\tif ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera );\n\n\t\t}\n\n\t\t//\n\n\t\tscene.onAfterRender( _this, scene, camera );\n\n\t\t//\n\n\t\tif ( _currentRenderTarget !== null ) {\n\n\t\t\t// Generate mipmap if we're using any kind of mipmap filtering\n\n\t\t\ttextures.updateRenderTargetMipmap( _currentRenderTarget );\n\n\t\t\t// resolve multisample renderbuffers to a single-sample texture if necessary\n\n\t\t\ttextures.updateMultisampleRenderTarget( _currentRenderTarget );\n\n\t\t}\n\n\t\t// Ensure depth buffer writing is enabled so it can be cleared on next render\n\n\t\tstate.buffers.depth.setTest( true );\n\t\tstate.buffers.depth.setMask( true );\n\t\tstate.buffers.color.setMask( true );\n\n\t\tstate.setPolygonOffset( false );\n\n\t\t// _gl.finish();\n\n\t\tcurrentRenderList = null;\n\t\tcurrentRenderState = null;\n\n\t};\n\n\tfunction projectObject( object, camera, groupOrder, sortObjects ) {\n\n\t\tif ( object.visible === false ) return;\n\n\t\tvar visible = object.layers.test( camera.layers );\n\n\t\tif ( visible ) {\n\n\t\t\tif ( object.isGroup ) {\n\n\t\t\t\tgroupOrder = object.renderOrder;\n\n\t\t\t} else if ( object.isLOD ) {\n\n\t\t\t\tif ( object.autoUpdate === true ) object.update( camera );\n\n\t\t\t} else if ( object.isLight ) {\n\n\t\t\t\tcurrentRenderState.pushLight( object );\n\n\t\t\t\tif ( object.castShadow ) {\n\n\t\t\t\t\tcurrentRenderState.pushShadow( object );\n\n\t\t\t\t}\n\n\t\t\t} else if ( object.isSprite ) {\n\n\t\t\t\tif ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {\n\n\t\t\t\t\tif ( sortObjects ) {\n\n\t\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\n\t\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tvar geometry = objects.update( object );\n\t\t\t\t\tvar material = object.material;\n\n\t\t\t\t\tif ( material.visible ) {\n\n\t\t\t\t\t\tcurrentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else if ( object.isImmediateRenderObject ) {\n\n\t\t\t\tif ( sortObjects ) {\n\n\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\n\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\n\n\t\t\t\t}\n\n\t\t\t\tcurrentRenderList.push( object, null, object.material, groupOrder, _vector3.z, null );\n\n\t\t\t} else if ( object.isMesh || object.isLine || object.isPoints ) {\n\n\t\t\t\tif ( object.isSkinnedMesh ) {\n\n\t\t\t\t\t// update skeleton only once in a frame\n\n\t\t\t\t\tif ( object.skeleton.frame !== info.render.frame ) {\n\n\t\t\t\t\t\tobject.skeleton.update();\n\t\t\t\t\t\tobject.skeleton.frame = info.render.frame;\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t\tif ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {\n\n\t\t\t\t\tif ( sortObjects ) {\n\n\t\t\t\t\t\t_vector3.setFromMatrixPosition( object.matrixWorld )\n\t\t\t\t\t\t\t.applyMatrix4( _projScreenMatrix );\n\n\t\t\t\t\t}\n\n\t\t\t\t\tvar geometry = objects.update( object );\n\t\t\t\t\tvar material = object.material;\n\n\t\t\t\t\tif ( Array.isArray( material ) ) {\n\n\t\t\t\t\t\tvar groups = geometry.groups;\n\n\t\t\t\t\t\tfor ( var i = 0, l = groups.length; i < l; i ++ ) {\n\n\t\t\t\t\t\t\tvar group = groups[ i ];\n\t\t\t\t\t\t\tvar groupMaterial = material[ group.materialIndex ];\n\n\t\t\t\t\t\t\tif ( groupMaterial && groupMaterial.visible ) {\n\n\t\t\t\t\t\t\t\tcurrentRenderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group );\n\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else if ( material.visible ) {\n\n\t\t\t\t\t\tcurrentRenderList.push( object, geometry, material, groupOrder, _vector3.z, null );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar children = object.children;\n\n\t\tfor ( var i = 0, l = children.length; i < l; i ++ ) {\n\n\t\t\tprojectObject( children[ i ], camera, groupOrder, sortObjects );\n\n\t\t}\n\n\t}\n\n\tfunction renderObjects( renderList, scene, camera, overrideMaterial ) {\n\n\t\tfor ( var i = 0, l = renderList.length; i < l; i ++ ) {\n\n\t\t\tvar renderItem = renderList[ i ];\n\n\t\t\tvar object = renderItem.object;\n\t\t\tvar geometry = renderItem.geometry;\n\t\t\tvar material = overrideMaterial === undefined ? renderItem.material : overrideMaterial;\n\t\t\tvar group = renderItem.group;\n\n\t\t\tif ( camera.isArrayCamera ) {\n\n\t\t\t\t_currentArrayCamera = camera;\n\n\t\t\t\tvar cameras = camera.cameras;\n\n\t\t\t\tfor ( var j = 0, jl = cameras.length; j < jl; j ++ ) {\n\n\t\t\t\t\tvar camera2 = cameras[ j ];\n\n\t\t\t\t\tif ( object.layers.test( camera2.layers ) ) {\n\n\t\t\t\t\t\tstate.viewport( _currentViewport.copy( camera2.viewport ) );\n\n\t\t\t\t\t\tcurrentRenderState.setupLights( camera2 );\n\n\t\t\t\t\t\trenderObject( object, scene, camera2, geometry, material, group );\n\n\t\t\t\t\t}\n\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\t_currentArrayCamera = null;\n\n\t\t\t\trenderObject( object, scene, camera, geometry, material, group );\n\n\t\t\t}\n\n\t\t}\n\n\t}\n\n\tfunction renderObject( object, scene, camera, geometry, material, group ) {\n\n\t\tobject.onBeforeRender( _this, scene, camera, geometry, material, group );\n\t\tcurrentRenderState = renderStates.get( scene, _currentArrayCamera || camera );\n\n\t\tobject.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );\n\t\tobject.normalMatrix.getNormalMatrix( object.modelViewMatrix );\n\n\t\tif ( object.isImmediateRenderObject ) {\n\n\t\t\tvar program = setProgram( camera, scene, material, object );\n\n\t\t\tstate.setMaterial( material );\n\n\t\t\t_currentGeometryProgram.geometry = null;\n\t\t\t_currentGeometryProgram.program = null;\n\t\t\t_currentGeometryProgram.wireframe = false;\n\n\t\t\trenderObjectImmediate( object, program );\n\n\t\t} else {\n\n\t\t\t_this.renderBufferDirect( camera, scene, geometry, material, object, group );\n\n\t\t}\n\n\t\tobject.onAfterRender( _this, scene, camera, geometry, material, group );\n\t\tcurrentRenderState = renderStates.get( scene, _currentArrayCamera || camera );\n\n\t}\n\n\tfunction initMaterial( material, scene, object ) {\n\n\t\tvar materialProperties = properties.get( material );\n\n\t\tvar lights = currentRenderState.state.lights;\n\t\tvar shadowsArray = currentRenderState.state.shadowsArray;\n\n\t\tvar lightsStateVersion = lights.state.version;\n\n\t\tvar parameters = programCache.getParameters( material, lights.state, shadowsArray, scene, _clipping.numPlanes, _clipping.numIntersection, object );\n\t\tvar programCacheKey = programCache.getProgramCacheKey( parameters );\n\n\t\tvar program = materialProperties.program;\n\t\tvar programChange = true;\n\n\t\tif ( program === undefined ) {\n\n\t\t\t// new material\n\t\t\tmaterial.addEventListener( 'dispose', onMaterialDispose );\n\n\t\t} else if ( program.cacheKey !== programCacheKey ) {\n\n\t\t\t// changed glsl or parameters\n\t\t\treleaseMaterialProgramReference( material );\n\n\t\t} else if ( materialProperties.lightsStateVersion !== lightsStateVersion ) {\n\n\t\t\tmaterialProperties.lightsStateVersion = lightsStateVersion;\n\n\t\t\tprogramChange = false;\n\n\t\t} else if ( parameters.shaderID !== undefined ) {\n\n\t\t\t// same glsl and uniform list\n\t\t\treturn;\n\n\t\t} else {\n\n\t\t\t// only rebuild uniform list\n\t\t\tprogramChange = false;\n\n\t\t}\n\n\t\tif ( programChange ) {\n\n\t\t\tprogram = programCache.acquireProgram( parameters, programCacheKey );\n\n\t\t\tmaterialProperties.program = program;\n\t\t\tmaterialProperties.uniforms = parameters.uniforms;\n\t\t\tmaterialProperties.outputEncoding = parameters.outputEncoding;\n\t\t\tmaterial.program = program;\n\n\t\t}\n\n\t\tvar programAttributes = program.getAttributes();\n\n\t\tif ( material.morphTargets ) {\n\n\t\t\tmaterial.numSupportedMorphTargets = 0;\n\n\t\t\tfor ( var i = 0; i < _this.maxMorphTargets; i ++ ) {\n\n\t\t\t\tif ( programAttributes[ 'morphTarget' + i ] >= 0 ) {\n\n\t\t\t\t\tmaterial.numSupportedMorphTargets ++;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( material.morphNormals ) {\n\n\t\t\tmaterial.numSupportedMorphNormals = 0;\n\n\t\t\tfor ( var i = 0; i < _this.maxMorphNormals; i ++ ) {\n\n\t\t\t\tif ( programAttributes[ 'morphNormal' + i ] >= 0 ) {\n\n\t\t\t\t\tmaterial.numSupportedMorphNormals ++;\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tvar uniforms = materialProperties.uniforms;\n\n\t\tif ( ! material.isShaderMaterial &&\n\t\t\t! material.isRawShaderMaterial ||\n\t\t\tmaterial.clipping === true ) {\n\n\t\t\tmaterialProperties.numClippingPlanes = _clipping.numPlanes;\n\t\t\tmaterialProperties.numIntersection = _clipping.numIntersection;\n\t\t\tuniforms.clippingPlanes = _clipping.uniform;\n\n\t\t}\n\n\t\tmaterialProperties.environment = material.isMeshStandardMaterial ? scene.environment : null;\n\t\tmaterialProperties.fog = scene.fog;\n\n\t\t// store the light setup it was created for\n\n\t\tmaterialProperties.needsLights = materialNeedsLights( material );\n\t\tmaterialProperties.lightsStateVersion = lightsStateVersion;\n\n\t\tif ( materialProperties.needsLights ) {\n\n\t\t\t// wire up the material to this renderer's lighting state\n\n\t\t\tuniforms.ambientLightColor.value = lights.state.ambient;\n\t\t\tuniforms.lightProbe.value = lights.state.probe;\n\t\t\tuniforms.directionalLights.value = lights.state.directional;\n\t\t\tuniforms.directionalLightShadows.value = lights.state.directionalShadow;\n\t\t\tuniforms.spotLights.value = lights.state.spot;\n\t\t\tuniforms.spotLightShadows.value = lights.state.spotShadow;\n\t\t\tuniforms.rectAreaLights.value = lights.state.rectArea;\n\t\t\tuniforms.pointLights.value = lights.state.point;\n\t\t\tuniforms.pointLightShadows.value = lights.state.pointShadow;\n\t\t\tuniforms.hemisphereLights.value = lights.state.hemi;\n\n\t\t\tuniforms.directionalShadowMap.value = lights.state.directionalShadowMap;\n\t\t\tuniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;\n\t\t\tuniforms.spotShadowMap.value = lights.state.spotShadowMap;\n\t\t\tuniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix;\n\t\t\tuniforms.pointShadowMap.value = lights.state.pointShadowMap;\n\t\t\tuniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;\n\t\t\t// TODO (abelnation): add area lights shadow info to uniforms\n\n\t\t}\n\n\t\tvar progUniforms = materialProperties.program.getUniforms(),\n\t\t\tuniformsList =\n\t\t\t\tWebGLUniforms.seqWithValue( progUniforms.seq, uniforms );\n\n\t\tmaterialProperties.uniformsList = uniformsList;\n\n\t}\n\n\tfunction setProgram( camera, scene, material, object ) {\n\n\t\ttextures.resetTextureUnits();\n\n\t\tvar fog = scene.fog;\n\t\tvar environment = material.isMeshStandardMaterial ? scene.environment : null;\n\t\tvar encoding = ( _currentRenderTarget === null ) ? _this.outputEncoding : _currentRenderTarget.texture.encoding;\n\n\t\tvar materialProperties = properties.get( material );\n\t\tvar lights = currentRenderState.state.lights;\n\n\t\tif ( _clippingEnabled ) {\n\n\t\t\tif ( _localClippingEnabled || camera !== _currentCamera ) {\n\n\t\t\t\tvar useCache =\n\t\t\t\t\tcamera === _currentCamera &&\n\t\t\t\t\tmaterial.id === _currentMaterialId;\n\n\t\t\t\t// we might want to call this function with some ClippingGroup\n\t\t\t\t// object instead of the material, once it becomes feasible\n\t\t\t\t// (#8465, #8379)\n\t\t\t\t_clipping.setState(\n\t\t\t\t\tmaterial.clippingPlanes, material.clipIntersection, material.clipShadows,\n\t\t\t\t\tcamera, materialProperties, useCache );\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( material.version === materialProperties.__version ) {\n\n\t\t\tif ( materialProperties.program === undefined ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t} else if ( material.fog && materialProperties.fog !== fog ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t} else if ( materialProperties.environment !== environment ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t} else if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t} else if ( materialProperties.numClippingPlanes !== undefined &&\n\t\t\t\t( materialProperties.numClippingPlanes !== _clipping.numPlanes ||\n\t\t\t\tmaterialProperties.numIntersection !== _clipping.numIntersection ) ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t} else if ( materialProperties.outputEncoding !== encoding ) {\n\n\t\t\t\tinitMaterial( material, scene, object );\n\n\t\t\t}\n\n\t\t} else {\n\n\t\t\tinitMaterial( material, scene, object );\n\t\t\tmaterialProperties.__version = material.version;\n\n\t\t}\n\n\t\tvar refreshProgram = false;\n\t\tvar refreshMaterial = false;\n\t\tvar refreshLights = false;\n\n\t\tvar program = materialProperties.program,\n\t\t\tp_uniforms = program.getUniforms(),\n\t\t\tm_uniforms = materialProperties.uniforms;\n\n\t\tif ( state.useProgram( program.program ) ) {\n\n\t\t\trefreshProgram = true;\n\t\t\trefreshMaterial = true;\n\t\t\trefreshLights = true;\n\n\t\t}\n\n\t\tif ( material.id !== _currentMaterialId ) {\n\n\t\t\t_currentMaterialId = material.id;\n\n\t\t\trefreshMaterial = true;\n\n\t\t}\n\n\t\tif ( refreshProgram || _currentCamera !== camera ) {\n\n\t\t\tp_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );\n\n\t\t\tif ( capabilities.logarithmicDepthBuffer ) {\n\n\t\t\t\tp_uniforms.setValue( _gl, 'logDepthBufFC',\n\t\t\t\t\t2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) );\n\n\t\t\t}\n\n\t\t\tif ( _currentCamera !== camera ) {\n\n\t\t\t\t_currentCamera = camera;\n\n\t\t\t\t// lighting uniforms depend on the camera so enforce an update\n\t\t\t\t// now, in case this material supports lights - or later, when\n\t\t\t\t// the next material that does gets activated:\n\n\t\t\t\trefreshMaterial = true;\t\t// set to true on material change\n\t\t\t\trefreshLights = true;\t\t// remains set until update done\n\n\t\t\t}\n\n\t\t\t// load material specific uniforms\n\t\t\t// (shader material also gets them for the sake of genericity)\n\n\t\t\tif ( material.isShaderMaterial ||\n\t\t\t\tmaterial.isMeshPhongMaterial ||\n\t\t\t\tmaterial.isMeshToonMaterial ||\n\t\t\t\tmaterial.isMeshStandardMaterial ||\n\t\t\t\tmaterial.envMap ) {\n\n\t\t\t\tvar uCamPos = p_uniforms.map.cameraPosition;\n\n\t\t\t\tif ( uCamPos !== undefined ) {\n\n\t\t\t\t\tuCamPos.setValue( _gl,\n\t\t\t\t\t\t_vector3.setFromMatrixPosition( camera.matrixWorld ) );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tif ( material.isMeshPhongMaterial ||\n\t\t\t\tmaterial.isMeshToonMaterial ||\n\t\t\t\tmaterial.isMeshLambertMaterial ||\n\t\t\t\tmaterial.isMeshBasicMaterial ||\n\t\t\t\tmaterial.isMeshStandardMaterial ||\n\t\t\t\tmaterial.isShaderMaterial ) {\n\n\t\t\t\tp_uniforms.setValue( _gl, 'isOrthographic', camera.isOrthographicCamera === true );\n\n\t\t\t}\n\n\t\t\tif ( material.isMeshPhongMaterial ||\n\t\t\t\tmaterial.isMeshToonMaterial ||\n\t\t\t\tmaterial.isMeshLambertMaterial ||\n\t\t\t\tmaterial.isMeshBasicMaterial ||\n\t\t\t\tmaterial.isMeshStandardMaterial ||\n\t\t\t\tmaterial.isShaderMaterial ||\n\t\t\t\tmaterial.skinning ) {\n\n\t\t\t\tp_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// skinning uniforms must be set even if material didn't change\n\t\t// auto-setting of texture unit for bone texture must go before other textures\n\t\t// otherwise textures used for skinning can take over texture units reserved for other material textures\n\n\t\tif ( material.skinning ) {\n\n\t\t\tp_uniforms.setOptional( _gl, object, 'bindMatrix' );\n\t\t\tp_uniforms.setOptional( _gl, object, 'bindMatrixInverse' );\n\n\t\t\tvar skeleton = object.skeleton;\n\n\t\t\tif ( skeleton ) {\n\n\t\t\t\tvar bones = skeleton.bones;\n\n\t\t\t\tif ( capabilities.floatVertexTextures ) {\n\n\t\t\t\t\tif ( skeleton.boneTexture === undefined ) {\n\n\t\t\t\t\t\t// layout (1 matrix = 4 pixels)\n\t\t\t\t\t\t// RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)\n\t\t\t\t\t\t// with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8)\n\t\t\t\t\t\t// 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16)\n\t\t\t\t\t\t// 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32)\n\t\t\t\t\t\t// 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)\n\n\n\t\t\t\t\t\tvar size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix\n\t\t\t\t\t\tsize = MathUtils.ceilPowerOfTwo( size );\n\t\t\t\t\t\tsize = Math.max( size, 4 );\n\n\t\t\t\t\t\tvar boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel\n\t\t\t\t\t\tboneMatrices.set( skeleton.boneMatrices ); // copy current values\n\n\t\t\t\t\t\tvar boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType );\n\n\t\t\t\t\t\tskeleton.boneMatrices = boneMatrices;\n\t\t\t\t\t\tskeleton.boneTexture = boneTexture;\n\t\t\t\t\t\tskeleton.boneTextureSize = size;\n\n\t\t\t\t\t}\n\n\t\t\t\t\tp_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture, textures );\n\t\t\t\t\tp_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize );\n\n\t\t\t\t} else {\n\n\t\t\t\t\tp_uniforms.setOptional( _gl, skeleton, 'boneMatrices' );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t\tif ( refreshMaterial || materialProperties.receiveShadow !== object.receiveShadow ) {\n\n\t\t\tmaterialProperties.receiveShadow = object.receiveShadow;\n\t\t\tp_uniforms.setValue( _gl, 'receiveShadow', object.receiveShadow );\n\n\t\t}\n\n\t\tif ( refreshMaterial ) {\n\n\t\t\tp_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure );\n\t\t\tp_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint );\n\n\t\t\tif ( materialProperties.needsLights ) {\n\n\t\t\t\t// the current material requires lighting info\n\n\t\t\t\t// note: all lighting uniforms are always set correctly\n\t\t\t\t// they simply reference the renderer's state for their\n\t\t\t\t// values\n\t\t\t\t//\n\t\t\t\t// use the current material's .needsUpdate flags to set\n\t\t\t\t// the GL state when required\n\n\t\t\t\tmarkUniformsLightsNeedsUpdate( m_uniforms, refreshLights );\n\n\t\t\t}\n\n\t\t\t// refresh uniforms common to several materials\n\n\t\t\tif ( fog && material.fog ) {\n\n\t\t\t\tmaterials.refreshFogUniforms( m_uniforms, fog );\n\n\t\t\t}\n\n\t\t\tmaterials.refreshMaterialUniforms( m_uniforms, material, environment, _pixelRatio, _height );\n\n\t\t\t// RectAreaLight Texture\n\t\t\t// TODO (mrdoob): Find a nicer implementation\n\n\t\t\tif ( m_uniforms.ltc_1 !== undefined ) m_uniforms.ltc_1.value = UniformsLib.LTC_1;\n\t\t\tif ( m_uniforms.ltc_2 !== undefined ) m_uniforms.ltc_2.value = UniformsLib.LTC_2;\n\n\t\t\tWebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );\n\n\t\t}\n\n\t\tif ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) {\n\n\t\t\tWebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, textures );\n\t\t\tmaterial.uniformsNeedUpdate = false;\n\n\t\t}\n\n\t\tif ( material.isSpriteMaterial ) {\n\n\t\t\tp_uniforms.setValue( _gl, 'center', object.center );\n\n\t\t}\n\n\t\t// common matrices\n\n\t\tp_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );\n\t\tp_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );\n\t\tp_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );\n\n\t\treturn program;\n\n\t}\n\n\t// If uniforms are marked as clean, they don't need to be loaded to the GPU.\n\n\tfunction markUniformsLightsNeedsUpdate( uniforms, value ) {\n\n\t\tuniforms.ambientLightColor.needsUpdate = value;\n\t\tuniforms.lightProbe.needsUpdate = value;\n\n\t\tuniforms.directionalLights.needsUpdate = value;\n\t\tuniforms.directionalLightShadows.needsUpdate = value;\n\t\tuniforms.pointLights.needsUpdate = value;\n\t\tuniforms.pointLightShadows.needsUpdate = value;\n\t\tuniforms.spotLights.needsUpdate = value;\n\t\tuniforms.spotLightShadows.needsUpdate = value;\n\t\tuniforms.rectAreaLights.needsUpdate = value;\n\t\tuniforms.hemisphereLights.needsUpdate = value;\n\n\t}\n\n\tfunction materialNeedsLights( material ) {\n\n\t\treturn material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||\n\t\t\tmaterial.isMeshStandardMaterial || material.isShadowMaterial ||\n\t\t\t( material.isShaderMaterial && material.lights === true );\n\n\t}\n\n\t//\n\tthis.setFramebuffer = function ( value ) {\n\n\t\tif ( _framebuffer !== value && _currentRenderTarget === null ) _gl.bindFramebuffer( _gl.FRAMEBUFFER, value );\n\n\t\t_framebuffer = value;\n\n\t};\n\n\tthis.getActiveCubeFace = function () {\n\n\t\treturn _currentActiveCubeFace;\n\n\t};\n\n\tthis.getActiveMipmapLevel = function () {\n\n\t\treturn _currentActiveMipmapLevel;\n\n\t};\n\n\tthis.getRenderTarget = function () {\n\n\t\treturn _currentRenderTarget;\n\n\t};\n\n\tthis.setRenderTarget = function ( renderTarget, activeCubeFace, activeMipmapLevel ) {\n\n\t\t_currentRenderTarget = renderTarget;\n\t\t_currentActiveCubeFace = activeCubeFace;\n\t\t_currentActiveMipmapLevel = activeMipmapLevel;\n\n\t\tif ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) {\n\n\t\t\ttextures.setupRenderTarget( renderTarget );\n\n\t\t}\n\n\t\tvar framebuffer = _framebuffer;\n\t\tvar isCube = false;\n\n\t\tif ( renderTarget ) {\n\n\t\t\tvar __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;\n\n\t\t\tif ( renderTarget.isWebGLCubeRenderTarget ) {\n\n\t\t\t\tframebuffer = __webglFramebuffer[ activeCubeFace || 0 ];\n\t\t\t\tisCube = true;\n\n\t\t\t} else if ( renderTarget.isWebGLMultisampleRenderTarget ) {\n\n\t\t\t\tframebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;\n\n\t\t\t} else {\n\n\t\t\t\tframebuffer = __webglFramebuffer;\n\n\t\t\t}\n\n\t\t\t_currentViewport.copy( renderTarget.viewport );\n\t\t\t_currentScissor.copy( renderTarget.scissor );\n\t\t\t_currentScissorTest = renderTarget.scissorTest;\n\n\t\t} else {\n\n\t\t\t_currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();\n\t\t\t_currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();\n\t\t\t_currentScissorTest = _scissorTest;\n\n\t\t}\n\n\t\tif ( _currentFramebuffer !== framebuffer ) {\n\n\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );\n\t\t\t_currentFramebuffer = framebuffer;\n\n\t\t}\n\n\t\tstate.viewport( _currentViewport );\n\t\tstate.scissor( _currentScissor );\n\t\tstate.setScissorTest( _currentScissorTest );\n\n\t\tif ( isCube ) {\n\n\t\t\tvar textureProperties = properties.get( renderTarget.texture );\n\t\t\t_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + ( activeCubeFace || 0 ), textureProperties.__webglTexture, activeMipmapLevel || 0 );\n\n\t\t}\n\n\t};\n\n\tthis.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer, activeCubeFaceIndex ) {\n\n\t\tif ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {\n\n\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );\n\t\t\treturn;\n\n\t\t}\n\n\t\tvar framebuffer = properties.get( renderTarget ).__webglFramebuffer;\n\n\t\tif ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !== undefined ) {\n\n\t\t\tframebuffer = framebuffer[ activeCubeFaceIndex ];\n\n\t\t}\n\n\t\tif ( framebuffer ) {\n\n\t\t\tvar restore = false;\n\n\t\t\tif ( framebuffer !== _currentFramebuffer ) {\n\n\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );\n\n\t\t\t\trestore = true;\n\n\t\t\t}\n\n\t\t\ttry {\n\n\t\t\t\tvar texture = renderTarget.texture;\n\t\t\t\tvar textureFormat = texture.format;\n\t\t\t\tvar textureType = texture.type;\n\n\t\t\t\tif ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {\n\n\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );\n\t\t\t\t\treturn;\n\n\t\t\t\t}\n\n\t\t\t\tif ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513)\n\t\t\t\t\t! ( textureType === FloatType && ( capabilities.isWebGL2 || extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox\n\t\t\t\t\t! ( textureType === HalfFloatType && ( capabilities.isWebGL2 ? extensions.get( 'EXT_color_buffer_float' ) : extensions.get( 'EXT_color_buffer_half_float' ) ) ) ) {\n\n\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );\n\t\t\t\t\treturn;\n\n\t\t\t\t}\n\n\t\t\t\tif ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) {\n\n\t\t\t\t\t// the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604)\n\n\t\t\t\t\tif ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) {\n\n\t\t\t\t\t\t_gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );\n\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\tconsole.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' );\n\n\t\t\t\t}\n\n\t\t\t} finally {\n\n\t\t\t\tif ( restore ) {\n\n\t\t\t\t\t_gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer );\n\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t}\n\n\t};\n\n\tthis.copyFramebufferToTexture = function ( position, texture, level ) {\n\n\t\tif ( level === undefined ) level = 0;\n\n\t\tvar levelScale = Math.pow( 2, - level );\n\t\tvar width = Math.floor( texture.image.width * levelScale );\n\t\tvar height = Math.floor( texture.image.height * levelScale );\n\t\tvar glFormat = utils.convert( texture.format );\n\n\t\ttextures.setTexture2D( texture, 0 );\n\n\t\t_gl.copyTexImage2D( _gl.TEXTURE_2D, level, glFormat, position.x, position.y, width, height, 0 );\n\n\t\tstate.unbindTexture();\n\n\t};\n\n\tthis.copyTextureToTexture = function ( position, srcTexture, dstTexture, level ) {\n\n\t\tif ( level === undefined ) level = 0;\n\n\t\tvar width = srcTexture.image.width;\n\t\tvar height = srcTexture.image.height;\n\t\tvar glFormat = utils.convert( dstTexture.format );\n\t\tvar glType = utils.convert( dstTexture.type );\n\n\t\ttextures.setTexture2D( dstTexture, 0 );\n\n\t\tif ( srcTexture.isDataTexture ) {\n\n\t\t\t_gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data );\n\n\t\t} else {\n\n\t\t\tif ( srcTexture.isCompressedTexture ) {\n\n\t\t\t\t_gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );\n\n\t\t\t} else {\n\n\t\t\t\t_gl.texSubImage2D( _gl.TEXTURE_2D, level, position.x, position.y, glFormat, glType, srcTexture.image );\n\n\t\t\t}\n\n\t\t}\n\n\t\t// Generate mipmaps only when copying level 0\n\t\tif ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D );\n\n\t\tstate.unbindTexture();\n\n\t};\n\n\tthis.initTexture = function ( texture ) {\n\n\t\ttextures.setTexture2D( texture, 0 );\n\n\t\tstate.unbindTexture();\n\n\t};\n\n\tif ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {\n\n\t\t__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); // eslint-disable-line no-undef\n\n\t}\n\n}\n\nexport { WebGLRenderer };\n","/**\n * @author alteredq / http://alteredqualia.com/\n */\n\nfunction Clock( autoStart ) {\n\n\tthis.autoStart = ( autoStart !== undefined ) ? autoStart : true;\n\n\tthis.startTime = 0;\n\tthis.oldTime = 0;\n\tthis.elapsedTime = 0;\n\n\tthis.running = false;\n\n}\n\nObject.assign( Clock.prototype, {\n\n\tstart: function () {\n\n\t\tthis.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732\n\n\t\tthis.oldTime = this.startTime;\n\t\tthis.elapsedTime = 0;\n\t\tthis.running = true;\n\n\t},\n\n\tstop: function () {\n\n\t\tthis.getElapsedTime();\n\t\tthis.running = false;\n\t\tthis.autoStart = false;\n\n\t},\n\n\tgetElapsedTime: function () {\n\n\t\tthis.getDelta();\n\t\treturn this.elapsedTime;\n\n\t},\n\n\tgetDelta: function () {\n\n\t\tvar diff = 0;\n\n\t\tif ( this.autoStart && ! this.running ) {\n\n\t\t\tthis.start();\n\t\t\treturn 0;\n\n\t\t}\n\n\t\tif ( this.running ) {\n\n\t\t\tvar newTime = ( typeof performance === 'undefined' ? Date : performance ).now();\n\n\t\t\tdiff = ( newTime - this.oldTime ) / 1000;\n\t\t\tthis.oldTime = newTime;\n\n\t\t\tthis.elapsedTime += diff;\n\n\t\t}\n\n\t\treturn diff;\n\n\t}\n\n} );\n\n\nexport { Clock };\n","import { MathUtils } from './MathUtils.js';\n\n/**\n * @author bhouston / http://clara.io\n * @author WestLangley / http://github.com/WestLangley\n *\n * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system\n *\n * The polar angle (phi) is measured from the positive y-axis. The positive y-axis is up.\n * The azimuthal angle (theta) is measured from the positive z-axis.\n */\n\nfunction Spherical( radius, phi, theta ) {\n\n\tthis.radius = ( radius !== undefined ) ? radius : 1.0;\n\tthis.phi = ( phi !== undefined ) ? phi : 0; // polar angle\n\tthis.theta = ( theta !== undefined ) ? theta : 0; // azimuthal angle\n\n\treturn this;\n\n}\n\nObject.assign( Spherical.prototype, {\n\n\tset: function ( radius, phi, theta ) {\n\n\t\tthis.radius = radius;\n\t\tthis.phi = phi;\n\t\tthis.theta = theta;\n\n\t\treturn this;\n\n\t},\n\n\tclone: function () {\n\n\t\treturn new this.constructor().copy( this );\n\n\t},\n\n\tcopy: function ( other ) {\n\n\t\tthis.radius = other.radius;\n\t\tthis.phi = other.phi;\n\t\tthis.theta = other.theta;\n\n\t\treturn this;\n\n\t},\n\n\t// restrict phi to be betwee EPS and PI-EPS\n\tmakeSafe: function () {\n\n\t\tvar EPS = 0.000001;\n\t\tthis.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );\n\n\t\treturn this;\n\n\t},\n\n\tsetFromVector3: function ( v ) {\n\n\t\treturn this.setFromCartesianCoords( v.x, v.y, v.z );\n\n\t},\n\n\tsetFromCartesianCoords: function ( x, y, z ) {\n\n\t\tthis.radius = Math.sqrt( x * x + y * y + z * z );\n\n\t\tif ( this.radius === 0 ) {\n\n\t\t\tthis.theta = 0;\n\t\t\tthis.phi = 0;\n\n\t\t} else {\n\n\t\t\tthis.theta = Math.atan2( x, z );\n\t\t\tthis.phi = Math.acos( MathUtils.clamp( y / this.radius, - 1, 1 ) );\n\n\t\t}\n\n\t\treturn this;\n\n\t}\n\n} );\n\n\nexport { Spherical };\n","import { ModelType } from \"skinview-utils\";\nimport { BoxGeometry, DoubleSide, FrontSide, Group, Mesh, MeshBasicMaterial, Object3D, Texture, Vector2 } from \"three\";\n\nfunction toFaceVertices(x1: number, y1: number, x2: number, y2: number, w: number, h: number): Array {\n\treturn [\n\t\tnew Vector2(x1 / w, 1.0 - y2 / h),\n\t\tnew Vector2(x2 / w, 1.0 - y2 / h),\n\t\tnew Vector2(x2 / w, 1.0 - y1 / h),\n\t\tnew Vector2(x1 / w, 1.0 - y1 / h)\n\t];\n}\n\nfunction toSkinVertices(x1: number, y1: number, x2: number, y2: number): Array {\n\treturn toFaceVertices(x1, y1, x2, y2, 64.0, 64.0);\n}\n\nfunction toCapeVertices(x1: number, y1: number, x2: number, y2: number): Array {\n\treturn toFaceVertices(x1, y1, x2, y2, 64.0, 32.0);\n}\n\nfunction setVertices(box: BoxGeometry, top: Array, bottom: Array, left: Array, front: Array, right: Array, back: Array): void {\n\tbox.faceVertexUvs[0] = [];\n\tbox.faceVertexUvs[0][0] = [right[3], right[0], right[2]];\n\tbox.faceVertexUvs[0][1] = [right[0], right[1], right[2]];\n\tbox.faceVertexUvs[0][2] = [left[3], left[0], left[2]];\n\tbox.faceVertexUvs[0][3] = [left[0], left[1], left[2]];\n\tbox.faceVertexUvs[0][4] = [top[3], top[0], top[2]];\n\tbox.faceVertexUvs[0][5] = [top[0], top[1], top[2]];\n\tbox.faceVertexUvs[0][6] = [bottom[0], bottom[3], bottom[1]];\n\tbox.faceVertexUvs[0][7] = [bottom[3], bottom[2], bottom[1]];\n\tbox.faceVertexUvs[0][8] = [front[3], front[0], front[2]];\n\tbox.faceVertexUvs[0][9] = [front[0], front[1], front[2]];\n\tbox.faceVertexUvs[0][10] = [back[3], back[0], back[2]];\n\tbox.faceVertexUvs[0][11] = [back[0], back[1], back[2]];\n}\n\n/**\n * Notice that innerLayer and outerLayer may NOT be the direct children of the Group.\n */\nexport class BodyPart extends Group {\n\tconstructor(\n\t\treadonly innerLayer: Object3D,\n\t\treadonly outerLayer: Object3D\n\t) {\n\t\tsuper();\n\t\tinnerLayer.name = \"inner\";\n\t\touterLayer.name = \"outer\";\n\t}\n}\n\nexport class SkinObject extends Group {\n\n\t// body parts\n\treadonly head: BodyPart;\n\treadonly body: BodyPart;\n\treadonly rightArm: BodyPart;\n\treadonly leftArm: BodyPart;\n\treadonly rightLeg: BodyPart;\n\treadonly leftLeg: BodyPart;\n\n\tprivate modelListeners: Array<() => void> = []; // called when model(slim property) is changed\n\tprivate slim = false;\n\n\tconstructor(texture: Texture) {\n\t\tsuper();\n\n\t\tconst layer1 = {\n\t\t\tmap: texture,\n\t\t\tside: FrontSide\n\t\t};\n\t\tconst layer2 = {\n\t\t\tmap: texture,\n\t\t\tside: DoubleSide,\n\t\t\ttransparent: true,\n\t\t\topacity: 1,\n\t\t\talphaTest: 0.5\n\t\t}\n\n\t\tconst layer1Material = new MeshBasicMaterial(layer1);\n\t\tconst layer2Material = new MeshBasicMaterial(layer2);\n\n\t\t// Head\n\t\tconst headBox = new BoxGeometry(8, 8, 8, 0, 0, 0);\n\t\tsetVertices(headBox,\n\t\t\ttoSkinVertices(8, 0, 16, 8),\n\t\t\ttoSkinVertices(16, 0, 24, 8),\n\t\t\ttoSkinVertices(0, 8, 8, 16),\n\t\t\ttoSkinVertices(8, 8, 16, 16),\n\t\t\ttoSkinVertices(16, 8, 24, 16),\n\t\t\ttoSkinVertices(24, 8, 32, 16)\n\t\t);\n\t\tconst headMesh = new Mesh(headBox, layer1Material);\n\n\t\tconst head2Box = new BoxGeometry(9, 9, 9, 0, 0, 0);\n\t\tsetVertices(head2Box,\n\t\t\ttoSkinVertices(40, 0, 48, 8),\n\t\t\ttoSkinVertices(48, 0, 56, 8),\n\t\t\ttoSkinVertices(32, 8, 40, 16),\n\t\t\ttoSkinVertices(40, 8, 48, 16),\n\t\t\ttoSkinVertices(48, 8, 56, 16),\n\t\t\ttoSkinVertices(56, 8, 64, 16)\n\t\t);\n\t\tconst head2Mesh = new Mesh(head2Box, layer2Material);\n\t\thead2Mesh.renderOrder = -1;\n\n\t\tthis.head = new BodyPart(headMesh, head2Mesh);\n\t\tthis.head.name = \"head\";\n\t\tthis.head.add(headMesh, head2Mesh);\n\t\tthis.add(this.head);\n\n\t\t// Body\n\t\tconst bodyBox = new BoxGeometry(8, 12, 4, 0, 0, 0);\n\t\tsetVertices(bodyBox,\n\t\t\ttoSkinVertices(20, 16, 28, 20),\n\t\t\ttoSkinVertices(28, 16, 36, 20),\n\t\t\ttoSkinVertices(16, 20, 20, 32),\n\t\t\ttoSkinVertices(20, 20, 28, 32),\n\t\t\ttoSkinVertices(28, 20, 32, 32),\n\t\t\ttoSkinVertices(32, 20, 40, 32)\n\t\t);\n\t\tconst bodyMesh = new Mesh(bodyBox, new MeshBasicMaterial({\n\t\t\t...layer1,\n\t\t\t// this pulls bodyMesh towards the camera\n\t\t\t// so body is given priority over others in z-fighting\n\t\t\tpolygonOffset: true,\n\t\t\tpolygonOffsetUnits: -1\n\t\t}));\n\n\t\tconst body2Box = new BoxGeometry(9, 13.5, 4.5, 0, 0, 0);\n\t\tsetVertices(body2Box,\n\t\t\ttoSkinVertices(20, 32, 28, 36),\n\t\t\ttoSkinVertices(28, 32, 36, 36),\n\t\t\ttoSkinVertices(16, 36, 20, 48),\n\t\t\ttoSkinVertices(20, 36, 28, 48),\n\t\t\ttoSkinVertices(28, 36, 32, 48),\n\t\t\ttoSkinVertices(32, 36, 40, 48)\n\t\t);\n\t\tconst body2Mesh = new Mesh(body2Box, new MeshBasicMaterial({\n\t\t\t...layer2,\n\t\t\t// same as above\n\t\t\tpolygonOffset: true,\n\t\t\tpolygonOffsetUnits: -1\n\t\t}));\n\n\t\tthis.body = new BodyPart(bodyMesh, body2Mesh);\n\t\tthis.body.name = \"body\";\n\t\tthis.body.add(bodyMesh, body2Mesh);\n\t\tthis.body.position.y = -10;\n\t\tthis.add(this.body);\n\n\t\t// Right Arm\n\t\tconst rightArmBox = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tconst rightArmMesh = new Mesh(rightArmBox, layer1Material);\n\t\tthis.modelListeners.push(() => {\n\t\t\trightArmMesh.scale.x = this.slim ? 3 : 4;\n\t\t\trightArmMesh.scale.y = 12;\n\t\t\trightArmMesh.scale.z = 4;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(rightArmBox,\n\t\t\t\t\ttoSkinVertices(44, 16, 47, 20),\n\t\t\t\t\ttoSkinVertices(47, 16, 50, 20),\n\t\t\t\t\ttoSkinVertices(40, 20, 44, 32),\n\t\t\t\t\ttoSkinVertices(44, 20, 47, 32),\n\t\t\t\t\ttoSkinVertices(47, 20, 51, 32),\n\t\t\t\t\ttoSkinVertices(51, 20, 54, 32)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(rightArmBox,\n\t\t\t\t\ttoSkinVertices(44, 16, 48, 20),\n\t\t\t\t\ttoSkinVertices(48, 16, 52, 20),\n\t\t\t\t\ttoSkinVertices(40, 20, 44, 32),\n\t\t\t\t\ttoSkinVertices(44, 20, 48, 32),\n\t\t\t\t\ttoSkinVertices(48, 20, 52, 32),\n\t\t\t\t\ttoSkinVertices(52, 20, 56, 32)\n\t\t\t\t);\n\t\t\t}\n\t\t\trightArmBox.uvsNeedUpdate = true;\n\t\t\trightArmBox.elementsNeedUpdate = true;\n\t\t});\n\n\t\tconst rightArm2Box = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tconst rightArm2Mesh = new Mesh(rightArm2Box, layer2Material);\n\t\trightArm2Mesh.renderOrder = 1;\n\t\tthis.modelListeners.push(() => {\n\t\t\trightArm2Mesh.scale.x = this.slim ? 3.375 : 4.5;\n\t\t\trightArm2Mesh.scale.y = 13.5;\n\t\t\trightArm2Mesh.scale.z = 4.5;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(rightArm2Box,\n\t\t\t\t\ttoSkinVertices(44, 32, 47, 36),\n\t\t\t\t\ttoSkinVertices(47, 32, 50, 36),\n\t\t\t\t\ttoSkinVertices(40, 36, 44, 48),\n\t\t\t\t\ttoSkinVertices(44, 36, 47, 48),\n\t\t\t\t\ttoSkinVertices(47, 36, 51, 48),\n\t\t\t\t\ttoSkinVertices(51, 36, 54, 48)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(rightArm2Box,\n\t\t\t\t\ttoSkinVertices(44, 32, 48, 36),\n\t\t\t\t\ttoSkinVertices(48, 32, 52, 36),\n\t\t\t\t\ttoSkinVertices(40, 36, 44, 48),\n\t\t\t\t\ttoSkinVertices(44, 36, 48, 48),\n\t\t\t\t\ttoSkinVertices(48, 36, 52, 48),\n\t\t\t\t\ttoSkinVertices(52, 36, 56, 48)\n\t\t\t\t);\n\t\t\t}\n\t\t\trightArm2Box.uvsNeedUpdate = true;\n\t\t\trightArm2Box.elementsNeedUpdate = true;\n\t\t});\n\n\t\tconst rightArmPivot = new Group();\n\t\trightArmPivot.add(rightArmMesh, rightArm2Mesh);\n\t\trightArmPivot.position.y = -4;\n\n\t\tthis.rightArm = new BodyPart(rightArmMesh, rightArm2Mesh);\n\t\tthis.rightArm.name = \"rightArm\";\n\t\tthis.rightArm.add(rightArmPivot);\n\t\tthis.rightArm.position.y = -6;\n\t\tthis.modelListeners.push(() => {\n\t\t\tthis.rightArm.position.x = this.slim ? -5.5 : -6;\n\t\t});\n\t\tthis.add(this.rightArm);\n\n\t\t// Left Arm\n\t\tconst leftArmBox = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tconst leftArmMesh = new Mesh(leftArmBox, layer1Material);\n\t\tthis.modelListeners.push(() => {\n\t\t\tleftArmMesh.scale.x = this.slim ? 3 : 4;\n\t\t\tleftArmMesh.scale.y = 12;\n\t\t\tleftArmMesh.scale.z = 4;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(leftArmBox,\n\t\t\t\t\ttoSkinVertices(36, 48, 39, 52),\n\t\t\t\t\ttoSkinVertices(39, 48, 42, 52),\n\t\t\t\t\ttoSkinVertices(32, 52, 36, 64),\n\t\t\t\t\ttoSkinVertices(36, 52, 39, 64),\n\t\t\t\t\ttoSkinVertices(39, 52, 43, 64),\n\t\t\t\t\ttoSkinVertices(43, 52, 46, 64)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(leftArmBox,\n\t\t\t\t\ttoSkinVertices(36, 48, 40, 52),\n\t\t\t\t\ttoSkinVertices(40, 48, 44, 52),\n\t\t\t\t\ttoSkinVertices(32, 52, 36, 64),\n\t\t\t\t\ttoSkinVertices(36, 52, 40, 64),\n\t\t\t\t\ttoSkinVertices(40, 52, 44, 64),\n\t\t\t\t\ttoSkinVertices(44, 52, 48, 64)\n\t\t\t\t);\n\t\t\t}\n\t\t\tleftArmBox.uvsNeedUpdate = true;\n\t\t\tleftArmBox.elementsNeedUpdate = true;\n\t\t});\n\n\t\tconst leftArm2Box = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tconst leftArm2Mesh = new Mesh(leftArm2Box, layer2Material);\n\t\tleftArm2Mesh.renderOrder = 1;\n\t\tthis.modelListeners.push(() => {\n\t\t\tleftArm2Mesh.scale.x = this.slim ? 3.375 : 4.5;\n\t\t\tleftArm2Mesh.scale.y = 13.5;\n\t\t\tleftArm2Mesh.scale.z = 4.5;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(leftArm2Box,\n\t\t\t\t\ttoSkinVertices(52, 48, 55, 52),\n\t\t\t\t\ttoSkinVertices(55, 48, 58, 52),\n\t\t\t\t\ttoSkinVertices(48, 52, 52, 64),\n\t\t\t\t\ttoSkinVertices(52, 52, 55, 64),\n\t\t\t\t\ttoSkinVertices(55, 52, 59, 64),\n\t\t\t\t\ttoSkinVertices(59, 52, 62, 64)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(leftArm2Box,\n\t\t\t\t\ttoSkinVertices(52, 48, 56, 52),\n\t\t\t\t\ttoSkinVertices(56, 48, 60, 52),\n\t\t\t\t\ttoSkinVertices(48, 52, 52, 64),\n\t\t\t\t\ttoSkinVertices(52, 52, 56, 64),\n\t\t\t\t\ttoSkinVertices(56, 52, 60, 64),\n\t\t\t\t\ttoSkinVertices(60, 52, 64, 64)\n\t\t\t\t);\n\t\t\t}\n\t\t\tleftArm2Box.uvsNeedUpdate = true;\n\t\t\tleftArm2Box.elementsNeedUpdate = true;\n\t\t});\n\n\t\tconst leftArmPivot = new Group();\n\t\tleftArmPivot.add(leftArmMesh, leftArm2Mesh);\n\t\tleftArmPivot.position.y = -4;\n\n\t\tthis.leftArm = new BodyPart(leftArmMesh, leftArm2Mesh);\n\t\tthis.leftArm.name = \"leftArm\";\n\t\tthis.leftArm.add(leftArmPivot);\n\t\tthis.leftArm.position.y = -6;\n\t\tthis.modelListeners.push(() => {\n\t\t\tthis.leftArm.position.x = this.slim ? 5.5 : 6;\n\t\t});\n\t\tthis.add(this.leftArm);\n\n\t\t// Right Leg\n\t\tconst rightLegBox = new BoxGeometry(4, 12, 4, 0, 0, 0);\n\t\tsetVertices(rightLegBox,\n\t\t\ttoSkinVertices(4, 16, 8, 20),\n\t\t\ttoSkinVertices(8, 16, 12, 20),\n\t\t\ttoSkinVertices(0, 20, 4, 32),\n\t\t\ttoSkinVertices(4, 20, 8, 32),\n\t\t\ttoSkinVertices(8, 20, 12, 32),\n\t\t\ttoSkinVertices(12, 20, 16, 32)\n\t\t);\n\t\tconst rightLegMesh = new Mesh(rightLegBox, layer1Material);\n\n\t\tconst rightLeg2Box = new BoxGeometry(4.5, 13.5, 4.5, 0, 0, 0);\n\t\tsetVertices(rightLeg2Box,\n\t\t\ttoSkinVertices(4, 32, 8, 36),\n\t\t\ttoSkinVertices(8, 32, 12, 36),\n\t\t\ttoSkinVertices(0, 36, 4, 48),\n\t\t\ttoSkinVertices(4, 36, 8, 48),\n\t\t\ttoSkinVertices(8, 36, 12, 48),\n\t\t\ttoSkinVertices(12, 36, 16, 48)\n\t\t);\n\t\tconst rightLeg2Mesh = new Mesh(rightLeg2Box, layer2Material);\n\t\trightLeg2Mesh.renderOrder = 1;\n\n\t\tconst rightLegPivot = new Group();\n\t\trightLegPivot.add(rightLegMesh, rightLeg2Mesh);\n\t\trightLegPivot.position.y = -6;\n\n\t\tthis.rightLeg = new BodyPart(rightLegMesh, rightLeg2Mesh);\n\t\tthis.rightLeg.name = \"rightLeg\";\n\t\tthis.rightLeg.add(rightLegPivot);\n\t\tthis.rightLeg.position.y = -16;\n\t\tthis.rightLeg.position.x = -2;\n\t\tthis.add(this.rightLeg);\n\n\t\t// Left Leg\n\t\tconst leftLegBox = new BoxGeometry(4, 12, 4, 0, 0, 0);\n\t\tsetVertices(leftLegBox,\n\t\t\ttoSkinVertices(20, 48, 24, 52),\n\t\t\ttoSkinVertices(24, 48, 28, 52),\n\t\t\ttoSkinVertices(16, 52, 20, 64),\n\t\t\ttoSkinVertices(20, 52, 24, 64),\n\t\t\ttoSkinVertices(24, 52, 28, 64),\n\t\t\ttoSkinVertices(28, 52, 32, 64)\n\t\t);\n\t\tconst leftLegMesh = new Mesh(leftLegBox, layer1Material);\n\n\t\tconst leftLeg2Box = new BoxGeometry(4.5, 13.5, 4.5, 0, 0, 0);\n\t\tsetVertices(leftLeg2Box,\n\t\t\ttoSkinVertices(4, 48, 8, 52),\n\t\t\ttoSkinVertices(8, 48, 12, 52),\n\t\t\ttoSkinVertices(0, 52, 4, 64),\n\t\t\ttoSkinVertices(4, 52, 8, 64),\n\t\t\ttoSkinVertices(8, 52, 12, 64),\n\t\t\ttoSkinVertices(12, 52, 16, 64)\n\t\t);\n\t\tconst leftLeg2Mesh = new Mesh(leftLeg2Box, layer2Material);\n\t\tleftLeg2Mesh.renderOrder = 1;\n\n\t\tconst leftLegPivot = new Group();\n\t\tleftLegPivot.add(leftLegMesh, leftLeg2Mesh);\n\t\tleftLegPivot.position.y = -6;\n\n\t\tthis.leftLeg = new BodyPart(leftLegMesh, leftLeg2Mesh);\n\t\tthis.leftLeg.name = \"leftLeg\";\n\t\tthis.leftLeg.add(leftLegPivot);\n\t\tthis.leftLeg.position.y = -16;\n\t\tthis.leftLeg.position.x = 2;\n\t\tthis.add(this.leftLeg);\n\n\t\tthis.modelType = \"default\";\n\t}\n\n\tget modelType(): ModelType {\n\t\treturn this.slim ? \"slim\" : \"default\";\n\t}\n\n\tset modelType(value: ModelType) {\n\t\tthis.slim = value === \"slim\";\n\t\tthis.modelListeners.forEach(listener => listener());\n\t}\n\n\tprivate getBodyParts(): Array {\n\t\treturn this.children.filter(it => it instanceof BodyPart) as Array;\n\t}\n\n\tsetInnerLayerVisible(value: boolean): void {\n\t\tthis.getBodyParts().forEach(part => part.innerLayer.visible = value);\n\t}\n\n\tsetOuterLayerVisible(value: boolean): void {\n\t\tthis.getBodyParts().forEach(part => part.outerLayer.visible = value);\n\t}\n}\n\nexport class CapeObject extends Group {\n\n\treadonly cape: Mesh;\n\n\tconstructor(texture: Texture) {\n\t\tsuper();\n\n\t\tconst capeMaterial = new MeshBasicMaterial({ map: texture, transparent: true, opacity: 1, side: DoubleSide, alphaTest: 0.5 });\n\n\t\t// back = outside\n\t\t// front = inside\n\t\tconst capeBox = new BoxGeometry(10, 16, 1, 0, 0, 0);\n\t\tsetVertices(capeBox,\n\t\t\ttoCapeVertices(1, 0, 11, 1),\n\t\t\ttoCapeVertices(11, 0, 21, 1),\n\t\t\ttoCapeVertices(11, 1, 12, 17),\n\t\t\ttoCapeVertices(12, 1, 22, 17),\n\t\t\ttoCapeVertices(0, 1, 1, 17),\n\t\t\ttoCapeVertices(1, 1, 11, 17)\n\t\t);\n\t\tthis.cape = new Mesh(capeBox, capeMaterial);\n\t\tthis.cape.position.y = -8;\n\t\tthis.cape.position.z = -0.5;\n\t\tthis.add(this.cape);\n\t}\n}\n\nexport class PlayerObject extends Group {\n\n\treadonly skin: SkinObject;\n\treadonly cape: CapeObject;\n\n\tconstructor(skinTexture: Texture, capeTexture: Texture) {\n\t\tsuper();\n\n\t\tthis.skin = new SkinObject(skinTexture);\n\t\tthis.skin.name = \"skin\";\n\t\tthis.add(this.skin);\n\n\t\tthis.cape = new CapeObject(capeTexture);\n\t\tthis.cape.name = \"cape\";\n\t\tthis.cape.position.z = -2;\n\t\tthis.cape.position.y = -4;\n\t\tthis.cape.rotation.x = 25 * Math.PI / 180;\n\t\tthis.add(this.cape);\n\t}\n}\n","function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) {\n const imgData = context.getImageData(sX, sY, w, h);\n if (flipHorizontal) {\n for (let y = 0; y < h; y++) {\n for (let x = 0; x < (w / 2); x++) {\n const index = (x + y * w) * 4;\n const index2 = ((w - x - 1) + y * w) * 4;\n const pA1 = imgData.data[index];\n const pA2 = imgData.data[index + 1];\n const pA3 = imgData.data[index + 2];\n const pA4 = imgData.data[index + 3];\n const pB1 = imgData.data[index2];\n const pB2 = imgData.data[index2 + 1];\n const pB3 = imgData.data[index2 + 2];\n const pB4 = imgData.data[index2 + 3];\n imgData.data[index] = pB1;\n imgData.data[index + 1] = pB2;\n imgData.data[index + 2] = pB3;\n imgData.data[index + 3] = pB4;\n imgData.data[index2] = pA1;\n imgData.data[index2 + 1] = pA2;\n imgData.data[index2 + 2] = pA3;\n imgData.data[index2 + 3] = pA4;\n }\n }\n }\n context.putImageData(imgData, dX, dY);\n}\nfunction hasTransparency(context, x0, y0, w, h) {\n const imgData = context.getImageData(x0, y0, w, h);\n for (let x = 0; x < w; x++) {\n for (let y = 0; y < h; y++) {\n const offset = (x + y * w) * 4;\n if (imgData.data[offset + 3] !== 0xff) {\n return true;\n }\n }\n }\n return false;\n}\nfunction computeSkinScale(width) {\n return width / 64.0;\n}\nfunction fixOpaqueSkin(context, width) {\n // Some ancient skins don't have transparent pixels (nor have helm).\n // We have to make the helm area transparent, otherwise it will be rendered as black.\n if (!hasTransparency(context, 0, 0, width, width / 2)) {\n const scale = computeSkinScale(width);\n const clearArea = (x, y, w, h) => context.clearRect(x * scale, y * scale, w * scale, h * scale);\n clearArea(40, 0, 8, 8); // Helm Top\n clearArea(48, 0, 8, 8); // Helm Bottom\n clearArea(32, 8, 8, 8); // Helm Right\n clearArea(40, 8, 8, 8); // Helm Front\n clearArea(48, 8, 8, 8); // Helm Left\n clearArea(56, 8, 8, 8); // Helm Back\n }\n}\nfunction convertSkinTo1_8(context, width) {\n const scale = computeSkinScale(width);\n const copySkin = (sX, sY, w, h, dX, dY, flipHorizontal) => copyImage(context, sX * scale, sY * scale, w * scale, h * scale, dX * scale, dY * scale, flipHorizontal);\n fixOpaqueSkin(context, width);\n copySkin(4, 16, 4, 4, 20, 48, true); // Top Leg\n copySkin(8, 16, 4, 4, 24, 48, true); // Bottom Leg\n copySkin(0, 20, 4, 12, 24, 52, true); // Outer Leg\n copySkin(4, 20, 4, 12, 20, 52, true); // Front Leg\n copySkin(8, 20, 4, 12, 16, 52, true); // Inner Leg\n copySkin(12, 20, 4, 12, 28, 52, true); // Back Leg\n copySkin(44, 16, 4, 4, 36, 48, true); // Top Arm\n copySkin(48, 16, 4, 4, 40, 48, true); // Bottom Arm\n copySkin(40, 20, 4, 12, 40, 52, true); // Outer Arm\n copySkin(44, 20, 4, 12, 36, 52, true); // Front Arm\n copySkin(48, 20, 4, 12, 32, 52, true); // Inner Arm\n copySkin(52, 20, 4, 12, 44, 52, true); // Back Arm\n}\nexport function loadSkinToCanvas(canvas, image) {\n let isOldFormat = false;\n if (image.width !== image.height) {\n if (image.width === 2 * image.height) {\n isOldFormat = true;\n }\n else {\n throw new Error(`Bad skin size: ${image.width}x${image.height}`);\n }\n }\n const context = canvas.getContext(\"2d\");\n if (isOldFormat) {\n const sideLength = image.width;\n canvas.width = sideLength;\n canvas.height = sideLength;\n context.clearRect(0, 0, sideLength, sideLength);\n context.drawImage(image, 0, 0, sideLength, sideLength / 2.0);\n convertSkinTo1_8(context, sideLength);\n }\n else {\n canvas.width = image.width;\n canvas.height = image.height;\n context.clearRect(0, 0, image.width, image.height);\n context.drawImage(image, 0, 0, canvas.width, canvas.height);\n }\n}\nfunction computeCapeScale(image) {\n if (image.width === 2 * image.height) {\n // 64x32\n return image.width / 64;\n }\n else if (image.width * 17 === image.height * 22) {\n // 22x17\n return image.width / 22;\n }\n else if (image.width * 11 === image.height * 23) {\n // 46x22\n return image.width / 46;\n }\n else {\n throw new Error(`Bad cape size: ${image.width}x${image.height}`);\n }\n}\nexport function loadCapeToCanvas(canvas, image) {\n const scale = computeCapeScale(image);\n canvas.width = 64 * scale;\n canvas.height = 32 * scale;\n const context = canvas.getContext(\"2d\");\n context.clearRect(0, 0, canvas.width, canvas.height);\n context.drawImage(image, 0, 0, image.width, image.height);\n}\nexport function inferModelType(canvas) {\n // The right arm area of *default* skins:\n // (44,16)->*-------*-------*\n // (40,20) |top |bottom |\n // \\|/ |4x4 |4x4 |\n // *-------*-------*-------*-------*\n // |right |front |left |back |\n // |4x12 |4x12 |4x12 |4x12 |\n // *-------*-------*-------*-------*\n // The right arm area of *slim* skins:\n // (44,16)->*------*------*-*\n // (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4]\n // \\|/ |3x4 |3x4 | |\n // *-------*------*------***-----*-*\n // |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12]\n // |4x12 |3x12 |4x12 |3x12 | |\n // *-------*------*-------*------*-*\n // Compared with default right arms, slim right arms have 2 unused areas.\n //\n // The same is true for left arm:\n // The left arm area of *default* skins:\n // (36,48)->*-------*-------*\n // (32,52) |top |bottom |\n // \\|/ |4x4 |4x4 |\n // *-------*-------*-------*-------*\n // |right |front |left |back |\n // |4x12 |4x12 |4x12 |4x12 |\n // *-------*-------*-------*-------*\n // The left arm area of *slim* skins:\n // (36,48)->*------*------*-*\n // (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4]\n // \\|/ |3x4 |3x4 | |\n // *-------*------*------***-----*-*\n // |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12]\n // |4x12 |3x12 |4x12 |3x12 | |\n // *-------*------*-------*------*-*\n //\n // If there is a transparent pixel in any of the 4 unused areas, the skin must be slim,\n // as transparent pixels are not allowed in the first layer.\n const scale = computeSkinScale(canvas.width);\n const context = canvas.getContext(\"2d\");\n const checkArea = (x, y, w, h) => hasTransparency(context, x * scale, y * scale, w * scale, h * scale);\n const isSlim = checkArea(50, 16, 2, 4) ||\n checkArea(54, 20, 2, 12) ||\n checkArea(42, 48, 2, 4) ||\n checkArea(46, 52, 2, 12);\n return isSlim ? \"slim\" : \"default\";\n}\n//# sourceMappingURL=process.js.map","export async function loadImage(source) {\n const image = document.createElement(\"img\");\n return new Promise((resolve, reject) => {\n image.onload = () => resolve(image);\n image.onerror = reject;\n if (typeof source === \"string\") {\n image.src = source;\n }\n else {\n if (source.crossOrigin !== undefined) {\n image.crossOrigin = source.crossOrigin;\n }\n if (source.referrerPolicy !== undefined) {\n image.referrerPolicy = source.referrerPolicy;\n }\n image.src = source.src;\n }\n });\n}\n//# sourceMappingURL=load-image.js.map","import { loadImage } from \"./load-image.js\";\nimport { inferModelType, loadCapeToCanvas, loadSkinToCanvas } from \"./process.js\";\n// https://www.typescriptlang.org/docs/handbook/mixins.html\n// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types, @typescript-eslint/no-explicit-any\nexport function applyMixins(derivedCtor, baseCtors) {\n baseCtors.forEach(baseCtor => {\n Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {\n Object.defineProperty(derivedCtor.prototype, name, Object.getOwnPropertyDescriptor(baseCtor.prototype, name));\n });\n });\n}\nexport function isTextureSource(value) {\n return value instanceof EventTarget || value instanceof ImageBitmap;\n}\nexport class SkinContainer {\n loadSkin(source, model = \"auto-detect\", options) {\n if (source === null) {\n this.resetSkin();\n }\n else if (isTextureSource(source)) {\n loadSkinToCanvas(this.skinCanvas, source);\n const actualModel = model === \"auto-detect\" ? inferModelType(this.skinCanvas) : model;\n this.skinLoaded(actualModel, options);\n }\n else {\n return loadImage(source).then(image => this.loadSkin(image, model, options));\n }\n }\n}\nexport class CapeContainer {\n loadCape(source, options) {\n if (source === null) {\n this.resetCape();\n }\n else if (isTextureSource(source)) {\n loadCapeToCanvas(this.capeCanvas, source);\n this.capeLoaded(options);\n }\n else {\n return loadImage(source).then(image => this.loadCape(image, options));\n }\n }\n}\n//# sourceMappingURL=viewer-mixins.js.map","import { Clock } from \"three\";\nimport { PlayerObject } from \"./model.js\";\n\nexport interface IAnimation {\n\tplay(player: PlayerObject, time: number): void;\n}\n\nexport type AnimationFn = (player: PlayerObject, time: number) => void;\n\nexport type Animation = AnimationFn | IAnimation;\n\nexport function invokeAnimation(animation: Animation, player: PlayerObject, time: number): void {\n\tif (animation instanceof Function) {\n\t\tanimation(player, time);\n\t} else {\n\t\t// must be IAnimation here\n\t\tanimation.play(player, time);\n\t}\n}\n\n// This interface is used to control animations\nexport interface AnimationHandle {\n\tspeed: number;\n\tpaused: boolean;\n\tprogress: number;\n\treadonly animation: Animation;\n\n\treset(): void;\n}\n\nexport interface SubAnimationHandle extends AnimationHandle {\n\tremove(): void;\n\tresetAndRemove(): void;\n}\n\nclass AnimationWrapper implements SubAnimationHandle, IAnimation {\n\tspeed: number = 1.0;\n\tpaused: boolean = false;\n\tprogress: number = 0;\n\treadonly animation: Animation;\n\n\tprivate lastTime: number = 0;\n\tprivate started: boolean = false;\n\tprivate toResetAndRemove: boolean = false;\n\n\tconstructor(animation: Animation) {\n\t\tthis.animation = animation;\n\t}\n\n\tplay(player: PlayerObject, time: number): void {\n\t\tif (this.toResetAndRemove) {\n\t\t\tinvokeAnimation(this.animation, player, 0);\n\t\t\tthis.remove();\n\t\t\treturn;\n\t\t}\n\n\t\tlet delta: number;\n\t\tif (this.started) {\n\t\t\tdelta = time - this.lastTime;\n\t\t} else {\n\t\t\tdelta = 0;\n\t\t\tthis.started = true;\n\t\t}\n\t\tthis.lastTime = time;\n\t\tif (!this.paused) {\n\t\t\tthis.progress += delta * this.speed;\n\t\t}\n\t\tinvokeAnimation(this.animation, player, this.progress);\n\t}\n\n\treset(): void {\n\t\tthis.progress = 0;\n\t}\n\n\tremove(): void {\n\t\t// stub get's overriden\n\t}\n\n\tresetAndRemove(): void {\n\t\tthis.toResetAndRemove = true;\n\t}\n}\n\nexport class CompositeAnimation implements IAnimation {\n\n\treadonly handles: Set = new Set();\n\n\tadd(animation: Animation): AnimationHandle {\n\t\tconst handle = new AnimationWrapper(animation);\n\t\thandle.remove = (): void => {\n\t\t\tthis.handles.delete(handle);\n\t\t};\n\t\tthis.handles.add(handle);\n\t\treturn handle;\n\t}\n\n\tplay(player: PlayerObject, time: number): void {\n\t\tthis.handles.forEach(handle => handle.play(player, time));\n\t}\n}\n\nexport class RootAnimation extends CompositeAnimation implements AnimationHandle {\n\tspeed: number = 1.0;\n\tprogress: number = 0.0;\n\tprivate readonly clock: Clock = new Clock(true);\n\n\tget animation(): RootAnimation {\n\t\treturn this;\n\t}\n\n\tget paused(): boolean {\n\t\treturn !this.clock.running;\n\t}\n\n\tset paused(value: boolean) {\n\t\tif (value) {\n\t\t\tthis.clock.stop();\n\t\t} else {\n\t\t\tthis.clock.start();\n\t\t}\n\t}\n\n\trunAnimationLoop(player: PlayerObject): void {\n\t\tif (this.handles.size === 0) {\n\t\t\treturn;\n\t\t}\n\t\tthis.progress += this.clock.getDelta() * this.speed;\n\t\tthis.play(player, this.progress);\n\t}\n\n\treset(): void {\n\t\tthis.progress = 0;\n\t}\n}\n\nexport const WalkingAnimation: Animation = (player, time) => {\n\tconst skin = player.skin;\n\n\t// Multiply by animation's natural speed\n\ttime *= 8;\n\n\t// Leg swing\n\tskin.leftLeg.rotation.x = Math.sin(time) * 0.5;\n\tskin.rightLeg.rotation.x = Math.sin(time + Math.PI) * 0.5;\n\n\t// Arm swing\n\tskin.leftArm.rotation.x = Math.sin(time + Math.PI) * 0.5;\n\tskin.rightArm.rotation.x = Math.sin(time) * 0.5;\n\tconst basicArmRotationZ = Math.PI * 0.02;\n\tskin.leftArm.rotation.z = Math.cos(time) * 0.03 + basicArmRotationZ;\n\tskin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.03 - basicArmRotationZ;\n\n\t// Head shaking with different frequency & amplitude\n\tskin.head.rotation.y = Math.sin(time / 4) * 0.2;\n\tskin.head.rotation.x = Math.sin(time / 5) * 0.1;\n\n\t// Always add an angle for cape around the x axis\n\tconst basicCapeRotationX = Math.PI * 0.06;\n\tplayer.cape.rotation.x = Math.sin(time / 1.5) * 0.06 + basicCapeRotationX;\n};\n\nexport const RunningAnimation: Animation = (player, time) => {\n\tconst skin = player.skin;\n\n\ttime *= 15;\n\n\t// Leg swing with larger amplitude\n\tskin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3;\n\tskin.rightLeg.rotation.x = Math.cos(time) * 1.3;\n\n\t// Arm swing\n\tskin.leftArm.rotation.x = Math.cos(time) * 1.5;\n\tskin.rightArm.rotation.x = Math.cos(time + Math.PI) * 1.5;\n\tconst basicArmRotationZ = Math.PI * 0.1;\n\tskin.leftArm.rotation.z = Math.cos(time) * 0.1 + basicArmRotationZ;\n\tskin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.1 - basicArmRotationZ;\n\n\t// Jumping\n\tplayer.position.y = Math.cos(time * 2);\n\t// Dodging when running\n\tplayer.position.x = Math.cos(time) * 0.15;\n\t// Slightly tilting when running\n\tplayer.rotation.z = Math.cos(time + Math.PI) * 0.01;\n\n\t// Apply higher swing frequency, lower amplitude,\n\t// and greater basic rotation around x axis,\n\t// to cape when running.\n\tconst basicCapeRotationX = Math.PI * 0.3;\n\tplayer.cape.rotation.x = Math.sin(time * 2) * 0.1 + basicCapeRotationX;\n\n\t// What about head shaking?\n\t// You shouldn't glance right and left when running dude :P\n};\n\nexport const RotatingAnimation: Animation = (player, time) => {\n\tplayer.rotation.y = time;\n};\n","import { applyMixins, CapeContainer, ModelType, SkinContainer, RemoteImage, TextureSource } from \"skinview-utils\";\nimport { NearestFilter, PerspectiveCamera, Scene, Texture, Vector2, WebGLRenderer } from \"three\";\nimport { RootAnimation } from \"./animation.js\";\nimport { PlayerObject } from \"./model.js\";\n\nexport type LoadOptions = {\n\t/**\n\t * Whether to make the object visible after the texture is loaded. (default: true)\n\t */\n\tmakeVisible?: boolean;\n}\n\nexport type SkinViewerOptions = {\n\twidth?: number;\n\theight?: number;\n\tskin?: RemoteImage | TextureSource;\n\tcape?: RemoteImage | TextureSource;\n}\n\nfunction toMakeVisible(options?: LoadOptions): boolean {\n\tif (options && options.makeVisible === false) {\n\t\treturn false;\n\t}\n\treturn true;\n}\n\nclass SkinViewer {\n\treadonly domElement: Node;\n\treadonly scene: Scene;\n\treadonly camera: PerspectiveCamera;\n\treadonly renderer: WebGLRenderer;\n\treadonly playerObject: PlayerObject;\n\treadonly animations: RootAnimation = new RootAnimation();\n\n\tprotected readonly skinCanvas: HTMLCanvasElement;\n\tprotected readonly capeCanvas: HTMLCanvasElement;\n\tprivate readonly skinTexture: Texture;\n\tprivate readonly capeTexture: Texture;\n\n\tprivate _disposed: boolean = false;\n\tprivate _renderPaused: boolean = false;\n\n\tconstructor(domElement: Node, options: SkinViewerOptions = {}) {\n\t\tthis.domElement = domElement;\n\n\t\t// texture\n\t\tthis.skinCanvas = document.createElement(\"canvas\");\n\t\tthis.skinTexture = new Texture(this.skinCanvas);\n\t\tthis.skinTexture.magFilter = NearestFilter;\n\t\tthis.skinTexture.minFilter = NearestFilter;\n\n\t\tthis.capeCanvas = document.createElement(\"canvas\");\n\t\tthis.capeTexture = new Texture(this.capeCanvas);\n\t\tthis.capeTexture.magFilter = NearestFilter;\n\t\tthis.capeTexture.minFilter = NearestFilter;\n\n\t\tthis.scene = new Scene();\n\n\t\t// Use smaller fov to avoid distortion\n\t\tthis.camera = new PerspectiveCamera(40);\n\t\tthis.camera.position.y = -12;\n\t\tthis.camera.position.z = 60;\n\n\t\tthis.renderer = new WebGLRenderer({ alpha: true });\n\t\tthis.domElement.appendChild(this.renderer.domElement);\n\n\t\tthis.playerObject = new PlayerObject(this.skinTexture, this.capeTexture);\n\t\tthis.playerObject.name = \"player\";\n\t\tthis.playerObject.skin.visible = false;\n\t\tthis.playerObject.cape.visible = false;\n\t\tthis.scene.add(this.playerObject);\n\n\t\twindow.requestAnimationFrame(() => this.draw());\n\n\t\tif (options.skin !== undefined) {\n\t\t\tthis.loadSkin(options.skin);\n\t\t}\n\t\tif (options.cape !== undefined) {\n\t\t\tthis.loadCape(options.cape);\n\t\t}\n\t\tif (options.width !== undefined) {\n\t\t\tthis.width = options.width;\n\t\t}\n\t\tif (options.height !== undefined) {\n\t\t\tthis.height = options.height;\n\t\t}\n\t}\n\n\tprotected skinLoaded(model: ModelType, options?: LoadOptions): void {\n\t\tthis.skinTexture.needsUpdate = true;\n\t\tthis.playerObject.skin.modelType = model;\n\t\tif (toMakeVisible(options)) {\n\t\t\tthis.playerObject.skin.visible = true;\n\t\t}\n\t}\n\n\tprotected capeLoaded(options?: LoadOptions): void {\n\t\tthis.capeTexture.needsUpdate = true;\n\t\tif (toMakeVisible(options)) {\n\t\t\tthis.playerObject.cape.visible = true;\n\t\t}\n\t}\n\n\tprotected resetSkin(): void {\n\t\tthis.playerObject.skin.visible = false;\n\t}\n\n\tprotected resetCape(): void {\n\t\tthis.playerObject.cape.visible = false;\n\t}\n\n\tprivate draw(): void {\n\t\tif (this.disposed || this._renderPaused) {\n\t\t\treturn;\n\t\t}\n\t\tthis.animations.runAnimationLoop(this.playerObject);\n\t\tthis.doRender();\n\t\twindow.requestAnimationFrame(() => this.draw());\n\t}\n\n\tprotected doRender(): void {\n\t\tthis.renderer.render(this.scene, this.camera);\n\t}\n\n\tsetSize(width: number, height: number): void {\n\t\tthis.camera.aspect = width / height;\n\t\tthis.camera.updateProjectionMatrix();\n\t\tthis.renderer.setSize(width, height);\n\t}\n\n\tdispose(): void {\n\t\tthis._disposed = true;\n\t\tthis.domElement.removeChild(this.renderer.domElement);\n\t\tthis.renderer.dispose();\n\t\tthis.skinTexture.dispose();\n\t\tthis.capeTexture.dispose();\n\t}\n\n\tget disposed(): boolean {\n\t\treturn this._disposed;\n\t}\n\n\tget renderPaused(): boolean {\n\t\treturn this._renderPaused;\n\t}\n\n\tset renderPaused(value: boolean) {\n\t\tconst toResume = !this.disposed && !value && this._renderPaused;\n\t\tthis._renderPaused = value;\n\t\tif (toResume) {\n\t\t\twindow.requestAnimationFrame(() => this.draw());\n\t\t}\n\t}\n\n\tget width(): number {\n\t\treturn this.renderer.getSize(new Vector2()).width;\n\t}\n\n\tset width(newWidth: number) {\n\t\tthis.setSize(newWidth, this.height);\n\t}\n\n\tget height(): number {\n\t\treturn this.renderer.getSize(new Vector2()).height;\n\t}\n\n\tset height(newHeight: number) {\n\t\tthis.setSize(this.width, newHeight);\n\t}\n}\ninterface SkinViewer extends SkinContainer, CapeContainer { }\napplyMixins(SkinViewer, [SkinContainer, CapeContainer]);\nexport { SkinViewer };\n","/**\n * @author qiao / https://github.com/qiao\n * @author mrdoob / http://mrdoob.com\n * @author alteredq / http://alteredqualia.com/\n * @author WestLangley / http://github.com/WestLangley\n * @author erich666 / http://erichaines.com\n * @author ScieCode / http://github.com/sciecode\n */\n\nimport {\n\tEventDispatcher,\n\tMOUSE,\n\tQuaternion,\n\tSpherical,\n\tTOUCH,\n\tVector2,\n\tVector3\n} from \"../../../build/three.module.js\";\n\n// This set of controls performs orbiting, dollying (zooming), and panning.\n// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n//\n// Orbit - left mouse / touch: one-finger move\n// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish\n// Pan - right mouse, or left mouse + ctrl/meta/shiftKey, or arrow keys / touch: two-finger move\n\nvar OrbitControls = function ( object, domElement ) {\n\n\tif ( domElement === undefined ) console.warn( 'THREE.OrbitControls: The second parameter \"domElement\" is now mandatory.' );\n\tif ( domElement === document ) console.error( 'THREE.OrbitControls: \"document\" should not be used as the target \"domElement\". Please use \"renderer.domElement\" instead.' );\n\n\tthis.object = object;\n\tthis.domElement = domElement;\n\n\t// Set to false to disable this control\n\tthis.enabled = true;\n\n\t// \"target\" sets the location of focus, where the object orbits around\n\tthis.target = new Vector3();\n\n\t// How far you can dolly in and out ( PerspectiveCamera only )\n\tthis.minDistance = 0;\n\tthis.maxDistance = Infinity;\n\n\t// How far you can zoom in and out ( OrthographicCamera only )\n\tthis.minZoom = 0;\n\tthis.maxZoom = Infinity;\n\n\t// How far you can orbit vertically, upper and lower limits.\n\t// Range is 0 to Math.PI radians.\n\tthis.minPolarAngle = 0; // radians\n\tthis.maxPolarAngle = Math.PI; // radians\n\n\t// How far you can orbit horizontally, upper and lower limits.\n\t// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].\n\tthis.minAzimuthAngle = - Infinity; // radians\n\tthis.maxAzimuthAngle = Infinity; // radians\n\n\t// Set to true to enable damping (inertia)\n\t// If damping is enabled, you must call controls.update() in your animation loop\n\tthis.enableDamping = false;\n\tthis.dampingFactor = 0.05;\n\n\t// This option actually enables dollying in and out; left as \"zoom\" for backwards compatibility.\n\t// Set to false to disable zooming\n\tthis.enableZoom = true;\n\tthis.zoomSpeed = 1.0;\n\n\t// Set to false to disable rotating\n\tthis.enableRotate = true;\n\tthis.rotateSpeed = 1.0;\n\n\t// Set to false to disable panning\n\tthis.enablePan = true;\n\tthis.panSpeed = 1.0;\n\tthis.screenSpacePanning = false; // if true, pan in screen-space\n\tthis.keyPanSpeed = 7.0;\t// pixels moved per arrow key push\n\n\t// Set to true to automatically rotate around the target\n\t// If auto-rotate is enabled, you must call controls.update() in your animation loop\n\tthis.autoRotate = false;\n\tthis.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\n\n\t// Set to false to disable use of the keys\n\tthis.enableKeys = true;\n\n\t// The four arrow keys\n\tthis.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\n\n\t// Mouse buttons\n\tthis.mouseButtons = { LEFT: MOUSE.ROTATE, MIDDLE: MOUSE.DOLLY, RIGHT: MOUSE.PAN };\n\n\t// Touch fingers\n\tthis.touches = { ONE: TOUCH.ROTATE, TWO: TOUCH.DOLLY_PAN };\n\n\t// for reset\n\tthis.target0 = this.target.clone();\n\tthis.position0 = this.object.position.clone();\n\tthis.zoom0 = this.object.zoom;\n\n\t//\n\t// public methods\n\t//\n\n\tthis.getPolarAngle = function () {\n\n\t\treturn spherical.phi;\n\n\t};\n\n\tthis.getAzimuthalAngle = function () {\n\n\t\treturn spherical.theta;\n\n\t};\n\n\tthis.saveState = function () {\n\n\t\tscope.target0.copy( scope.target );\n\t\tscope.position0.copy( scope.object.position );\n\t\tscope.zoom0 = scope.object.zoom;\n\n\t};\n\n\tthis.reset = function () {\n\n\t\tscope.target.copy( scope.target0 );\n\t\tscope.object.position.copy( scope.position0 );\n\t\tscope.object.zoom = scope.zoom0;\n\n\t\tscope.object.updateProjectionMatrix();\n\t\tscope.dispatchEvent( changeEvent );\n\n\t\tscope.update();\n\n\t\tstate = STATE.NONE;\n\n\t};\n\n\t// this method is exposed, but perhaps it would be better if we can make it private...\n\tthis.update = function () {\n\n\t\tvar offset = new Vector3();\n\n\t\t// so camera.up is the orbit axis\n\t\tvar quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) );\n\t\tvar quatInverse = quat.clone().inverse();\n\n\t\tvar lastPosition = new Vector3();\n\t\tvar lastQuaternion = new Quaternion();\n\n\t\treturn function update() {\n\n\t\t\tvar position = scope.object.position;\n\n\t\t\toffset.copy( position ).sub( scope.target );\n\n\t\t\t// rotate offset to \"y-axis-is-up\" space\n\t\t\toffset.applyQuaternion( quat );\n\n\t\t\t// angle from z-axis around y-axis\n\t\t\tspherical.setFromVector3( offset );\n\n\t\t\tif ( scope.autoRotate && state === STATE.NONE ) {\n\n\t\t\t\trotateLeft( getAutoRotationAngle() );\n\n\t\t\t}\n\n\t\t\tif ( scope.enableDamping ) {\n\n\t\t\t\tspherical.theta += sphericalDelta.theta * scope.dampingFactor;\n\t\t\t\tspherical.phi += sphericalDelta.phi * scope.dampingFactor;\n\n\t\t\t} else {\n\n\t\t\t\tspherical.theta += sphericalDelta.theta;\n\t\t\t\tspherical.phi += sphericalDelta.phi;\n\n\t\t\t}\n\n\t\t\t// restrict theta to be between desired limits\n\t\t\tspherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) );\n\n\t\t\t// restrict phi to be between desired limits\n\t\t\tspherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) );\n\n\t\t\tspherical.makeSafe();\n\n\n\t\t\tspherical.radius *= scale;\n\n\t\t\t// restrict radius to be between desired limits\n\t\t\tspherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) );\n\n\t\t\t// move target to panned location\n\n\t\t\tif ( scope.enableDamping === true ) {\n\n\t\t\t\tscope.target.addScaledVector( panOffset, scope.dampingFactor );\n\n\t\t\t} else {\n\n\t\t\t\tscope.target.add( panOffset );\n\n\t\t\t}\n\n\t\t\toffset.setFromSpherical( spherical );\n\n\t\t\t// rotate offset back to \"camera-up-vector-is-up\" space\n\t\t\toffset.applyQuaternion( quatInverse );\n\n\t\t\tposition.copy( scope.target ).add( offset );\n\n\t\t\tscope.object.lookAt( scope.target );\n\n\t\t\tif ( scope.enableDamping === true ) {\n\n\t\t\t\tsphericalDelta.theta *= ( 1 - scope.dampingFactor );\n\t\t\t\tsphericalDelta.phi *= ( 1 - scope.dampingFactor );\n\n\t\t\t\tpanOffset.multiplyScalar( 1 - scope.dampingFactor );\n\n\t\t\t} else {\n\n\t\t\t\tsphericalDelta.set( 0, 0, 0 );\n\n\t\t\t\tpanOffset.set( 0, 0, 0 );\n\n\t\t\t}\n\n\t\t\tscale = 1;\n\n\t\t\t// update condition is:\n\t\t\t// min(camera displacement, camera rotation in radians)^2 > EPS\n\t\t\t// using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\n\t\t\tif ( zoomChanged ||\n\t\t\t\tlastPosition.distanceToSquared( scope.object.position ) > EPS ||\n\t\t\t\t8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) {\n\n\t\t\t\tscope.dispatchEvent( changeEvent );\n\n\t\t\t\tlastPosition.copy( scope.object.position );\n\t\t\t\tlastQuaternion.copy( scope.object.quaternion );\n\t\t\t\tzoomChanged = false;\n\n\t\t\t\treturn true;\n\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t};\n\n\t}();\n\n\tthis.dispose = function () {\n\n\t\tscope.domElement.removeEventListener( 'contextmenu', onContextMenu, false );\n\t\tscope.domElement.removeEventListener( 'mousedown', onMouseDown, false );\n\t\tscope.domElement.removeEventListener( 'wheel', onMouseWheel, false );\n\n\t\tscope.domElement.removeEventListener( 'touchstart', onTouchStart, false );\n\t\tscope.domElement.removeEventListener( 'touchend', onTouchEnd, false );\n\t\tscope.domElement.removeEventListener( 'touchmove', onTouchMove, false );\n\n\t\tdocument.removeEventListener( 'mousemove', onMouseMove, false );\n\t\tdocument.removeEventListener( 'mouseup', onMouseUp, false );\n\n\t\tscope.domElement.removeEventListener( 'keydown', onKeyDown, false );\n\n\t\t//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?\n\n\t};\n\n\t//\n\t// internals\n\t//\n\n\tvar scope = this;\n\n\tvar changeEvent = { type: 'change' };\n\tvar startEvent = { type: 'start' };\n\tvar endEvent = { type: 'end' };\n\n\tvar STATE = {\n\t\tNONE: - 1,\n\t\tROTATE: 0,\n\t\tDOLLY: 1,\n\t\tPAN: 2,\n\t\tTOUCH_ROTATE: 3,\n\t\tTOUCH_PAN: 4,\n\t\tTOUCH_DOLLY_PAN: 5,\n\t\tTOUCH_DOLLY_ROTATE: 6\n\t};\n\n\tvar state = STATE.NONE;\n\n\tvar EPS = 0.000001;\n\n\t// current position in spherical coordinates\n\tvar spherical = new Spherical();\n\tvar sphericalDelta = new Spherical();\n\n\tvar scale = 1;\n\tvar panOffset = new Vector3();\n\tvar zoomChanged = false;\n\n\tvar rotateStart = new Vector2();\n\tvar rotateEnd = new Vector2();\n\tvar rotateDelta = new Vector2();\n\n\tvar panStart = new Vector2();\n\tvar panEnd = new Vector2();\n\tvar panDelta = new Vector2();\n\n\tvar dollyStart = new Vector2();\n\tvar dollyEnd = new Vector2();\n\tvar dollyDelta = new Vector2();\n\n\tfunction getAutoRotationAngle() {\n\n\t\treturn 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n\n\t}\n\n\tfunction getZoomScale() {\n\n\t\treturn Math.pow( 0.95, scope.zoomSpeed );\n\n\t}\n\n\tfunction rotateLeft( angle ) {\n\n\t\tsphericalDelta.theta -= angle;\n\n\t}\n\n\tfunction rotateUp( angle ) {\n\n\t\tsphericalDelta.phi -= angle;\n\n\t}\n\n\tvar panLeft = function () {\n\n\t\tvar v = new Vector3();\n\n\t\treturn function panLeft( distance, objectMatrix ) {\n\n\t\t\tv.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix\n\t\t\tv.multiplyScalar( - distance );\n\n\t\t\tpanOffset.add( v );\n\n\t\t};\n\n\t}();\n\n\tvar panUp = function () {\n\n\t\tvar v = new Vector3();\n\n\t\treturn function panUp( distance, objectMatrix ) {\n\n\t\t\tif ( scope.screenSpacePanning === true ) {\n\n\t\t\t\tv.setFromMatrixColumn( objectMatrix, 1 );\n\n\t\t\t} else {\n\n\t\t\t\tv.setFromMatrixColumn( objectMatrix, 0 );\n\t\t\t\tv.crossVectors( scope.object.up, v );\n\n\t\t\t}\n\n\t\t\tv.multiplyScalar( distance );\n\n\t\t\tpanOffset.add( v );\n\n\t\t};\n\n\t}();\n\n\t// deltaX and deltaY are in pixels; right and down are positive\n\tvar pan = function () {\n\n\t\tvar offset = new Vector3();\n\n\t\treturn function pan( deltaX, deltaY ) {\n\n\t\t\tvar element = scope.domElement;\n\n\t\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\t\t// perspective\n\t\t\t\tvar position = scope.object.position;\n\t\t\t\toffset.copy( position ).sub( scope.target );\n\t\t\t\tvar targetDistance = offset.length();\n\n\t\t\t\t// half of the fov is center to top of screen\n\t\t\t\ttargetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );\n\n\t\t\t\t// we use only clientHeight here so aspect ratio does not distort speed\n\t\t\t\tpanLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix );\n\t\t\t\tpanUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix );\n\n\t\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\t\t// orthographic\n\t\t\t\tpanLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );\n\t\t\t\tpanUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );\n\n\t\t\t} else {\n\n\t\t\t\t// camera neither orthographic nor perspective\n\t\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );\n\t\t\t\tscope.enablePan = false;\n\n\t\t\t}\n\n\t\t};\n\n\t}();\n\n\tfunction dollyOut( dollyScale ) {\n\n\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\tscale /= dollyScale;\n\n\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\tscope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) );\n\t\t\tscope.object.updateProjectionMatrix();\n\t\t\tzoomChanged = true;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n\t\t\tscope.enableZoom = false;\n\n\t\t}\n\n\t}\n\n\tfunction dollyIn( dollyScale ) {\n\n\t\tif ( scope.object.isPerspectiveCamera ) {\n\n\t\t\tscale *= dollyScale;\n\n\t\t} else if ( scope.object.isOrthographicCamera ) {\n\n\t\t\tscope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) );\n\t\t\tscope.object.updateProjectionMatrix();\n\t\t\tzoomChanged = true;\n\n\t\t} else {\n\n\t\t\tconsole.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );\n\t\t\tscope.enableZoom = false;\n\n\t\t}\n\n\t}\n\n\t//\n\t// event callbacks - update the object state\n\t//\n\n\tfunction handleMouseDownRotate( event ) {\n\n\t\trotateStart.set( event.clientX, event.clientY );\n\n\t}\n\n\tfunction handleMouseDownDolly( event ) {\n\n\t\tdollyStart.set( event.clientX, event.clientY );\n\n\t}\n\n\tfunction handleMouseDownPan( event ) {\n\n\t\tpanStart.set( event.clientX, event.clientY );\n\n\t}\n\n\tfunction handleMouseMoveRotate( event ) {\n\n\t\trotateEnd.set( event.clientX, event.clientY );\n\n\t\trotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\n\n\t\tvar element = scope.domElement;\n\n\t\trotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height\n\n\t\trotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\n\n\t\trotateStart.copy( rotateEnd );\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleMouseMoveDolly( event ) {\n\n\t\tdollyEnd.set( event.clientX, event.clientY );\n\n\t\tdollyDelta.subVectors( dollyEnd, dollyStart );\n\n\t\tif ( dollyDelta.y > 0 ) {\n\n\t\t\tdollyOut( getZoomScale() );\n\n\t\t} else if ( dollyDelta.y < 0 ) {\n\n\t\t\tdollyIn( getZoomScale() );\n\n\t\t}\n\n\t\tdollyStart.copy( dollyEnd );\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleMouseMovePan( event ) {\n\n\t\tpanEnd.set( event.clientX, event.clientY );\n\n\t\tpanDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\n\n\t\tpan( panDelta.x, panDelta.y );\n\n\t\tpanStart.copy( panEnd );\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleMouseUp( /*event*/ ) {\n\n\t\t// no-op\n\n\t}\n\n\tfunction handleMouseWheel( event ) {\n\n\t\tif ( event.deltaY < 0 ) {\n\n\t\t\tdollyIn( getZoomScale() );\n\n\t\t} else if ( event.deltaY > 0 ) {\n\n\t\t\tdollyOut( getZoomScale() );\n\n\t\t}\n\n\t\tscope.update();\n\n\t}\n\n\tfunction handleKeyDown( event ) {\n\n\t\tvar needsUpdate = false;\n\n\t\tswitch ( event.keyCode ) {\n\n\t\t\tcase scope.keys.UP:\n\t\t\t\tpan( 0, scope.keyPanSpeed );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.BOTTOM:\n\t\t\t\tpan( 0, - scope.keyPanSpeed );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.LEFT:\n\t\t\t\tpan( scope.keyPanSpeed, 0 );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t\tcase scope.keys.RIGHT:\n\t\t\t\tpan( - scope.keyPanSpeed, 0 );\n\t\t\t\tneedsUpdate = true;\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\tif ( needsUpdate ) {\n\n\t\t\t// prevent the browser from scrolling on cursor keys\n\t\t\tevent.preventDefault();\n\n\t\t\tscope.update();\n\n\t\t}\n\n\n\t}\n\n\tfunction handleTouchStartRotate( event ) {\n\n\t\tif ( event.touches.length == 1 ) {\n\n\t\t\trotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n\t\t} else {\n\n\t\t\tvar x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\n\t\t\tvar y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\n\n\t\t\trotateStart.set( x, y );\n\n\t\t}\n\n\t}\n\n\tfunction handleTouchStartPan( event ) {\n\n\t\tif ( event.touches.length == 1 ) {\n\n\t\t\tpanStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n\t\t} else {\n\n\t\t\tvar x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\n\t\t\tvar y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\n\n\t\t\tpanStart.set( x, y );\n\n\t\t}\n\n\t}\n\n\tfunction handleTouchStartDolly( event ) {\n\n\t\tvar dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n\t\tvar dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\n\t\tvar distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\tdollyStart.set( 0, distance );\n\n\t}\n\n\tfunction handleTouchStartDollyPan( event ) {\n\n\t\tif ( scope.enableZoom ) handleTouchStartDolly( event );\n\n\t\tif ( scope.enablePan ) handleTouchStartPan( event );\n\n\t}\n\n\tfunction handleTouchStartDollyRotate( event ) {\n\n\t\tif ( scope.enableZoom ) handleTouchStartDolly( event );\n\n\t\tif ( scope.enableRotate ) handleTouchStartRotate( event );\n\n\t}\n\n\tfunction handleTouchMoveRotate( event ) {\n\n\t\tif ( event.touches.length == 1 ) {\n\n\t\t\trotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n\t\t} else {\n\n\t\t\tvar x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\n\t\t\tvar y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\n\n\t\t\trotateEnd.set( x, y );\n\n\t\t}\n\n\t\trotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed );\n\n\t\tvar element = scope.domElement;\n\n\t\trotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height\n\n\t\trotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight );\n\n\t\trotateStart.copy( rotateEnd );\n\n\t}\n\n\tfunction handleTouchMovePan( event ) {\n\n\t\tif ( event.touches.length == 1 ) {\n\n\t\t\tpanEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );\n\n\t\t} else {\n\n\t\t\tvar x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX );\n\t\t\tvar y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY );\n\n\t\t\tpanEnd.set( x, y );\n\n\t\t}\n\n\t\tpanDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed );\n\n\t\tpan( panDelta.x, panDelta.y );\n\n\t\tpanStart.copy( panEnd );\n\n\t}\n\n\tfunction handleTouchMoveDolly( event ) {\n\n\t\tvar dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;\n\t\tvar dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;\n\n\t\tvar distance = Math.sqrt( dx * dx + dy * dy );\n\n\t\tdollyEnd.set( 0, distance );\n\n\t\tdollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) );\n\n\t\tdollyOut( dollyDelta.y );\n\n\t\tdollyStart.copy( dollyEnd );\n\n\t}\n\n\tfunction handleTouchMoveDollyPan( event ) {\n\n\t\tif ( scope.enableZoom ) handleTouchMoveDolly( event );\n\n\t\tif ( scope.enablePan ) handleTouchMovePan( event );\n\n\t}\n\n\tfunction handleTouchMoveDollyRotate( event ) {\n\n\t\tif ( scope.enableZoom ) handleTouchMoveDolly( event );\n\n\t\tif ( scope.enableRotate ) handleTouchMoveRotate( event );\n\n\t}\n\n\tfunction handleTouchEnd( /*event*/ ) {\n\n\t\t// no-op\n\n\t}\n\n\t//\n\t// event handlers - FSM: listen for events and reset state\n\t//\n\n\tfunction onMouseDown( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\t// Prevent the browser from scrolling.\n\t\tevent.preventDefault();\n\n\t\t// Manually set the focus since calling preventDefault above\n\t\t// prevents the browser from setting it automatically.\n\n\t\tscope.domElement.focus ? scope.domElement.focus() : window.focus();\n\n\t\tvar mouseAction;\n\n\t\tswitch ( event.button ) {\n\n\t\t\tcase 0:\n\n\t\t\t\tmouseAction = scope.mouseButtons.LEFT;\n\t\t\t\tbreak;\n\n\t\t\tcase 1:\n\n\t\t\t\tmouseAction = scope.mouseButtons.MIDDLE;\n\t\t\t\tbreak;\n\n\t\t\tcase 2:\n\n\t\t\t\tmouseAction = scope.mouseButtons.RIGHT;\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tmouseAction = - 1;\n\n\t\t}\n\n\t\tswitch ( mouseAction ) {\n\n\t\t\tcase MOUSE.DOLLY:\n\n\t\t\t\tif ( scope.enableZoom === false ) return;\n\n\t\t\t\thandleMouseDownDolly( event );\n\n\t\t\t\tstate = STATE.DOLLY;\n\n\t\t\t\tbreak;\n\n\t\t\tcase MOUSE.ROTATE:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\thandleMouseDownPan( event );\n\n\t\t\t\t\tstate = STATE.PAN;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\thandleMouseDownRotate( event );\n\n\t\t\t\t\tstate = STATE.ROTATE;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase MOUSE.PAN:\n\n\t\t\t\tif ( event.ctrlKey || event.metaKey || event.shiftKey ) {\n\n\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\thandleMouseDownRotate( event );\n\n\t\t\t\t\tstate = STATE.ROTATE;\n\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\thandleMouseDownPan( event );\n\n\t\t\t\t\tstate = STATE.PAN;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tstate = STATE.NONE;\n\n\t\t}\n\n\t\tif ( state !== STATE.NONE ) {\n\n\t\t\tdocument.addEventListener( 'mousemove', onMouseMove, false );\n\t\t\tdocument.addEventListener( 'mouseup', onMouseUp, false );\n\n\t\t\tscope.dispatchEvent( startEvent );\n\n\t\t}\n\n\t}\n\n\tfunction onMouseMove( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\n\t\tswitch ( state ) {\n\n\t\t\tcase STATE.ROTATE:\n\n\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\thandleMouseMoveRotate( event );\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.DOLLY:\n\n\t\t\t\tif ( scope.enableZoom === false ) return;\n\n\t\t\t\thandleMouseMoveDolly( event );\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.PAN:\n\n\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\thandleMouseMovePan( event );\n\n\t\t\t\tbreak;\n\n\t\t}\n\n\t}\n\n\tfunction onMouseUp( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\thandleMouseUp( event );\n\n\t\tdocument.removeEventListener( 'mousemove', onMouseMove, false );\n\t\tdocument.removeEventListener( 'mouseup', onMouseUp, false );\n\n\t\tscope.dispatchEvent( endEvent );\n\n\t\tstate = STATE.NONE;\n\n\t}\n\n\tfunction onMouseWheel( event ) {\n\n\t\tif ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return;\n\n\t\tevent.preventDefault();\n\t\tevent.stopPropagation();\n\n\t\tscope.dispatchEvent( startEvent );\n\n\t\thandleMouseWheel( event );\n\n\t\tscope.dispatchEvent( endEvent );\n\n\t}\n\n\tfunction onKeyDown( event ) {\n\n\t\tif ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return;\n\n\t\thandleKeyDown( event );\n\n\t}\n\n\tfunction onTouchStart( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault(); // prevent scrolling\n\n\t\tswitch ( event.touches.length ) {\n\n\t\t\tcase 1:\n\n\t\t\t\tswitch ( scope.touches.ONE ) {\n\n\t\t\t\t\tcase TOUCH.ROTATE:\n\n\t\t\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\t\t\thandleTouchStartRotate( event );\n\n\t\t\t\t\t\tstate = STATE.TOUCH_ROTATE;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase TOUCH.PAN:\n\n\t\t\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\t\t\thandleTouchStartPan( event );\n\n\t\t\t\t\t\tstate = STATE.TOUCH_PAN;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tstate = STATE.NONE;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tcase 2:\n\n\t\t\t\tswitch ( scope.touches.TWO ) {\n\n\t\t\t\t\tcase TOUCH.DOLLY_PAN:\n\n\t\t\t\t\t\tif ( scope.enableZoom === false && scope.enablePan === false ) return;\n\n\t\t\t\t\t\thandleTouchStartDollyPan( event );\n\n\t\t\t\t\t\tstate = STATE.TOUCH_DOLLY_PAN;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tcase TOUCH.DOLLY_ROTATE:\n\n\t\t\t\t\t\tif ( scope.enableZoom === false && scope.enableRotate === false ) return;\n\n\t\t\t\t\t\thandleTouchStartDollyRotate( event );\n\n\t\t\t\t\t\tstate = STATE.TOUCH_DOLLY_ROTATE;\n\n\t\t\t\t\t\tbreak;\n\n\t\t\t\t\tdefault:\n\n\t\t\t\t\t\tstate = STATE.NONE;\n\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tstate = STATE.NONE;\n\n\t\t}\n\n\t\tif ( state !== STATE.NONE ) {\n\n\t\t\tscope.dispatchEvent( startEvent );\n\n\t\t}\n\n\t}\n\n\tfunction onTouchMove( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault(); // prevent scrolling\n\t\tevent.stopPropagation();\n\n\t\tswitch ( state ) {\n\n\t\t\tcase STATE.TOUCH_ROTATE:\n\n\t\t\t\tif ( scope.enableRotate === false ) return;\n\n\t\t\t\thandleTouchMoveRotate( event );\n\n\t\t\t\tscope.update();\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.TOUCH_PAN:\n\n\t\t\t\tif ( scope.enablePan === false ) return;\n\n\t\t\t\thandleTouchMovePan( event );\n\n\t\t\t\tscope.update();\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.TOUCH_DOLLY_PAN:\n\n\t\t\t\tif ( scope.enableZoom === false && scope.enablePan === false ) return;\n\n\t\t\t\thandleTouchMoveDollyPan( event );\n\n\t\t\t\tscope.update();\n\n\t\t\t\tbreak;\n\n\t\t\tcase STATE.TOUCH_DOLLY_ROTATE:\n\n\t\t\t\tif ( scope.enableZoom === false && scope.enableRotate === false ) return;\n\n\t\t\t\thandleTouchMoveDollyRotate( event );\n\n\t\t\t\tscope.update();\n\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\n\t\t\t\tstate = STATE.NONE;\n\n\t\t}\n\n\t}\n\n\tfunction onTouchEnd( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\thandleTouchEnd( event );\n\n\t\tscope.dispatchEvent( endEvent );\n\n\t\tstate = STATE.NONE;\n\n\t}\n\n\tfunction onContextMenu( event ) {\n\n\t\tif ( scope.enabled === false ) return;\n\n\t\tevent.preventDefault();\n\n\t}\n\n\t//\n\n\tscope.domElement.addEventListener( 'contextmenu', onContextMenu, false );\n\n\tscope.domElement.addEventListener( 'mousedown', onMouseDown, false );\n\tscope.domElement.addEventListener( 'wheel', onMouseWheel, false );\n\n\tscope.domElement.addEventListener( 'touchstart', onTouchStart, false );\n\tscope.domElement.addEventListener( 'touchend', onTouchEnd, false );\n\tscope.domElement.addEventListener( 'touchmove', onTouchMove, false );\n\n\tscope.domElement.addEventListener( 'keydown', onKeyDown, false );\n\n\t// make sure element can receive keys.\n\n\tif ( scope.domElement.tabIndex === - 1 ) {\n\n\t\tscope.domElement.tabIndex = 0;\n\n\t}\n\n\t// force an update at start\n\n\tthis.update();\n\n};\n\nOrbitControls.prototype = Object.create( EventDispatcher.prototype );\nOrbitControls.prototype.constructor = OrbitControls;\n\n\n// This set of controls performs orbiting, dollying (zooming), and panning.\n// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n// This is very similar to OrbitControls, another set of touch behavior\n//\n// Orbit - right mouse, or left mouse + ctrl/meta/shiftKey / touch: two-finger rotate\n// Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish\n// Pan - left mouse, or arrow keys / touch: one-finger move\n\nvar MapControls = function ( object, domElement ) {\n\n\tOrbitControls.call( this, object, domElement );\n\n\tthis.mouseButtons.LEFT = MOUSE.PAN;\n\tthis.mouseButtons.RIGHT = MOUSE.ROTATE;\n\n\tthis.touches.ONE = TOUCH.PAN;\n\tthis.touches.TWO = TOUCH.DOLLY_ROTATE;\n\n};\n\nMapControls.prototype = Object.create( EventDispatcher.prototype );\nMapControls.prototype.constructor = MapControls;\n\nexport { OrbitControls, MapControls };\n","import { SkinViewer } from \"./viewer.js\";\nimport { Vector3 } from \"three\";\nimport { OrbitControls } from \"three/examples/jsm/controls/OrbitControls.js\";\n\nexport function createOrbitControls(skinViewer: SkinViewer): OrbitControls {\n\tconst control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement);\n\n\t// default configuration\n\tcontrol.enablePan = false;\n\tcontrol.target = new Vector3(0, -12, 0);\n\tcontrol.minDistance = 10;\n\tcontrol.maxDistance = 256;\n\tcontrol.update();\n\n\treturn control;\n}\n"],"names":["Object","Texture","WebGLRenderTarget","Euler","Object3D","Scene","Color","Material","MeshBasicMaterial","Int8BufferAttribute","Uint8BufferAttribute","Uint8ClampedBufferAttribute","Int16BufferAttribute","Uint16BufferAttribute","Int32BufferAttribute","Uint32BufferAttribute","Float32BufferAttribute","Float64BufferAttribute","BufferGeometry","Mesh","Geometry","ShaderMaterial","Camera","PerspectiveCamera","DataTexture","PlaneGeometry","PlaneBufferGeometry","ShaderLib","CubeTexture","DataTexture2DArray","DataTexture3D","PureArrayUniform","StructuredUniform","WebGLUniforms","MeshDepthMaterial","MeshDistanceMaterial","toFaceVertices","x1","y1","x2","y2","w","h","Vector2","toSkinVertices","toCapeVertices","setVertices","box","top","bottom","left","front","right","back","faceVertexUvs","ArrayCamera","Group","BodyPart","[object Object]","innerLayer","outerLayer","super","this","name","SkinObject","texture","layer1","map","side","layer2","transparent","opacity","alphaTest","layer1Material","layer2Material","headBox","BoxGeometry","headMesh","head2Box","head2Mesh","renderOrder","head","add","bodyBox","bodyMesh","polygonOffset","polygonOffsetUnits","body2Box","body2Mesh","body","position","y","rightArmBox","rightArmMesh","modelListeners","push","scale","x","slim","z","uvsNeedUpdate","elementsNeedUpdate","rightArm2Box","rightArm2Mesh","rightArmPivot","rightArm","leftArmBox","leftArmMesh","leftArm2Box","leftArm2Mesh","leftArmPivot","leftArm","rightLegBox","rightLegMesh","rightLeg2Box","rightLeg2Mesh","rightLegPivot","rightLeg","leftLegBox","leftLegMesh","leftLeg2Box","leftLeg2Mesh","leftLegPivot","leftLeg","modelType","value","forEach","listener","children","filter","it","getBodyParts","part","visible","CapeObject","capeMaterial","capeBox","cape","PlayerObject","skinTexture","capeTexture","skin","rotation","Math","PI","hasTransparency","context","x0","y0","imgData","getImageData","offset","data","computeSkinScale","width","convertSkinTo1_8","copySkin","sX","sY","dX","dY","flipHorizontal","index","index2","pA1","pA2","pA3","pA4","pB1","pB2","pB3","pB4","putImageData","copyImage","clearArea","clearRect","fixOpaqueSkin","loadCapeToCanvas","canvas","image","height","Error","computeCapeScale","getContext","drawImage","async","loadImage","source","document","createElement","Promise","resolve","reject","onload","onerror","src","undefined","crossOrigin","referrerPolicy","isTextureSource","EventTarget","ImageBitmap","invokeAnimation","animation","player","time","Function","play","AnimationWrapper","toResetAndRemove","remove","delta","started","lastTime","paused","progress","speed","CompositeAnimation","Set","handle","handles","delete","RootAnimation","Clock","clock","running","stop","start","size","getDelta","toMakeVisible","options","makeVisible","SkinViewer","domElement","skinCanvas","magFilter","minFilter","capeCanvas","scene","camera","renderer","WebGLRenderer","alpha","appendChild","playerObject","window","requestAnimationFrame","draw","loadSkin","loadCape","model","needsUpdate","disposed","_renderPaused","animations","runAnimationLoop","doRender","render","aspect","updateProjectionMatrix","setSize","_disposed","removeChild","dispose","renderPaused","toResume","getSize","newWidth","newHeight","derivedCtor","resetSkin","then","isOldFormat","sideLength","loadSkinToCanvas","actualModel","checkArea","inferModelType","skinLoaded","resetCape","capeLoaded","baseCtor","getOwnPropertyNames","prototype","defineProperty","getOwnPropertyDescriptor","OrbitControls","MapControls","cos","basicArmRotationZ","basicCapeRotationX","sin","skinViewer","control","enablePan","target","Vector3","minDistance","maxDistance","update"],"mappings":";0OAIA,cAEAA,0oBCGA,IAFA,yDAQA,svDCRA,wCCAA,kKDOAA,wKAoCAA,8hICzBAA,2tGCjBA,ybCiBA,8tBCjBA,8ECQA,8nBCPA,kFHiEAC,uBACAA,sBAEAA,24EAuPAD,2FCnTAA,wKAoCAA,y2LCVAE,uoBCzBAF,wtBA6FAA,mYAwEAA,kwJC3KA,oBAGA,sDAQAA,0jPCrBA,0EAqBA,gLAmBAA,quRC/BA,oBAGA,yFCVA,yBDmBAG,uDAEAA,qBAEAH,+YAwEAA,01ECzFAA,0SCDA,QAEA,+IAwBA,q2BC7BA,sQD+GAI,yBACAA,6BAEAA,uzOC5FAC,wwBC1BA,mKAqCA,sGA6eA,sPAreAL,wiKC5CA,cAOA,4EAOAA,ssDCfA,mEAaA,0FAOAA,s0HCfA,+BAIA,oFASAA,gqECZA,8FAYA,iGAQAA,q9BAoGAA,smEC1HA,krFA4BA,gFAaA,qGAWA,qFAMA,uECxDA,2OD8DAA,mqJAwgBAM,YCtjBAN,maCfA,SAEA,46BC4BA,8cDwCAO,k9NAmWAP,4FCtWAQ,yCACAA,4BAEAA,oCAEAA,gnBCvEA,aAEA,6RAkYA,sDAUA,uDAUA,8DAUA,uDAUA,wDAUA,uDAUA,wDAUA,yDAUA,yDCxdA,+UCcA,8GFcAR,4FAUAA,kwGAwWAS,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BASAC,yCACAA,4BCjcAjB,4jEEnBA,iEASA,0UA0BAkB,ogWCjCA,+JAuBA,6IAoTA,yRA+BA,ogCAtUAC,kyFClCA,oCAKA,+gBAqCAC,o2XCnDA,4OA0BA,q6CCyBA,2BCpCA,2GC3ByB,oHCAA,glBCUzB,2ICCA,oRCJA,6QL6EAC,yCACAA,4BAEAA,iCAEAA,sdA4BAA,m0BG9FAC,s1BCWAC,shECVAC,wCACAA,4BAEAA,8BCjBA,uBAGA,+JAeAxB,mjDCpBA,kqECJA,mQCAA,udAkBa,wCAIH,+IAQA,+BAIA,gCAIA,+BAIA,8BAIA,iCAIA,8ZC3CV,+LAuBA,imBALAyB,yCACAA,4BA2FAC,yCACAA,4BC1HA,0BAAyB,wGCAA,gFCAA,wFCAA,+bCAA,qGCAA,0DCAA,qHCAA,qrPCAA,0+BCAA,2pBCAA,wJCAA,4FCAA,0FCAA,8ECAA,qECAA,gECAA,6DCAA,g2FCAA,+hHCAA,ulBCAA,yKCAA,wLCAA,uOCAA,sFCAA,8ECAA,6vFCAA,40DCAA,8PCAA,4UCAA,6TCAA,+rGCAA,wpBCAA,sECAA,iECAA,0SCAA,oOCAA,mZCAA,mNCAA,uHCAA,0xFCAA,mrKCAA,0NCAA,mvCCAA,iOCAA,kzCCAA,s2CCAA,ilLCAA,k4HCAA,i5BCAA,gSCAA,6MCAA,iMCAA,yMCAA,4YCAA,sKCAA,yECAA,6WCAA,6NCAA,kMCAA,wFCAA,+VCAA,yOCAA,knBCAA,k5BCAA,qrBCAA,q8BCAA,oGCAA,4XCAA,2RCAA,slDCAA,2FCAA,uOCAA,wGCAA,iWCAA,kMCAA,6FCAA,qtQCAA,wjBCAA,0vBCAA,k6CCAA,uPCAA,giCCAA,iZCAA,2eCAA,oNCAA,wFCAA,uHCAA,qnCCAA,wGCAA,kJCAA,uFCAA,oGCAA,oJCAA,8HCAA,kSCAA,4OCAA,wKCAA,oWCAA,4OCAA,q2BCAA,0vBCAA,+sBCAA,guBCAA,wXCAA,+MCAA,mzBCAA,8iBCAA,+qDCAA,s3BCAA,81ECAA,6oCCAA,6hDCAA,2+BCAA,o8DCAA,wnCCAA,ijECAA,urCCAA,27FCAA,22CCAA,+uBCAA,+yCCAA,gwBCAA,isBCAA,+aCAA,2OCAA,suBCAA,22HCazB,6/DCTA,yeCAA,qFA4BqC,MAAkB,+CACtB,MAAoB,6FAYhB,MAAkB,+CACtB,MAAoB,wZA6BjB,wBACM,wBACH,uBACA,wBAED,wBACI,wBACN,wBACQ,ygBAME,UClF9C,yhCCHA,s6BCIA,unBAuJgC,+XAvEH,uBAMqB,kGAcf,6ICxGnC,0jBCAA,gRAuBQ,kCAIA,8BAIA,8BAIA,0BAIA,wFCvCR,sDAMA,8wBCNA,+OA6B6C,6CC1B7C,yICAA,qNCAA,qNCiSAC,+VHrRAC,wCACAA,4BAEAA,8BAEA5B,+GCCA6B,wCACAA,4BACAA,qCCOAC,wCACAA,4BACAA,gCEgBA,6HAoBA,qMAmCA,iHAcA,0DAYA,mIAyBA,8EAcA,uLA2BA,yUAwCA,yOA+BA,yMA2BA,yMA2BA,yMA6BA,sIAgBA,uIAgBA,kIAgBA,wIAkBA,8EAYA,+EAYA,+EAYA,+EAcA,+EA+DA,2CAOA,2CAMA,2CAMA,2CAMA,2CASA,mEAQA,mEAQA,mEAUA,4EAQA,4EAQA,6EAUA,8HAgBA,gIAuDA,qEA9MA,6hBAyNA,sFAhDA,waA0EA,iDAdAC,uJAuBAC,wHAiBA,kCAWA,6CAOA,4QAoDA,2EAK0C,6FCvzB1C,2FDo0BAC,yFAQAA,sFAWAA,iIAkBAA,+GEp2BA,SAgBA,maA2BA,gDAE6C,+GA3C7C,qHAyDA,mGAcA,0SAuFA,4BAMA,0aAcA,0JAUA,0CAEA,uCAMA,4GAgBA,2OAGA,sDAQA,4KAOA,kJAkBA,iQAgIA,oGA1GA,iMAsBA,kQAmCA,wIAqBA,oPAlPA,6kBAaA,+uNA6kBuC,kBACE,qXA8BD,yJAOsF,mZAjmB9H,qDAI0C,0SC/I1C,83MCLA,uNCAA,8QA8BA,oKAuBA,60BAqHA,6UCrKA,4hBAuIA,SAEA,6DAMA,ulIClJA,6OAkDA,2VC9BA,8SCAA,oTD4BAC,yCACAA,4BAEAA,oCAEAA,gZCNAC,yCACAA,4BAEAA,uCAEAA,wZCtCA,2OCpByB,0ECAA,k1JCOzB,sbA6Ea,QAIC,2HA2BQ,8BAKA,8BAKA,8BAKA,8BAKA,8BAKA,8BAKA,8BAKA,+BAKA,sBAMF,4PA8DN,QAIC,8YA6F6B,gMA2BR,iCAIF,2SA0BR,MAAuB,wBACvB,MAAuB,6CAIhB,WAAkB,KAAS,sTAS5C,QAAiC,KAAe,UAChD,SAAuC,MAAqB,2DAQnE,gCAKA,sBAgHU,UACK,UACO,mBAKC,aACA,oGAgBd,MACD,MACK,QACA,QACQ,QACR,QACA,QACQ,QACA,QACA,QACA,oDAoBnB,gQAWY,2DAYM,EAAQ,IAAwB,EAAQ,8BAIhD,EAAQ,oCAIA,EAAS,EAAS,IAAwB,sCAI1C,EAAS,IAAc,EAAS,qHAchC,IAAc,IAAwB,EAAQ,8BAItD,IAAc,4BAId,EAAS,8BAIT,EAAS,2HAxEjB,gDA0KK,kBAIA,kCAcP,+BAMO,uBAIA,iBAIA,UAQN,iCAwBD,uDAaC,oCAwBiC,kYA7WN,UAAmB,wNAiO5C,QACD,mqBA6HF,QAIC,k+BC9yBZ,0+CAkJoB,WAED,aAA6B,OAC7B,aAAkC,OAClC,aAAqC,QAIpC,WAED,aAA6B,OAC7B,aAAkC,OAClC,aAAqC,QAIpC,WAED,aAA6B,OAC7B,aAAkC,OAClC,aAAqC,QAI9B,WAA+B,WACnC,WAAkC,+FAgB9C,KAID,s7CAoJc,uBACF,6IA8CG,uBACF,sCAEF,0SA2BK,sJAkBW,oKAUX,2HAkBD,uHAOC,gEAMD,kEAMC,kEAeL,+FAUI,uBACF,yDAQC,uBACF,0CAKC,WACK,WACG,eAIT,UACa,UACD,UAEb,UACa,UACD,6CAOG,oCACA,kBAEX,WAAkC,6BAEtB,oCAID,wCACA,0CAIA,MAAoB,yBACpB,MAAoB,OAE/B,WAAkC,6BAEtB,MAAoB,uMAUrB,wCACA,ovBA8Cf,gCAEgC,6BACL,8BAIxB,yDAGJ,6BACA,wCACA,qSAkBG,uBAME,oBAIA,oBAIA,MAIA,oHAgBuC,uMAgBO,aAI/C,sKAkBF,mIAaE,0GASD,4LAeY,gKAUX,+GAUF,0GAKA,yIAgBE,kFASD,wSA4BC,gCACK,+DACL,oDAOC,gDAIE,uEAUD,wBAIA,oDAQe,uDAIX,oDAIG,MAAiB,MAAsB,+FAQ/B,QAA2B,mDAItC,MAAkB,kDAKf,MAAiB,MAA8B,4JAYvC,uDAIX,6CAML,6TAUD,keAyBM,MAAiB,MAAsB,qHAIvC,MAAiB,MAA8B,6GA+BlD,qIAQD,uHAQF,icAtoBA,uBACF,wIAeE,uBACF,kzBA0qBM,0KAMc,8CAEf,kEACQ,MAAiB,MAAuB,qDAC/C,oIASD,qIAiBJ,0BACG,+DAIkE,MAAuB,2BAM9F,gDAIE,+BAIA,yBACG,2CAC4D,MAAuB,wBAIxF,+CAIE,2IAqBiC,MAAuB,4NAmBrD,0DACA,uDAIV,yBAE6B,0BACE,0CAE2B,wBAEhD,yqBCppCzB,wFAQuC,wBACK,yBACA,yBACD,yBAEZ,wBACC,wBACQ,wBACV,wBACQ,wBACN,0BAIN,yFAgBQ,wBACF,wBACC,wBACK,wBACK,wBACT,wBACO,yBACT,wBAIO,yBACR,yBACO,yBACC,yBACC,+1CAsHd,sFC3K1B,gDCAA,6CCAA,mDCMA,y5HCNA,62MC2CA,grKA4e8C,4BACA,0BACI,urBA8H/B,+BACA,sBAAwC,wEAGA,0CAMxC,6BACA,oBAAsC,oEAGA,sCAMtC,yBACA,gBAAkC,4DAGA,yCAMlC,4BACA,mBAAqC,kEAGA,uDAMtC,yxCAgPI,uPAqBA,8SAqBD,ibA/LD,oSA8BE,cAIA,2GAcA,0BAIA,aAIA,6BAMD,yBAIA,gqSA8iCiE,ylBAwE9D,8GAYK,MAAiB,MAAuB,kPA6B5C,kGAYqE,2LAOE,6UASrC,iCAAtB,2PAoBX,wUAqBJ,4OAmBA,qFAMW,2FAIV,uEAOgD,gNCtmEvE,+GCQA,4GCTA,SAASC,GAAeC,EAAYC,EAAYC,EAAYC,EAAYC,EAAWC,GAClF,MAAO,CACN,IAAIC,EAAQN,EAAKI,EAAG,EAAMD,EAAKE,GAC/B,IAAIC,EAAQJ,EAAKE,EAAG,EAAMD,EAAKE,GAC/B,IAAIC,EAAQJ,EAAKE,EAAG,EAAMH,EAAKI,GAC/B,IAAIC,EAAQN,EAAKI,EAAG,EAAMH,EAAKI,IAIjC,SAASE,GAAeP,EAAYC,EAAYC,EAAYC,GAC3D,OAAOJ,GAAeC,EAAIC,EAAIC,EAAIC,EAAI,GAAM,IAG7C,SAASK,GAAeR,EAAYC,EAAYC,EAAYC,GAC3D,OAAOJ,GAAeC,EAAIC,EAAIC,EAAIC,EAAI,GAAM,IAG7C,SAASM,GAAYC,EAAkBC,EAAqBC,EAAwBC,EAAsBC,EAAuBC,EAAuBC,GACvJN,EAAIO,cAAc,GAAK,GACvBP,EAAIO,cAAc,GAAG,GAAK,CAACF,EAAM,GAAIA,EAAM,GAAIA,EAAM,IACrDL,EAAIO,cAAc,GAAG,GAAK,CAACF,EAAM,GAAIA,EAAM,GAAIA,EAAM,IACrDL,EAAIO,cAAc,GAAG,GAAK,CAACJ,EAAK,GAAIA,EAAK,GAAIA,EAAK,IAClDH,EAAIO,cAAc,GAAG,GAAK,CAACJ,EAAK,GAAIA,EAAK,GAAIA,EAAK,IAClDH,EAAIO,cAAc,GAAG,GAAK,CAACN,EAAI,GAAIA,EAAI,GAAIA,EAAI,IAC/CD,EAAIO,cAAc,GAAG,GAAK,CAACN,EAAI,GAAIA,EAAI,GAAIA,EAAI,IAC/CD,EAAIO,cAAc,GAAG,GAAK,CAACL,EAAO,GAAIA,EAAO,GAAIA,EAAO,IACxDF,EAAIO,cAAc,GAAG,GAAK,CAACL,EAAO,GAAIA,EAAO,GAAIA,EAAO,IACxDF,EAAIO,cAAc,GAAG,GAAK,CAACH,EAAM,GAAIA,EAAM,GAAIA,EAAM,IACrDJ,EAAIO,cAAc,GAAG,GAAK,CAACH,EAAM,GAAIA,EAAM,GAAIA,EAAM,IACrDJ,EAAIO,cAAc,GAAG,IAAM,CAACD,EAAK,GAAIA,EAAK,GAAIA,EAAK,IACnDN,EAAIO,cAAc,GAAG,IAAM,CAACD,EAAK,GAAIA,EAAK,GAAIA,EAAK,IRnBpDE,0FCAAC,mFCDAxD,2lCCidAA,wCG9cAA,0iBCMAA,6mBCiBayD,WAAiBD,GAC7BE,YACUC,EACAC,GAETC,QAHSC,gBAAAH,EACAG,gBAAAF,EAGTD,EAAWI,KAAO,QAClBH,EAAWG,KAAO,eAIPC,WAAmBR,GAa/BE,YAAYO,GACXJ,QAJOC,oBAAoC,GACpCA,WAAO,EAKd,MAAMI,EAAS,CACdC,IAAKF,EACLG,QAEKC,EAAS,CACdF,IAAKF,EACLG,OACAE,aAAa,EACbC,QAAS,EACTC,UAAW,IAGNC,EAAiB,IAAIjE,GAAkB0D,GACvCQ,EAAiB,IAAIlE,GAAkB6D,GAGvCM,EAAU,IAAIC,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAC/C9B,GAAY6B,EACX/B,GAAe,EAAG,EAAG,GAAI,GACzBA,GAAe,GAAI,EAAG,GAAI,GAC1BA,GAAe,EAAG,EAAG,EAAG,IACxBA,GAAe,EAAG,EAAG,GAAI,IACzBA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,GAAI,EAAG,GAAI,KAE3B,MAAMiC,EAAW,IAAI1D,GAAKwD,EAASF,GAE7BK,EAAW,IAAIF,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAChD9B,GAAYgC,EACXlC,GAAe,GAAI,EAAG,GAAI,GAC1BA,GAAe,GAAI,EAAG,GAAI,GAC1BA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,GAAI,EAAG,GAAI,KAE3B,MAAMmC,EAAY,IAAI5D,GAAK2D,EAAUJ,GACrCK,EAAUC,aAAe,EAEzBlB,KAAKmB,KAAO,IAAIxB,GAASoB,EAAUE,GACnCjB,KAAKmB,KAAKlB,KAAO,OACjBD,KAAKmB,KAAKC,IAAIL,EAAUE,GACxBjB,KAAKoB,IAAIpB,KAAKmB,MAGd,MAAME,EAAU,IAAIP,GAAY,EAAG,GAAI,EAAG,EAAG,EAAG,GAChD9B,GAAYqC,EACXvC,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAMwC,EAAW,IAAIjE,GAAKgE,EAAS,IAAI3E,kCACnC0D,IAGHmB,eAAe,EACfC,oBAAqB,MAGhBC,EAAW,IAAIX,GAAY,EAAG,KAAM,IAAK,EAAG,EAAG,GACrD9B,GAAYyC,EACX3C,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAM4C,EAAY,IAAIrE,GAAKoE,EAAU,IAAI/E,kCACrC6D,IAEHgB,eAAe,EACfC,oBAAqB,MAGtBxB,KAAK2B,KAAO,IAAIhC,GAAS2B,EAAUI,GACnC1B,KAAK2B,KAAK1B,KAAO,OACjBD,KAAK2B,KAAKP,IAAIE,EAAUI,GACxB1B,KAAK2B,KAAKC,SAASC,GAAK,GACxB7B,KAAKoB,IAAIpB,KAAK2B,MAGd,MAAMG,EAAc,IAAIhB,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAC7CiB,EAAe,IAAI1E,GAAKyE,EAAanB,GAC3CX,KAAKgC,eAAeC,KAAK,KACxBF,EAAaG,MAAMC,EAAInC,KAAKoC,KAAO,EAAI,EACvCL,EAAaG,MAAML,EAAI,GACvBE,EAAaG,MAAMG,EAAI,EACnBrC,KAAKoC,KACRpD,GAAY8C,EACXhD,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG5BE,GAAY8C,EACXhD,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG7BgD,EAAYQ,eAAgB,EAC5BR,EAAYS,oBAAqB,IAGlC,MAAMC,EAAe,IAAI1B,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAC9C2B,EAAgB,IAAIpF,GAAKmF,EAAc5B,GAC7C6B,EAAcvB,YAAc,EAC5BlB,KAAKgC,eAAeC,KAAK,KACxBQ,EAAcP,MAAMC,EAAInC,KAAKoC,KAAO,MAAQ,IAC5CK,EAAcP,MAAML,EAAI,KACxBY,EAAcP,MAAMG,EAAI,IACpBrC,KAAKoC,KACRpD,GAAYwD,EACX1D,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG5BE,GAAYwD,EACX1D,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG7B0D,EAAaF,eAAgB,EAC7BE,EAAaD,oBAAqB,IAGnC,MAAMG,EAAgB,IAAIhD,GAC1BgD,EAActB,IAAIW,EAAcU,GAChCC,EAAcd,SAASC,GAAK,EAE5B7B,KAAK2C,SAAW,IAAIhD,GAASoC,EAAcU,GAC3CzC,KAAK2C,SAAS1C,KAAO,WACrBD,KAAK2C,SAASvB,IAAIsB,GAClB1C,KAAK2C,SAASf,SAASC,GAAK,EAC5B7B,KAAKgC,eAAeC,KAAK,KACxBjC,KAAK2C,SAASf,SAASO,EAAInC,KAAKoC,MAAQ,KAAO,IAEhDpC,KAAKoB,IAAIpB,KAAK2C,UAGd,MAAMC,EAAa,IAAI9B,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAC5C+B,EAAc,IAAIxF,GAAKuF,EAAYjC,GACzCX,KAAKgC,eAAeC,KAAK,KACxBY,EAAYX,MAAMC,EAAInC,KAAKoC,KAAO,EAAI,EACtCS,EAAYX,MAAML,EAAI,GACtBgB,EAAYX,MAAMG,EAAI,EAClBrC,KAAKoC,KACRpD,GAAY4D,EACX9D,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG5BE,GAAY4D,EACX9D,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG7B8D,EAAWN,eAAgB,EAC3BM,EAAWL,oBAAqB,IAGjC,MAAMO,EAAc,IAAIhC,GAAY,EAAG,EAAG,EAAG,EAAG,EAAG,GAC7CiC,EAAe,IAAI1F,GAAKyF,EAAalC,GAC3CmC,EAAa7B,YAAc,EAC3BlB,KAAKgC,eAAeC,KAAK,KACxBc,EAAab,MAAMC,EAAInC,KAAKoC,KAAO,MAAQ,IAC3CW,EAAab,MAAML,EAAI,KACvBkB,EAAab,MAAMG,EAAI,IACnBrC,KAAKoC,KACRpD,GAAY8D,EACXhE,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG5BE,GAAY8D,EACXhE,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAG7BgE,EAAYR,eAAgB,EAC5BQ,EAAYP,oBAAqB,IAGlC,MAAMS,EAAe,IAAItD,GACzBsD,EAAa5B,IAAIyB,EAAaE,GAC9BC,EAAapB,SAASC,GAAK,EAE3B7B,KAAKiD,QAAU,IAAItD,GAASkD,EAAaE,GACzC/C,KAAKiD,QAAQhD,KAAO,UACpBD,KAAKiD,QAAQ7B,IAAI4B,GACjBhD,KAAKiD,QAAQrB,SAASC,GAAK,EAC3B7B,KAAKgC,eAAeC,KAAK,KACxBjC,KAAKiD,QAAQrB,SAASO,EAAInC,KAAKoC,KAAO,IAAM,IAE7CpC,KAAKoB,IAAIpB,KAAKiD,SAGd,MAAMC,EAAc,IAAIpC,GAAY,EAAG,GAAI,EAAG,EAAG,EAAG,GACpD9B,GAAYkE,EACXpE,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAMqE,EAAe,IAAI9F,GAAK6F,EAAavC,GAErCyC,EAAe,IAAItC,GAAY,IAAK,KAAM,IAAK,EAAG,EAAG,GAC3D9B,GAAYoE,EACXtE,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAMuE,EAAgB,IAAIhG,GAAK+F,EAAcxC,GAC7CyC,EAAcnC,YAAc,EAE5B,MAAMoC,EAAgB,IAAI5D,GAC1B4D,EAAclC,IAAI+B,EAAcE,GAChCC,EAAc1B,SAASC,GAAK,EAE5B7B,KAAKuD,SAAW,IAAI5D,GAASwD,EAAcE,GAC3CrD,KAAKuD,SAAStD,KAAO,WACrBD,KAAKuD,SAASnC,IAAIkC,GAClBtD,KAAKuD,SAAS3B,SAASC,GAAK,GAC5B7B,KAAKuD,SAAS3B,SAASO,GAAK,EAC5BnC,KAAKoB,IAAIpB,KAAKuD,UAGd,MAAMC,EAAa,IAAI1C,GAAY,EAAG,GAAI,EAAG,EAAG,EAAG,GACnD9B,GAAYwE,EACX1E,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,IAC3BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAM2E,EAAc,IAAIpG,GAAKmG,EAAY7C,GAEnC+C,EAAc,IAAI5C,GAAY,IAAK,KAAM,IAAK,EAAG,EAAG,GAC1D9B,GAAY0E,EACX5E,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,EAAG,IACzBA,GAAe,EAAG,GAAI,GAAI,IAC1BA,GAAe,GAAI,GAAI,GAAI,KAE5B,MAAM6E,EAAe,IAAItG,GAAKqG,EAAa9C,GAC3C+C,EAAazC,YAAc,EAE3B,MAAM0C,EAAe,IAAIlE,GACzBkE,EAAaxC,IAAIqC,EAAaE,GAC9BC,EAAahC,SAASC,GAAK,EAE3B7B,KAAK6D,QAAU,IAAIlE,GAAS8D,EAAaE,GACzC3D,KAAK6D,QAAQ5D,KAAO,UACpBD,KAAK6D,QAAQzC,IAAIwC,GACjB5D,KAAK6D,QAAQjC,SAASC,GAAK,GAC3B7B,KAAK6D,QAAQjC,SAASO,EAAI,EAC1BnC,KAAKoB,IAAIpB,KAAK6D,SAEd7D,KAAK8D,UAAY,UAGlBA,gBACC,OAAO9D,KAAKoC,KAAO,OAAS,UAG7B0B,cAAcC,GACb/D,KAAKoC,KAAiB,SAAV2B,EACZ/D,KAAKgC,eAAegC,QAAQC,GAAYA,KAGjCrE,eACP,OAAOI,KAAKkE,SAASC,OAAOC,GAAMA,aAAczE,IAGjDC,qBAAqBmE,GACpB/D,KAAKqE,eAAeL,QAAQM,GAAQA,EAAKzE,WAAW0E,QAAUR,GAG/DnE,qBAAqBmE,GACpB/D,KAAKqE,eAAeL,QAAQM,GAAQA,EAAKxE,WAAWyE,QAAUR,UAInDS,WAAmB9E,GAI/BE,YAAYO,GACXJ,QAEA,MAAM0E,EAAe,IAAI/H,GAAkB,CAAE2D,IAAKF,EAASK,aAAa,EAAMC,QAAS,EAAGH,OAAkBI,UAAW,KAIjHgE,EAAU,IAAI5D,GAAY,GAAI,GAAI,EAAG,EAAG,EAAG,GACjD9B,GAAY0F,EACX3F,GAAe,EAAG,EAAG,GAAI,GACzBA,GAAe,GAAI,EAAG,GAAI,GAC1BA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,GAAI,EAAG,GAAI,IAC1BA,GAAe,EAAG,EAAG,EAAG,IACxBA,GAAe,EAAG,EAAG,GAAI,KAE1BiB,KAAK2E,KAAO,IAAItH,GAAKqH,EAASD,GAC9BzE,KAAK2E,KAAK/C,SAASC,GAAK,EACxB7B,KAAK2E,KAAK/C,SAASS,GAAK,GACxBrC,KAAKoB,IAAIpB,KAAK2E,aAIHC,WAAqBlF,GAKjCE,YAAYiF,EAAsBC,GACjC/E,QAEAC,KAAK+E,KAAO,IAAI7E,GAAW2E,GAC3B7E,KAAK+E,KAAK9E,KAAO,OACjBD,KAAKoB,IAAIpB,KAAK+E,MAEd/E,KAAK2E,KAAO,IAAIH,GAAWM,GAC3B9E,KAAK2E,KAAK1E,KAAO,OACjBD,KAAK2E,KAAK/C,SAASS,GAAK,EACxBrC,KAAK2E,KAAK/C,SAASC,GAAK,EACxB7B,KAAK2E,KAAKK,SAAS7C,EAAI,GAAK8C,KAAKC,GAAK,IACtClF,KAAKoB,IAAIpB,KAAK2E,OCvZhB,SAASQ,GAAgBC,EAASC,EAAIC,EAAI3G,EAAGC,GACzC,MAAM2G,EAAUH,EAAQI,aAAaH,EAAIC,EAAI3G,EAAGC,GAChD,IAAK,IAAIuD,EAAI,EAAGA,EAAIxD,EAAGwD,IACnB,IAAK,IAAIN,EAAI,EAAGA,EAAIjD,EAAGiD,IAAK,CACxB,MAAM4D,EAAuB,GAAbtD,EAAIN,EAAIlD,GACxB,GAAiC,MAA7B4G,EAAQG,KAAKD,EAAS,GACtB,OAAO,EAInB,OAAO,EAEX,SAASE,GAAiBC,GACtB,OAAOA,EAAQ,GAgBnB,SAASC,GAAiBT,EAASQ,GAC/B,MAAM1D,EAAQyD,GAAiBC,GACzBE,EAAW,CAACC,EAAIC,EAAIrH,EAAGC,EAAGqH,EAAIC,EAAIC,IA3D5C,SAAmBf,EAASW,EAAIC,EAAIrH,EAAGC,EAAGqH,EAAIC,EAAIC,GAC9C,MAAMZ,EAAUH,EAAQI,aAAaO,EAAIC,EAAIrH,EAAGC,GAChD,GAAIuH,EACA,IAAK,IAAItE,EAAI,EAAGA,EAAIjD,EAAGiD,IACnB,IAAK,IAAIM,EAAI,EAAGA,EAAKxD,EAAI,EAAIwD,IAAK,CAC9B,MAAMiE,EAAsB,GAAbjE,EAAIN,EAAIlD,GACjB0H,EAAiC,GAAtB1H,EAAIwD,EAAI,EAAKN,EAAIlD,GAC5B2H,EAAMf,EAAQG,KAAKU,GACnBG,EAAMhB,EAAQG,KAAKU,EAAQ,GAC3BI,EAAMjB,EAAQG,KAAKU,EAAQ,GAC3BK,EAAMlB,EAAQG,KAAKU,EAAQ,GAC3BM,EAAMnB,EAAQG,KAAKW,GACnBM,EAAMpB,EAAQG,KAAKW,EAAS,GAC5BO,EAAMrB,EAAQG,KAAKW,EAAS,GAC5BQ,EAAMtB,EAAQG,KAAKW,EAAS,GAClCd,EAAQG,KAAKU,GAASM,EACtBnB,EAAQG,KAAKU,EAAQ,GAAKO,EAC1BpB,EAAQG,KAAKU,EAAQ,GAAKQ,EAC1BrB,EAAQG,KAAKU,EAAQ,GAAKS,EAC1BtB,EAAQG,KAAKW,GAAUC,EACvBf,EAAQG,KAAKW,EAAS,GAAKE,EAC3BhB,EAAQG,KAAKW,EAAS,GAAKG,EAC3BjB,EAAQG,KAAKW,EAAS,GAAKI,EAIvCrB,EAAQ0B,aAAavB,EAASU,EAAIC,GAiCyBa,CAAU3B,EAASW,EAAK7D,EAAO8D,EAAK9D,EAAOvD,EAAIuD,EAAOtD,EAAIsD,EAAO+D,EAAK/D,EAAOgE,EAAKhE,EAAOiE,IAhBxJ,SAAuBf,EAASQ,GAG5B,IAAKT,GAAgBC,EAAS,EAAG,EAAGQ,EAAOA,EAAQ,GAAI,CACnD,MAAM1D,EAAQyD,GAAiBC,GACzBoB,EAAY,CAAC7E,EAAGN,EAAGlD,EAAGC,IAAMwG,EAAQ6B,UAAU9E,EAAID,EAAOL,EAAIK,EAAOvD,EAAIuD,EAAOtD,EAAIsD,GACzF8E,EAAU,GAAI,EAAG,EAAG,GACpBA,EAAU,GAAI,EAAG,EAAG,GACpBA,EAAU,GAAI,EAAG,EAAG,GACpBA,EAAU,GAAI,EAAG,EAAG,GACpBA,EAAU,GAAI,EAAG,EAAG,GACpBA,EAAU,GAAI,EAAG,EAAG,IAMxBE,CAAc9B,EAASQ,GACvBE,EAAS,EAAG,GAAI,EAAG,EAAG,GAAI,IAAI,GAC9BA,EAAS,EAAG,GAAI,EAAG,EAAG,GAAI,IAAI,GAC9BA,EAAS,EAAG,GAAI,EAAG,GAAI,GAAI,IAAI,GAC/BA,EAAS,EAAG,GAAI,EAAG,GAAI,GAAI,IAAI,GAC/BA,EAAS,EAAG,GAAI,EAAG,GAAI,GAAI,IAAI,GAC/BA,EAAS,GAAI,GAAI,EAAG,GAAI,GAAI,IAAI,GAChCA,EAAS,GAAI,GAAI,EAAG,EAAG,GAAI,IAAI,GAC/BA,EAAS,GAAI,GAAI,EAAG,EAAG,GAAI,IAAI,GAC/BA,EAAS,GAAI,GAAI,EAAG,GAAI,GAAI,IAAI,GAChCA,EAAS,GAAI,GAAI,EAAG,GAAI,GAAI,IAAI,GAChCA,EAAS,GAAI,GAAI,EAAG,GAAI,GAAI,IAAI,GAChCA,EAAS,GAAI,GAAI,EAAG,GAAI,GAAI,IAAI,GA6C7B,SAASqB,GAAiBC,EAAQC,GACrC,MAAMnF,EAlBV,SAA0BmF,GACtB,GAAIA,EAAMzB,QAAU,EAAIyB,EAAMC,OAE1B,OAAOD,EAAMzB,MAAQ,GAEpB,GAAkB,GAAdyB,EAAMzB,OAA8B,GAAfyB,EAAMC,OAEhC,OAAOD,EAAMzB,MAAQ,GAEpB,GAAkB,GAAdyB,EAAMzB,OAA8B,GAAfyB,EAAMC,OAEhC,OAAOD,EAAMzB,MAAQ,GAGrB,MAAM,IAAI2B,MAAM,kBAAkBF,EAAMzB,SAASyB,EAAMC,UAI7CE,CAAiBH,GAC/BD,EAAOxB,MAAQ,GAAK1D,EACpBkF,EAAOE,OAAS,GAAKpF,EACrB,MAAMkD,EAAUgC,EAAOK,WAAW,MAClCrC,EAAQ6B,UAAU,EAAG,EAAGG,EAAOxB,MAAOwB,EAAOE,QAC7ClC,EAAQsC,UAAUL,EAAO,EAAG,EAAGA,EAAMzB,MAAOyB,EAAMC,QC3H/CK,eAAeC,GAAUC,GAC5B,MAAMR,EAAQS,SAASC,cAAc,OACrC,OAAO,IAAIC,QAAQ,CAACC,EAASC,KACzBb,EAAMc,OAAS,IAAMF,EAAQZ,GAC7BA,EAAMe,QAAUF,EACM,iBAAXL,EACPR,EAAMgB,IAAMR,QAGeS,IAAvBT,EAAOU,cACPlB,EAAMkB,YAAcV,EAAOU,kBAEDD,IAA1BT,EAAOW,iBACPnB,EAAMmB,eAAiBX,EAAOW,gBAElCnB,EAAMgB,IAAMR,EAAOQ,OCJxB,SAASI,GAAgB1E,GAC5B,OAAOA,aAAiB2E,aAAe3E,aAAiB4E,qBCD5CC,GAAgBC,EAAsBC,EAAsBC,GACvEF,aAAqBG,SACxBH,EAAUC,EAAQC,GAGlBF,EAAUI,KAAKH,EAAQC,GAmBzB,MAAMG,GAULtJ,YAAYiJ,GATZ7I,WAAgB,EAChBA,aAAkB,EAClBA,cAAmB,EAGXA,cAAmB,EACnBA,cAAmB,EACnBA,uBAA4B,EAGnCA,KAAK6I,UAAYA,EAGlBjJ,KAAKkJ,EAAsBC,GAC1B,GAAI/I,KAAKmJ,iBAGR,OAFAP,GAAgB5I,KAAK6I,UAAWC,EAAQ,QACxC9I,KAAKoJ,SAIN,IAAIC,EACArJ,KAAKsJ,QACRD,EAAQN,EAAO/I,KAAKuJ,UAEpBF,EAAQ,EACRrJ,KAAKsJ,SAAU,GAEhBtJ,KAAKuJ,SAAWR,EACX/I,KAAKwJ,SACTxJ,KAAKyJ,UAAYJ,EAAQrJ,KAAK0J,OAE/Bd,GAAgB5I,KAAK6I,UAAWC,EAAQ9I,KAAKyJ,UAG9C7J,QACCI,KAAKyJ,SAAW,EAGjB7J,UAIAA,iBACCI,KAAKmJ,kBAAmB,SAIbQ,GAAb/J,cAEUI,aAA6C,IAAI4J,IAE1DhK,IAAIiJ,GACH,MAAMgB,EAAS,IAAIX,GAAiBL,GAKpC,OAJAgB,EAAOT,OAAS,KACfpJ,KAAK8J,QAAQC,OAAOF,IAErB7J,KAAK8J,QAAQ1I,IAAIyI,GACVA,EAGRjK,KAAKkJ,EAAsBC,GAC1B/I,KAAK8J,QAAQ9F,QAAQ6F,GAAUA,EAAOZ,KAAKH,EAAQC,WAIxCiB,WAAsBL,GAAnC/J,kCACCI,WAAgB,EAChBA,cAAmB,EACFA,WAAe,IAAIiK,IAAM,GAE1CpB,gBACC,OAAO7I,KAGRwJ,aACC,OAAQxJ,KAAKkK,MAAMC,QAGpBX,WAAWzF,GACNA,EACH/D,KAAKkK,MAAME,OAEXpK,KAAKkK,MAAMG,QAIbzK,iBAAiBkJ,GACU,IAAtB9I,KAAK8J,QAAQQ,OAGjBtK,KAAKyJ,UAAYzJ,KAAKkK,MAAMK,WAAavK,KAAK0J,MAC9C1J,KAAKiJ,KAAKH,EAAQ9I,KAAKyJ,WAGxB7J,QACCI,KAAKyJ,SAAW,GChHlB,SAASe,GAAcC,GACtB,OAAIA,IAAmC,IAAxBA,EAAQC,YAMxB,MAAMC,GAgBL/K,YAAYgL,EAAkBH,EAA6B,IAVlDzK,gBAA4B,IAAIgK,GAOjChK,gBAAqB,EACrBA,oBAAyB,EAGhCA,KAAK4K,WAAaA,EAGlB5K,KAAK6K,WAAa/C,SAASC,cAAc,UACzC/H,KAAK6E,YAAc,IAAI1I,EAAQ6D,KAAK6K,YACpC7K,KAAK6E,YAAYiG,eACjB9K,KAAK6E,YAAYkG,eAEjB/K,KAAKgL,WAAalD,SAASC,cAAc,UACzC/H,KAAK8E,YAAc,IAAI3I,EAAQ6D,KAAKgL,YACpChL,KAAK8E,YAAYgG,eACjB9K,KAAK8E,YAAYiG,eAEjB/K,KAAKiL,MAAQ,IAAI1O,EAGjByD,KAAKkL,OAAS,IAAIzN,GAAkB,IACpCuC,KAAKkL,OAAOtJ,SAASC,GAAK,GAC1B7B,KAAKkL,OAAOtJ,SAASS,EAAI,GAEzBrC,KAAKmL,SAAW,IAAIC,GAAc,CAAEC,OAAO,IAC3CrL,KAAK4K,WAAWU,YAAYtL,KAAKmL,SAASP,YAE1C5K,KAAKuL,aAAe,IAAI3G,GAAa5E,KAAK6E,YAAa7E,KAAK8E,aAC5D9E,KAAKuL,aAAatL,KAAO,SACzBD,KAAKuL,aAAaxG,KAAKR,SAAU,EACjCvE,KAAKuL,aAAa5G,KAAKJ,SAAU,EACjCvE,KAAKiL,MAAM7J,IAAIpB,KAAKuL,cAEpBC,OAAOC,sBAAsB,IAAMzL,KAAK0L,aAEnBpD,IAAjBmC,EAAQ1F,MACX/E,KAAK2L,SAASlB,EAAQ1F,WAEFuD,IAAjBmC,EAAQ9F,MACX3E,KAAK4L,SAASnB,EAAQ9F,WAED2D,IAAlBmC,EAAQ7E,QACX5F,KAAK4F,MAAQ6E,EAAQ7E,YAEC0C,IAAnBmC,EAAQnD,SACXtH,KAAKsH,OAASmD,EAAQnD,QAId1H,WAAWiM,EAAkBpB,GACtCzK,KAAK6E,YAAYiH,aAAc,EAC/B9L,KAAKuL,aAAaxG,KAAKjB,UAAY+H,EAC/BrB,GAAcC,KACjBzK,KAAKuL,aAAaxG,KAAKR,SAAU,GAIzB3E,WAAW6K,GACpBzK,KAAK8E,YAAYgH,aAAc,EAC3BtB,GAAcC,KACjBzK,KAAKuL,aAAa5G,KAAKJ,SAAU,GAIzB3E,YACTI,KAAKuL,aAAaxG,KAAKR,SAAU,EAGxB3E,YACTI,KAAKuL,aAAa5G,KAAKJ,SAAU,EAG1B3E,OACHI,KAAK+L,UAAY/L,KAAKgM,gBAG1BhM,KAAKiM,WAAWC,iBAAiBlM,KAAKuL,cACtCvL,KAAKmM,WACLX,OAAOC,sBAAsB,IAAMzL,KAAK0L,SAG/B9L,WACTI,KAAKmL,SAASiB,OAAOpM,KAAKiL,MAAOjL,KAAKkL,QAGvCtL,QAAQgG,EAAe0B,GACtBtH,KAAKkL,OAAOmB,OAASzG,EAAQ0B,EAC7BtH,KAAKkL,OAAOoB,yBACZtM,KAAKmL,SAASoB,QAAQ3G,EAAO0B,GAG9B1H,UACCI,KAAKwM,WAAY,EACjBxM,KAAK4K,WAAW6B,YAAYzM,KAAKmL,SAASP,YAC1C5K,KAAKmL,SAASuB,UACd1M,KAAK6E,YAAY6H,UACjB1M,KAAK8E,YAAY4H,UAGlBX,eACC,OAAO/L,KAAKwM,UAGbG,mBACC,OAAO3M,KAAKgM,cAGbW,iBAAiB5I,GAChB,MAAM6I,GAAY5M,KAAK+L,WAAahI,GAAS/D,KAAKgM,cAClDhM,KAAKgM,cAAgBjI,EACjB6I,GACHpB,OAAOC,sBAAsB,IAAMzL,KAAK0L,QAI1C9F,YACC,OAAO5F,KAAKmL,SAAS0B,QAAQ,IAAIhO,GAAW+G,MAG7CA,UAAUkH,GACT9M,KAAKuM,QAAQO,EAAU9M,KAAKsH,QAG7BA,aACC,OAAOtH,KAAKmL,SAAS0B,QAAQ,IAAIhO,GAAWyI,OAG7CA,WAAWyF,GACV/M,KAAKuM,QAAQvM,KAAK4F,MAAOmH,IFnKpB,IAAqBC,GAAAA,GEuKhBrC,GAAY,CF7JjB,MACH/K,SAASiI,EAAQgE,EAAQ,cAAepB,GACpC,GAAe,OAAX5C,EACA7H,KAAKiN,gBAEJ,CAAA,IAAIxE,GAAgBZ,GAMrB,OAAOD,GAAUC,GAAQqF,KAAK7F,GAASrH,KAAK2L,SAAStE,EAAOwE,EAAOpB,IANrC,EFuDnC,SAA0BrD,EAAQC,GACrC,IAAI8F,GAAc,EAClB,GAAI9F,EAAMzB,QAAUyB,EAAMC,OAAQ,CAC9B,GAAID,EAAMzB,QAAU,EAAIyB,EAAMC,OAI1B,MAAM,IAAIC,MAAM,kBAAkBF,EAAMzB,SAASyB,EAAMC,UAHvD6F,GAAc,EAMtB,MAAM/H,EAAUgC,EAAOK,WAAW,MAClC,GAAI0F,EAAa,CACb,MAAMC,EAAa/F,EAAMzB,MACzBwB,EAAOxB,MAAQwH,EACfhG,EAAOE,OAAS8F,EAChBhI,EAAQ6B,UAAU,EAAG,EAAGmG,EAAYA,GACpChI,EAAQsC,UAAUL,EAAO,EAAG,EAAG+F,EAAYA,EAAa,GACxDvH,GAAiBT,EAASgI,QAG1BhG,EAAOxB,MAAQyB,EAAMzB,MACrBwB,EAAOE,OAASD,EAAMC,OACtBlC,EAAQ6B,UAAU,EAAG,EAAGI,EAAMzB,MAAOyB,EAAMC,QAC3ClC,EAAQsC,UAAUL,EAAO,EAAG,EAAGD,EAAOxB,MAAOwB,EAAOE,QE7EhD+F,CAAiBrN,KAAK6K,WAAYhD,GAClC,MAAMyF,EAAwB,gBAAVzB,EFwGzB,SAAwBzE,GAuC3B,MAAMlF,EAAQyD,GAAiByB,EAAOxB,OAChCR,EAAUgC,EAAOK,WAAW,MAC5B8F,EAAY,CAACpL,EAAGN,EAAGlD,EAAGC,IAAMuG,GAAgBC,EAASjD,EAAID,EAAOL,EAAIK,EAAOvD,EAAIuD,EAAOtD,EAAIsD,GAKhG,OAJeqL,EAAU,GAAI,GAAI,EAAG,IAChCA,EAAU,GAAI,GAAI,EAAG,KACrBA,EAAU,GAAI,GAAI,EAAG,IACrBA,EAAU,GAAI,GAAI,EAAG,IACT,OAAS,UEtJ6BC,CAAexN,KAAK6K,YAAcgB,EAChF7L,KAAKyN,WAAWH,EAAa7C,OAOlC,MACH7K,SAASiI,EAAQ4C,GACb,GAAe,OAAX5C,EACA7H,KAAK0N,gBAEJ,CAAA,IAAIjF,GAAgBZ,GAKrB,OAAOD,GAAUC,GAAQqF,KAAK7F,GAASrH,KAAK4L,SAASvE,EAAOoD,IAJ5DtD,GAAiBnH,KAAKgL,WAAYnD,GAClC7H,KAAK2N,WAAWlD,OA/BdzG,QAAQ4J,IACd1R,OAAO2R,oBAAoBD,EAASE,WAAW9J,QAAQ/D,IACnD/D,OAAO6R,eAAef,GAAYc,UAAW7N,EAAM/D,OAAO8R,yBAAyBJ,EAASE,UAAW7N,QGmBnH,qxTAolCAgO,wDAYA,kIAYAC,uKFp8B4C,CAACpF,EAAQC,KACpDD,EAAO9D,SAASnD,EAAIkH,sBAlCsB,CAACD,EAAQC,KACnD,MAAMhE,EAAO+D,EAAO/D,KAEpBgE,GAAQ,GAGRhE,EAAKlB,QAAQmB,SAAS7C,EAA+B,IAA3B8C,KAAKkJ,IAAIpF,EAAO9D,KAAKC,IAC/CH,EAAKxB,SAASyB,SAAS7C,EAAqB,IAAjB8C,KAAKkJ,IAAIpF,GAGpChE,EAAK9B,QAAQ+B,SAAS7C,EAAqB,IAAjB8C,KAAKkJ,IAAIpF,GACnChE,EAAKpC,SAASqC,SAAS7C,EAA+B,IAA3B8C,KAAKkJ,IAAIpF,EAAO9D,KAAKC,IAChD,MAAMkJ,EAA8B,GAAVnJ,KAAKC,GAC/BH,EAAK9B,QAAQ+B,SAAS3C,EAAqB,GAAjB4C,KAAKkJ,IAAIpF,GAAcqF,EACjDrJ,EAAKpC,SAASqC,SAAS3C,EAA+B,GAA3B4C,KAAKkJ,IAAIpF,EAAO9D,KAAKC,IAAYkJ,EAG5DtF,EAAOlH,SAASC,EAAIoD,KAAKkJ,IAAW,EAAPpF,GAE7BD,EAAOlH,SAASO,EAAqB,IAAjB8C,KAAKkJ,IAAIpF,GAE7BD,EAAO9D,SAAS3C,EAA+B,IAA3B4C,KAAKkJ,IAAIpF,EAAO9D,KAAKC,IAKzC,MAAMmJ,EAA+B,GAAVpJ,KAAKC,GAChC4D,EAAOnE,KAAKK,SAAS7C,EAAyB,GAArB8C,KAAKqJ,IAAW,EAAPvF,GAAkBsF,sDArDV,CAACvF,EAAQC,KACnD,MAAMhE,EAAO+D,EAAO/D,KAGpBgE,GAAQ,EAGRhE,EAAKlB,QAAQmB,SAAS7C,EAAqB,GAAjB8C,KAAKqJ,IAAIvF,GACnChE,EAAKxB,SAASyB,SAAS7C,EAA+B,GAA3B8C,KAAKqJ,IAAIvF,EAAO9D,KAAKC,IAGhDH,EAAK9B,QAAQ+B,SAAS7C,EAA+B,GAA3B8C,KAAKqJ,IAAIvF,EAAO9D,KAAKC,IAC/CH,EAAKpC,SAASqC,SAAS7C,EAAqB,GAAjB8C,KAAKqJ,IAAIvF,GACpC,MAAMqF,EAA8B,IAAVnJ,KAAKC,GAC/BH,EAAK9B,QAAQ+B,SAAS3C,EAAqB,IAAjB4C,KAAKkJ,IAAIpF,GAAeqF,EAClDrJ,EAAKpC,SAASqC,SAAS3C,EAA+B,IAA3B4C,KAAKkJ,IAAIpF,EAAO9D,KAAKC,IAAakJ,EAG7DrJ,EAAK5D,KAAK6D,SAASnD,EAAyB,GAArBoD,KAAKqJ,IAAIvF,EAAO,GACvChE,EAAK5D,KAAK6D,SAAS7C,EAAyB,GAArB8C,KAAKqJ,IAAIvF,EAAO,GAGvC,MAAMsF,EAA+B,IAAVpJ,KAAKC,GAChC4D,EAAOnE,KAAKK,SAAS7C,EAA2B,IAAvB8C,KAAKqJ,IAAIvF,EAAO,KAAcsF,kCG1JpBE,GACnC,MAAMC,EAAU,IAAIP,GAAcM,EAAWrD,OAAQqD,EAAWpD,SAASP,YASzE,OANA4D,EAAQC,WAAY,EACpBD,EAAQE,OAAS,IAAIC,EAAQ,GAAI,GAAI,GACrCH,EAAQI,YAAc,GACtBJ,EAAQK,YAAc,IACtBL,EAAQM,SAEDN"} \ No newline at end of file diff --git a/js/example.js b/js/example.js index b7eb9da..5446d26 100644 --- a/js/example.js +++ b/js/example.js @@ -18,13 +18,11 @@ function initSkinViewer() { // Reset animation speed el('speed').value = globalAnimationSpeed = 1; - skinViewer = new skinview3d.SkinViewer({ - domElement: el("skin_container"), + skinViewer = new skinview3d.SkinViewer(el("skin_container"), { width: el('width').value, - height: el('height').value, - skinUrl: el('skin_url').value, - capeUrl: el('cape_url').value || null + height: el('height').value }); + reloadTextures(); skinViewer.camera.position.z = 70; @@ -50,20 +48,11 @@ function initSkinViewer() { } -function hotReloadTextures() { - var capeObject = skinViewer.playerObject.cape; - var capeUrl = el('cape_url').value; +function reloadTextures() { var skinUrl = el('skin_url').value; - - // I've noted there is not a good way to set the cape to null - // so we hide it as work around but need to raise an issue - if (capeUrl === "") { - capeObject.visible = false; - } else { - skinViewer.capeUrl = capeUrl; - } - - skinViewer.skinUrl = skinUrl; + var capeUrl = el('cape_url').value; + skinViewer.loadSkin(skinUrl === "" ? null : skinUrl); + skinViewer.loadCape(capeUrl === "" ? null : capeUrl); } function resizeSkinViewer() {