From 967e9f2f604be52bf398d89a2f822b60727fedd4 Mon Sep 17 00:00:00 2001 From: atobaruela-ibrobotics Date: Mon, 26 Jun 2023 13:55:12 +0200 Subject: [PATCH 1/5] =?UTF-8?q?Cambios=20que=20hacen=20funcionar=20la=20vi?= =?UTF-8?q?sualizaci=C3=B3n=20en=20ROS2=20Galactic.=20Los=20cambios=20est?= =?UTF-8?q?=C3=A1n=20en=20el=20archivo=20build,=20hay=20que=20realizar=20l?= =?UTF-8?q?os=20cambios=20en=20los=20archivos=20de=20src=20para=20afianzar?= =?UTF-8?q?=20la=20funcionalidad?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/ros3d.cjs.js | 2 +- build/ros3d.esm.js | 2 +- build/ros3d.js | 16 ++-- build/ros3d.min.js | 4 +- examples/mappa.py | 33 ++++++++ examples/markers.html | 2 +- examples/nubepun.py | 156 ++++++++++++++++++++++++++++++++++++ examples/pointcloud2.html | 7 +- examples/pyesfera.py | 45 +++++++++++ package-lock.json | 16 ++-- package.json | 2 +- src/markers/MarkerClient.js | 3 +- 12 files changed, 264 insertions(+), 24 deletions(-) create mode 100644 examples/mappa.py create mode 100644 examples/nubepun.py create mode 100644 examples/pyesfera.py diff --git a/build/ros3d.cjs.js b/build/ros3d.cjs.js index 7070a937..927c6084 100644 --- a/build/ros3d.cjs.js +++ b/build/ros3d.cjs.js @@ -53363,7 +53363,7 @@ eventemitter2.exports; var obj = {}; var key; var len = keys.length; - var valuesCount = values ? value.length : 0; + var valuesCount = values ? values.length : 0; for (var i = 0; i < len; i++) { key = keys[i]; obj[key] = i < valuesCount ? values[i] : undefined$1; diff --git a/build/ros3d.esm.js b/build/ros3d.esm.js index ebe7b039..83a73a22 100644 --- a/build/ros3d.esm.js +++ b/build/ros3d.esm.js @@ -53339,7 +53339,7 @@ eventemitter2.exports; var obj = {}; var key; var len = keys.length; - var valuesCount = values ? value.length : 0; + var valuesCount = values ? values.length : 0; for (var i = 0; i < len; i++) { key = keys[i]; obj[key] = i < valuesCount ? values[i] : undefined$1; diff --git a/build/ros3d.js b/build/ros3d.js index cf204ed1..ad2cfdd0 100644 --- a/build/ros3d.js +++ b/build/ros3d.js @@ -53429,7 +53429,7 @@ var ROS3D = (function (exports, ROSLIB) { var obj = {}; var key; var len = keys.length; - var valuesCount = values ? value.length : 0; + var valuesCount = values ? values.length : 0; for (var i = 0; i < len; i++) { key = keys[i]; obj[key] = i < valuesCount ? values[i] : undefined$1; @@ -55209,7 +55209,8 @@ var ROS3D = (function (exports, ROSLIB) { ros : this.ros, name : topic + '/tunneled/update', messageType : 'visualization_msgs/InteractiveMarkerUpdate', - compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.updateTopic.subscribe(this.processUpdate.bind(this)); @@ -55217,7 +55218,8 @@ var ROS3D = (function (exports, ROSLIB) { ros : this.ros, name : topic + '/feedback', messageType : 'visualization_msgs/InteractiveMarkerFeedback', - compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.feedbackTopic.advertise(); @@ -55392,7 +55394,7 @@ var ROS3D = (function (exports, ROSLIB) { this.pose = options.pose || new ROSLIB__namespace.Pose(); // Do not render this object until we receive a TF update - this.visible = false; + this.visible = true; // add the model this.add(object); @@ -55482,7 +55484,8 @@ var ROS3D = (function (exports, ROSLIB) { ros : this.ros, name : this.topicName, messageType : 'visualization_msgs/MarkerArray', - compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.rosTopic.subscribe(this.processMessage.bind(this)); }; @@ -55619,7 +55622,8 @@ var ROS3D = (function (exports, ROSLIB) { ros : this.ros, name : this.topicName, messageType : 'visualization_msgs/Marker', - compression : 'png' + compression : 'cbor' + // compression : 'png' }); this.rosTopic.subscribe(this.processMessage.bind(this)); }; diff --git a/build/ros3d.min.js b/build/ros3d.min.js index 2edfce24..893f17f9 100644 --- a/build/ros3d.min.js +++ b/build/ros3d.min.js @@ -1,4 +1,4 @@ -var ROS3D=function(e,t){"use strict";function i(e){if(e&&e.__esModule)return e;var t=Object.create(null);return e&&Object.keys(e).forEach((function(i){if("default"!==i){var r=Object.getOwnPropertyDescriptor(e,i);Object.defineProperty(t,i,r.get?r:{enumerable:!0,get:function(){return e[i]}})}})),t.default=e,Object.freeze(t)}var r=i(t);function n(){}void 0===Number.EPSILON&&(Number.EPSILON=Math.pow(2,-52)),void 0===Number.isInteger&&(Number.isInteger=function(e){return"number"==typeof e&&isFinite(e)&&Math.floor(e)===e}),void 0===Math.sign&&(Math.sign=function(e){return e<0?-1:e>0?1:+e}),"name"in Function.prototype==!1&&Object.defineProperty(Function.prototype,"name",{get:function(){return this.toString().match(/^\s*function\s*([^\(\s]*)/)[1]}}),void 0===Object.assign&&(Object.assign=function(e){if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),i=1;i>8&255]+e[t>>16&255]+e[t>>24&255]+"-"+e[255&i]+e[i>>8&255]+"-"+e[i>>16&15|64]+e[i>>24&255]+"-"+e[63&r|128]+e[r>>8&255]+"-"+e[r>>16&255]+e[r>>24&255]+e[255&n]+e[n>>8&255]+e[n>>16&255]+e[n>>24&255]}}(),clamp:function(e,t,i){return Math.max(t,Math.min(i,e))},euclideanModulo:function(e,t){return(e%t+t)%t},mapLinear:function(e,t,i,r,n){return r+(e-t)*(n-r)/(i-t)},lerp:function(e,t,i){return(1-i)*e+i*t},smoothstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-t))*e*(3-2*e)},smootherstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-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*te.DEG2RAD},radToDeg:function(e){return e*te.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))}};function ie(e,t){this.x=e||0,this.y=t||0}function re(){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.")}function ne(e,t,i,r){this._x=e||0,this._y=t||0,this._z=i||0,this._w=void 0!==r?r:1}function oe(e,t,i){this.x=e||0,this.y=t||0,this.z=i||0}function ae(){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(ie.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(ie.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,i=this.y,r=e.elements;return this.x=r[0]*t+r[3]*i+r[6],this.y=r[1]*t+r[4]*i+r[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:(o=new ie,a=new ie,function(e,t){return o.set(e,e),a.set(t,t),this.clamp(o,a)}),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},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},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(){var e=Math.atan2(this.y,this.x);return e<0&&(e+=2*Math.PI),e},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y;return t*t+i*i},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,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},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,i){return void 0!==i&&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 i=Math.cos(t),r=Math.sin(t),n=this.x-e.x,o=this.y-e.y;return this.x=n*i-o*r+e.x,this.y=n*r+o*i+e.y,this}}),Object.assign(re.prototype,{isMatrix4:!0,set:function(e,t,i,r,n,o,a,s,c,h,l,u,p,d,f,m){var v=this.elements;return v[0]=e,v[4]=t,v[8]=i,v[12]=r,v[1]=n,v[5]=o,v[9]=a,v[13]=s,v[2]=c,v[6]=h,v[10]=l,v[14]=u,v[3]=p,v[7]=d,v[11]=f,v[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 re).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],t[9]=i[9],t[10]=i[10],t[11]=i[11],t[12]=i[12],t[13]=i[13],t[14]=i[14],t[15]=i[15],this},copyPosition:function(e){var t=this.elements,i=e.elements;return t[12]=i[12],t[13]=i[13],t[14]=i[14],this},extractBasis:function(e,t,i){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this},makeBasis:function(e,t,i){return this.set(e.x,t.x,i.x,0,e.y,t.y,i.y,0,e.z,t.z,i.z,0,0,0,0,1),this},extractRotation:(p=new oe,function(e){var t=this.elements,i=e.elements,r=1/p.setFromMatrixColumn(e,0).length(),n=1/p.setFromMatrixColumn(e,1).length(),o=1/p.setFromMatrixColumn(e,2).length();return t[0]=i[0]*r,t[1]=i[1]*r,t[2]=i[2]*r,t[4]=i[4]*n,t[5]=i[5]*n,t[6]=i[6]*n,t[8]=i[8]*o,t[9]=i[9]*o,t[10]=i[10]*o,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,i=e.x,r=e.y,n=e.z,o=Math.cos(i),a=Math.sin(i),s=Math.cos(r),c=Math.sin(r),h=Math.cos(n),l=Math.sin(n);if("XYZ"===e.order){var u=o*h,p=o*l,d=a*h,f=a*l;t[0]=s*h,t[4]=-s*l,t[8]=c,t[1]=p+d*c,t[5]=u-f*c,t[9]=-a*s,t[2]=f-u*c,t[6]=d+p*c,t[10]=o*s}else if("YXZ"===e.order){var m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m+y*a,t[4]=g*a-v,t[8]=o*c,t[1]=o*l,t[5]=o*h,t[9]=-a,t[2]=v*a-g,t[6]=y+m*a,t[10]=o*s}else if("ZXY"===e.order){m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m-y*a,t[4]=-o*l,t[8]=g+v*a,t[1]=v+g*a,t[5]=o*h,t[9]=y-m*a,t[2]=-o*c,t[6]=a,t[10]=o*s}else if("ZYX"===e.order){u=o*h,p=o*l,d=a*h,f=a*l;t[0]=s*h,t[4]=d*c-p,t[8]=u*c+f,t[1]=s*l,t[5]=f*c+u,t[9]=p*c-d,t[2]=-c,t[6]=a*s,t[10]=o*s}else if("YZX"===e.order){var x=o*s,b=o*c,w=a*s,_=a*c;t[0]=s*h,t[4]=_-x*l,t[8]=w*l+b,t[1]=l,t[5]=o*h,t[9]=-a*h,t[2]=-c*h,t[6]=b*l+w,t[10]=x-_*l}else if("XZY"===e.order){x=o*s,b=o*c,w=a*s,_=a*c;t[0]=s*h,t[4]=-l,t[8]=c*h,t[1]=x*l+_,t[5]=o*h,t[9]=b*l-w,t[2]=w*l-b,t[6]=a*h,t[10]=_*l+x}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){var t=this.elements,i=e._x,r=e._y,n=e._z,o=e._w,a=i+i,s=r+r,c=n+n,h=i*a,l=i*s,u=i*c,p=r*s,d=r*c,f=n*c,m=o*a,v=o*s,g=o*c;return t[0]=1-(p+f),t[4]=l-g,t[8]=u+v,t[1]=l+g,t[5]=1-(h+f),t[9]=d-m,t[2]=u-v,t[6]=d+m,t[10]=1-(h+p),t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},lookAt:(h=new oe,l=new oe,u=new oe,function(e,t,i){var r=this.elements;return u.subVectors(e,t),0===u.lengthSq()&&(u.z=1),u.normalize(),h.crossVectors(i,u),0===h.lengthSq()&&(1===Math.abs(i.z)?u.x+=1e-4:u.z+=1e-4,u.normalize(),h.crossVectors(i,u)),h.normalize(),l.crossVectors(u,h),r[0]=h.x,r[4]=l.x,r[8]=u.x,r[1]=h.y,r[5]=l.y,r[9]=u.y,r[2]=h.z,r[6]=l.z,r[10]=u.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 i=e.elements,r=t.elements,n=this.elements,o=i[0],a=i[4],s=i[8],c=i[12],h=i[1],l=i[5],u=i[9],p=i[13],d=i[2],f=i[6],m=i[10],v=i[14],g=i[3],y=i[7],x=i[11],b=i[15],w=r[0],_=r[4],M=r[8],E=r[12],T=r[1],S=r[5],A=r[9],L=r[13],R=r[2],C=r[6],P=r[10],N=r[14],O=r[3],I=r[7],D=r[11],U=r[15];return n[0]=o*w+a*T+s*R+c*O,n[4]=o*_+a*S+s*C+c*I,n[8]=o*M+a*A+s*P+c*D,n[12]=o*E+a*L+s*N+c*U,n[1]=h*w+l*T+u*R+p*O,n[5]=h*_+l*S+u*C+p*I,n[9]=h*M+l*A+u*P+p*D,n[13]=h*E+l*L+u*N+p*U,n[2]=d*w+f*T+m*R+v*O,n[6]=d*_+f*S+m*C+v*I,n[10]=d*M+f*A+m*P+v*D,n[14]=d*E+f*L+m*N+v*U,n[3]=g*w+y*T+x*R+b*O,n[7]=g*_+y*S+x*C+b*I,n[11]=g*M+y*A+x*P+b*D,n[15]=g*E+y*L+x*N+b*U,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},applyToBufferAttribute:function(){var e=new oe;return function(t){for(var i=0,r=t.count;i=0?1:-1,y=1-v*v;if(y>Number.EPSILON){var x=Math.sqrt(y),b=Math.atan2(x,v*g);m=Math.sin(m*b)/x,a=Math.sin(a*b)/x}var w=a*g;if(s=s*m+u*w,c=c*m+p*w,h=h*m+d*w,l=l*m+f*w,m===1-a){var _=1/Math.sqrt(s*s+c*c+h*h+l*l);s*=_,c*=_,h*=_,l*=_}}e[t]=s,e[t+1]=c,e[t+2]=h,e[t+3]=l}}),Object.defineProperties(ne.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(ne.prototype,{set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._w=r,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 i=e._x,r=e._y,n=e._z,o=e.order,a=Math.cos,s=Math.sin,c=a(i/2),h=a(r/2),l=a(n/2),u=s(i/2),p=s(r/2),d=s(n/2);return"XYZ"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"YXZ"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"ZXY"===o?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"ZYX"===o?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"YZX"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l-u*p*d):"XZY"===o&&(this._x=u*h*l-c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l+u*p*d),!1!==t&&this.onChangeCallback(),this},setFromAxisAngle:function(e,t){var i=t/2,r=Math.sin(i);return this._x=e.x*r,this._y=e.y*r,this._z=e.z*r,this._w=Math.cos(i),this.onChangeCallback(),this},setFromRotationMatrix:function(e){var t,i=e.elements,r=i[0],n=i[4],o=i[8],a=i[1],s=i[5],c=i[9],h=i[2],l=i[6],u=i[10],p=r+s+u;return p>0?(t=.5/Math.sqrt(p+1),this._w=.25/t,this._x=(l-c)*t,this._y=(o-h)*t,this._z=(a-n)*t):r>s&&r>u?(t=2*Math.sqrt(1+r-s-u),this._w=(l-c)/t,this._x=.25*t,this._y=(n+a)/t,this._z=(o+h)/t):s>u?(t=2*Math.sqrt(1+s-r-u),this._w=(o-h)/t,this._x=(n+a)/t,this._y=.25*t,this._z=(c+l)/t):(t=2*Math.sqrt(1+u-r-s),this._w=(a-n)/t,this._x=(o+h)/t,this._y=(c+l)/t,this._z=.25*t),this.onChangeCallback(),this},setFromUnitVectors:function(){var e,t=new oe;return function(i,r){return void 0===t&&(t=new oe),(e=i.dot(r)+1)<1e-6?(e=0,Math.abs(i.x)>Math.abs(i.z)?t.set(-i.y,i.x,0):t.set(0,-i.z,i.y)):t.crossVectors(i,r),this._x=t.x,this._y=t.y,this._z=t.z,this._w=e,this.normalize()}}(),inverse:function(){return this.conjugate().normalize()},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 i=e._x,r=e._y,n=e._z,o=e._w,a=t._x,s=t._y,c=t._z,h=t._w;return this._x=i*h+o*a+r*c-n*s,this._y=r*h+o*s+n*a-i*c,this._z=n*h+o*c+i*s-r*a,this._w=o*h-i*a-r*s-n*c,this.onChangeCallback(),this},slerp:function(e,t){if(0===t)return this;if(1===t)return this.copy(e);var i=this._x,r=this._y,n=this._z,o=this._w,a=o*e._w+i*e._x+r*e._y+n*e._z;if(a<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,a=-a):this.copy(e),a>=1)return this._w=o,this._x=i,this._y=r,this._z=n,this;var s=Math.sqrt(1-a*a);if(Math.abs(s)<.001)return this._w=.5*(o+this._w),this._x=.5*(i+this._x),this._y=.5*(r+this._y),this._z=.5*(n+this._z),this;var c=Math.atan2(s,a),h=Math.sin((1-t)*c)/s,l=Math.sin(t*c)/s;return this._w=o*h+this._w*l,this._x=i*h+this._x*l,this._y=r*h+this._y*l,this._z=n*h+this._z*l,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},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(oe.prototype,{isVector3:!0,set:function(e,t,i){return this.x=e,this.y=t,this.z=i,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:(d=new ne,function(e){return e&&e.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(d.setFromEuler(e))}),applyAxisAngle:function(){var e=new ne;return function(t,i){return this.applyQuaternion(e.setFromAxisAngle(t,i))}}(),applyMatrix3:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[3]*i+n[6]*r,this.y=n[1]*t+n[4]*i+n[7]*r,this.z=n[2]*t+n[5]*i+n[8]*r,this},applyMatrix4:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements,o=1/(n[3]*t+n[7]*i+n[11]*r+n[15]);return this.x=(n[0]*t+n[4]*i+n[8]*r+n[12])*o,this.y=(n[1]*t+n[5]*i+n[9]*r+n[13])*o,this.z=(n[2]*t+n[6]*i+n[10]*r+n[14])*o,this},applyQuaternion:function(e){var t=this.x,i=this.y,r=this.z,n=e.x,o=e.y,a=e.z,s=e.w,c=s*t+o*r-a*i,h=s*i+a*t-n*r,l=s*r+n*i-o*t,u=-n*t-o*i-a*r;return this.x=c*s+u*-n+h*-a-l*-o,this.y=h*s+u*-o+l*-n-c*-a,this.z=l*s+u*-a+c*-o-h*-n,this},project:function(){var e=new re;return function(t){return e.multiplyMatrices(t.projectionMatrix,e.getInverse(t.matrixWorld)),this.applyMatrix4(e)}}(),unproject:function(){var e=new re;return function(t){return e.multiplyMatrices(t.matrixWorld,e.getInverse(t.projectionMatrix)),this.applyMatrix4(e)}}(),transformDirection:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[4]*i+n[8]*r,this.y=n[1]*t+n[5]*i+n[9]*r,this.z=n[2]*t+n[6]*i+n[10]*r,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(){var e=new oe,t=new oe;return function(i,r){return e.set(i,i,i),t.set(r,r,r),this.clamp(e,t)}}(),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},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,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},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 i=e.x,r=e.y,n=e.z,o=t.x,a=t.y,s=t.z;return this.x=r*s-n*a,this.y=n*o-i*s,this.z=i*a-r*o,this},projectOnVector:function(e){var t=e.dot(this)/e.lengthSq();return this.copy(e).multiplyScalar(t)},projectOnPlane:function(){var e=new oe;return function(t){return e.copy(this).projectOnVector(t),this.sub(e)}}(),reflect:function(){var e=new oe;return function(t){return this.sub(e.copy(t).multiplyScalar(2*this.dot(t)))}}(),angleTo:function(e){var t=this.dot(e)/Math.sqrt(this.lengthSq()*e.lengthSq());return Math.acos(te.clamp(t,-1,1))},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y,r=this.z-e.z;return t*t+i*i+r*r},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){var t=Math.sin(e.phi)*e.radius;return this.x=t*Math.sin(e.theta),this.y=Math.cos(e.phi)*e.radius,this.z=t*Math.cos(e.theta),this},setFromCylindrical:function(e){return this.x=e.radius*Math.sin(e.theta),this.y=e.y,this.z=e.radius*Math.cos(e.theta),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(),i=this.setFromMatrixColumn(e,1).length(),r=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=i,this.z=r,this},setFromMatrixColumn:function(e,t){return this.fromArray(e.elements,4*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,i){return void 0!==i&&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}}),Object.assign(ae.prototype,{isMatrix3:!0,set:function(e,t,i,r,n,o,a,s,c){var h=this.elements;return h[0]=e,h[1]=r,h[2]=a,h[3]=t,h[4]=n,h[5]=s,h[6]=i,h[7]=o,h[8]=c,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,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],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},applyToBufferAttribute:function(){var e=new oe;return function(t){for(var i=0,r=t.count;i2048||t.height>2048?t.toDataURL("image/jpeg",.6):t.toDataURL("image/png")}(r)}),i.image=r.uuid}return t||(e.textures[this.uuid]=i),i},dispose:function(){this.dispatchEvent({type:"dispose"})},transformUv:function(e){if(this.mapping===f){if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case b:e.x=e.x-Math.floor(e.x);break;case w:e.x=e.x<0?0:1;break;case _: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 b:e.y=e.y-Math.floor(e.y);break;case w:e.y=e.y<0?0:1;break;case _:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}this.flipY&&(e.y=1-e.y)}}}),Object.defineProperty(ce.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),Object.assign(he.prototype,{isVector4:!0,set:function(e,t,i,r){return this.x=e,this.y=t,this.z=i,this.w=r,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,i=this.y,r=this.z,n=this.w,o=e.elements;return this.x=o[0]*t+o[4]*i+o[8]*r+o[12]*n,this.y=o[1]*t+o[5]*i+o[9]*r+o[13]*n,this.z=o[2]*t+o[6]*i+o[10]*r+o[14]*n,this.w=o[3]*t+o[7]*i+o[11]*r+o[15]*n,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,i,r,n,o=.01,a=.1,s=e.elements,c=s[0],h=s[4],l=s[8],u=s[1],p=s[5],d=s[9],f=s[2],m=s[6],v=s[10];if(Math.abs(h-u)y&&g>x?gx?y0)return e;var n=t*i,o=ge[n];if(void 0===o&&(o=new Float32Array(n),ge[n]=o),0!==t){r.toArray(o,0);for(var a=1,s=0;a!==t;++a)s+=i,e[a].toArray(o,s)}return o}function _e(e,t){var i=ye[t];void 0===i&&(i=new Int32Array(t),ye[t]=i);for(var r=0;r!==t;++r)i[r]=e.allocTextureUnit();return i}function Me(e,t){e.uniform1f(this.addr,t)}function Ee(e,t){e.uniform1i(this.addr,t)}function Te(e,t){void 0===t.x?e.uniform2fv(this.addr,t):e.uniform2f(this.addr,t.x,t.y)}function Se(e,t){void 0!==t.x?e.uniform3f(this.addr,t.x,t.y,t.z):void 0!==t.r?e.uniform3f(this.addr,t.r,t.g,t.b):e.uniform3fv(this.addr,t)}function Ae(e,t){void 0===t.x?e.uniform4fv(this.addr,t):e.uniform4f(this.addr,t.x,t.y,t.z,t.w)}function Le(e,t){e.uniformMatrix2fv(this.addr,!1,t.elements||t)}function Re(e,t){void 0===t.elements?e.uniformMatrix3fv(this.addr,!1,t):(be.set(t.elements),e.uniformMatrix3fv(this.addr,!1,be))}function Ce(e,t){void 0===t.elements?e.uniformMatrix4fv(this.addr,!1,t):(xe.set(t.elements),e.uniformMatrix4fv(this.addr,!1,xe))}function Pe(e,t,i){var r=i.allocTextureUnit();e.uniform1i(this.addr,r),i.setTexture2D(t||fe,r)}function Ne(e,t,i){var r=i.allocTextureUnit();e.uniform1i(this.addr,r),i.setTextureCube(t||me,r)}function Oe(e,t){e.uniform2iv(this.addr,t)}function Ie(e,t){e.uniform3iv(this.addr,t)}function De(e,t){e.uniform4iv(this.addr,t)}function Ue(e,t){e.uniform1fv(this.addr,t)}function Fe(e,t){e.uniform1iv(this.addr,t)}function Be(e,t){e.uniform2fv(this.addr,we(t,this.size,2))}function ze(e,t){e.uniform3fv(this.addr,we(t,this.size,3))}function ke(e,t){e.uniform4fv(this.addr,we(t,this.size,4))}function Ge(e,t){e.uniformMatrix2fv(this.addr,!1,we(t,this.size,4))}function Ve(e,t){e.uniformMatrix3fv(this.addr,!1,we(t,this.size,9))}function je(e,t){e.uniformMatrix4fv(this.addr,!1,we(t,this.size,16))}function He(e,t,i){var r=t.length,n=_e(i,r);e.uniform1iv(this.addr,n);for(var o=0;o!==r;++o)i.setTexture2D(t[o]||fe,n[o])}function We(e,t,i){var r=t.length,n=_e(i,r);e.uniform1iv(this.addr,n);for(var o=0;o!==r;++o)i.setTextureCube(t[o]||me,n[o])}function Xe(e,t,i){this.id=e,this.addr=i,this.setValue=function(e){switch(e){case 5126:return Me;case 35664:return Te;case 35665:return Se;case 35666:return Ae;case 35674:return Le;case 35675:return Re;case 35676:return Ce;case 35678:case 36198:return Pe;case 35680:return Ne;case 5124:case 35670:return Ee;case 35667:case 35671:return Oe;case 35668:case 35672:return Ie;case 35669:case 35673:return De}}(t.type)}function qe(e,t,i){this.id=e,this.addr=i,this.size=t.size,this.setValue=function(e){switch(e){case 5126:return Ue;case 35664:return Be;case 35665:return ze;case 35666:return ke;case 35674:return Ge;case 35675:return Ve;case 35676:return je;case 35678:return He;case 35680:return We;case 5124:case 35670:return Fe;case 35667:case 35671:return Oe;case 35668:case 35672:return Ie;case 35669:case 35673:return De}}(t.type)}function Ye(e){this.id=e,ve.call(this)}Ye.prototype.setValue=function(e,t){for(var i=this.seq,r=0,n=i.length;r!==n;++r){var o=i[r];o.setValue(e,t[o.id])}};var Ze=/([\w\d_]+)(\])?(\[|\.)?/g;function Je(e,t){e.seq.push(t),e.map[t.id]=t}function Ke(e,t,i){var r=e.name,n=r.length;for(Ze.lastIndex=0;;){var o=Ze.exec(r),a=Ze.lastIndex,s=o[1],c="]"===o[2],h=o[3];if(c&&(s|=0),void 0===h||"["===h&&a+2===n){Je(i,void 0===h?new Xe(s,e,t):new qe(s,e,t));break}var l=i.map[s];void 0===l&&Je(i,l=new Ye(s)),i=l}}function Qe(e,t,i){ve.call(this),this.renderer=i;for(var r=e.getProgramParameter(t,e.ACTIVE_UNIFORMS),n=0;n>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,this},setRGB:function(e,t,i){return this.r=e,this.g=t,this.b=i,this},setHSL:function(){function e(e,t,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?e+6*(t-e)*i:i<.5?t:i<2/3?e+6*(t-e)*(2/3-i):e}return function(t,i,r){if(t=te.euclideanModulo(t,1),i=te.clamp(i,0,1),r=te.clamp(r,0,1),0===i)this.r=this.g=this.b=r;else{var n=r<=.5?r*(1+i):r+i-r*i,o=2*r-n;this.r=e(o,n,t+1/3),this.g=e(o,n,t),this.b=e(o,n,t-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 i;if(i=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(e)){var r,n=i[1],o=i[2];switch(n){case"rgb":case"rgba":if(r=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o))return this.r=Math.min(255,parseInt(r[1],10))/255,this.g=Math.min(255,parseInt(r[2],10))/255,this.b=Math.min(255,parseInt(r[3],10))/255,t(r[5]),this;if(r=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o))return this.r=Math.min(100,parseInt(r[1],10))/100,this.g=Math.min(100,parseInt(r[2],10))/100,this.b=Math.min(100,parseInt(r[3],10))/100,t(r[5]),this;break;case"hsl":case"hsla":if(r=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o)){var a=parseFloat(r[1])/360,s=parseInt(r[2],10)/100,c=parseInt(r[3],10)/100;return t(r[5]),this.setHSL(a,s,c)}}}else if(i=/^\#([A-Fa-f0-9]+)$/.exec(e)){var h,l=(h=i[1]).length;if(3===l)return this.r=parseInt(h.charAt(0)+h.charAt(0),16)/255,this.g=parseInt(h.charAt(1)+h.charAt(1),16)/255,this.b=parseInt(h.charAt(2)+h.charAt(2),16)/255,this;if(6===l)return this.r=parseInt(h.charAt(0)+h.charAt(1),16)/255,this.g=parseInt(h.charAt(2)+h.charAt(3),16)/255,this.b=parseInt(h.charAt(4)+h.charAt(5),16)/255,this}e&&e.length>0&&(void 0!==(h=$e[e])?this.setHex(h):console.warn("THREE.Color: Unknown color "+e));return 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 i=t>0?1/t:1;return this.r=Math.pow(e.r,i),this.g=Math.pow(e.g,i),this.b=Math.pow(e.b,i),this},convertGammaToLinear:function(){var e=this.r,t=this.g,i=this.b;return this.r=e*e,this.g=t*t,this.b=i*i,this},convertLinearToGamma:function(){return this.r=Math.sqrt(this.r),this.g=Math.sqrt(this.g),this.b=Math.sqrt(this.b),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){var t,i,r=e||{h:0,s:0,l:0},n=this.r,o=this.g,a=this.b,s=Math.max(n,o,a),c=Math.min(n,o,a),h=(c+s)/2;if(c===s)t=0,i=0;else{var l=s-c;switch(i=h<=.5?l/(s+c):l/(2-s-c),s){case n:t=(o-a)/l+(o 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\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}\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 GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, 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_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 theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\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.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - 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\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\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",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\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n",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#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(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}\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};\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}\n",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n",defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n",encodings_fragment:" gl_FragColor = linearToOutputTexel( gl_FragColor );\n",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.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\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.w );\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.w );\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.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, 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.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.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 = value.rgb * cLogLuvM;\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 = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n",envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, 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_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\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\tenvColor = envMapTexelToLinear( envColor );\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\n",envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\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\n",fog_vertex:"\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n varying float fogDepth;\n#endif\n",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\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\n",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\n",gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n",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 = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\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#endif\n#if NUM_SPOT_LIGHTS > 0\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#endif\n#if NUM_DIR_LIGHTS > 0\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#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n",lights_pars:"uniform vec3 ambientLightColor;\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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\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 ltcMat;\tuniform sampler2D ltcMag;\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\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\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\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 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 blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, 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\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\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\n",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n",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\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\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)\n",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#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\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), 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#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\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 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\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#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\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}\n",lights_template:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\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#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * 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 ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\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 += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n",normal_fragment:"#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#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\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\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n",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}\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}\n",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n",dithering_fragment:"#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n",dithering_pars_fragment:"#if defined( 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\n",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\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\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( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, 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( 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 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\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\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\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 )\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\n",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\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 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\n",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\n",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#endif\n",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 gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n",tonemapping_pars_fragment:"#ifndef saturate\n\t#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}\n",uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n",uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\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#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n",cube_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\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 \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\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n",depth_vert:"#include \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}\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}\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}\n",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n",equirect_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\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}\n",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\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 \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\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * 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}\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}\n",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \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\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\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}\n",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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}\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 \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\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}\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}\n",meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\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 \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\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}\n",meshphysical_vert:"#define PHYSICAL\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}\n",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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#endif\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( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \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\t#include \n}\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#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\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}\n",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"},nt={basic:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.fog]),vertexShader:rt.meshbasic_vert,fragmentShader:rt.meshbasic_frag},lambert:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.fog,tt.lights,{emissive:{value:new et(0)}}]),vertexShader:rt.meshlambert_vert,fragmentShader:rt.meshlambert_frag},phong:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.bumpmap,tt.normalmap,tt.displacementmap,tt.gradientmap,tt.fog,tt.lights,{emissive:{value:new et(0)},specular:{value:new et(1118481)},shininess:{value:30}}]),vertexShader:rt.meshphong_vert,fragmentShader:rt.meshphong_frag},standard:{uniforms:it.merge([tt.common,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.bumpmap,tt.normalmap,tt.displacementmap,tt.roughnessmap,tt.metalnessmap,tt.fog,tt.lights,{emissive:{value:new et(0)},roughness:{value:.5},metalness:{value:.5},envMapIntensity:{value:1}}]),vertexShader:rt.meshphysical_vert,fragmentShader:rt.meshphysical_frag},points:{uniforms:it.merge([tt.points,tt.fog]),vertexShader:rt.points_vert,fragmentShader:rt.points_frag},dashed:{uniforms:it.merge([tt.common,tt.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:rt.linedashed_vert,fragmentShader:rt.linedashed_frag},depth:{uniforms:it.merge([tt.common,tt.displacementmap]),vertexShader:rt.depth_vert,fragmentShader:rt.depth_frag},normal:{uniforms:it.merge([tt.common,tt.bumpmap,tt.normalmap,tt.displacementmap,{opacity:{value:1}}]),vertexShader:rt.normal_vert,fragmentShader:rt.normal_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:rt.cube_vert,fragmentShader:rt.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:rt.equirect_vert,fragmentShader:rt.equirect_frag},distanceRGBA:{uniforms:it.merge([tt.common,tt.displacementmap,{referencePosition:{value:new oe},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:rt.distanceRGBA_vert,fragmentShader:rt.distanceRGBA_frag},shadow:{uniforms:it.merge([tt.lights,tt.fog,{color:{value:new et(0)},opacity:{value:1}}]),vertexShader:rt.shadow_vert,fragmentShader:rt.shadow_frag}};function ot(e,t){this.min=void 0!==e?e:new ie(1/0,1/0),this.max=void 0!==t?t:new ie(-1/0,-1/0)}function at(e,t,i,r,n){var o,a,s,c,h,l,u,p;function d(){var e=new Float32Array([-1,-1,0,0,1,-1,1,0,1,1,1,1,-1,1,0,1]),r=new Uint16Array([0,1,2,0,2,3]);o=t.createBuffer(),a=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,o),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.bufferData(t.ELEMENT_ARRAY_BUFFER,r,t.STATIC_DRAW),u=t.createTexture(),p=t.createTexture(),i.bindTexture(t.TEXTURE_2D,u),t.texImage2D(t.TEXTURE_2D,0,t.RGB,16,16,0,t.RGB,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),i.bindTexture(t.TEXTURE_2D,p),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,16,16,0,t.RGBA,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),s={vertexShader:["uniform lowp int renderType;","uniform vec3 screenPosition;","uniform vec2 scale;","uniform float rotation;","uniform sampler2D occlusionMap;","attribute vec2 position;","attribute vec2 uv;","varying vec2 vUV;","varying float vVisibility;","void main() {","\tvUV = uv;","\tvec2 pos = position;","\tif ( renderType == 2 ) {","\t\tvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );","\t\tvVisibility = visibility.r / 9.0;","\t\tvVisibility *= 1.0 - visibility.g / 9.0;","\t\tvVisibility *= visibility.b / 9.0;","\t\tvVisibility *= 1.0 - visibility.a / 9.0;","\t\tpos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;","\t\tpos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;","\t}","\tgl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );","}"].join("\n"),fragmentShader:["uniform lowp int renderType;","uniform sampler2D map;","uniform float opacity;","uniform vec3 color;","varying vec2 vUV;","varying float vVisibility;","void main() {","\tif ( renderType == 0 ) {","\t\tgl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );","\t} else if ( renderType == 1 ) {","\t\tgl_FragColor = texture2D( map, vUV );","\t} else {","\t\tvec4 texture = texture2D( map, vUV );","\t\ttexture.a *= opacity * vVisibility;","\t\tgl_FragColor = texture;","\t\tgl_FragColor.rgb *= color;","\t}","}"].join("\n")},c=function(e){var i=t.createProgram(),r=t.createShader(t.FRAGMENT_SHADER),o=t.createShader(t.VERTEX_SHADER),a="precision "+n.precision+" float;\n";return t.shaderSource(r,a+e.fragmentShader),t.shaderSource(o,a+e.vertexShader),t.compileShader(r),t.compileShader(o),t.attachShader(i,r),t.attachShader(i,o),t.linkProgram(i),i}(s),h={vertex:t.getAttribLocation(c,"position"),uv:t.getAttribLocation(c,"uv")},l={renderType:t.getUniformLocation(c,"renderType"),map:t.getUniformLocation(c,"map"),occlusionMap:t.getUniformLocation(c,"occlusionMap"),opacity:t.getUniformLocation(c,"opacity"),color:t.getUniformLocation(c,"color"),scale:t.getUniformLocation(c,"scale"),rotation:t.getUniformLocation(c,"rotation"),screenPosition:t.getUniformLocation(c,"screenPosition")}}this.render=function(e,n,s,f){if(0!==e.length){var m=new oe,v=f.w/f.z,g=.5*f.z,y=.5*f.w,x=16/f.w,b=new ie(x*v,x),w=new oe(1,1,0),_=new ie(1,1),M=new ot;M.min.set(f.x,f.y),M.max.set(f.x+(f.z-16),f.y+(f.w-16)),void 0===c&&d(),i.useProgram(c),i.initAttributes(),i.enableAttribute(h.vertex),i.enableAttribute(h.uv),i.disableUnusedAttributes(),t.uniform1i(l.occlusionMap,0),t.uniform1i(l.map,1),t.bindBuffer(t.ARRAY_BUFFER,o),t.vertexAttribPointer(h.vertex,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(h.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),i.disable(t.CULL_FACE),i.buffers.depth.setMask(!1);for(var E=0,T=e.length;E.001&&R.scale>.001&&(w.x=R.x,w.y=R.y,w.z=R.z,x=R.size*R.scale/f.w,b.x=x*v,b.y=x,t.uniform3f(l.screenPosition,w.x,w.y,w.z),t.uniform2f(l.scale,b.x,b.y),t.uniform1f(l.rotation,R.rotation),t.uniform1f(l.opacity,R.opacity),t.uniform3f(l.color,R.color.r,R.color.g,R.color.b),i.setBlending(R.blending,R.blendEquation,R.blendSrc,R.blendDst),r.setTexture2D(R.texture,1),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0))}}}i.enable(t.CULL_FACE),i.enable(t.DEPTH_TEST),i.buffers.depth.setMask(!0),i.reset()}}}function st(e,t,i,r,n,o,a,s,c){ce.call(this,e,t,i,r,n,o,a,s,c),this.needsUpdate=!0}function ct(e,t,i,r,n){var o,a,s,c,h,l,u=new oe,p=new ne,d=new oe;function f(){var e=new Float32Array([-.5,-.5,0,0,.5,-.5,1,0,.5,.5,1,1,-.5,.5,0,1]),i=new Uint16Array([0,1,2,0,2,3]);o=t.createBuffer(),a=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,o),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.bufferData(t.ELEMENT_ARRAY_BUFFER,i,t.STATIC_DRAW),s=function(){var e=t.createProgram(),i=t.createShader(t.VERTEX_SHADER),r=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(i,["precision "+n.precision+" float;","#define SHADER_NAME SpriteMaterial","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform float rotation;","uniform vec2 scale;","uniform vec2 uvOffset;","uniform vec2 uvScale;","attribute vec2 position;","attribute vec2 uv;","varying vec2 vUV;","varying float fogDepth;","void main() {","\tvUV = uvOffset + uv * uvScale;","\tvec2 alignedPosition = position * scale;","\tvec2 rotatedPosition;","\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;","\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;","\tvec4 mvPosition;","\tmvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );","\tmvPosition.xy += rotatedPosition;","\tgl_Position = projectionMatrix * mvPosition;","\tfogDepth = - mvPosition.z;","}"].join("\n")),t.shaderSource(r,["precision "+n.precision+" float;","#define SHADER_NAME SpriteMaterial","uniform vec3 color;","uniform sampler2D map;","uniform float opacity;","uniform int fogType;","uniform vec3 fogColor;","uniform float fogDensity;","uniform float fogNear;","uniform float fogFar;","uniform float alphaTest;","varying vec2 vUV;","varying float fogDepth;","void main() {","\tvec4 texture = texture2D( map, vUV );","\tgl_FragColor = vec4( color * texture.xyz, texture.a * opacity );","\tif ( gl_FragColor.a < alphaTest ) discard;","\tif ( fogType > 0 ) {","\t\tfloat fogFactor = 0.0;","\t\tif ( fogType == 1 ) {","\t\t\tfogFactor = smoothstep( fogNear, fogFar, fogDepth );","\t\t} else {","\t\t\tconst float LOG2 = 1.442695;","\t\t\tfogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );","\t\t\tfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );","\t\t}","\t\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );","\t}","}"].join("\n")),t.compileShader(i),t.compileShader(r),t.attachShader(e,i),t.attachShader(e,r),t.linkProgram(e),e}(),c={position:t.getAttribLocation(s,"position"),uv:t.getAttribLocation(s,"uv")},h={uvOffset:t.getUniformLocation(s,"uvOffset"),uvScale:t.getUniformLocation(s,"uvScale"),rotation:t.getUniformLocation(s,"rotation"),scale:t.getUniformLocation(s,"scale"),color:t.getUniformLocation(s,"color"),map:t.getUniformLocation(s,"map"),opacity:t.getUniformLocation(s,"opacity"),modelViewMatrix:t.getUniformLocation(s,"modelViewMatrix"),projectionMatrix:t.getUniformLocation(s,"projectionMatrix"),fogType:t.getUniformLocation(s,"fogType"),fogDensity:t.getUniformLocation(s,"fogDensity"),fogNear:t.getUniformLocation(s,"fogNear"),fogFar:t.getUniformLocation(s,"fogFar"),fogColor:t.getUniformLocation(s,"fogColor"),fogDepth:t.getUniformLocation(s,"fogDepth"),alphaTest:t.getUniformLocation(s,"alphaTest")};var r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");r.width=8,r.height=8;var u=r.getContext("2d");u.fillStyle="white",u.fillRect(0,0,8,8),l=new st(r)}function m(e,t){return e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:t.id-e.id}this.render=function(n,v,g){if(0!==n.length){void 0===s&&f(),i.useProgram(s),i.initAttributes(),i.enableAttribute(c.position),i.enableAttribute(c.uv),i.disableUnusedAttributes(),i.disable(t.CULL_FACE),i.enable(t.BLEND),t.bindBuffer(t.ARRAY_BUFFER,o),t.vertexAttribPointer(c.position,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(c.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.uniformMatrix4fv(h.projectionMatrix,!1,g.projectionMatrix.elements),i.activeTexture(t.TEXTURE0),t.uniform1i(h.map,0);var y=0,x=0,b=v.fog;b?(t.uniform3f(h.fogColor,b.color.r,b.color.g,b.color.b),b.isFog?(t.uniform1f(h.fogNear,b.near),t.uniform1f(h.fogFar,b.far),t.uniform1i(h.fogType,1),y=1,x=1):b.isFogExp2&&(t.uniform1f(h.fogDensity,b.density),t.uniform1i(h.fogType,2),y=2,x=2)):(t.uniform1i(h.fogType,0),y=0,x=0);for(var w=0,_=n.length;w<_;w++){(E=n[w]).modelViewMatrix.multiplyMatrices(g.matrixWorldInverse,E.matrixWorld),E.z=-E.modelViewMatrix.elements[14]}n.sort(m);var M=[];for(w=0,_=n.length;w<_;w++){var E,T=(E=n[w]).material;if(!1!==T.visible){E.onBeforeRender(e,v,g,void 0,T,void 0),t.uniform1f(h.alphaTest,T.alphaTest),t.uniformMatrix4fv(h.modelViewMatrix,!1,E.modelViewMatrix.elements),E.matrixWorld.decompose(u,p,d),M[0]=d.x,M[1]=d.y;var S=0;v.fog&&T.fog&&(S=x),y!==S&&(t.uniform1i(h.fogType,S),y=S),null!==T.map?(t.uniform2f(h.uvOffset,T.map.offset.x,T.map.offset.y),t.uniform2f(h.uvScale,T.map.repeat.x,T.map.repeat.y)):(t.uniform2f(h.uvOffset,0,0),t.uniform2f(h.uvScale,1,1)),t.uniform1f(h.opacity,T.opacity),t.uniform3f(h.color,T.color.r,T.color.g,T.color.b),t.uniform1f(h.rotation,T.rotation),t.uniform2fv(h.scale,M),i.setBlending(T.blending,T.blendEquation,T.blendSrc,T.blendDst,T.blendEquationAlpha,T.blendSrcAlpha,T.blendDstAlpha,T.premultipliedAlpha),i.buffers.depth.setTest(T.depthTest),i.buffers.depth.setMask(T.depthWrite),i.buffers.color.setMask(T.colorWrite),r.setTexture2D(T.map||l,0),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0),E.onAfterRender(e,v,g,void 0,T,void 0)}}i.enable(t.CULL_FACE),i.reset()}}}nt.physical={uniforms:it.merge([nt.standard.uniforms,{clearCoat:{value:0},clearCoatRoughness:{value:0}}]),vertexShader:rt.meshphysical_vert,fragmentShader:rt.meshphysical_frag},Object.assign(ot.prototype,{set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=e.length;tthis.max.x||e.ythis.max.y)},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},getParameter:function(e,t){return(t||new ie).set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y)},clampPoint:function(e,t){return(t||new ie).copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new ie;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),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)}}),st.prototype=Object.create(ce.prototype),st.prototype.constructor=st;var ht,lt,ut,pt,dt,ft,mt,vt=0;function gt(){Object.defineProperty(this,"id",{value:vt++}),this.uuid=te.generateUUID(),this.name="",this.type="Material",this.fog=!0,this.lights=!0,this.blending=1,this.side=0,this.flatShading=!1,this.vertexColors=0,this.opacity=1,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=100,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaTest=0,this.premultipliedAlpha=!1,this.overdraw=0,this.visible=!0,this.userData={},this.needsUpdate=!0}function yt(e){gt.call(this),this.type="MeshDepthMaterial",this.depthPacking=3200,this.skinning=!1,this.morphTargets=!1,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.setValues(e)}function xt(e){gt.call(this),this.type="MeshDistanceMaterial",this.referencePosition=new oe,this.nearDistance=1,this.farDistance=1e3,this.skinning=!1,this.morphTargets=!1,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.fog=!1,this.lights=!1,this.setValues(e)}function bt(e,t){this.min=void 0!==e?e:new oe(1/0,1/0,1/0),this.max=void 0!==t?t:new oe(-1/0,-1/0,-1/0)}function wt(e,t){this.center=void 0!==e?e:new oe,this.radius=void 0!==t?t:0}function _t(e,t){this.normal=void 0!==e?e:new oe(1,0,0),this.constant=void 0!==t?t:0}function Mt(e,t,i,r,n,o){this.planes=[void 0!==e?e:new _t,void 0!==t?t:new _t,void 0!==i?i:new _t,void 0!==r?r:new _t,void 0!==n?n:new _t,void 0!==o?o:new _t]}function Et(e,t,i){for(var r=new Mt,n=new re,o=new ie,a=new ie(i,i),s=new oe,c=new oe,h=new Array(4),l=new Array(4),u={},p=[new oe(1,0,0),new oe(-1,0,0),new oe(0,0,1),new oe(0,0,-1),new oe(0,1,0),new oe(0,-1,0)],d=[new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,0,1),new oe(0,0,-1)],f=[new he,new he,new he,new he,new he,new he],m=0;4!==m;++m){var v=0!=(1&m),g=0!=(2&m),y=new yt({depthPacking:3201,morphTargets:v,skinning:g});h[m]=y;var x=new xt({morphTargets:v,skinning:g});l[m]=x}var b=this;function w(t,i,r,n,o,a){var s=t.geometry,c=null,p=h,d=t.customDepthMaterial;if(r&&(p=l,d=t.customDistanceMaterial),d)c=d;else{var f=!1;i.morphTargets&&(s&&s.isBufferGeometry?f=s.morphAttributes&&s.morphAttributes.position&&s.morphAttributes.position.length>0:s&&s.isGeometry&&(f=s.morphTargets&&s.morphTargets.length>0)),t.isSkinnedMesh&&!1===i.skinning&&console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",t);var m=0;f&&(m|=1),t.isSkinnedMesh&&i.skinning&&(m|=2),c=p[m]}if(e.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length){var v=c.uuid,g=i.uuid,y=u[v];void 0===y&&(y={},u[v]=y);var x=y[g];void 0===x&&(x=c.clone(),y[g]=x),c=x}c.visible=i.visible,c.wireframe=i.wireframe;var w=i.side;return b.renderSingleSided&&2==w&&(w=0),b.renderReverseSided&&(0===w?w=1:1===w&&(w=0)),c.side=w,c.clipShadows=i.clipShadows,c.clippingPlanes=i.clippingPlanes,c.clipIntersection=i.clipIntersection,c.wireframeLinewidth=i.wireframeLinewidth,c.linewidth=i.linewidth,r&&c.isMeshDistanceMaterial&&(c.referencePosition.copy(n),c.nearDistance=o,c.farDistance=a),c}function _(i,n,o,a){if(!1!==i.visible){if(i.layers.test(n.layers)&&(i.isMesh||i.isLine||i.isPoints)&&i.castShadow&&(!i.frustumCulled||r.intersectsObject(i))){i.modelViewMatrix.multiplyMatrices(o.matrixWorldInverse,i.matrixWorld);var s=t.update(i),h=i.material;if(Array.isArray(h))for(var l=s.groups,u=0,p=l.length;u0&&(i.alphaTest=this.alphaTest),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.morphTargets&&(i.morphTargets=!0),!0===this.skinning&&(i.skinning=!0),!1===this.visible&&(i.visible=!1),"{}"!==JSON.stringify(this.userData)&&(i.userData=this.userData),t){var n=r(e.textures),o=r(e.images);n.length>0&&(i.textures=n),o.length>0&&(i.images=o)}return i},clone:function(){return(new this.constructor).copy(this)},copy:function(e){this.name=e.name,this.fog=e.fog,this.lights=e.lights,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.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.overdraw=e.overdraw,this.visible=e.visible,this.userData=JSON.parse(JSON.stringify(e.userData)),this.clipShadows=e.clipShadows,this.clipIntersection=e.clipIntersection;var t=e.clippingPlanes,i=null;if(null!==t){var r=t.length;i=new Array(r);for(var n=0;n!==r;++n)i[n]=t[n].clone()}return this.clippingPlanes=i,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),yt.prototype=Object.create(gt.prototype),yt.prototype.constructor=yt,yt.prototype.isMeshDepthMaterial=!0,yt.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.depthPacking=e.depthPacking,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this},xt.prototype=Object.create(gt.prototype),xt.prototype.constructor=xt,xt.prototype.isMeshDistanceMaterial=!0,xt.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.referencePosition.copy(e.referencePosition),this.nearDistance=e.nearDistance,this.farDistance=e.farDistance,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this},Object.assign(bt.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,i=1/0,r=1/0,n=-1/0,o=-1/0,a=-1/0,s=0,c=e.length;sn&&(n=h),l>o&&(o=l),u>a&&(a=u)}return this.min.set(t,i,r),this.max.set(n,o,a),this},setFromBufferAttribute:function(e){for(var t=1/0,i=1/0,r=1/0,n=-1/0,o=-1/0,a=-1/0,s=0,c=e.count;sn&&(n=h),l>o&&(o=l),u>a&&(a=u)}return this.min.set(t,i,r),this.max.set(n,o,a),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=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(t||new oe).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:(lt=new oe,function(e){return this.clampPoint(e.center,lt),lt.distanceToSquared(e.center)<=e.radius*e.radius}),intersectsPlane:function(e){var t,i;return e.normal.x>0?(t=e.normal.x*this.min.x,i=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,i=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,i+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,i+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,i+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,i+=e.normal.z*this.min.z),t<=e.constant&&i>=e.constant},clampPoint:function(e,t){return(t||new oe).copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new oe;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),getBoundingSphere:function(){var e=new oe;return function(t){var i=t||new wt;return this.getCenter(i.center),i.radius=.5*this.getSize(e).length(),i}}(),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:(ht=[new oe,new oe,new oe,new oe,new oe,new oe,new oe,new oe],function(e){return this.isEmpty()||(ht[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),ht[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),ht[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),ht[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),ht[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),ht[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),ht[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),ht[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(ht)),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)}}),Object.assign(wt.prototype,{set:function(e,t){return this.center.copy(e),this.radius=t,this},setFromPoints:(ut=new bt,function(e,t){var i=this.center;void 0!==t?i.copy(t):ut.setFromPoints(e).getCenter(i);for(var r=0,n=0,o=e.length;nthis.radius*this.radius&&(r.sub(this.center).normalize(),r.multiplyScalar(this.radius).add(this.center)),r},getBoundingBox:function(e){var t=e||new bt;return t.set(this.center,this.center),t.expandByScalar(this.radius),t},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}}),Object.assign(_t.prototype,{set:function(e,t){return this.normal.copy(e),this.constant=t,this},setComponents:function(e,t,i,r){return this.normal.set(e,t,i),this.constant=r,this},setFromNormalAndCoplanarPoint:function(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this},setFromCoplanarPoints:function(){var e=new oe,t=new oe;return function(i,r,n){var o=e.subVectors(n,r).cross(t.subVectors(i,r)).normalize();return this.setFromNormalAndCoplanarPoint(o,i),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(t||new oe).copy(this.normal).multiplyScalar(-this.distanceToPoint(e)).add(e)},intersectLine:function(){var e=new oe;return function(t,i){var r=i||new oe,n=t.delta(e),o=this.normal.dot(n);if(0===o)return 0===this.distanceToPoint(t.start)?r.copy(t.start):void 0;var a=-(t.start.dot(this.normal)+this.constant)/o;return a<0||a>1?void 0:r.copy(n).multiplyScalar(a).add(t.start)}}(),intersectsLine:function(e){var t=this.distanceToPoint(e.start),i=this.distanceToPoint(e.end);return t<0&&i>0||i<0&&t>0},intersectsBox:function(e){return e.intersectsPlane(this)},intersectsSphere:function(e){return e.intersectsPlane(this)},coplanarPoint:function(e){return(e||new oe).copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(){var e=new oe,t=new ae;return function(i,r){var n=r||t.getNormalMatrix(i),o=this.coplanarPoint(e).applyMatrix4(i),a=this.normal.applyMatrix3(n).normalize();return this.constant=-o.dot(a),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}}),Object.assign(Mt.prototype,{set:function(e,t,i,r,n,o){var a=this.planes;return a[0].copy(e),a[1].copy(t),a[2].copy(i),a[3].copy(r),a[4].copy(n),a[5].copy(o),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){for(var t=this.planes,i=0;i<6;i++)t[i].copy(e.planes[i]);return this},setFromMatrix:function(e){var t=this.planes,i=e.elements,r=i[0],n=i[1],o=i[2],a=i[3],s=i[4],c=i[5],h=i[6],l=i[7],u=i[8],p=i[9],d=i[10],f=i[11],m=i[12],v=i[13],g=i[14],y=i[15];return t[0].setComponents(a-r,l-s,f-u,y-m).normalize(),t[1].setComponents(a+r,l+s,f+u,y+m).normalize(),t[2].setComponents(a+n,l+c,f+p,y+v).normalize(),t[3].setComponents(a-n,l-c,f-p,y-v).normalize(),t[4].setComponents(a-o,l-h,f-d,y-g).normalize(),t[5].setComponents(a+o,l+h,f+d,y+g).normalize(),this},intersectsObject:(ft=new wt,function(e){var t=e.geometry;return null===t.boundingSphere&&t.computeBoundingSphere(),ft.copy(t.boundingSphere).applyMatrix4(e.matrixWorld),this.intersectsSphere(ft)}),intersectsSprite:function(){var e=new wt;return function(t){return e.center.set(0,0,0),e.radius=.7071067811865476,e.applyMatrix4(t.matrixWorld),this.intersectsSphere(e)}}(),intersectsSphere:function(e){for(var t=this.planes,i=e.center,r=-e.radius,n=0;n<6;n++){if(t[n].distanceToPoint(i)0?e.min.x:e.max.x,dt.x=r.normal.x>0?e.max.x:e.min.x,pt.y=r.normal.y>0?e.min.y:e.max.y,dt.y=r.normal.y>0?e.max.y:e.min.y,pt.z=r.normal.z>0?e.min.z:e.max.z,dt.z=r.normal.z>0?e.max.z:e.min.z;var n=r.distanceToPoint(pt),o=r.distanceToPoint(dt);if(n<0&&o<0)return!1}return!0}),containsPoint:function(e){for(var t=this.planes,i=0;i<6;i++)if(t[i].distanceToPoint(e)<0)return!1;return!0}}),St.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"],St.DefaultOrder="XYZ",Object.defineProperties(St.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(St.prototype,{isEuler:!0,set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._order=r||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,i){var r=te.clamp,n=e.elements,o=n[0],a=n[4],s=n[8],c=n[1],h=n[5],l=n[9],u=n[2],p=n[6],d=n[10];return"XYZ"===(t=t||this._order)?(this._y=Math.asin(r(s,-1,1)),Math.abs(s)<.99999?(this._x=Math.atan2(-l,d),this._z=Math.atan2(-a,o)):(this._x=Math.atan2(p,h),this._z=0)):"YXZ"===t?(this._x=Math.asin(-r(l,-1,1)),Math.abs(l)<.99999?(this._y=Math.atan2(s,d),this._z=Math.atan2(c,h)):(this._y=Math.atan2(-u,o),this._z=0)):"ZXY"===t?(this._x=Math.asin(r(p,-1,1)),Math.abs(p)<.99999?(this._y=Math.atan2(-u,d),this._z=Math.atan2(-a,h)):(this._y=0,this._z=Math.atan2(c,o))):"ZYX"===t?(this._y=Math.asin(-r(u,-1,1)),Math.abs(u)<.99999?(this._x=Math.atan2(p,d),this._z=Math.atan2(c,o)):(this._x=0,this._z=Math.atan2(-a,h))):"YZX"===t?(this._z=Math.asin(r(c,-1,1)),Math.abs(c)<.99999?(this._x=Math.atan2(-l,h),this._y=Math.atan2(-u,o)):(this._x=0,this._y=Math.atan2(s,d))):"XZY"===t?(this._z=Math.asin(-r(a,-1,1)),Math.abs(a)<.99999?(this._x=Math.atan2(p,h),this._y=Math.atan2(s,o)):(this._x=Math.atan2(-l,d),this._y=0)):console.warn("THREE.Euler: .setFromRotationMatrix() given unsupported order: "+t),this._order=t,!1!==i&&this.onChangeCallback(),this},setFromQuaternion:function(){var e=new re;return function(t,i,r){return e.makeRotationFromQuaternion(t),this.setFromRotationMatrix(e,i,r)}}(),setFromVector3:function(e,t){return this.set(e.x,e.y,e.z,t||this._order)},reorder:(mt=new ne,function(e){return mt.setFromEuler(this),this.setFromQuaternion(mt,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 oe(this._x,this._y,this._z)},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(At.prototype,{set:function(e){this.mask=1<1){for(var t=0;t1){for(var t=0;t0){r.children=[];for(s=0;s0&&(i.geometries=u),p.length>0&&(i.materials=p),d.length>0&&(i.textures=d),f.length>0&&(i.images=f),a.length>0&&(i.shapes=a)}return i.object=r,i;function m(e){var t=[];for(var i in e){var r=e[i];delete r.metadata,t.push(r)}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 i=0;it&&(t=e[i]);return t}zt.prototype=Object.assign(Object.create(n.prototype),{constructor:zt,isGeometry:!0,applyMatrix:function(e){for(var t=(new ae).getNormalMatrix(e),i=0,r=this.vertices.length;i0)for(p=0;p0&&(this.normalsNeedUpdate=!0)},computeFlatVertexNormals:function(){var e,t,i;for(this.computeFaceNormals(),e=0,t=this.faces.length;e0&&(this.normalsNeedUpdate=!0)},computeMorphNormals:function(){var e,t,i,r,n;for(i=0,r=this.faces.length;i0&&(e+=t[i].distanceTo(t[i-1])),this.lineDistances[i]=e},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new bt),this.boundingBox.setFromPoints(this.vertices)},computeBoundingSphere:function(){null===this.boundingSphere&&(this.boundingSphere=new wt),this.boundingSphere.setFromPoints(this.vertices)},merge:function(e,t,i){if(e&&e.isGeometry){var r,n=this.vertices.length,o=this.vertices,a=e.vertices,s=this.faces,c=e.faces,h=this.faceVertexUvs[0],l=e.faceVertexUvs[0],u=this.colors,p=e.colors;void 0===i&&(i=0),void 0!==t&&(r=(new ae).getNormalMatrix(t));for(var d=0,f=a.length;d=0;i--){var f=p[i];for(this.faces.splice(f,1),a=0,s=this.faceVertexUvs.length;a0,v=d.vertexNormals.length>0,g=1!==d.color.r||1!==d.color.g||1!==d.color.b,y=d.vertexColors.length>0,x=0;if(x=M(x,0,0),x=M(x,1,!0),x=M(x,2,!1),x=M(x,3,f),x=M(x,4,m),x=M(x,5,v),x=M(x,6,g),x=M(x,7,y),a.push(x),a.push(d.a,d.b,d.c),a.push(d.materialIndex),f){var b=this.faceVertexUvs[0][n];a.push(S(b[0]),S(b[1]),S(b[2]))}if(m&&a.push(E(d.normal)),v){var w=d.vertexNormals;a.push(E(w[0]),E(w[1]),E(w[2]))}if(g&&a.push(T(d.color)),y){var _=d.vertexColors;a.push(T(_[0]),T(_[1]),T(_[2]))}}function M(e,t,i){return i?e|1<0&&(e.data.colors=h),u.length>0&&(e.data.uvs=[u]),e.data.faces=a,e},clone:function(){return(new zt).copy(this)},copy:function(e){var t,i,r,n,o,a;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,i=s.length;t0,a=n[1]&&n[1].length>0,s=e.morphTargets,c=s.length;if(c>0){t=[];for(var h=0;h0){l=[];for(h=0;h0?1:-1,h.push(R.x,R.y,R.z),l.push(y/m),l.push(1-x/v),A+=1}}for(x=0;x1&&i.sort(yi),r.length>1&&r.sort(xi)}}}function wi(){var e={};return{get:function(t,i){var r=t.id+","+i.id,n=e[r];return void 0===n&&(n=new bi,e[r]=n),n},dispose:function(){e={}}}}function _i(e,t){return Math.abs(t[1])-Math.abs(e[1])}function Mi(e){var t={},i=new Float32Array(8);return{update:function(r,n,o,a){var s=r.morphTargetInfluences,c=s.length,h=t[n.id];if(void 0===h){h=[];for(var l=0;l65535?qt:Wt)(a,1),t.update(r,e.ELEMENT_ARRAY_BUFFER),n[i.id]=r,r}}}function Ai(){var e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];var i;switch(t.type){case"DirectionalLight":i={direction:new oe,color:new et,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie};break;case"SpotLight":i={position:new oe,direction:new oe,color:new et,distance:0,coneCos:0,penumbraCos:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie};break;case"PointLight":i={position:new oe,color:new et,distance:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie,shadowCameraNear:1,shadowCameraFar:1e3};break;case"HemisphereLight":i={direction:new oe,skyColor:new et,groundColor:new et};break;case"RectAreaLight":i={color:new et,position:new oe,halfWidth:new oe,halfHeight:new oe}}return e[t.id]=i,i}}}function Li(){var e=new Ai,t={hash:"",ambient:[0,0,0],directional:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],point:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]},i=new oe,r=new re,n=new re;return{setup:function(o,a,s){for(var c=0,h=0,l=0,u=0,p=0,d=0,f=0,m=0,v=s.matrixWorldInverse,g=0,y=o.length;g65535?qt:Wt)(e,1):this.index=e},addAttribute:function(e,t){return t&&t.isBufferAttribute||t&&t.isInterleavedBufferAttribute?"index"===e?(console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute."),void this.setIndex(t)):(this.attributes[e]=t,this):(console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )."),void this.addAttribute(e,new kt(arguments[1],arguments[2])))},getAttribute:function(e){return this.attributes[e]},removeAttribute:function(e){return delete this.attributes[e],this},addGroup:function(e,t,i){this.groups.push({start:e,count:t,materialIndex:void 0!==i?i:0})},clearGroups:function(){this.groups=[]},setDrawRange:function(e,t){this.drawRange.start=e,this.drawRange.count=t},applyMatrix:function(e){var t=this.attributes.position;void 0!==t&&(e.applyToBufferAttribute(t),t.needsUpdate=!0);var i=this.attributes.normal;void 0!==i&&((new ae).getNormalMatrix(e).applyToBufferAttribute(i),i.needsUpdate=!0);return null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},rotateX:function(){var e=new re;return function(t){return e.makeRotationX(t),this.applyMatrix(e),this}}(),rotateY:function(){var e=new re;return function(t){return e.makeRotationY(t),this.applyMatrix(e),this}}(),rotateZ:function(){var e=new re;return function(t){return e.makeRotationZ(t),this.applyMatrix(e),this}}(),translate:function(){var e=new re;return function(t,i,r){return e.makeTranslation(t,i,r),this.applyMatrix(e),this}}(),scale:function(){var e=new re;return function(t,i,r){return e.makeScale(t,i,r),this.applyMatrix(e),this}}(),lookAt:function(){var e=new Ot;return function(t){e.lookAt(t),e.updateMatrix(),this.applyMatrix(e.matrix)}}(),center:function(){this.computeBoundingBox();var e=this.boundingBox.getCenter().negate();return this.translate(e.x,e.y,e.z),e},setFromObject:function(e){var t=e.geometry;if(e.isPoints||e.isLine){var i=new Yt(3*t.vertices.length,3),r=new Yt(3*t.colors.length,3);if(this.addAttribute("position",i.copyVector3sArray(t.vertices)),this.addAttribute("color",r.copyColorsArray(t.colors)),t.lineDistances&&t.lineDistances.length===t.vertices.length){var n=new Yt(t.lineDistances.length,1);this.addAttribute("lineDistance",n.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=[],i=0,r=e.length;i0){var i=new Float32Array(3*e.normals.length);this.addAttribute("normal",new kt(i,3).copyVector3sArray(e.normals))}if(e.colors.length>0){var r=new Float32Array(3*e.colors.length);this.addAttribute("color",new kt(r,3).copyColorsArray(e.colors))}if(e.uvs.length>0){var n=new Float32Array(2*e.uvs.length);this.addAttribute("uv",new kt(n,2).copyVector2sArray(e.uvs))}if(e.uvs2.length>0){var o=new Float32Array(2*e.uvs2.length);this.addAttribute("uv2",new kt(o,2).copyVector2sArray(e.uvs2))}if(e.indices.length>0){var a=new(Kt(e.indices)>65535?Uint32Array:Uint16Array)(3*e.indices.length);this.setIndex(new kt(a,1).copyIndicesArray(e.indices))}for(var s in this.groups=e.groups,e.morphTargets){for(var c=[],h=e.morphTargets[s],l=0,u=h.length;l0){var f=new Yt(4*e.skinIndices.length,4);this.addAttribute("skinIndex",f.copyVector4sArray(e.skinIndices))}if(e.skinWeights.length>0){var m=new Yt(4*e.skinWeights.length,4);this.addAttribute("skinWeight",m.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 bt);var e=this.attributes.position;void 0!==e?this.boundingBox.setFromBufferAttribute(e):this.boundingBox.makeEmpty(),(isNaN(this.boundingBox.min.x)||isNaN(this.boundingBox.min.y)||isNaN(this.boundingBox.min.z))&&console.error('THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.',this)},computeBoundingSphere:function(){var e=new bt,t=new oe;return function(){null===this.boundingSphere&&(this.boundingSphere=new wt);var i=this.attributes.position;if(i){var r=this.boundingSphere.center;e.setFromBufferAttribute(i),e.getCenter(r);for(var n=0,o=0,a=i.count;o0&&(e.data.groups=JSON.parse(JSON.stringify(s)));var c=this.boundingSphere;return null!==c&&(e.data.boundingSphere={center:c.center.toArray(),radius:c.radius}),e},clone:function(){return(new ai).copy(this)},copy:function(e){var t,i,r;this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var n=e.index;null!==n&&this.setIndex(n.clone());var o=e.attributes;for(t in o){var a=o[t];this.addAttribute(t,a.clone())}var s=e.morphAttributes;for(t in s){var c=[],h=s[t];for(i=0,r=h.length;i0)if(o=h*l-u,s=c*d,(n=h*u-l)>=0)if(o>=-s)if(o<=s){var f=1/d;a=(n*=f)*(n+h*(o*=f)+2*l)+o*(h*n+o+2*u)+p}else o=c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;else o=-c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;else o<=-s?a=-(n=Math.max(0,-(-h*c+l)))*n+(o=n>0?-c:Math.min(Math.max(-c,-u),c))*(o+2*u)+p:o<=s?(n=0,a=(o=Math.min(Math.max(-c,-u),c))*(o+2*u)+p):a=-(n=Math.max(0,-(h*c+l)))*n+(o=n>0?c:Math.min(Math.max(-c,-u),c))*(o+2*u)+p;else o=h>0?-c:c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;return i&&i.copy(this.direction).multiplyScalar(n).add(this.origin),r&&r.copy(ei).multiplyScalar(o).add($t),a}),intersectSphere:function(){var e=new oe;return function(t,i){e.subVectors(t.center,this.origin);var r=e.dot(this.direction),n=e.dot(e)-r*r,o=t.radius*t.radius;if(n>o)return null;var a=Math.sqrt(o-n),s=r-a,c=r+a;return s<0&&c<0?null:s<0?this.at(c,i):this.at(s,i)}}(),intersectsSphere:function(e){return this.distanceToPoint(e.center)<=e.radius},distanceToPlane:function(e){var t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;var i=-(this.origin.dot(e.normal)+e.constant)/t;return i>=0?i:null},intersectPlane:function(e,t){var i=this.distanceToPlane(e);return null===i?null:this.at(i,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 i,r,n,o,a,s,c=1/this.direction.x,h=1/this.direction.y,l=1/this.direction.z,u=this.origin;return c>=0?(i=(e.min.x-u.x)*c,r=(e.max.x-u.x)*c):(i=(e.max.x-u.x)*c,r=(e.min.x-u.x)*c),h>=0?(n=(e.min.y-u.y)*h,o=(e.max.y-u.y)*h):(n=(e.max.y-u.y)*h,o=(e.min.y-u.y)*h),i>o||n>r?null:((n>i||i!=i)&&(i=n),(o=0?(a=(e.min.z-u.z)*l,s=(e.max.z-u.z)*l):(a=(e.max.z-u.z)*l,s=(e.min.z-u.z)*l),i>s||a>r?null:((a>i||i!=i)&&(i=a),(s=0?i:r,t)))},intersectsBox:(Qt=new oe,function(e){return null!==this.intersectBox(e,Qt)}),intersectTriangle:function(){var e=new oe,t=new oe,i=new oe,r=new oe;return function(n,o,a,s,c){t.subVectors(o,n),i.subVectors(a,n),r.crossVectors(t,i);var h,l=this.direction.dot(r);if(l>0){if(s)return null;h=1}else{if(!(l<0))return null;h=-1,l=-l}e.subVectors(this.origin,n);var u=h*this.direction.dot(i.crossVectors(e,i));if(u<0)return null;var p=h*this.direction.dot(t.cross(e));if(p<0)return null;if(u+p>l)return null;var d=-h*e.dot(r);return d<0?null:this.at(d/l,c)}}(),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)}}),Object.assign(fi.prototype,{set:function(e,t){return this.start.copy(e),this.end.copy(t),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.start.copy(e.start),this.end.copy(e.end),this},getCenter:function(e){return(e||new oe).addVectors(this.start,this.end).multiplyScalar(.5)},delta:function(e){return(e||new oe).subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(e,t){var i=t||new oe;return this.delta(i).multiplyScalar(e).add(this.start)},closestPointToPointParameter:(ii=new oe,ri=new oe,function(e,t){ii.subVectors(e,this.start),ri.subVectors(this.end,this.start);var i=ri.dot(ri),r=ri.dot(ii)/i;return t&&(r=te.clamp(r,0,1)),r}),closestPointToPoint:function(e,t,i){var r=this.closestPointToPointParameter(e,t),n=i||new oe;return this.delta(n).multiplyScalar(r).add(this.start)},applyMatrix4:function(e){return this.start.applyMatrix4(e),this.end.applyMatrix4(e),this},equals:function(e){return e.start.equals(this.start)&&e.end.equals(this.end)}}),Object.assign(mi,{normal:(ni=new oe,function(e,t,i,r){var n=r||new oe;n.subVectors(i,t),ni.subVectors(e,t),n.cross(ni);var o=n.lengthSq();return o>0?n.multiplyScalar(1/Math.sqrt(o)):n.set(0,0,0)}),barycoordFromPoint:function(){var e=new oe,t=new oe,i=new oe;return function(r,n,o,a,s){e.subVectors(a,n),t.subVectors(o,n),i.subVectors(r,n);var c=e.dot(e),h=e.dot(t),l=e.dot(i),u=t.dot(t),p=t.dot(i),d=c*u-h*h,f=s||new oe;if(0===d)return f.set(-2,-1,-1);var m=1/d,v=(u*l-h*p)*m,g=(c*p-h*l)*m;return f.set(1-v-g,g,v)}}(),containsPoint:function(){var e=new oe;return function(t,i,r,n){var o=mi.barycoordFromPoint(t,i,r,n,e);return o.x>=0&&o.y>=0&&o.x+o.y<=1}}()}),Object.assign(mi.prototype,{set:function(e,t,i){return this.a.copy(e),this.b.copy(t),this.c.copy(i),this},setFromPointsAndIndices:function(e,t,i,r){return this.a.copy(e[t]),this.b.copy(e[i]),this.c.copy(e[r]),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},area:function(){var e=new oe,t=new oe;return function(){return e.subVectors(this.c,this.b),t.subVectors(this.a,this.b),.5*e.cross(t).length()}}(),midpoint:function(e){return(e||new oe).addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},normal:function(e){return mi.normal(this.a,this.b,this.c,e)},plane:function(e){return(e||new _t).setFromCoplanarPoints(this.a,this.b,this.c)},barycoordFromPoint:function(e,t){return mi.barycoordFromPoint(e,this.a,this.b,this.c,t)},containsPoint:function(e){return mi.containsPoint(e,this.a,this.b,this.c)},closestPointToPoint:function(){var e=new _t,t=[new fi,new fi,new fi],i=new oe,r=new oe;return function(n,o){var a=o||new oe,s=1/0;if(e.setFromCoplanarPoints(this.a,this.b,this.c),e.projectPoint(n,i),!0===this.containsPoint(i))a.copy(i);else{t[0].set(this.a,this.b),t[1].set(this.b,this.c),t[2].set(this.c,this.a);for(var c=0;c0){var a=n[o[0]];if(void 0!==a)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=a.length;e0)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=s.length;ei.far?null:{distance:c,point:f.clone(),object:e}}function g(e,t,i,a,s,c,p,f){r.fromBufferAttribute(a,c),n.fromBufferAttribute(a,p),o.fromBufferAttribute(a,f);var g=v(e,e.material,t,i,r,n,o,d);return g&&(s&&(h.fromBufferAttribute(s,c),l.fromBufferAttribute(s,p),u.fromBufferAttribute(s,f),g.uv=m(d,r,n,o,h,l,u)),g.face=new Ut(c,p,f,mi.normal(r,n,o)),g.faceIndex=c),g}return function(p,f){var y,x=this.geometry,b=this.material,w=this.matrixWorld;if(void 0!==b&&(null===x.boundingSphere&&x.computeBoundingSphere(),i.copy(x.boundingSphere),i.applyMatrix4(w),!1!==p.ray.intersectsSphere(i)&&(e.getInverse(w),t.copy(p.ray).applyMatrix4(e),null===x.boundingBox||!1!==t.intersectsBox(x.boundingBox))))if(x.isBufferGeometry){var _,M,E,T,S,A=x.index,L=x.attributes.position,R=x.attributes.uv;if(null!==A)for(T=0,S=A.count;T0&&(O=F);for(var B=0,z=U.length;B/gm,(function(e,t){var i=rt[t];if(void 0===i)throw new Error("Can not resolve #include <"+t+">");return ji(i)}))}function Hi(e){return e.replace(/for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,(function(e,t,i,r){for(var n="",o=parseInt(t);o0?e.gammaFactor:1,T=function(e,t,i){return[(e=e||{}).derivatives||t.envMapCubeUV||t.bumpMap||t.normalMap||t.flatShading?"#extension GL_OES_standard_derivatives : enable":"",(e.fragDepth||t.logarithmicDepthBuffer)&&i.get("EXT_frag_depth")?"#extension GL_EXT_frag_depth : enable":"",e.drawBuffers&&i.get("WEBGL_draw_buffers")?"#extension GL_EXT_draw_buffers : require":"",(e.shaderTextureLOD||t.envMap)&&i.get("EXT_shader_texture_lod")?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Gi).join("\n")}(r.extensions,o,t),S=function(e){var t=[];for(var i in e){var r=e[i];!1!==r&&t.push("#define "+i+" "+r)}return t.join("\n")}(s),A=a.createProgram();r.isRawShaderMaterial?((f=[S].filter(Gi).join("\n")).length>0&&(f+="\n"),(b=[T,S].filter(Gi).join("\n")).length>0&&(b+="\n")):(f=["precision "+o.precision+" float;","precision "+o.precision+" int;","#define SHADER_NAME "+n.name,S,o.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+E,"#define MAX_BONES "+o.maxBones,o.useFog&&o.fog?"#define USE_FOG":"",o.useFog&&o.fogExp?"#define FOG_EXP2":"",o.map?"#define USE_MAP":"",o.envMap?"#define USE_ENVMAP":"",o.envMap?"#define "+p:"",o.lightMap?"#define USE_LIGHTMAP":"",o.aoMap?"#define USE_AOMAP":"",o.emissiveMap?"#define USE_EMISSIVEMAP":"",o.bumpMap?"#define USE_BUMPMAP":"",o.normalMap?"#define USE_NORMALMAP":"",o.displacementMap&&o.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",o.specularMap?"#define USE_SPECULARMAP":"",o.roughnessMap?"#define USE_ROUGHNESSMAP":"",o.metalnessMap?"#define USE_METALNESSMAP":"",o.alphaMap?"#define USE_ALPHAMAP":"",o.vertexColors?"#define USE_COLOR":"",o.flatShading?"#define FLAT_SHADED":"",o.skinning?"#define USE_SKINNING":"",o.useVertexTexture?"#define BONE_TEXTURE":"",o.morphTargets?"#define USE_MORPHTARGETS":"",o.morphNormals&&!1===o.flatShading?"#define USE_MORPHNORMALS":"",o.doubleSided?"#define DOUBLE_SIDED":"",o.flipSided?"#define FLIP_SIDED":"","#define NUM_CLIPPING_PLANES "+o.numClippingPlanes,o.shadowMapEnabled?"#define USE_SHADOWMAP":"",o.shadowMapEnabled?"#define "+l:"",o.sizeAttenuation?"#define USE_SIZEATTENUATION":"",o.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",o.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#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(Gi).join("\n"),b=[T,"precision "+o.precision+" float;","precision "+o.precision+" int;","#define SHADER_NAME "+n.name,S,o.alphaTest?"#define ALPHATEST "+o.alphaTest:"","#define GAMMA_FACTOR "+E,o.useFog&&o.fog?"#define USE_FOG":"",o.useFog&&o.fogExp?"#define FOG_EXP2":"",o.map?"#define USE_MAP":"",o.envMap?"#define USE_ENVMAP":"",o.envMap?"#define "+u:"",o.envMap?"#define "+p:"",o.envMap?"#define "+d:"",o.lightMap?"#define USE_LIGHTMAP":"",o.aoMap?"#define USE_AOMAP":"",o.emissiveMap?"#define USE_EMISSIVEMAP":"",o.bumpMap?"#define USE_BUMPMAP":"",o.normalMap?"#define USE_NORMALMAP":"",o.specularMap?"#define USE_SPECULARMAP":"",o.roughnessMap?"#define USE_ROUGHNESSMAP":"",o.metalnessMap?"#define USE_METALNESSMAP":"",o.alphaMap?"#define USE_ALPHAMAP":"",o.vertexColors?"#define USE_COLOR":"",o.gradientMap?"#define USE_GRADIENTMAP":"",o.flatShading?"#define FLAT_SHADED":"",o.doubleSided?"#define DOUBLE_SIDED":"",o.flipSided?"#define FLIP_SIDED":"","#define NUM_CLIPPING_PLANES "+o.numClippingPlanes,"#define UNION_CLIPPING_PLANES "+(o.numClippingPlanes-o.numClipIntersection),o.shadowMapEnabled?"#define USE_SHADOWMAP":"",o.shadowMapEnabled?"#define "+l:"",o.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",o.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",o.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",o.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"",o.envMap&&t.get("EXT_shader_texture_lod")?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;",0!==o.toneMapping?"#define TONE_MAPPING":"",0!==o.toneMapping?rt.tonemapping_pars_fragment:"",0!==o.toneMapping?ki("toneMapping",o.toneMapping):"",o.dithering?"#define DITHERING":"",o.outputEncoding||o.mapEncoding||o.envMapEncoding||o.emissiveMapEncoding?rt.encodings_pars_fragment:"",o.mapEncoding?zi("mapTexelToLinear",o.mapEncoding):"",o.envMapEncoding?zi("envMapTexelToLinear",o.envMapEncoding):"",o.emissiveMapEncoding?zi("emissiveMapTexelToLinear",o.emissiveMapEncoding):"",o.outputEncoding?(w="linearToOutputTexel",_=o.outputEncoding,M=Bi(_),"vec4 "+w+"( vec4 value ) { return LinearTo"+M[0]+M[1]+"; }"):"",o.depthPacking?"#define DEPTH_PACKING "+r.depthPacking:"","\n"].filter(Gi).join("\n")),c=Vi(c=ji(c),o),h=Vi(h=ji(h),o),r.isShaderMaterial||(c=Hi(c),h=Hi(h));var L=f+c,R=b+h,C=Ci(a,a.VERTEX_SHADER,L),P=Ci(a,a.FRAGMENT_SHADER,R);a.attachShader(A,C),a.attachShader(A,P),void 0!==r.index0AttributeName?a.bindAttribLocation(A,0,r.index0AttributeName):!0===o.morphTargets&&a.bindAttribLocation(A,0,"position"),a.linkProgram(A);var N,O,I=a.getProgramInfoLog(A),D=a.getShaderInfoLog(C),U=a.getShaderInfoLog(P),F=!0,B=!0;return!1===a.getProgramParameter(A,a.LINK_STATUS)?(F=!1,console.error("THREE.WebGLProgram: shader error: ",a.getError(),"gl.VALIDATE_STATUS",a.getProgramParameter(A,a.VALIDATE_STATUS),"gl.getProgramInfoLog",I,D,U)):""!==I?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",I):""!==D&&""!==U||(B=!1),B&&(this.diagnostics={runnable:F,material:r,programLog:I,vertexShader:{log:D,prefix:f},fragmentShader:{log:U,prefix:b}}),a.deleteShader(C),a.deleteShader(P),this.getUniforms=function(){return void 0===N&&(N=new Qe(a,A,e)),N},this.getAttributes=function(){return void 0===O&&(O=function(e,t){for(var i={},r=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES),n=0;n0,maxBones:p,useVertexTexture:i.floatVertexTextures,morphTargets:t.morphTargets,morphNormals:t.morphNormals,maxMorphTargets:e.maxMorphTargets,maxMorphNormals:e.maxMorphNormals,numDirLights:r.directional.length,numPointLights:r.point.length,numSpotLights:r.spot.length,numRectAreaLights:r.rectArea.length,numHemiLights:r.hemi.length,numClippingPlanes:c,numClipIntersection:h,dithering:t.dithering,shadowMapEnabled:e.shadowMap.enabled&&l.receiveShadow&&o.length>0,shadowMapType:e.shadowMap.type,toneMapping:e.toneMapping,physicallyCorrectLights:e.physicallyCorrectLights,premultipliedAlpha:t.premultipliedAlpha,alphaTest:t.alphaTest,doubleSided:2===t.side,flipSided:1===t.side,depthPacking:void 0!==t.depthPacking&&t.depthPacking}},this.getProgramCode=function(t,i){var r=[];if(i.shaderID?r.push(i.shaderID):(r.push(t.fragmentShader),r.push(t.vertexShader)),void 0!==t.defines)for(var n in t.defines)r.push(n),r.push(t.defines[n]);for(var a=0;at||e.height>t){var i=t/Math.max(e.width,e.height),r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return r.width=Math.floor(e.width*i),r.height=Math.floor(e.height*i),r.getContext("2d").drawImage(e,0,0,e.width,e.height,0,0,r.width,r.height),console.warn("THREE.WebGLRenderer: image is too big ("+e.width+"x"+e.height+"). Resized to "+r.width+"x"+r.height,e),r}return e}function l(e){return te.isPowerOfTwo(e.width)&&te.isPowerOfTwo(e.height)}function u(e,t){return e.generateMipmaps&&t&&e.minFilter!==M&&e.minFilter!==S}function p(t){return t===M||t===E||t===T?e.NEAREST:e.LINEAR}function d(t){var i=t.target;i.removeEventListener("dispose",d),function(t){var i=r.get(t);if(t.image&&i.__image__webglTextureCube)e.deleteTexture(i.__image__webglTextureCube);else{if(void 0===i.__webglInit)return;e.deleteTexture(i.__webglTexture)}r.remove(t)}(i),i.isVideoTexture&&delete c[i.id],a.textures--}function f(t){var i=t.target;i.removeEventListener("dispose",f),function(t){var i=r.get(t),n=r.get(t.texture);if(!t)return;void 0!==n.__webglTexture&&e.deleteTexture(n.__webglTexture);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLRenderTargetCube)for(var o=0;o<6;o++)e.deleteFramebuffer(i.__webglFramebuffer[o]),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer[o]);else e.deleteFramebuffer(i.__webglFramebuffer),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer);r.remove(t.texture),r.remove(t)}(i),a.textures--}function m(t,p){var f=r.get(t);if(t.version>0&&f.__version!==t.version){var m=t.image;if(void 0===m)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined",t);else{if(!1!==m.complete)return void function(t,r,p){void 0===t.__webglInit&&(t.__webglInit=!0,r.addEventListener("dispose",d),t.__webglTexture=e.createTexture(),r.isVideoTexture&&(c[r.id]=r),a.textures++);i.activeTexture(e.TEXTURE0+p),i.bindTexture(e.TEXTURE_2D,t.__webglTexture),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,r.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,r.unpackAlignment);var f=h(r.image,n.maxTextureSize);(function(e){return e.wrapS!==w||e.wrapT!==w||e.minFilter!==M&&e.minFilter!==S})(r)&&!1===l(f)&&(f=function(e){if(e instanceof HTMLImageElement||e instanceof HTMLCanvasElement||e instanceof ImageBitmap){var t=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return t.width=te.floorPowerOfTwo(e.width),t.height=te.floorPowerOfTwo(e.height),t.getContext("2d").drawImage(e,0,0,t.width,t.height),console.warn("THREE.WebGLRenderer: image is not power of two ("+e.width+"x"+e.height+"). Resized to "+t.width+"x"+t.height,e),t}return e}(f));var m=l(f),g=o.convert(r.format),y=o.convert(r.type);v(e.TEXTURE_2D,r,m);var x,b=r.mipmaps;if(r.isDepthTexture){var _=e.DEPTH_COMPONENT;if(r.type===N){if(!s)throw new Error("Float Depth Texture only supported in WebGL2.0");_=e.DEPTH_COMPONENT32F}else s&&(_=e.DEPTH_COMPONENT16);r.format===F&&_===e.DEPTH_COMPONENT&&r.type!==C&&r.type!==P&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=C,y=o.convert(r.type)),r.format===B&&(_=e.DEPTH_STENCIL,r.type!==I&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=I,y=o.convert(r.type))),i.texImage2D(e.TEXTURE_2D,0,_,f.width,f.height,0,g,y,null)}else if(r.isDataTexture)if(b.length>0&&m){for(var E=0,T=b.length;E-1?i.compressedTexImage2D(e.TEXTURE_2D,E,g,x.width,x.height,0,x.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"):i.texImage2D(e.TEXTURE_2D,E,g,x.width,x.height,0,g,y,x.data);else if(b.length>0&&m){for(E=0,T=b.length;E1||r.get(a).__currentAnisotropy)&&(e.texParameterf(i,c.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,n.getMaxAnisotropy())),r.get(a).__currentAnisotropy=a.anisotropy)}}function g(t,n,a,s){var c=o.convert(n.texture.format),h=o.convert(n.texture.type);i.texImage2D(s,0,c,n.width,n.height,0,c,h,null),e.bindFramebuffer(e.FRAMEBUFFER,t),e.framebufferTexture2D(e.FRAMEBUFFER,a,s,r.get(n.texture).__webglTexture,0),e.bindFramebuffer(e.FRAMEBUFFER,null)}function y(t,i){e.bindRenderbuffer(e.RENDERBUFFER,t),i.depthBuffer&&!i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_COMPONENT16,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.RENDERBUFFER,t)):i.depthBuffer&&i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_STENCIL,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.RENDERBUFFER,t)):e.renderbufferStorage(e.RENDERBUFFER,e.RGBA4,i.width,i.height),e.bindRenderbuffer(e.RENDERBUFFER,null)}function x(t){var i=r.get(t),n=!0===t.isWebGLRenderTargetCube;if(t.depthTexture){if(n)throw new Error("target.depthTexture not supported in Cube render targets");!function(t,i){if(i&&i.isWebGLRenderTargetCube)throw new Error("Depth Texture with cube render targets is not supported");if(e.bindFramebuffer(e.FRAMEBUFFER,t),!i.depthTexture||!i.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");r.get(i.depthTexture).__webglTexture&&i.depthTexture.image.width===i.width&&i.depthTexture.image.height===i.height||(i.depthTexture.image.width=i.width,i.depthTexture.image.height=i.height,i.depthTexture.needsUpdate=!0),m(i.depthTexture,0);var n=r.get(i.depthTexture).__webglTexture;if(i.depthTexture.format===F)e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.TEXTURE_2D,n,0);else{if(i.depthTexture.format!==B)throw new Error("Unknown depthTexture format");e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.TEXTURE_2D,n,0)}}(i.__webglFramebuffer,t)}else if(n){i.__webglDepthbuffer=[];for(var o=0;o<6;o++)e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer[o]),i.__webglDepthbuffer[o]=e.createRenderbuffer(),y(i.__webglDepthbuffer[o],t)}else e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer),i.__webglDepthbuffer=e.createRenderbuffer(),y(i.__webglDepthbuffer,t);e.bindFramebuffer(e.FRAMEBUFFER,null)}this.setTexture2D=m,this.setTextureCube=function(t,s){var c=r.get(t);if(6===t.image.length)if(t.version>0&&c.__version!==t.version){c.__image__webglTextureCube||(t.addEventListener("dispose",d),c.__image__webglTextureCube=e.createTexture(),a.textures++),i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,t.flipY);for(var p=t&&t.isCompressedTexture,f=t.image[0]&&t.image[0].isDataTexture,m=[],g=0;g<6;g++)m[g]=p||f?f?t.image[g].image:t.image[g]:h(t.image[g],n.maxCubemapSize);var y=l(m[0]),x=o.convert(t.format),b=o.convert(t.type);v(e.TEXTURE_CUBE_MAP,t,y);for(g=0;g<6;g++)if(p)for(var w,_=m[g].mipmaps,M=0,E=_.length;M-1?i.compressedTexImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,x,w.width,w.height,0,w.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,x,w.width,w.height,0,x,b,w.data);else f?i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,x,m[g].width,m[g].height,0,x,b,m[g].data):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,x,x,b,m[g]);u(t,y)&&e.generateMipmap(e.TEXTURE_CUBE_MAP),c.__version=t.version,t.onUpdate&&t.onUpdate(t)}else i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube)},this.setTextureCubeDynamic=function(t,n){i.activeTexture(e.TEXTURE0+n),i.bindTexture(e.TEXTURE_CUBE_MAP,r.get(t).__webglTexture)},this.setupRenderTarget=function(t){var n=r.get(t),o=r.get(t.texture);t.addEventListener("dispose",f),o.__webglTexture=e.createTexture(),a.textures++;var s=!0===t.isWebGLRenderTargetCube,c=l(t);if(s){n.__webglFramebuffer=[];for(var h=0;h<6;h++)n.__webglFramebuffer[h]=e.createFramebuffer()}else n.__webglFramebuffer=e.createFramebuffer();if(s){i.bindTexture(e.TEXTURE_CUBE_MAP,o.__webglTexture),v(e.TEXTURE_CUBE_MAP,t.texture,c);for(h=0;h<6;h++)g(n.__webglFramebuffer[h],t,e.COLOR_ATTACHMENT0,e.TEXTURE_CUBE_MAP_POSITIVE_X+h);u(t.texture,c)&&e.generateMipmap(e.TEXTURE_CUBE_MAP),i.bindTexture(e.TEXTURE_CUBE_MAP,null)}else i.bindTexture(e.TEXTURE_2D,o.__webglTexture),v(e.TEXTURE_2D,t.texture,c),g(n.__webglFramebuffer,t,e.COLOR_ATTACHMENT0,e.TEXTURE_2D),u(t.texture,c)&&e.generateMipmap(e.TEXTURE_2D),i.bindTexture(e.TEXTURE_2D,null);t.depthBuffer&&x(t)},this.updateRenderTargetMipmap=function(t){var n=t.texture;if(u(n,l(t))){var o=t.isWebGLRenderTargetCube?e.TEXTURE_CUBE_MAP:e.TEXTURE_2D,a=r.get(n).__webglTexture;i.bindTexture(o,a),e.generateMipmap(o),i.bindTexture(o,null)}},this.updateVideoTextures=function(){for(var e in c)c[e].update()}}function Yi(){var e={};return{get:function(t){var i=t.uuid,r=e[i];return void 0===r&&(r={},e[i]=r),r},remove:function(t){delete e[t.uuid]},clear:function(){e={}}}}function Zi(e,t,i){var r=new function(){var t=!1,i=new he,r=null,n=new he(0,0,0,0);return{setMask:function(i){r===i||t||(e.colorMask(i,i,i,i),r=i)},setLocked:function(e){t=e},setClear:function(t,r,o,a,s){!0===s&&(t*=a,r*=a,o*=a),i.set(t,r,o,a),!1===n.equals(i)&&(e.clearColor(t,r,o,a),n.copy(i))},reset:function(){t=!1,r=null,n.set(-1,0,0,0)}}},n=new function(){var t=!1,i=null,r=null,n=null;return{setTest:function(t){t?D(e.DEPTH_TEST):U(e.DEPTH_TEST)},setMask:function(r){i===r||t||(e.depthMask(r),i=r)},setFunc:function(t){if(r!==t){if(t)switch(t){case 0:e.depthFunc(e.NEVER);break;case 1:e.depthFunc(e.ALWAYS);break;case 2:e.depthFunc(e.LESS);break;case 3:default:e.depthFunc(e.LEQUAL);break;case 4:e.depthFunc(e.EQUAL);break;case 5:e.depthFunc(e.GEQUAL);break;case 6:e.depthFunc(e.GREATER);break;case 7:e.depthFunc(e.NOTEQUAL)}else e.depthFunc(e.LEQUAL);r=t}},setLocked:function(e){t=e},setClear:function(t){n!==t&&(e.clearDepth(t),n=t)},reset:function(){t=!1,i=null,r=null,n=null}}},o=new function(){var t=!1,i=null,r=null,n=null,o=null,a=null,s=null,c=null,h=null;return{setTest:function(t){t?D(e.STENCIL_TEST):U(e.STENCIL_TEST)},setMask:function(r){i===r||t||(e.stencilMask(r),i=r)},setFunc:function(t,i,a){r===t&&n===i&&o===a||(e.stencilFunc(t,i,a),r=t,n=i,o=a)},setOp:function(t,i,r){a===t&&s===i&&c===r||(e.stencilOp(t,i,r),a=t,s=i,c=r)},setLocked:function(e){t=e},setClear:function(t){h!==t&&(e.clearStencil(t),h=t)},reset:function(){t=!1,i=null,r=null,n=null,o=null,a=null,s=null,c=null,h=null}}},a=e.getParameter(e.MAX_VERTEX_ATTRIBS),s=new Uint8Array(a),c=new Uint8Array(a),h=new Uint8Array(a),l={},u=null,p=null,d=null,f=null,m=null,v=null,g=null,y=null,x=null,b=!1,w=null,_=null,M=null,E=null,T=null,S=e.getParameter(e.MAX_COMBINED_TEXTURE_IMAGE_UNITS),A=parseFloat(/^WebGL\ ([0-9])/.exec(e.getParameter(e.VERSION))[1]),L=parseFloat(A)>=1,R=null,C={},P=new he,N=new he;function O(t,i,r){var n=new Uint8Array(4),o=e.createTexture();e.bindTexture(t,o),e.texParameteri(t,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(t,e.TEXTURE_MAG_FILTER,e.NEAREST);for(var a=0;a0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}var o=void 0!==i.precision?i.precision:"highp",a=n(o);a!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",a,"instead."),o=a);var s=!0===i.logarithmicDepthBuffer,c=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),h=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS),l=e.getParameter(e.MAX_TEXTURE_SIZE),u=e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),p=e.getParameter(e.MAX_VERTEX_ATTRIBS),d=e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),f=e.getParameter(e.MAX_VARYING_VECTORS),m=e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),v=h>0,g=!!t.get("OES_texture_float");return{getMaxAnisotropy:function(){if(void 0!==r)return r;var i=t.get("EXT_texture_filter_anisotropic");return r=null!==i?e.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0},getMaxPrecision:n,precision:o,logarithmicDepthBuffer:s,maxTextures:c,maxVertexTextures:h,maxTextureSize:l,maxCubemapSize:u,maxAttributes:p,maxVertexUniforms:d,maxVaryings:f,maxFragmentUniforms:m,vertexTextures:v,floatFragmentTextures:g,floatVertexTextures:v&&g}}function Ki(e,t,i,r){It.call(this),this.type="PerspectiveCamera",this.fov=void 0!==e?e:50,this.zoom=1,this.near=void 0!==i?i:.1,this.far=void 0!==r?r:2e3,this.focus=10,this.aspect=void 0!==t?t:1,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}function Qi(e){Ki.call(this),this.cameras=e||[]}function $i(e){var t=this,i=null,r=null,n=null;"undefined"!=typeof window&&"VRFrameData"in window&&(r=new window.VRFrameData);var o=new re,a=new Ki;a.bounds=new he(0,0,.5,1),a.layers.enable(1);var s=new Ki;s.bounds=new he(.5,0,.5,1),s.layers.enable(2);var c,h,l=new Qi([a,s]);function u(){if(null!==i&&i.isPresenting){var r=i.getEyeParameters("left"),n=r.renderWidth,o=r.renderHeight;h=e.getPixelRatio(),c=e.getSize(),e.setDrawingBufferSize(2*n,o,1)}else t.enabled&&e.setDrawingBufferSize(c.width,c.height,h)}l.layers.enable(1),l.layers.enable(2),"undefined"!=typeof window&&window.addEventListener("vrdisplaypresentchange",u,!1),this.enabled=!1,this.getDevice=function(){return i},this.setDevice=function(e){void 0!==e&&(i=e)},this.setPoseTarget=function(e){void 0!==e&&(n=e)},this.getCamera=function(e){if(null===i)return e;i.depthNear=e.near,i.depthFar=e.far,i.getFrameData(r);var t=r.pose,c=null!==n?n:e;if(null!==t.position?c.position.fromArray(t.position):c.position.set(0,0,0),null!==t.orientation&&c.quaternion.fromArray(t.orientation),c.updateMatrixWorld(),!1===i.isPresenting)return e;a.near=e.near,s.near=e.near,a.far=e.far,s.far=e.far,l.matrixWorld.copy(e.matrixWorld),l.matrixWorldInverse.copy(e.matrixWorldInverse),a.matrixWorldInverse.fromArray(r.leftViewMatrix),s.matrixWorldInverse.fromArray(r.rightViewMatrix);var h=c.parent;null!==h&&(o.getInverse(h.matrixWorld),a.matrixWorldInverse.multiply(o),s.matrixWorldInverse.multiply(o)),a.matrixWorld.getInverse(a.matrixWorldInverse),s.matrixWorld.getInverse(s.matrixWorldInverse),a.projectionMatrix.fromArray(r.leftProjectionMatrix),s.projectionMatrix.fromArray(r.rightProjectionMatrix),l.projectionMatrix.copy(a.projectionMatrix);var u=i.getLayers();if(u.length){var p=u[0];null!==p.leftBounds&&4===p.leftBounds.length&&a.bounds.fromArray(p.leftBounds),null!==p.rightBounds&&4===p.rightBounds.length&&s.bounds.fromArray(p.rightBounds)}return l},this.submitFrame=function(){i&&i.isPresenting&&i.submitFrame()},this.dispose=function(){"undefined"!=typeof window&&window.removeEventListener("vrdisplaypresentchange",u)}}function er(e){var t={};return{get:function(i){if(void 0!==t[i])return t[i];var r;switch(i){case"WEBGL_depth_texture":r=e.getExtension("WEBGL_depth_texture")||e.getExtension("MOZ_WEBGL_depth_texture")||e.getExtension("WEBKIT_WEBGL_depth_texture");break;case"EXT_texture_filter_anisotropic":r=e.getExtension("EXT_texture_filter_anisotropic")||e.getExtension("MOZ_EXT_texture_filter_anisotropic")||e.getExtension("WEBKIT_EXT_texture_filter_anisotropic");break;case"WEBGL_compressed_texture_s3tc":r=e.getExtension("WEBGL_compressed_texture_s3tc")||e.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");break;case"WEBGL_compressed_texture_pvrtc":r=e.getExtension("WEBGL_compressed_texture_pvrtc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");break;case"WEBGL_compressed_texture_etc1":r=e.getExtension("WEBGL_compressed_texture_etc1");break;default:r=e.getExtension(i)}return null===r&&console.warn("THREE.WebGLRenderer: "+i+" extension not supported."),t[i]=r,r}}}function tr(){var e=this,t=null,i=0,r=!1,n=!1,o=new _t,a=new ae,s={value:null,needsUpdate:!1};function c(){s.value!==t&&(s.value=t,s.needsUpdate=i>0),e.numPlanes=i,e.numIntersection=0}function h(t,i,r,n){var c=null!==t?t.length:0,h=null;if(0!==c){if(h=s.value,!0!==n||null===h){var l=r+4*c,u=i.matrixWorldInverse;a.getNormalMatrix(u),(null===h||h.length=0){var h=n[s];if(void 0!==h){var l=h.normalized,u=h.itemSize,p=w.get(h);if(void 0===p)continue;var d=p.buffer,f=p.type,g=p.bytesPerElement;if(h.isInterleavedBufferAttribute){var x=h.data,b=x.stride,_=h.offset;x&&x.isInstancedInterleavedBuffer?(y.enableAttributeAndDivisor(c,x.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=x.meshPerAttribute*x.count)):y.enableAttribute(c),m.bindBuffer(m.ARRAY_BUFFER,d),m.vertexAttribPointer(c,u,f,l,b*g,(r*b+_)*g)}else h.isInstancedBufferAttribute?(y.enableAttributeAndDivisor(c,h.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=h.meshPerAttribute*h.count)):y.enableAttribute(c),m.bindBuffer(m.ARRAY_BUFFER,d),m.vertexAttribPointer(c,u,f,l,0,r*u*g)}else if(void 0!==a){var M=a[s];if(void 0!==M)switch(M.length){case 2:m.vertexAttrib2fv(c,M);break;case 3:m.vertexAttrib3fv(c,M);break;case 4:m.vertexAttrib4fv(c,M);break;default:m.vertexAttrib1fv(c,M)}}}}y.disableUnusedAttributes()}(r,s,i),null!==u&&m.bindBuffer(m.ELEMENT_ARRAY_BUFFER,l.buffer));var g=0;null!==u?g=u.count:void 0!==p&&(g=p.count);var x=i.drawRange.start*d,b=i.drawRange.count*d,M=null!==o?o.start*d:0,E=null!==o?o.count*d:1/0,T=Math.max(x,M),S=Math.min(g,x+b,M+E)-1,A=Math.max(0,S-T+1);if(0!==A){if(n.isMesh)if(!0===r.wireframe)y.setLineWidth(r.wireframeLinewidth*me()),f.setMode(m.LINES);else switch(n.drawMode){case 0:f.setMode(m.TRIANGLES);break;case 1:f.setMode(m.TRIANGLE_STRIP);break;case 2:f.setMode(m.TRIANGLE_FAN)}else if(n.isLine){var R=r.linewidth;void 0===R&&(R=1),y.setLineWidth(R*me()),n.isLineSegments?f.setMode(m.LINES):n.isLineLoop?f.setMode(m.LINE_LOOP):f.setMode(m.LINE_STRIP)}else n.isPoints&&f.setMode(m.POINTS);i&&i.isInstancedBufferGeometry?i.maxInstancedCount>0&&f.renderInstances(i,T,A):f.render(T,A)}},this.compile=function(e,t){l.length=0,u.length=0,e.traverse((function(e){e.isLight&&(l.push(e),e.castShadow&&u.push(e))})),E.setup(l,u,t),e.traverse((function(t){if(t.material)if(Array.isArray(t.material))for(var i=0;i=0&&e.numSupportedMorphTargets++}if(e.morphNormals){e.numSupportedMorphNormals=0;for(l=0;l=0&&e.numSupportedMorphNormals++}var p=r.shader.uniforms;(e.isShaderMaterial||e.isRawShaderMaterial)&&!0!==e.clipping||(r.numClippingPlanes=ae.numPlanes,r.numIntersection=ae.numIntersection,p.clippingPlanes=ae.uniform),r.fog=t,r.lightsHash=E.state.hash,e.lights&&(p.ambientLightColor.value=E.state.ambient,p.directionalLights.value=E.state.directional,p.spotLights.value=E.state.spot,p.rectAreaLights.value=E.state.rectArea,p.pointLights.value=E.state.point,p.hemisphereLights.value=E.state.hemi,p.directionalShadowMap.value=E.state.directionalShadowMap,p.directionalShadowMatrix.value=E.state.directionalShadowMatrix,p.spotShadowMap.value=E.state.spotShadowMap,p.spotShadowMatrix.value=E.state.spotShadowMatrix,p.pointShadowMap.value=E.state.pointShadowMap,p.pointShadowMatrix.value=E.state.pointShadowMatrix);var d=r.program.getUniforms(),f=Qe.seqWithValue(d.seq,p);r.uniformsList=f}function Ne(e,t,i,r){Z=0;var n=x.get(i);if(se&&(ce||e!==H)){var o=e===H&&i.id===V;ae.setState(i.clippingPlanes,i.clipIntersection,i.clipShadows,e,n,o)}!1===i.needsUpdate&&(void 0===n.program||i.fog&&n.fog!==t||i.lights&&n.lightsHash!==E.state.hash?i.needsUpdate=!0:void 0===n.numClippingPlanes||n.numClippingPlanes===ae.numPlanes&&n.numIntersection===ae.numIntersection||(i.needsUpdate=!0)),i.needsUpdate&&(Pe(i,t,r),i.needsUpdate=!1);var a=!1,s=!1,c=!1,h=n.program,l=h.getUniforms(),u=n.shader.uniforms;if(y.useProgram(h.program)&&(a=!0,s=!0,c=!0),i.id!==V&&(V=i.id,s=!0),a||e!==H){if(l.setValue(m,"projectionMatrix",e.projectionMatrix),g.logarithmicDepthBuffer&&l.setValue(m,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),H!==(W||e)&&(H=W||e,s=!0,c=!0),i.isShaderMaterial||i.isMeshPhongMaterial||i.isMeshStandardMaterial||i.envMap){var p=l.map.cameraPosition;void 0!==p&&p.setValue(m,ue.setFromMatrixPosition(e.matrixWorld))}(i.isMeshPhongMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial||i.skinning)&&l.setValue(m,"viewMatrix",e.matrixWorldInverse)}if(i.skinning){l.setOptional(m,r,"bindMatrix"),l.setOptional(m,r,"bindMatrixInverse");var d=r.skeleton;if(d){var f=d.bones;if(g.floatVertexTextures){if(void 0===d.boneTexture){var v=Math.sqrt(4*f.length);v=te.ceilPowerOfTwo(v),v=Math.max(v,4);var b=new Float32Array(v*v*4);b.set(d.boneMatrices);var w=new pe(b,v,v,U,N);d.boneMatrices=b,d.boneTexture=w,d.boneTextureSize=v}l.setValue(m,"boneTexture",d.boneTexture),l.setValue(m,"boneTextureSize",d.boneTextureSize)}else l.setOptional(m,d,"boneMatrices")}}return s&&(l.setValue(m,"toneMappingExposure",B.toneMappingExposure),l.setValue(m,"toneMappingWhitePoint",B.toneMappingWhitePoint),i.lights&&function(e,t){e.ambientLightColor.needsUpdate=t,e.directionalLights.needsUpdate=t,e.pointLights.needsUpdate=t,e.spotLights.needsUpdate=t,e.rectAreaLights.needsUpdate=t,e.hemisphereLights.needsUpdate=t}(u,c),t&&i.fog&&function(e,t){e.fogColor.value=t.color,t.isFog?(e.fogNear.value=t.near,e.fogFar.value=t.far):t.isFogExp2&&(e.fogDensity.value=t.density)}(u,t),i.isMeshBasicMaterial?Oe(u,i):i.isMeshLambertMaterial?(Oe(u,i),function(e,t){t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap)}(u,i)):i.isMeshPhongMaterial?(Oe(u,i),i.isMeshToonMaterial?function(e,t){Ie(e,t),t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(u,i):Ie(u,i)):i.isMeshStandardMaterial?(Oe(u,i),i.isMeshPhysicalMaterial?function(e,t){e.clearCoat.value=t.clearCoat,e.clearCoatRoughness.value=t.clearCoatRoughness,De(e,t)}(u,i):De(u,i)):i.isMeshDepthMaterial?(Oe(u,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(u,i)):i.isMeshDistanceMaterial?(Oe(u,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias);e.referencePosition.value.copy(t.referencePosition),e.nearDistance.value=t.nearDistance,e.farDistance.value=t.farDistance}(u,i)):i.isMeshNormalMaterial?(Oe(u,i),function(e,t){t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale);t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale));t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(u,i)):i.isLineBasicMaterial?(function(e,t){e.diffuse.value=t.color,e.opacity.value=t.opacity}(u,i),i.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(u,i)):i.isPointsMaterial?function(e,t){if(e.diffuse.value=t.color,e.opacity.value=t.opacity,e.size.value=t.size*Q,e.scale.value=.5*K,e.map.value=t.map,null!==t.map){if(!0===t.map.matrixAutoUpdate){var i=t.map.offset,r=t.map.repeat,n=t.map.rotation,o=t.map.center;t.map.matrix.setUvTransform(i.x,i.y,r.x,r.y,n,o.x,o.y)}e.uvTransform.value.copy(t.map.matrix)}}(u,i):i.isShadowMaterial&&(u.color.value=i.color,u.opacity.value=i.opacity),void 0!==u.ltcMat&&(u.ltcMat.value=tt.LTC_MAT_TEXTURE),void 0!==u.ltcMag&&(u.ltcMag.value=tt.LTC_MAG_TEXTURE),Qe.upload(m,n.uniformsList,u,B)),l.setValue(m,"modelViewMatrix",r.modelViewMatrix),l.setValue(m,"normalMatrix",r.normalMatrix),l.setValue(m,"modelMatrix",r.matrixWorld),h}function Oe(e,t){var i;if(e.opacity.value=t.opacity,t.color&&(e.diffuse.value=t.color),t.emissive&&e.emissive.value.copy(t.emissive).multiplyScalar(t.emissiveIntensity),t.map&&(e.map.value=t.map),t.alphaMap&&(e.alphaMap.value=t.alphaMap),t.specularMap&&(e.specularMap.value=t.specularMap),t.envMap&&(e.envMap.value=t.envMap,e.flipEnvMap.value=t.envMap&&t.envMap.isCubeTexture?-1:1,e.reflectivity.value=t.reflectivity,e.refractionRatio.value=t.refractionRatio),t.lightMap&&(e.lightMap.value=t.lightMap,e.lightMapIntensity.value=t.lightMapIntensity),t.aoMap&&(e.aoMap.value=t.aoMap,e.aoMapIntensity.value=t.aoMapIntensity),t.map?i=t.map:t.specularMap?i=t.specularMap:t.displacementMap?i=t.displacementMap:t.normalMap?i=t.normalMap:t.bumpMap?i=t.bumpMap:t.roughnessMap?i=t.roughnessMap:t.metalnessMap?i=t.metalnessMap:t.alphaMap?i=t.alphaMap:t.emissiveMap&&(i=t.emissiveMap),void 0!==i){if(i.isWebGLRenderTarget&&(i=i.texture),!0===i.matrixAutoUpdate){var r=i.offset,n=i.repeat,o=i.rotation,a=i.center;i.matrix.setUvTransform(r.x,r.y,n.x,n.y,o,a.x,a.y)}e.uvTransform.value.copy(i.matrix)}}function Ie(e,t){e.specular.value=t.specular,e.shininess.value=Math.max(t.shininess,1e-4),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale)),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}function De(e,t){e.roughness.value=t.roughness,e.metalness.value=t.metalness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap),t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale)),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias),t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}this.animate=function(e){Se=e,function(){if(!Te){var e=ye.getDevice();e&&e.isPresenting?e.requestAnimationFrame(Ae):window.requestAnimationFrame(Ae),Te=!0}}()},this.render=function(e,t,i,r){if(t&&t.isCamera){if(!z){j="",V=-1,H=null,!0===e.autoUpdate&&e.updateMatrixWorld(),null===t.parent&&t.updateMatrixWorld(),ye.enabled&&(t=ye.getCamera(t)),le.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),ne.setFromMatrix(le),l.length=0,u.length=0,d.length=0,f.length=0,ce=this.localClippingEnabled,se=ae.init(this.clippingPlanes,ce,t),(p=S.get(e,t)).init(),Le(e,t,B.sortObjects),!0===B.sortObjects&&p.sort(),b.updateVideoTextures(),se&&ae.beginShadows(),xe.render(u,e,t),E.setup(l,u,t),se&&ae.endShadows(),fe.frame++,fe.calls=0,fe.vertices=0,fe.faces=0,fe.points=0,void 0===i&&(i=null),this.setRenderTarget(i),A.render(p,e,t,r);var n=p.opaque,o=p.transparent;if(e.overrideMaterial){var a=e.overrideMaterial;n.length&&Re(n,e,t,a),o.length&&Re(o,e,t,a)}else n.length&&Re(n,e,t),o.length&&Re(o,e,t);D.render(d,e,t),I.render(f,e,t,X),i&&b.updateRenderTargetMipmap(i),y.buffers.depth.setTest(!0),y.buffers.depth.setMask(!0),y.buffers.color.setMask(!0),y.setPolygonOffset(!1),ye.enabled&&ye.submitFrame()}}else console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.")},this.setFaceCulling=function(e,t){y.setCullFace(e),y.setFlipSided(0===t)},this.allocTextureUnit=function(){var e=Z;return e>=g.maxTextures&&console.warn("THREE.WebGLRenderer: Trying to use "+e+" texture units while this GPU supports only "+g.maxTextures),Z+=1,e},this.setTexture2D=(Ee=!1,function(e,t){e&&e.isWebGLRenderTarget&&(Ee||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),Ee=!0),e=e.texture),b.setTexture2D(e,t)}),this.setTexture=function(){var e=!1;return function(t,i){e||(console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead."),e=!0),b.setTexture2D(t,i)}}(),this.setTextureCube=function(){var e=!1;return function(t,i){t&&t.isWebGLRenderTargetCube&&(e||(console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead."),e=!0),t=t.texture),t&&t.isCubeTexture||Array.isArray(t.image)&&6===t.image.length?b.setTextureCube(t,i):b.setTextureCubeDynamic(t,i)}}(),this.getRenderTarget=function(){return k},this.setRenderTarget=function(e){k=e,e&&void 0===x.get(e).__webglFramebuffer&&b.setupRenderTarget(e);var t=null,i=!1;if(e){var r=x.get(e).__webglFramebuffer;e.isWebGLRenderTargetCube?(t=r[e.activeCubeFace],i=!0):t=r,X.copy(e.viewport),q.copy(e.scissor),Y=e.scissorTest}else X.copy($).multiplyScalar(Q),q.copy(ee).multiplyScalar(Q),Y=ie;if(G!==t&&(m.bindFramebuffer(m.FRAMEBUFFER,t),G=t),y.viewport(X),y.scissor(q),y.setScissorTest(Y),i){var n=x.get(e.texture);m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,m.TEXTURE_CUBE_MAP_POSITIVE_X+e.activeCubeFace,n.__webglTexture,e.activeMipMapLevel)}},this.readRenderTargetPixels=function(e,t,i,r,n,o){if(e&&e.isWebGLRenderTarget){var a=x.get(e).__webglFramebuffer;if(a){var s=!1;a!==G&&(m.bindFramebuffer(m.FRAMEBUFFER,a),s=!0);try{var c=e.texture,h=c.format,l=c.type;if(h!==U&&F.convert(h)!==m.getParameter(m.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!(l===R||F.convert(l)===m.getParameter(m.IMPLEMENTATION_COLOR_READ_TYPE)||l===N&&(v.get("OES_texture_float")||v.get("WEBGL_color_buffer_float"))||l===O&&v.get("EXT_color_buffer_half_float")))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");m.checkFramebufferStatus(m.FRAMEBUFFER)===m.FRAMEBUFFER_COMPLETE?t>=0&&t<=e.width-r&&i>=0&&i<=e.height-n&&m.readPixels(t,i,r,n,F.convert(h),F.convert(l),o):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{s&&m.bindFramebuffer(m.FRAMEBUFFER,G)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")}}function nr(e,t){this.name="",this.color=new et(e),this.density=void 0!==t?t:25e-5}function or(e,t,i){this.name="",this.color=new et(e),this.near=void 0!==t?t:1,this.far=void 0!==i?i:1e3}function ar(){Ot.call(this),this.type="Scene",this.background=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0}function sr(e,t,i,r,n){Ot.call(this),this.lensFlares=[],this.positionScreen=new oe,this.customUpdateCallback=void 0,void 0!==e&&this.add(e,t,i,r,n)}function cr(e){gt.call(this),this.type="SpriteMaterial",this.color=new et(16777215),this.map=null,this.rotation=0,this.fog=!1,this.lights=!1,this.setValues(e)}function hr(e){Ot.call(this),this.type="Sprite",this.material=void 0!==e?e:new cr}function lr(){Ot.call(this),this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function ur(e,t){if(e=e||[],this.bones=e.slice(0),this.boneMatrices=new Float32Array(16*this.bones.length),void 0===t)this.calculateInverses();else if(this.bones.length===t.length)this.boneInverses=t.slice(0);else{console.warn("THREE.Skeleton boneInverses is the wrong length."),this.boneInverses=[];for(var i=0,r=this.bones.length;i=0?(p=e(g-h,v,p),d.subVectors(u,p)):(p=e(g+h,v,p),d.subVectors(p,u)),v-h>=0?(p=e(g,v-h,p),f.subVectors(u,p)):(p=e(g,v+h,p),f.subVectors(p,u)),l.crossVectors(d,f).normalize(),s.push(l.x,l.y,l.z),c.push(g,v)}}for(r=0;r.9&&a<.1&&(t<.2&&(o[e+0]+=1),i<.2&&(o[e+2]+=1),r<.2&&(o[e+4]+=1))}}()}(),this.addAttribute("position",new Yt(n,3)),this.addAttribute("normal",new Yt(n.slice(),3)),this.addAttribute("uv",new Yt(o,2)),0===r?this.computeVertexNormals():this.normalizeNormals()}function Rr(e,t){zt.call(this),this.type="TetrahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Cr(e,t)),this.mergeVertices()}function Cr(e,t){Lr.call(this,[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],e,t),this.type="TetrahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Pr(e,t){zt.call(this),this.type="OctahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Nr(e,t)),this.mergeVertices()}function Nr(e,t){Lr.call(this,[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],e,t),this.type="OctahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Or(e,t){zt.call(this),this.type="IcosahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Ir(e,t)),this.mergeVertices()}function Ir(e,t){var i=(1+Math.sqrt(5))/2,r=[-1,i,0,1,i,0,-1,-i,0,1,-i,0,0,-1,i,0,1,i,0,-1,-i,0,1,-i,i,0,-1,i,0,1,-i,0,-1,-i,0,1];Lr.call(this,r,[0,11,5,0,5,1,0,1,7,0,7,10,0,10,11,1,5,9,5,11,4,11,10,2,10,7,6,7,1,8,3,9,4,3,4,2,3,2,6,3,6,8,3,8,9,4,9,5,2,4,11,6,2,10,8,6,7,9,8,1],e,t),this.type="IcosahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Dr(e,t){zt.call(this),this.type="DodecahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Ur(e,t)),this.mergeVertices()}function Ur(e,t){var i=(1+Math.sqrt(5))/2,r=1/i,n=[-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-r,-i,0,-r,i,0,r,-i,0,r,i,-r,-i,0,-r,i,0,r,-i,0,r,i,0,-i,0,-r,i,0,-r,-i,0,r,i,0,r];Lr.call(this,n,[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],e,t),this.type="DodecahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Fr(e,t,i,r,n,o){zt.call(this),this.type="TubeGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},void 0!==o&&console.warn("THREE.TubeGeometry: taper has been removed.");var a=new Br(e,t,i,r,n);this.tangents=a.tangents,this.normals=a.normals,this.binormals=a.binormals,this.fromBufferGeometry(a),this.mergeVertices()}function Br(e,t,i,r,n){ai.call(this),this.type="TubeBufferGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},t=t||64,i=i||1,r=r||8,n=n||!1;var o=e.computeFrenetFrames(t,n);this.tangents=o.tangents,this.normals=o.normals,this.binormals=o.binormals;var a,s,c=new oe,h=new oe,l=new ie,u=new oe,p=[],d=[],f=[],m=[];function v(n){u=e.getPointAt(n/t,u);var a=o.normals[n],l=o.binormals[n];for(s=0;s<=r;s++){var f=s/r*Math.PI*2,m=Math.sin(f),v=-Math.cos(f);h.x=v*a.x+m*l.x,h.y=v*a.y+m*l.y,h.z=v*a.z+m*l.z,h.normalize(),d.push(h.x,h.y,h.z),c.x=u.x+i*h.x,c.y=u.y+i*h.y,c.z=u.z+i*h.z,p.push(c.x,c.y,c.z)}}!function(){for(a=0;ai)){var r=e.ray.origin.distanceTo(Pi);re.far||t.push({distance:r,point:Pi.clone(),face:null,object:this})}}),clone:function(){return new this.constructor(this.material).copy(this)}}),lr.prototype=Object.assign(Object.create(Ot.prototype),{constructor:lr,copy:function(e){Ot.prototype.copy.call(this,e,!1);for(var t=e.levels,i=0,r=t.length;i1){e.setFromMatrixPosition(i.matrixWorld),t.setFromMatrixPosition(this.matrixWorld);var n=e.distanceTo(t);r[0].object.visible=!0;for(var o=1,a=r.length;o=r[o].distance;o++)r[o-1].object.visible=!1,r[o].object.visible=!0;for(;oa))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}else for(g=0,y=m.length/3-1;ga))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}else if(s.isGeometry){var w=s.vertices,_=w.length;for(g=0;g<_-1;g+=d){var M;if(!(t.distanceSqToSegment(w[g],w[g+1],p,u)>a))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),vr.prototype=Object.assign(Object.create(mr.prototype),{constructor:vr,isLineSegments:!0}),gr.prototype=Object.assign(Object.create(mr.prototype),{constructor:gr,isLineLoop:!0}),yr.prototype=Object.create(gt.prototype),yr.prototype.constructor=yr,yr.prototype.isPointsMaterial=!0,yr.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.color.copy(e.color),this.map=e.map,this.size=e.size,this.sizeAttenuation=e.sizeAttenuation,this},xr.prototype=Object.assign(Object.create(Ot.prototype),{constructor:xr,isPoints:!0,raycast:function(){var e=new re,t=new di,i=new wt;return function(r,n){var o=this,a=this.geometry,s=this.matrixWorld,c=r.params.Points.threshold;if(null===a.boundingSphere&&a.computeBoundingSphere(),i.copy(a.boundingSphere),i.applyMatrix4(s),i.radius+=c,!1!==r.ray.intersectsSphere(i)){e.getInverse(s),t.copy(r.ray).applyMatrix4(e);var h=c/((this.scale.x+this.scale.y+this.scale.z)/3),l=h*h,u=new oe;if(a.isBufferGeometry){var p=a.index,d=a.attributes.position.array;if(null!==p)for(var f=p.array,m=0,v=f.length;mr.far)return;n.push({distance:h,distanceToRay:Math.sqrt(a),point:c.clone(),index:i,face:null,object:o})}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),br.prototype=Object.assign(Object.create(Ot.prototype),{constructor:br,isGroup:!0}),wr.prototype=Object.assign(Object.create(ce.prototype),{constructor:wr,isVideoTexture:!0,update:function(){var e=this.image;e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}),_r.prototype=Object.create(ce.prototype),_r.prototype.constructor=_r,_r.prototype.isCompressedTexture=!0,Mr.prototype=Object.create(ce.prototype),Mr.prototype.constructor=Mr,Mr.prototype.isDepthTexture=!0,Er.prototype=Object.create(ai.prototype),Er.prototype.constructor=Er,Tr.prototype=Object.create(zt.prototype),Tr.prototype.constructor=Tr,Sr.prototype=Object.create(ai.prototype),Sr.prototype.constructor=Sr,Ar.prototype=Object.create(zt.prototype),Ar.prototype.constructor=Ar,Lr.prototype=Object.create(ai.prototype),Lr.prototype.constructor=Lr,Rr.prototype=Object.create(zt.prototype),Rr.prototype.constructor=Rr,Cr.prototype=Object.create(Lr.prototype),Cr.prototype.constructor=Cr,Pr.prototype=Object.create(zt.prototype),Pr.prototype.constructor=Pr,Nr.prototype=Object.create(Lr.prototype),Nr.prototype.constructor=Nr,Or.prototype=Object.create(zt.prototype),Or.prototype.constructor=Or,Ir.prototype=Object.create(Lr.prototype),Ir.prototype.constructor=Ir,Dr.prototype=Object.create(zt.prototype),Dr.prototype.constructor=Dr,Ur.prototype=Object.create(Lr.prototype),Ur.prototype.constructor=Ur,Fr.prototype=Object.create(zt.prototype),Fr.prototype.constructor=Fr,Br.prototype=Object.create(ai.prototype),Br.prototype.constructor=Br,zr.prototype=Object.create(zt.prototype),zr.prototype.constructor=zr,kr.prototype=Object.create(ai.prototype),kr.prototype.constructor=kr,Gr.prototype=Object.create(zt.prototype),Gr.prototype.constructor=Gr,Vr.prototype=Object.create(ai.prototype),Vr.prototype.constructor=Vr;var jr=function(e,t,i){i=i||2;var r,n,o,a,s,c,h,l=t&&t.length,u=l?t[0]*i:e.length,p=Hr(e,0,u,i,!0),d=[];if(!p)return d;if(l&&(p=function(e,t,i,r){var n,o,a,s=[];for(n=0,o=t.length;n80*i){r=o=e[0],n=a=e[1];for(var f=i;fo&&(o=s),c>a&&(a=c);h=0!==(h=Math.max(o-r,a-n))?1/h:0}return Xr(p,d,i,r,n,h),d};function Hr(e,t,i,r,n){var o,a;if(n===function(e,t,i,r){for(var n=0,o=t,a=i-r;o0)for(o=t;o=t;o-=r)a=hn(o,e[o],e[o+1],a);return a&&on(a,a.next)&&(ln(a),a=a.next),a}function Wr(e,t){if(!e)return e;t||(t=e);var i,r=e;do{if(i=!1,r.steiner||!on(r,r.next)&&0!==nn(r.prev,r,r.next))r=r.next;else{if(ln(r),(r=t=r.prev)===r.next)break;i=!0}}while(i||r!==t);return t}function Xr(e,t,i,r,n,o,a){if(e){!a&&o&&function(e,t,i,r){var n=e;do{null===n.z&&(n.z=$r(n.x,n.y,t,i,r)),n.prevZ=n.prev,n.nextZ=n.next,n=n.next}while(n!==e);n.prevZ.nextZ=null,n.prevZ=null,function(e){var t,i,r,n,o,a,s,c,h=1;do{for(i=e,e=null,o=null,a=0;i;){for(a++,r=i,s=0,t=0;t0||c>0&&r;)0!==s&&(0===c||!r||i.z<=r.z)?(n=i,i=i.nextZ,s--):(n=r,r=r.nextZ,c--),o?o.nextZ=n:e=n,n.prevZ=o,o=n;i=r}o.nextZ=null,h*=2}while(a>1)}(n)}(e,r,n,o);for(var s,c,h=e;e.prev!==e.next;)if(s=e.prev,c=e.next,o?Yr(e,r,n,o):qr(e))t.push(s.i/i),t.push(e.i/i),t.push(c.i/i),ln(e),e=c.next,h=c.next;else if((e=c)===h){a?1===a?Xr(e=Zr(e,t,i),t,i,r,n,o,2):2===a&&Jr(e,t,i,r,n,o):Xr(Wr(e),t,i,r,n,o,1);break}}}function qr(e){var t=e.prev,i=e,r=e.next;if(nn(t,i,r)>=0)return!1;for(var n=e.next.next;n!==e.prev;){if(tn(t.x,t.y,i.x,i.y,r.x,r.y,n.x,n.y)&&nn(n.prev,n,n.next)>=0)return!1;n=n.next}return!0}function Yr(e,t,i,r){var n=e.prev,o=e,a=e.next;if(nn(n,o,a)>=0)return!1;for(var s=n.xo.x?n.x>a.x?n.x:a.x:o.x>a.x?o.x:a.x,l=n.y>o.y?n.y>a.y?n.y:a.y:o.y>a.y?o.y:a.y,u=$r(s,c,t,i,r),p=$r(h,l,t,i,r),d=e.nextZ;d&&d.z<=p;){if(d!==e.prev&&d!==e.next&&tn(n.x,n.y,o.x,o.y,a.x,a.y,d.x,d.y)&&nn(d.prev,d,d.next)>=0)return!1;d=d.nextZ}for(d=e.prevZ;d&&d.z>=u;){if(d!==e.prev&&d!==e.next&&tn(n.x,n.y,o.x,o.y,a.x,a.y,d.x,d.y)&&nn(d.prev,d,d.next)>=0)return!1;d=d.prevZ}return!0}function Zr(e,t,i){var r=e;do{var n=r.prev,o=r.next.next;!on(n,o)&&an(n,r,r.next,o)&&sn(n,o)&&sn(o,n)&&(t.push(n.i/i),t.push(r.i/i),t.push(o.i/i),ln(r),ln(r.next),r=e=o),r=r.next}while(r!==e);return r}function Jr(e,t,i,r,n,o){var a=e;do{for(var s=a.next.next;s!==a.prev;){if(a.i!==s.i&&rn(a,s)){var c=cn(a,s);return a=Wr(a,a.next),c=Wr(c,c.next),Xr(a,t,i,r,n,o),void Xr(c,t,i,r,n,o)}s=s.next}a=a.next}while(a!==e)}function Kr(e,t){return e.x-t.x}function Qr(e,t){if(t=function(e,t){var i,r=t,n=e.x,o=e.y,a=-1/0;do{if(o<=r.y&&o>=r.next.y&&r.next.y!==r.y){var s=r.x+(o-r.y)*(r.next.x-r.x)/(r.next.y-r.y);if(s<=n&&s>a){if(a=s,s===n){if(o===r.y)return r;if(o===r.next.y)return r.next}i=r.x=r.x&&r.x>=l&&n!==r.x&&tn(oi.x)&&sn(r,e)&&(i=r,p=c),r=r.next;return i}(e,t),t){var i=cn(t,e);Wr(i,i.next)}}function $r(e,t,i,r,n){return(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*n)|e<<8))|e<<4))|e<<2))|e<<1))|(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*n)|t<<8))|t<<4))|t<<2))|t<<1))<<1}function en(e){var t=e,i=e;do{t.x=0&&(e-a)*(r-s)-(i-a)*(t-s)>=0&&(i-a)*(o-s)-(n-a)*(r-s)>=0}function rn(e,t){return e.next.i!==t.i&&e.prev.i!==t.i&&!function(e,t){var i=e;do{if(i.i!==e.i&&i.next.i!==e.i&&i.i!==t.i&&i.next.i!==t.i&&an(i,i.next,e,t))return!0;i=i.next}while(i!==e);return!1}(e,t)&&sn(e,t)&&sn(t,e)&&function(e,t){var i=e,r=!1,n=(e.x+t.x)/2,o=(e.y+t.y)/2;do{i.y>o!=i.next.y>o&&i.next.y!==i.y&&n<(i.next.x-i.x)*(o-i.y)/(i.next.y-i.y)+i.x&&(r=!r),i=i.next}while(i!==e);return r}(e,t)}function nn(e,t,i){return(t.y-e.y)*(i.x-t.x)-(t.x-e.x)*(i.y-t.y)}function on(e,t){return e.x===t.x&&e.y===t.y}function an(e,t,i,r){return!!(on(e,t)&&on(i,r)||on(e,r)&&on(i,t))||nn(e,t,i)>0!=nn(e,t,r)>0&&nn(i,r,e)>0!=nn(i,r,t)>0}function sn(e,t){return nn(e.prev,e,e.next)<0?nn(e,t,e.next)>=0&&nn(e,e.prev,t)>=0:nn(e,t,e.prev)<0||nn(e,e.next,t)<0}function cn(e,t){var i=new un(e.i,e.x,e.y),r=new un(t.i,t.x,t.y),n=e.next,o=t.prev;return e.next=t,t.prev=e,i.next=n,n.prev=i,r.next=i,i.prev=r,o.next=r,r.prev=o,r}function hn(e,t,i,r){var n=new un(e,t,i);return r?(n.next=r.next,n.prev=r,r.next.prev=n,r.next=n):(n.prev=n,n.next=n),n}function ln(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ)}function un(e,t,i){this.i=e,this.x=t,this.y=i,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}var pn={area:function(e){for(var t=e.length,i=0,r=t-1,n=0;n2&&e[t-1].equals(e[0])&&e.pop()}function r(e,t){for(var i=0;i0)&&f.push(w,_,E),(c!==i-1||h0&&g(!0),t>0&&g(!1)),this.setIndex(h),this.addAttribute("position",new Yt(l,3)),this.addAttribute("normal",new Yt(u,3)),this.addAttribute("uv",new Yt(p,2))}function Rn(e,t,i,r,n,o,a){An.call(this,0,e,t,i,r,n,o,a),this.type="ConeGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:o,thetaLength:a}}function Cn(e,t,i,r,n,o,a){Ln.call(this,0,e,t,i,r,n,o,a),this.type="ConeBufferGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:o,thetaLength:a}}function Pn(e,t,i,r){zt.call(this),this.type="CircleGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},this.fromBufferGeometry(new Nn(e,t,i,r)),this.mergeVertices()}function Nn(e,t,i,r){ai.call(this),this.type="CircleBufferGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},e=e||1,t=void 0!==t?Math.max(3,t):8,i=void 0!==i?i:0,r=void 0!==r?r:2*Math.PI;var n,o,a=[],s=[],c=[],h=[],l=new oe,u=new ie;for(s.push(0,0,0),c.push(0,0,1),h.push(.5,.5),o=0,n=3;o<=t;o++,n+=3){var p=i+o/t*r;l.x=e*Math.cos(p),l.y=e*Math.sin(p),s.push(l.x,l.y,l.z),c.push(0,0,1),u.x=(s[n]/e+1)/2,u.y=(s[n+1]/e+1)/2,h.push(u.x,u.y)}for(n=1;n<=t;n++)a.push(n,n+1,0);this.setIndex(a),this.addAttribute("position",new Yt(s,3)),this.addAttribute("normal",new Yt(c,3)),this.addAttribute("uv",new Yt(h,2))}dn.prototype=Object.create(zt.prototype),dn.prototype.constructor=dn,fn.prototype=Object.create(ai.prototype),fn.prototype.constructor=fn,fn.prototype.getArrays=function(){var e=this.getAttribute("position"),t=e?Array.prototype.slice.call(e.array):[],i=this.getAttribute("uv"),r=i?Array.prototype.slice.call(i.array):[],n=this.index;return{position:t,uv:r,index:n?Array.prototype.slice.call(n.array):[]}},fn.prototype.addShapeList=function(e,t){var i=e.length;t.arrays=this.getArrays();for(var r=0;rNumber.EPSILON){var p=Math.sqrt(l),d=Math.sqrt(c*c+h*h),f=t.x-s/p,m=t.y+a/p,v=((i.x-h/d-f)*h-(i.y+c/d-m)*c)/(a*h-s*c),g=(r=f+a*v-e.x)*r+(n=m+s*v-e.y)*n;if(g<=2)return new ie(r,n);o=Math.sqrt(g/2)}else{var y=!1;a>Number.EPSILON?c>Number.EPSILON&&(y=!0):a<-Number.EPSILON?c<-Number.EPSILON&&(y=!0):Math.sign(s)===Math.sign(h)&&(y=!0),y?(r=-s,n=a,o=Math.sqrt(l)):(r=a,n=s,o=Math.sqrt(l/2))}return new ie(r/o,n/o)}for(var G=[],V=0,j=C.length,H=j-1,W=V+1;V=0;N--){for(I=N/y,D=v*Math.cos(I*Math.PI/2),O=g*Math.sin(I*Math.PI/2),V=0,j=C.length;V=0;){i=V,(r=V-1)<0&&(r=e.length-1);var n=0,o=w+2*y;for(n=0;n0||0===e.search(/^data\:image\/jpeg/);n.format=r?D:U,n.needsUpdate=!0,void 0!==t&&t(n)}),i,r),n},setCrossOrigin:function(e){return this.crossOrigin=e,this},setPath:function(e){return this.path=e,this}}),Object.assign(eo.prototype,{getPoint:function(){return console.warn("THREE.Curve: .getPoint() not implemented."),null},getPointAt:function(e,t){var i=this.getUtoTmapping(e);return this.getPoint(i,t)},getPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPoint(i/e));return t},getSpacedPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPointAt(i/e));return t},getLength:function(){var e=this.getLengths();return e[e.length-1]},getLengths:function(e){if(void 0===e&&(e=this.arcLengthDivisions),this.cacheArcLengths&&this.cacheArcLengths.length===e+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var t,i,r=[],n=this.getPoint(0),o=0;for(r.push(0),i=1;i<=e;i++)o+=(t=this.getPoint(i/e)).distanceTo(n),r.push(o),n=t;return this.cacheArcLengths=r,r},updateArcLengths:function(){this.needsUpdate=!0,this.getLengths()},getUtoTmapping:function(e,t){var i,r=this.getLengths(),n=0,o=r.length;i=t||e*r[o-1];for(var a,s=0,c=o-1;s<=c;)if((a=r[n=Math.floor(s+(c-s)/2)]-i)<0)s=n+1;else{if(!(a>0)){c=n;break}c=n-1}if(r[n=c]===i)return n/(o-1);var h=r[n];return(n+(i-h)/(r[n+1]-h))/(o-1)},getTangent:function(e){var t=1e-4,i=e-t,r=e+t;i<0&&(i=0),r>1&&(r=1);var n=this.getPoint(i);return this.getPoint(r).clone().sub(n).normalize()},getTangentAt:function(e){var t=this.getUtoTmapping(e);return this.getTangent(t)},computeFrenetFrames:function(e,t){var i,r,n,o=new oe,a=[],s=[],c=[],h=new oe,l=new re;for(i=0;i<=e;i++)r=i/e,a[i]=this.getTangentAt(r),a[i].normalize();s[0]=new oe,c[0]=new oe;var u=Number.MAX_VALUE,p=Math.abs(a[0].x),d=Math.abs(a[0].y),f=Math.abs(a[0].z);for(p<=u&&(u=p,o.set(1,0,0)),d<=u&&(u=d,o.set(0,1,0)),f<=u&&o.set(0,0,1),h.crossVectors(a[0],o).normalize(),s[0].crossVectors(a[0],h),c[0].crossVectors(a[0],s[0]),i=1;i<=e;i++)s[i]=s[i-1].clone(),c[i]=c[i-1].clone(),h.crossVectors(a[i-1],a[i]),h.length()>Number.EPSILON&&(h.normalize(),n=Math.acos(te.clamp(a[i-1].dot(a[i]),-1,1)),s[i].applyMatrix4(l.makeRotationAxis(h,n))),c[i].crossVectors(a[i],s[i]);if(!0===t)for(n=Math.acos(te.clamp(s[0].dot(s[e]),-1,1)),n/=e,a[0].dot(h.crossVectors(s[0],s[e]))>0&&(n=-n),i=1;i<=e;i++)s[i].applyMatrix4(l.makeRotationAxis(a[i],n*i)),c[i].crossVectors(a[i],s[i]);return{tangents:a,normals:s,binormals:c}},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this},toJSON:function(){var e={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e},fromJSON:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}}),to.prototype=Object.create(eo.prototype),to.prototype.constructor=to,to.prototype.isEllipseCurve=!0,to.prototype.getPoint=function(e,t){for(var i=t||new ie,r=2*Math.PI,n=this.aEndAngle-this.aStartAngle,o=Math.abs(n)r;)n-=r;n0?0:(Math.floor(Math.abs(l)/s.length)+1)*s.length:0===u&&l===c-1&&(l=c-2,u=1),this.closed||l>0?i=s[(l-1)%c]:(no.subVectors(s[0],s[1]).add(s[0]),i=no),r=s[l%c],n=s[(l+1)%c],this.closed||l+2r.length-2?r.length-1:o+1],l=r[o>r.length-3?r.length-1:o+2];return i.set(ho(a,s.x,c.x,h.x,l.x),ho(a,s.y,c.y,h.y,l.y)),i},xo.prototype.copy=function(e){eo.prototype.copy.call(this,e),this.points=[];for(var t=0,i=e.points.length;t=t){var n=i[r]-t,o=this.curves[r],a=o.getLength(),s=0===a?0:1-n/a;return o.getPointAt(s)}r++}return null},getLength:function(){var e=this.getCurveLengths();return e[e.length-1]},updateArcLengths:function(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var e=[],t=0,i=0,r=this.curves.length;i1&&!i[i.length-1].equals(i[0])&&i.push(i[0]),i},copy:function(e){eo.prototype.copy.call(this,e),this.curves=[];for(var t=0,i=e.curves.length;t0){var h=c.getPoint(0);h.equals(this.currentPoint)||this.lineTo(h.x,h.y)}this.curves.push(c);var l=c.getPoint(1);this.currentPoint.copy(l)},copy:function(e){return wo.prototype.copy.call(this,e),this.currentPoint.copy(e.currentPoint),this},toJSON:function(){var e=wo.prototype.toJSON.call(this);return e.currentPoint=this.currentPoint.toArray(),e},fromJSON:function(e){return wo.prototype.fromJSON.call(this,e),this.currentPoint.fromArray(e.currentPoint),this}}),Mo.prototype=Object.assign(Object.create(_o.prototype),{constructor:Mo,getPointsHoles:function(e){for(var t=[],i=0,r=this.holes.length;i=n)break e;var s=t[1];e=(n=t[--i-1]))break t}o=i,i=0}for(;i>>1;e0?1:+e}),"name"in Function.prototype==!1&&Object.defineProperty(Function.prototype,"name",{get:function(){return this.toString().match(/^\s*function\s*([^\(\s]*)/)[1]}}),void 0===Object.assign&&(Object.assign=function(e){if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),i=1;i>8&255]+e[t>>16&255]+e[t>>24&255]+"-"+e[255&i]+e[i>>8&255]+"-"+e[i>>16&15|64]+e[i>>24&255]+"-"+e[63&r|128]+e[r>>8&255]+"-"+e[r>>16&255]+e[r>>24&255]+e[255&n]+e[n>>8&255]+e[n>>16&255]+e[n>>24&255]}}(),clamp:function(e,t,i){return Math.max(t,Math.min(i,e))},euclideanModulo:function(e,t){return(e%t+t)%t},mapLinear:function(e,t,i,r,n){return r+(e-t)*(n-r)/(i-t)},lerp:function(e,t,i){return(1-i)*e+i*t},smoothstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-t))*e*(3-2*e)},smootherstep:function(e,t,i){return e<=t?0:e>=i?1:(e=(e-t)/(i-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*te.DEG2RAD},radToDeg:function(e){return e*te.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))}};function ie(e,t){this.x=e||0,this.y=t||0}function re(){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.")}function ne(e,t,i,r){this._x=e||0,this._y=t||0,this._z=i||0,this._w=void 0!==r?r:1}function oe(e,t,i){this.x=e||0,this.y=t||0,this.z=i||0}function ae(){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(ie.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(ie.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,i=this.y,r=e.elements;return this.x=r[0]*t+r[3]*i+r[6],this.y=r[1]*t+r[4]*i+r[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:(o=new ie,a=new ie,function(e,t){return o.set(e,e),a.set(t,t),this.clamp(o,a)}),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},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},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(){var e=Math.atan2(this.y,this.x);return e<0&&(e+=2*Math.PI),e},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y;return t*t+i*i},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,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},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,i){return void 0!==i&&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 i=Math.cos(t),r=Math.sin(t),n=this.x-e.x,o=this.y-e.y;return this.x=n*i-o*r+e.x,this.y=n*r+o*i+e.y,this}}),Object.assign(re.prototype,{isMatrix4:!0,set:function(e,t,i,r,n,o,a,s,c,h,l,u,p,d,f,m){var v=this.elements;return v[0]=e,v[4]=t,v[8]=i,v[12]=r,v[1]=n,v[5]=o,v[9]=a,v[13]=s,v[2]=c,v[6]=h,v[10]=l,v[14]=u,v[3]=p,v[7]=d,v[11]=f,v[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 re).fromArray(this.elements)},copy:function(e){var t=this.elements,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],t[9]=i[9],t[10]=i[10],t[11]=i[11],t[12]=i[12],t[13]=i[13],t[14]=i[14],t[15]=i[15],this},copyPosition:function(e){var t=this.elements,i=e.elements;return t[12]=i[12],t[13]=i[13],t[14]=i[14],this},extractBasis:function(e,t,i){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),i.setFromMatrixColumn(this,2),this},makeBasis:function(e,t,i){return this.set(e.x,t.x,i.x,0,e.y,t.y,i.y,0,e.z,t.z,i.z,0,0,0,0,1),this},extractRotation:(p=new oe,function(e){var t=this.elements,i=e.elements,r=1/p.setFromMatrixColumn(e,0).length(),n=1/p.setFromMatrixColumn(e,1).length(),o=1/p.setFromMatrixColumn(e,2).length();return t[0]=i[0]*r,t[1]=i[1]*r,t[2]=i[2]*r,t[4]=i[4]*n,t[5]=i[5]*n,t[6]=i[6]*n,t[8]=i[8]*o,t[9]=i[9]*o,t[10]=i[10]*o,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,i=e.x,r=e.y,n=e.z,o=Math.cos(i),a=Math.sin(i),s=Math.cos(r),c=Math.sin(r),h=Math.cos(n),l=Math.sin(n);if("XYZ"===e.order){var u=o*h,p=o*l,d=a*h,f=a*l;t[0]=s*h,t[4]=-s*l,t[8]=c,t[1]=p+d*c,t[5]=u-f*c,t[9]=-a*s,t[2]=f-u*c,t[6]=d+p*c,t[10]=o*s}else if("YXZ"===e.order){var m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m+y*a,t[4]=g*a-v,t[8]=o*c,t[1]=o*l,t[5]=o*h,t[9]=-a,t[2]=v*a-g,t[6]=y+m*a,t[10]=o*s}else if("ZXY"===e.order){m=s*h,v=s*l,g=c*h,y=c*l;t[0]=m-y*a,t[4]=-o*l,t[8]=g+v*a,t[1]=v+g*a,t[5]=o*h,t[9]=y-m*a,t[2]=-o*c,t[6]=a,t[10]=o*s}else if("ZYX"===e.order){u=o*h,p=o*l,d=a*h,f=a*l;t[0]=s*h,t[4]=d*c-p,t[8]=u*c+f,t[1]=s*l,t[5]=f*c+u,t[9]=p*c-d,t[2]=-c,t[6]=a*s,t[10]=o*s}else if("YZX"===e.order){var x=o*s,b=o*c,w=a*s,_=a*c;t[0]=s*h,t[4]=_-x*l,t[8]=w*l+b,t[1]=l,t[5]=o*h,t[9]=-a*h,t[2]=-c*h,t[6]=b*l+w,t[10]=x-_*l}else if("XZY"===e.order){x=o*s,b=o*c,w=a*s,_=a*c;t[0]=s*h,t[4]=-l,t[8]=c*h,t[1]=x*l+_,t[5]=o*h,t[9]=b*l-w,t[2]=w*l-b,t[6]=a*h,t[10]=_*l+x}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){var t=this.elements,i=e._x,r=e._y,n=e._z,o=e._w,a=i+i,s=r+r,c=n+n,h=i*a,l=i*s,u=i*c,p=r*s,d=r*c,f=n*c,m=o*a,v=o*s,g=o*c;return t[0]=1-(p+f),t[4]=l-g,t[8]=u+v,t[1]=l+g,t[5]=1-(h+f),t[9]=d-m,t[2]=u-v,t[6]=d+m,t[10]=1-(h+p),t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this},lookAt:(h=new oe,l=new oe,u=new oe,function(e,t,i){var r=this.elements;return u.subVectors(e,t),0===u.lengthSq()&&(u.z=1),u.normalize(),h.crossVectors(i,u),0===h.lengthSq()&&(1===Math.abs(i.z)?u.x+=1e-4:u.z+=1e-4,u.normalize(),h.crossVectors(i,u)),h.normalize(),l.crossVectors(u,h),r[0]=h.x,r[4]=l.x,r[8]=u.x,r[1]=h.y,r[5]=l.y,r[9]=u.y,r[2]=h.z,r[6]=l.z,r[10]=u.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 i=e.elements,r=t.elements,n=this.elements,o=i[0],a=i[4],s=i[8],c=i[12],h=i[1],l=i[5],u=i[9],p=i[13],d=i[2],f=i[6],m=i[10],v=i[14],g=i[3],y=i[7],x=i[11],b=i[15],w=r[0],_=r[4],M=r[8],E=r[12],T=r[1],S=r[5],A=r[9],L=r[13],R=r[2],C=r[6],P=r[10],N=r[14],O=r[3],I=r[7],D=r[11],U=r[15];return n[0]=o*w+a*T+s*R+c*O,n[4]=o*_+a*S+s*C+c*I,n[8]=o*M+a*A+s*P+c*D,n[12]=o*E+a*L+s*N+c*U,n[1]=h*w+l*T+u*R+p*O,n[5]=h*_+l*S+u*C+p*I,n[9]=h*M+l*A+u*P+p*D,n[13]=h*E+l*L+u*N+p*U,n[2]=d*w+f*T+m*R+v*O,n[6]=d*_+f*S+m*C+v*I,n[10]=d*M+f*A+m*P+v*D,n[14]=d*E+f*L+m*N+v*U,n[3]=g*w+y*T+x*R+b*O,n[7]=g*_+y*S+x*C+b*I,n[11]=g*M+y*A+x*P+b*D,n[15]=g*E+y*L+x*N+b*U,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},applyToBufferAttribute:function(){var e=new oe;return function(t){for(var i=0,r=t.count;i=0?1:-1,y=1-v*v;if(y>Number.EPSILON){var x=Math.sqrt(y),b=Math.atan2(x,v*g);m=Math.sin(m*b)/x,a=Math.sin(a*b)/x}var w=a*g;if(s=s*m+u*w,c=c*m+p*w,h=h*m+d*w,l=l*m+f*w,m===1-a){var _=1/Math.sqrt(s*s+c*c+h*h+l*l);s*=_,c*=_,h*=_,l*=_}}e[t]=s,e[t+1]=c,e[t+2]=h,e[t+3]=l}}),Object.defineProperties(ne.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(ne.prototype,{set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._w=r,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 i=e._x,r=e._y,n=e._z,o=e.order,a=Math.cos,s=Math.sin,c=a(i/2),h=a(r/2),l=a(n/2),u=s(i/2),p=s(r/2),d=s(n/2);return"XYZ"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"YXZ"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"ZXY"===o?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l-u*p*d):"ZYX"===o?(this._x=u*h*l-c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l+u*p*d):"YZX"===o?(this._x=u*h*l+c*p*d,this._y=c*p*l+u*h*d,this._z=c*h*d-u*p*l,this._w=c*h*l-u*p*d):"XZY"===o&&(this._x=u*h*l-c*p*d,this._y=c*p*l-u*h*d,this._z=c*h*d+u*p*l,this._w=c*h*l+u*p*d),!1!==t&&this.onChangeCallback(),this},setFromAxisAngle:function(e,t){var i=t/2,r=Math.sin(i);return this._x=e.x*r,this._y=e.y*r,this._z=e.z*r,this._w=Math.cos(i),this.onChangeCallback(),this},setFromRotationMatrix:function(e){var t,i=e.elements,r=i[0],n=i[4],o=i[8],a=i[1],s=i[5],c=i[9],h=i[2],l=i[6],u=i[10],p=r+s+u;return p>0?(t=.5/Math.sqrt(p+1),this._w=.25/t,this._x=(l-c)*t,this._y=(o-h)*t,this._z=(a-n)*t):r>s&&r>u?(t=2*Math.sqrt(1+r-s-u),this._w=(l-c)/t,this._x=.25*t,this._y=(n+a)/t,this._z=(o+h)/t):s>u?(t=2*Math.sqrt(1+s-r-u),this._w=(o-h)/t,this._x=(n+a)/t,this._y=.25*t,this._z=(c+l)/t):(t=2*Math.sqrt(1+u-r-s),this._w=(a-n)/t,this._x=(o+h)/t,this._y=(c+l)/t,this._z=.25*t),this.onChangeCallback(),this},setFromUnitVectors:function(){var e,t=new oe;return function(i,r){return void 0===t&&(t=new oe),(e=i.dot(r)+1)<1e-6?(e=0,Math.abs(i.x)>Math.abs(i.z)?t.set(-i.y,i.x,0):t.set(0,-i.z,i.y)):t.crossVectors(i,r),this._x=t.x,this._y=t.y,this._z=t.z,this._w=e,this.normalize()}}(),inverse:function(){return this.conjugate().normalize()},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 i=e._x,r=e._y,n=e._z,o=e._w,a=t._x,s=t._y,c=t._z,h=t._w;return this._x=i*h+o*a+r*c-n*s,this._y=r*h+o*s+n*a-i*c,this._z=n*h+o*c+i*s-r*a,this._w=o*h-i*a-r*s-n*c,this.onChangeCallback(),this},slerp:function(e,t){if(0===t)return this;if(1===t)return this.copy(e);var i=this._x,r=this._y,n=this._z,o=this._w,a=o*e._w+i*e._x+r*e._y+n*e._z;if(a<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,a=-a):this.copy(e),a>=1)return this._w=o,this._x=i,this._y=r,this._z=n,this;var s=Math.sqrt(1-a*a);if(Math.abs(s)<.001)return this._w=.5*(o+this._w),this._x=.5*(i+this._x),this._y=.5*(r+this._y),this._z=.5*(n+this._z),this;var c=Math.atan2(s,a),h=Math.sin((1-t)*c)/s,l=Math.sin(t*c)/s;return this._w=o*h+this._w*l,this._x=i*h+this._x*l,this._y=r*h+this._y*l,this._z=n*h+this._z*l,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},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(oe.prototype,{isVector3:!0,set:function(e,t,i){return this.x=e,this.y=t,this.z=i,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:(d=new ne,function(e){return e&&e.isEuler||console.error("THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order."),this.applyQuaternion(d.setFromEuler(e))}),applyAxisAngle:function(){var e=new ne;return function(t,i){return this.applyQuaternion(e.setFromAxisAngle(t,i))}}(),applyMatrix3:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[3]*i+n[6]*r,this.y=n[1]*t+n[4]*i+n[7]*r,this.z=n[2]*t+n[5]*i+n[8]*r,this},applyMatrix4:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements,o=1/(n[3]*t+n[7]*i+n[11]*r+n[15]);return this.x=(n[0]*t+n[4]*i+n[8]*r+n[12])*o,this.y=(n[1]*t+n[5]*i+n[9]*r+n[13])*o,this.z=(n[2]*t+n[6]*i+n[10]*r+n[14])*o,this},applyQuaternion:function(e){var t=this.x,i=this.y,r=this.z,n=e.x,o=e.y,a=e.z,s=e.w,c=s*t+o*r-a*i,h=s*i+a*t-n*r,l=s*r+n*i-o*t,u=-n*t-o*i-a*r;return this.x=c*s+u*-n+h*-a-l*-o,this.y=h*s+u*-o+l*-n-c*-a,this.z=l*s+u*-a+c*-o-h*-n,this},project:function(){var e=new re;return function(t){return e.multiplyMatrices(t.projectionMatrix,e.getInverse(t.matrixWorld)),this.applyMatrix4(e)}}(),unproject:function(){var e=new re;return function(t){return e.multiplyMatrices(t.matrixWorld,e.getInverse(t.projectionMatrix)),this.applyMatrix4(e)}}(),transformDirection:function(e){var t=this.x,i=this.y,r=this.z,n=e.elements;return this.x=n[0]*t+n[4]*i+n[8]*r,this.y=n[1]*t+n[5]*i+n[9]*r,this.z=n[2]*t+n[6]*i+n[10]*r,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(){var e=new oe,t=new oe;return function(i,r){return e.set(i,i,i),t.set(r,r,r),this.clamp(e,t)}}(),clampLength:function(e,t){var i=this.length();return this.divideScalar(i||1).multiplyScalar(Math.max(e,Math.min(t,i)))},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,i){return this.subVectors(t,e).multiplyScalar(i).add(e)},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 i=e.x,r=e.y,n=e.z,o=t.x,a=t.y,s=t.z;return this.x=r*s-n*a,this.y=n*o-i*s,this.z=i*a-r*o,this},projectOnVector:function(e){var t=e.dot(this)/e.lengthSq();return this.copy(e).multiplyScalar(t)},projectOnPlane:function(){var e=new oe;return function(t){return e.copy(this).projectOnVector(t),this.sub(e)}}(),reflect:function(){var e=new oe;return function(t){return this.sub(e.copy(t).multiplyScalar(2*this.dot(t)))}}(),angleTo:function(e){var t=this.dot(e)/Math.sqrt(this.lengthSq()*e.lengthSq());return Math.acos(te.clamp(t,-1,1))},distanceTo:function(e){return Math.sqrt(this.distanceToSquared(e))},distanceToSquared:function(e){var t=this.x-e.x,i=this.y-e.y,r=this.z-e.z;return t*t+i*i+r*r},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){var t=Math.sin(e.phi)*e.radius;return this.x=t*Math.sin(e.theta),this.y=Math.cos(e.phi)*e.radius,this.z=t*Math.cos(e.theta),this},setFromCylindrical:function(e){return this.x=e.radius*Math.sin(e.theta),this.y=e.y,this.z=e.radius*Math.cos(e.theta),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(),i=this.setFromMatrixColumn(e,1).length(),r=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=i,this.z=r,this},setFromMatrixColumn:function(e,t){return this.fromArray(e.elements,4*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,i){return void 0!==i&&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}}),Object.assign(ae.prototype,{isMatrix3:!0,set:function(e,t,i,r,n,o,a,s,c){var h=this.elements;return h[0]=e,h[1]=r,h[2]=a,h[3]=t,h[4]=n,h[5]=s,h[6]=i,h[7]=o,h[8]=c,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,i=e.elements;return t[0]=i[0],t[1]=i[1],t[2]=i[2],t[3]=i[3],t[4]=i[4],t[5]=i[5],t[6]=i[6],t[7]=i[7],t[8]=i[8],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},applyToBufferAttribute:function(){var e=new oe;return function(t){for(var i=0,r=t.count;i2048||t.height>2048?t.toDataURL("image/jpeg",.6):t.toDataURL("image/png")}(r)}),i.image=r.uuid}return t||(e.textures[this.uuid]=i),i},dispose:function(){this.dispatchEvent({type:"dispose"})},transformUv:function(e){if(this.mapping===f){if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case b:e.x=e.x-Math.floor(e.x);break;case w:e.x=e.x<0?0:1;break;case _: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 b:e.y=e.y-Math.floor(e.y);break;case w:e.y=e.y<0?0:1;break;case _:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}this.flipY&&(e.y=1-e.y)}}}),Object.defineProperty(ce.prototype,"needsUpdate",{set:function(e){!0===e&&this.version++}}),Object.assign(he.prototype,{isVector4:!0,set:function(e,t,i,r){return this.x=e,this.y=t,this.z=i,this.w=r,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,i=this.y,r=this.z,n=this.w,o=e.elements;return this.x=o[0]*t+o[4]*i+o[8]*r+o[12]*n,this.y=o[1]*t+o[5]*i+o[9]*r+o[13]*n,this.z=o[2]*t+o[6]*i+o[10]*r+o[14]*n,this.w=o[3]*t+o[7]*i+o[11]*r+o[15]*n,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,i,r,n,o=.01,a=.1,s=e.elements,c=s[0],h=s[4],l=s[8],u=s[1],p=s[5],d=s[9],f=s[2],m=s[6],v=s[10];if(Math.abs(h-u)y&&g>x?gx?y0)return e;var n=t*i,o=ge[n];if(void 0===o&&(o=new Float32Array(n),ge[n]=o),0!==t){r.toArray(o,0);for(var a=1,s=0;a!==t;++a)s+=i,e[a].toArray(o,s)}return o}function _e(e,t){var i=ye[t];void 0===i&&(i=new Int32Array(t),ye[t]=i);for(var r=0;r!==t;++r)i[r]=e.allocTextureUnit();return i}function Me(e,t){e.uniform1f(this.addr,t)}function Ee(e,t){e.uniform1i(this.addr,t)}function Te(e,t){void 0===t.x?e.uniform2fv(this.addr,t):e.uniform2f(this.addr,t.x,t.y)}function Se(e,t){void 0!==t.x?e.uniform3f(this.addr,t.x,t.y,t.z):void 0!==t.r?e.uniform3f(this.addr,t.r,t.g,t.b):e.uniform3fv(this.addr,t)}function Ae(e,t){void 0===t.x?e.uniform4fv(this.addr,t):e.uniform4f(this.addr,t.x,t.y,t.z,t.w)}function Le(e,t){e.uniformMatrix2fv(this.addr,!1,t.elements||t)}function Re(e,t){void 0===t.elements?e.uniformMatrix3fv(this.addr,!1,t):(be.set(t.elements),e.uniformMatrix3fv(this.addr,!1,be))}function Ce(e,t){void 0===t.elements?e.uniformMatrix4fv(this.addr,!1,t):(xe.set(t.elements),e.uniformMatrix4fv(this.addr,!1,xe))}function Pe(e,t,i){var r=i.allocTextureUnit();e.uniform1i(this.addr,r),i.setTexture2D(t||fe,r)}function Ne(e,t,i){var r=i.allocTextureUnit();e.uniform1i(this.addr,r),i.setTextureCube(t||me,r)}function Oe(e,t){e.uniform2iv(this.addr,t)}function Ie(e,t){e.uniform3iv(this.addr,t)}function De(e,t){e.uniform4iv(this.addr,t)}function Ue(e,t){e.uniform1fv(this.addr,t)}function Fe(e,t){e.uniform1iv(this.addr,t)}function Be(e,t){e.uniform2fv(this.addr,we(t,this.size,2))}function ze(e,t){e.uniform3fv(this.addr,we(t,this.size,3))}function ke(e,t){e.uniform4fv(this.addr,we(t,this.size,4))}function Ge(e,t){e.uniformMatrix2fv(this.addr,!1,we(t,this.size,4))}function Ve(e,t){e.uniformMatrix3fv(this.addr,!1,we(t,this.size,9))}function je(e,t){e.uniformMatrix4fv(this.addr,!1,we(t,this.size,16))}function He(e,t,i){var r=t.length,n=_e(i,r);e.uniform1iv(this.addr,n);for(var o=0;o!==r;++o)i.setTexture2D(t[o]||fe,n[o])}function We(e,t,i){var r=t.length,n=_e(i,r);e.uniform1iv(this.addr,n);for(var o=0;o!==r;++o)i.setTextureCube(t[o]||me,n[o])}function Xe(e,t,i){this.id=e,this.addr=i,this.setValue=function(e){switch(e){case 5126:return Me;case 35664:return Te;case 35665:return Se;case 35666:return Ae;case 35674:return Le;case 35675:return Re;case 35676:return Ce;case 35678:case 36198:return Pe;case 35680:return Ne;case 5124:case 35670:return Ee;case 35667:case 35671:return Oe;case 35668:case 35672:return Ie;case 35669:case 35673:return De}}(t.type)}function qe(e,t,i){this.id=e,this.addr=i,this.size=t.size,this.setValue=function(e){switch(e){case 5126:return Ue;case 35664:return Be;case 35665:return ze;case 35666:return ke;case 35674:return Ge;case 35675:return Ve;case 35676:return je;case 35678:return He;case 35680:return We;case 5124:case 35670:return Fe;case 35667:case 35671:return Oe;case 35668:case 35672:return Ie;case 35669:case 35673:return De}}(t.type)}function Ye(e){this.id=e,ve.call(this)}Ye.prototype.setValue=function(e,t){for(var i=this.seq,r=0,n=i.length;r!==n;++r){var o=i[r];o.setValue(e,t[o.id])}};var Ze=/([\w\d_]+)(\])?(\[|\.)?/g;function Je(e,t){e.seq.push(t),e.map[t.id]=t}function Ke(e,t,i){var r=e.name,n=r.length;for(Ze.lastIndex=0;;){var o=Ze.exec(r),a=Ze.lastIndex,s=o[1],c="]"===o[2],h=o[3];if(c&&(s|=0),void 0===h||"["===h&&a+2===n){Je(i,void 0===h?new Xe(s,e,t):new qe(s,e,t));break}var l=i.map[s];void 0===l&&Je(i,l=new Ye(s)),i=l}}function Qe(e,t,i){ve.call(this),this.renderer=i;for(var r=e.getProgramParameter(t,e.ACTIVE_UNIFORMS),n=0;n>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,this},setRGB:function(e,t,i){return this.r=e,this.g=t,this.b=i,this},setHSL:function(){function e(e,t,i){return i<0&&(i+=1),i>1&&(i-=1),i<1/6?e+6*(t-e)*i:i<.5?t:i<2/3?e+6*(t-e)*(2/3-i):e}return function(t,i,r){if(t=te.euclideanModulo(t,1),i=te.clamp(i,0,1),r=te.clamp(r,0,1),0===i)this.r=this.g=this.b=r;else{var n=r<=.5?r*(1+i):r+i-r*i,o=2*r-n;this.r=e(o,n,t+1/3),this.g=e(o,n,t),this.b=e(o,n,t-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 i;if(i=/^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec(e)){var r,n=i[1],o=i[2];switch(n){case"rgb":case"rgba":if(r=/^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o))return this.r=Math.min(255,parseInt(r[1],10))/255,this.g=Math.min(255,parseInt(r[2],10))/255,this.b=Math.min(255,parseInt(r[3],10))/255,t(r[5]),this;if(r=/^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o))return this.r=Math.min(100,parseInt(r[1],10))/100,this.g=Math.min(100,parseInt(r[2],10))/100,this.b=Math.min(100,parseInt(r[3],10))/100,t(r[5]),this;break;case"hsl":case"hsla":if(r=/^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec(o)){var a=parseFloat(r[1])/360,s=parseInt(r[2],10)/100,c=parseInt(r[3],10)/100;return t(r[5]),this.setHSL(a,s,c)}}}else if(i=/^\#([A-Fa-f0-9]+)$/.exec(e)){var h,l=(h=i[1]).length;if(3===l)return this.r=parseInt(h.charAt(0)+h.charAt(0),16)/255,this.g=parseInt(h.charAt(1)+h.charAt(1),16)/255,this.b=parseInt(h.charAt(2)+h.charAt(2),16)/255,this;if(6===l)return this.r=parseInt(h.charAt(0)+h.charAt(1),16)/255,this.g=parseInt(h.charAt(2)+h.charAt(3),16)/255,this.b=parseInt(h.charAt(4)+h.charAt(5),16)/255,this}e&&e.length>0&&(void 0!==(h=$e[e])?this.setHex(h):console.warn("THREE.Color: Unknown color "+e));return 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 i=t>0?1/t:1;return this.r=Math.pow(e.r,i),this.g=Math.pow(e.g,i),this.b=Math.pow(e.b,i),this},convertGammaToLinear:function(){var e=this.r,t=this.g,i=this.b;return this.r=e*e,this.g=t*t,this.b=i*i,this},convertLinearToGamma:function(){return this.r=Math.sqrt(this.r),this.g=Math.sqrt(this.g),this.b=Math.sqrt(this.b),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){var t,i,r=e||{h:0,s:0,l:0},n=this.r,o=this.g,a=this.b,s=Math.max(n,o,a),c=Math.min(n,o,a),h=(c+s)/2;if(c===s)t=0,i=0;else{var l=s-c;switch(i=h<=.5?l/(s+c):l/(2-s-c),s){case n:t=(o-a)/l+(o 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\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}\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 GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, 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_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 theta = acos( dot( N, V ) );\n\tvec2 uv = vec2(\n\t\tsqrt( saturate( roughness ) ),\n\t\tsaturate( theta / ( 0.5 * PI ) ) );\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.86267 + (0.49788 + 0.01436 * y ) * y;\n\tfloat b = 3.45068 + (4.18814 + y) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt( 1.0 - x * x ) - 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\tvec3 result = vec3( LTC_ClippedSphereFormFactor( vectorFormFactor ) );\n\treturn result;\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\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",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\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n",clipping_planes_fragment:"#if NUM_CLIPPING_PLANES > 0\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; ++ i ) {\n\t\tvec4 plane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t\t\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; ++ i ) {\n\t\t\tvec4 plane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t\n\t#endif\n#endif\n",clipping_planes_pars_fragment:"#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n",clipping_planes_pars_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n",clipping_planes_vertex:"#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n",color_fragment:"#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif",color_pars_fragment:"#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n",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#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(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}\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};\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}\n",cube_uv_reflection_fragment:"#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n",defaultnormal_vertex:"vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n",displacementmap_pars_vertex:"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n",displacementmap_vertex:"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n",encodings_fragment:" gl_FragColor = linearToOutputTexel( gl_FragColor );\n",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.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\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.w );\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.w );\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.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, 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.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.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 = value.rgb * cLogLuvM;\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 = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n",envmap_fragment:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, 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_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\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\tenvColor = envMapTexelToLinear( envColor );\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\n",envmap_pars_fragment:"#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n",envmap_pars_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n",envmap_vertex:"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\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\n",fog_vertex:"\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif",fog_pars_vertex:"#ifdef USE_FOG\n varying float fogDepth;\n#endif\n",fog_fragment:"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\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\n",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\n",gradientmap_pars_fragment:"#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n",lightmap_fragment:"#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n",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 = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\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#endif\n#if NUM_SPOT_LIGHTS > 0\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#endif\n#if NUM_DIR_LIGHTS > 0\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#endif\n#if NUM_HEMI_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n",lights_pars:"uniform vec3 ambientLightColor;\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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\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\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\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 ltcMat;\tuniform sampler2D ltcMag;\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\n#if defined( USE_ENVMAP ) && defined( PHYSICAL )\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\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 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 blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, 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\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShininessExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\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\n",lights_phong_fragment:"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n",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\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\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)\n",lights_physical_fragment:"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#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\tfloat norm = texture2D( ltcMag, uv ).a;\n\t\tvec4 t = texture2D( ltcMat, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( 1, 0, t.y ),\n\t\t\tvec3( 0, t.z, 0 ),\n\t\t\tvec3( t.w, 0, t.x )\n\t\t);\n\t\treflectedLight.directSpecular += lightColor * material.specularColor * norm * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1 ), 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#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\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 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\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#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\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}\n",lights_template:"\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\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#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * 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 ( NUM_HEMI_LIGHTS > 0 )\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, 8 );\n\t#endif\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tvec3 radiance = getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), 8 );\n\t#ifndef STANDARD\n\t\tvec3 clearCoatRadiance = getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), 8 );\n\t#else\n\t\tvec3 clearCoatRadiance = vec3( 0.0 );\n\t#endif\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n",map_fragment:"#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n",map_pars_fragment:"#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n",map_particle_fragment:"#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n",map_particle_pars_fragment:"#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n",metalnessmap_fragment:"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphnormal_vertex:"#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\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 += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n",normal_fragment:"#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#endif\n#ifdef USE_NORMALMAP\n\tnormal = perturbNormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n",normalmap_pars_fragment:"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\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\tvec3 S = normalize( q0 * st1.t - q1 * st0.t );\n\t\tvec3 T = normalize( -q0 * st1.s + q1 * st0.s );\n\t\tvec3 N = normalize( surf_norm );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy = normalScale * mapN.xy;\n\t\tmat3 tsn = mat3( S, T, N );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n",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}\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}\n",premultiplied_alpha_fragment:"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n",project_vertex:"vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n",dithering_fragment:"#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n",dithering_pars_fragment:"#if defined( 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\n",roughnessmap_fragment:"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n",roughnessmap_pars_fragment:"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif",shadowmap_pars_fragment:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\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\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( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, 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( 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 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\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\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\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 )\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\n",shadowmap_pars_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n",shadowmap_vertex:"#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n",shadowmask_pars_fragment:"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\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 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\n",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\n",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#endif\n",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 gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n",tonemapping_pars_fragment:"#ifndef saturate\n\t#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}\n",uv_pars_fragment:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif",uv_pars_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n",uv_vertex:"#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\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#endif",uv2_vertex:"#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif",worldpos_vertex:"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n",cube_frag:"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n",cube_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n\tgl_Position.z = gl_Position.w;\n}\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 \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\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n",depth_vert:"#include \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}\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}\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}\n",equirect_frag:"uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n",equirect_vert:"varying vec3 vWorldPosition;\n#include \nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include \n\t#include \n}\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}\n",linedashed_vert:"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include \n\t#include \n\t#include \n}\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 \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\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * 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}\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}\n",meshlambert_frag:"uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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 \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\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\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}\n",meshlambert_vert:"#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\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}\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 \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\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}\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}\n",meshphysical_frag:"#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\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 \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\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}\n",meshphysical_vert:"#define PHYSICAL\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}\n",normal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n",normal_vert:"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\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#endif\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( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n",points_frag:"uniform vec3 diffuse;\nuniform float opacity;\n#include \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\t#include \n}\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#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\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}\n",shadow_vert:"#include \n#include \nvoid main() {\n\t#include \n\t#include \n\t#include \n\t#include \n\t#include \n}\n"},nt={basic:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.fog]),vertexShader:rt.meshbasic_vert,fragmentShader:rt.meshbasic_frag},lambert:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.fog,tt.lights,{emissive:{value:new et(0)}}]),vertexShader:rt.meshlambert_vert,fragmentShader:rt.meshlambert_frag},phong:{uniforms:it.merge([tt.common,tt.specularmap,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.bumpmap,tt.normalmap,tt.displacementmap,tt.gradientmap,tt.fog,tt.lights,{emissive:{value:new et(0)},specular:{value:new et(1118481)},shininess:{value:30}}]),vertexShader:rt.meshphong_vert,fragmentShader:rt.meshphong_frag},standard:{uniforms:it.merge([tt.common,tt.envmap,tt.aomap,tt.lightmap,tt.emissivemap,tt.bumpmap,tt.normalmap,tt.displacementmap,tt.roughnessmap,tt.metalnessmap,tt.fog,tt.lights,{emissive:{value:new et(0)},roughness:{value:.5},metalness:{value:.5},envMapIntensity:{value:1}}]),vertexShader:rt.meshphysical_vert,fragmentShader:rt.meshphysical_frag},points:{uniforms:it.merge([tt.points,tt.fog]),vertexShader:rt.points_vert,fragmentShader:rt.points_frag},dashed:{uniforms:it.merge([tt.common,tt.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:rt.linedashed_vert,fragmentShader:rt.linedashed_frag},depth:{uniforms:it.merge([tt.common,tt.displacementmap]),vertexShader:rt.depth_vert,fragmentShader:rt.depth_frag},normal:{uniforms:it.merge([tt.common,tt.bumpmap,tt.normalmap,tt.displacementmap,{opacity:{value:1}}]),vertexShader:rt.normal_vert,fragmentShader:rt.normal_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:rt.cube_vert,fragmentShader:rt.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:rt.equirect_vert,fragmentShader:rt.equirect_frag},distanceRGBA:{uniforms:it.merge([tt.common,tt.displacementmap,{referencePosition:{value:new oe},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:rt.distanceRGBA_vert,fragmentShader:rt.distanceRGBA_frag},shadow:{uniforms:it.merge([tt.lights,tt.fog,{color:{value:new et(0)},opacity:{value:1}}]),vertexShader:rt.shadow_vert,fragmentShader:rt.shadow_frag}};function ot(e,t){this.min=void 0!==e?e:new ie(1/0,1/0),this.max=void 0!==t?t:new ie(-1/0,-1/0)}function at(e,t,i,r,n){var o,a,s,c,h,l,u,p;function d(){var e=new Float32Array([-1,-1,0,0,1,-1,1,0,1,1,1,1,-1,1,0,1]),r=new Uint16Array([0,1,2,0,2,3]);o=t.createBuffer(),a=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,o),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.bufferData(t.ELEMENT_ARRAY_BUFFER,r,t.STATIC_DRAW),u=t.createTexture(),p=t.createTexture(),i.bindTexture(t.TEXTURE_2D,u),t.texImage2D(t.TEXTURE_2D,0,t.RGB,16,16,0,t.RGB,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),i.bindTexture(t.TEXTURE_2D,p),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,16,16,0,t.RGBA,t.UNSIGNED_BYTE,null),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),s={vertexShader:["uniform lowp int renderType;","uniform vec3 screenPosition;","uniform vec2 scale;","uniform float rotation;","uniform sampler2D occlusionMap;","attribute vec2 position;","attribute vec2 uv;","varying vec2 vUV;","varying float vVisibility;","void main() {","\tvUV = uv;","\tvec2 pos = position;","\tif ( renderType == 2 ) {","\t\tvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );","\t\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );","\t\tvVisibility = visibility.r / 9.0;","\t\tvVisibility *= 1.0 - visibility.g / 9.0;","\t\tvVisibility *= visibility.b / 9.0;","\t\tvVisibility *= 1.0 - visibility.a / 9.0;","\t\tpos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;","\t\tpos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;","\t}","\tgl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );","}"].join("\n"),fragmentShader:["uniform lowp int renderType;","uniform sampler2D map;","uniform float opacity;","uniform vec3 color;","varying vec2 vUV;","varying float vVisibility;","void main() {","\tif ( renderType == 0 ) {","\t\tgl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );","\t} else if ( renderType == 1 ) {","\t\tgl_FragColor = texture2D( map, vUV );","\t} else {","\t\tvec4 texture = texture2D( map, vUV );","\t\ttexture.a *= opacity * vVisibility;","\t\tgl_FragColor = texture;","\t\tgl_FragColor.rgb *= color;","\t}","}"].join("\n")},c=function(e){var i=t.createProgram(),r=t.createShader(t.FRAGMENT_SHADER),o=t.createShader(t.VERTEX_SHADER),a="precision "+n.precision+" float;\n";return t.shaderSource(r,a+e.fragmentShader),t.shaderSource(o,a+e.vertexShader),t.compileShader(r),t.compileShader(o),t.attachShader(i,r),t.attachShader(i,o),t.linkProgram(i),i}(s),h={vertex:t.getAttribLocation(c,"position"),uv:t.getAttribLocation(c,"uv")},l={renderType:t.getUniformLocation(c,"renderType"),map:t.getUniformLocation(c,"map"),occlusionMap:t.getUniformLocation(c,"occlusionMap"),opacity:t.getUniformLocation(c,"opacity"),color:t.getUniformLocation(c,"color"),scale:t.getUniformLocation(c,"scale"),rotation:t.getUniformLocation(c,"rotation"),screenPosition:t.getUniformLocation(c,"screenPosition")}}this.render=function(e,n,s,f){if(0!==e.length){var m=new oe,v=f.w/f.z,g=.5*f.z,y=.5*f.w,x=16/f.w,b=new ie(x*v,x),w=new oe(1,1,0),_=new ie(1,1),M=new ot;M.min.set(f.x,f.y),M.max.set(f.x+(f.z-16),f.y+(f.w-16)),void 0===c&&d(),i.useProgram(c),i.initAttributes(),i.enableAttribute(h.vertex),i.enableAttribute(h.uv),i.disableUnusedAttributes(),t.uniform1i(l.occlusionMap,0),t.uniform1i(l.map,1),t.bindBuffer(t.ARRAY_BUFFER,o),t.vertexAttribPointer(h.vertex,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(h.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),i.disable(t.CULL_FACE),i.buffers.depth.setMask(!1);for(var E=0,T=e.length;E.001&&R.scale>.001&&(w.x=R.x,w.y=R.y,w.z=R.z,x=R.size*R.scale/f.w,b.x=x*v,b.y=x,t.uniform3f(l.screenPosition,w.x,w.y,w.z),t.uniform2f(l.scale,b.x,b.y),t.uniform1f(l.rotation,R.rotation),t.uniform1f(l.opacity,R.opacity),t.uniform3f(l.color,R.color.r,R.color.g,R.color.b),i.setBlending(R.blending,R.blendEquation,R.blendSrc,R.blendDst),r.setTexture2D(R.texture,1),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0))}}}i.enable(t.CULL_FACE),i.enable(t.DEPTH_TEST),i.buffers.depth.setMask(!0),i.reset()}}}function st(e,t,i,r,n,o,a,s,c){ce.call(this,e,t,i,r,n,o,a,s,c),this.needsUpdate=!0}function ct(e,t,i,r,n){var o,a,s,c,h,l,u=new oe,p=new ne,d=new oe;function f(){var e=new Float32Array([-.5,-.5,0,0,.5,-.5,1,0,.5,.5,1,1,-.5,.5,0,1]),i=new Uint16Array([0,1,2,0,2,3]);o=t.createBuffer(),a=t.createBuffer(),t.bindBuffer(t.ARRAY_BUFFER,o),t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.bufferData(t.ELEMENT_ARRAY_BUFFER,i,t.STATIC_DRAW),s=function(){var e=t.createProgram(),i=t.createShader(t.VERTEX_SHADER),r=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(i,["precision "+n.precision+" float;","#define SHADER_NAME SpriteMaterial","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform float rotation;","uniform vec2 scale;","uniform vec2 uvOffset;","uniform vec2 uvScale;","attribute vec2 position;","attribute vec2 uv;","varying vec2 vUV;","varying float fogDepth;","void main() {","\tvUV = uvOffset + uv * uvScale;","\tvec2 alignedPosition = position * scale;","\tvec2 rotatedPosition;","\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;","\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;","\tvec4 mvPosition;","\tmvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );","\tmvPosition.xy += rotatedPosition;","\tgl_Position = projectionMatrix * mvPosition;","\tfogDepth = - mvPosition.z;","}"].join("\n")),t.shaderSource(r,["precision "+n.precision+" float;","#define SHADER_NAME SpriteMaterial","uniform vec3 color;","uniform sampler2D map;","uniform float opacity;","uniform int fogType;","uniform vec3 fogColor;","uniform float fogDensity;","uniform float fogNear;","uniform float fogFar;","uniform float alphaTest;","varying vec2 vUV;","varying float fogDepth;","void main() {","\tvec4 texture = texture2D( map, vUV );","\tgl_FragColor = vec4( color * texture.xyz, texture.a * opacity );","\tif ( gl_FragColor.a < alphaTest ) discard;","\tif ( fogType > 0 ) {","\t\tfloat fogFactor = 0.0;","\t\tif ( fogType == 1 ) {","\t\t\tfogFactor = smoothstep( fogNear, fogFar, fogDepth );","\t\t} else {","\t\t\tconst float LOG2 = 1.442695;","\t\t\tfogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );","\t\t\tfogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );","\t\t}","\t\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );","\t}","}"].join("\n")),t.compileShader(i),t.compileShader(r),t.attachShader(e,i),t.attachShader(e,r),t.linkProgram(e),e}(),c={position:t.getAttribLocation(s,"position"),uv:t.getAttribLocation(s,"uv")},h={uvOffset:t.getUniformLocation(s,"uvOffset"),uvScale:t.getUniformLocation(s,"uvScale"),rotation:t.getUniformLocation(s,"rotation"),scale:t.getUniformLocation(s,"scale"),color:t.getUniformLocation(s,"color"),map:t.getUniformLocation(s,"map"),opacity:t.getUniformLocation(s,"opacity"),modelViewMatrix:t.getUniformLocation(s,"modelViewMatrix"),projectionMatrix:t.getUniformLocation(s,"projectionMatrix"),fogType:t.getUniformLocation(s,"fogType"),fogDensity:t.getUniformLocation(s,"fogDensity"),fogNear:t.getUniformLocation(s,"fogNear"),fogFar:t.getUniformLocation(s,"fogFar"),fogColor:t.getUniformLocation(s,"fogColor"),fogDepth:t.getUniformLocation(s,"fogDepth"),alphaTest:t.getUniformLocation(s,"alphaTest")};var r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");r.width=8,r.height=8;var u=r.getContext("2d");u.fillStyle="white",u.fillRect(0,0,8,8),l=new st(r)}function m(e,t){return e.renderOrder!==t.renderOrder?e.renderOrder-t.renderOrder:e.z!==t.z?t.z-e.z:t.id-e.id}this.render=function(n,v,g){if(0!==n.length){void 0===s&&f(),i.useProgram(s),i.initAttributes(),i.enableAttribute(c.position),i.enableAttribute(c.uv),i.disableUnusedAttributes(),i.disable(t.CULL_FACE),i.enable(t.BLEND),t.bindBuffer(t.ARRAY_BUFFER,o),t.vertexAttribPointer(c.position,2,t.FLOAT,!1,16,0),t.vertexAttribPointer(c.uv,2,t.FLOAT,!1,16,8),t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,a),t.uniformMatrix4fv(h.projectionMatrix,!1,g.projectionMatrix.elements),i.activeTexture(t.TEXTURE0),t.uniform1i(h.map,0);var y=0,x=0,b=v.fog;b?(t.uniform3f(h.fogColor,b.color.r,b.color.g,b.color.b),b.isFog?(t.uniform1f(h.fogNear,b.near),t.uniform1f(h.fogFar,b.far),t.uniform1i(h.fogType,1),y=1,x=1):b.isFogExp2&&(t.uniform1f(h.fogDensity,b.density),t.uniform1i(h.fogType,2),y=2,x=2)):(t.uniform1i(h.fogType,0),y=0,x=0);for(var w=0,_=n.length;w<_;w++){(E=n[w]).modelViewMatrix.multiplyMatrices(g.matrixWorldInverse,E.matrixWorld),E.z=-E.modelViewMatrix.elements[14]}n.sort(m);var M=[];for(w=0,_=n.length;w<_;w++){var E,T=(E=n[w]).material;if(!1!==T.visible){E.onBeforeRender(e,v,g,void 0,T,void 0),t.uniform1f(h.alphaTest,T.alphaTest),t.uniformMatrix4fv(h.modelViewMatrix,!1,E.modelViewMatrix.elements),E.matrixWorld.decompose(u,p,d),M[0]=d.x,M[1]=d.y;var S=0;v.fog&&T.fog&&(S=x),y!==S&&(t.uniform1i(h.fogType,S),y=S),null!==T.map?(t.uniform2f(h.uvOffset,T.map.offset.x,T.map.offset.y),t.uniform2f(h.uvScale,T.map.repeat.x,T.map.repeat.y)):(t.uniform2f(h.uvOffset,0,0),t.uniform2f(h.uvScale,1,1)),t.uniform1f(h.opacity,T.opacity),t.uniform3f(h.color,T.color.r,T.color.g,T.color.b),t.uniform1f(h.rotation,T.rotation),t.uniform2fv(h.scale,M),i.setBlending(T.blending,T.blendEquation,T.blendSrc,T.blendDst,T.blendEquationAlpha,T.blendSrcAlpha,T.blendDstAlpha,T.premultipliedAlpha),i.buffers.depth.setTest(T.depthTest),i.buffers.depth.setMask(T.depthWrite),i.buffers.color.setMask(T.colorWrite),r.setTexture2D(T.map||l,0),t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0),E.onAfterRender(e,v,g,void 0,T,void 0)}}i.enable(t.CULL_FACE),i.reset()}}}nt.physical={uniforms:it.merge([nt.standard.uniforms,{clearCoat:{value:0},clearCoatRoughness:{value:0}}]),vertexShader:rt.meshphysical_vert,fragmentShader:rt.meshphysical_frag},Object.assign(ot.prototype,{set:function(e,t){return this.min.copy(e),this.max.copy(t),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=e.length;tthis.max.x||e.ythis.max.y)},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},getParameter:function(e,t){return(t||new ie).set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y))},intersectsBox:function(e){return!(e.max.xthis.max.x||e.max.ythis.max.y)},clampPoint:function(e,t){return(t||new ie).copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new ie;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),intersect:function(e){return this.min.max(e.min),this.max.min(e.max),this},union:function(e){return this.min.min(e.min),this.max.max(e.max),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)}}),st.prototype=Object.create(ce.prototype),st.prototype.constructor=st;var ht,lt,ut,pt,dt,ft,mt,vt=0;function gt(){Object.defineProperty(this,"id",{value:vt++}),this.uuid=te.generateUUID(),this.name="",this.type="Material",this.fog=!0,this.lights=!0,this.blending=1,this.side=0,this.flatShading=!1,this.vertexColors=0,this.opacity=1,this.transparent=!1,this.blendSrc=204,this.blendDst=205,this.blendEquation=100,this.blendSrcAlpha=null,this.blendDstAlpha=null,this.blendEquationAlpha=null,this.depthFunc=3,this.depthTest=!0,this.depthWrite=!0,this.clippingPlanes=null,this.clipIntersection=!1,this.clipShadows=!1,this.colorWrite=!0,this.precision=null,this.polygonOffset=!1,this.polygonOffsetFactor=0,this.polygonOffsetUnits=0,this.dithering=!1,this.alphaTest=0,this.premultipliedAlpha=!1,this.overdraw=0,this.visible=!0,this.userData={},this.needsUpdate=!0}function yt(e){gt.call(this),this.type="MeshDepthMaterial",this.depthPacking=3200,this.skinning=!1,this.morphTargets=!1,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.fog=!1,this.lights=!1,this.setValues(e)}function xt(e){gt.call(this),this.type="MeshDistanceMaterial",this.referencePosition=new oe,this.nearDistance=1,this.farDistance=1e3,this.skinning=!1,this.morphTargets=!1,this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.fog=!1,this.lights=!1,this.setValues(e)}function bt(e,t){this.min=void 0!==e?e:new oe(1/0,1/0,1/0),this.max=void 0!==t?t:new oe(-1/0,-1/0,-1/0)}function wt(e,t){this.center=void 0!==e?e:new oe,this.radius=void 0!==t?t:0}function _t(e,t){this.normal=void 0!==e?e:new oe(1,0,0),this.constant=void 0!==t?t:0}function Mt(e,t,i,r,n,o){this.planes=[void 0!==e?e:new _t,void 0!==t?t:new _t,void 0!==i?i:new _t,void 0!==r?r:new _t,void 0!==n?n:new _t,void 0!==o?o:new _t]}function Et(e,t,i){for(var r=new Mt,n=new re,o=new ie,a=new ie(i,i),s=new oe,c=new oe,h=new Array(4),l=new Array(4),u={},p=[new oe(1,0,0),new oe(-1,0,0),new oe(0,0,1),new oe(0,0,-1),new oe(0,1,0),new oe(0,-1,0)],d=[new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,1,0),new oe(0,0,1),new oe(0,0,-1)],f=[new he,new he,new he,new he,new he,new he],m=0;4!==m;++m){var v=0!=(1&m),g=0!=(2&m),y=new yt({depthPacking:3201,morphTargets:v,skinning:g});h[m]=y;var x=new xt({morphTargets:v,skinning:g});l[m]=x}var b=this;function w(t,i,r,n,o,a){var s=t.geometry,c=null,p=h,d=t.customDepthMaterial;if(r&&(p=l,d=t.customDistanceMaterial),d)c=d;else{var f=!1;i.morphTargets&&(s&&s.isBufferGeometry?f=s.morphAttributes&&s.morphAttributes.position&&s.morphAttributes.position.length>0:s&&s.isGeometry&&(f=s.morphTargets&&s.morphTargets.length>0)),t.isSkinnedMesh&&!1===i.skinning&&console.warn("THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:",t);var m=0;f&&(m|=1),t.isSkinnedMesh&&i.skinning&&(m|=2),c=p[m]}if(e.localClippingEnabled&&!0===i.clipShadows&&0!==i.clippingPlanes.length){var v=c.uuid,g=i.uuid,y=u[v];void 0===y&&(y={},u[v]=y);var x=y[g];void 0===x&&(x=c.clone(),y[g]=x),c=x}c.visible=i.visible,c.wireframe=i.wireframe;var w=i.side;return b.renderSingleSided&&2==w&&(w=0),b.renderReverseSided&&(0===w?w=1:1===w&&(w=0)),c.side=w,c.clipShadows=i.clipShadows,c.clippingPlanes=i.clippingPlanes,c.clipIntersection=i.clipIntersection,c.wireframeLinewidth=i.wireframeLinewidth,c.linewidth=i.linewidth,r&&c.isMeshDistanceMaterial&&(c.referencePosition.copy(n),c.nearDistance=o,c.farDistance=a),c}function _(i,n,o,a){if(!1!==i.visible){if(i.layers.test(n.layers)&&(i.isMesh||i.isLine||i.isPoints)&&i.castShadow&&(!i.frustumCulled||r.intersectsObject(i))){i.modelViewMatrix.multiplyMatrices(o.matrixWorldInverse,i.matrixWorld);var s=t.update(i),h=i.material;if(Array.isArray(h))for(var l=s.groups,u=0,p=l.length;u0&&(i.alphaTest=this.alphaTest),!0===this.premultipliedAlpha&&(i.premultipliedAlpha=this.premultipliedAlpha),!0===this.wireframe&&(i.wireframe=this.wireframe),this.wireframeLinewidth>1&&(i.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(i.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(i.wireframeLinejoin=this.wireframeLinejoin),!0===this.morphTargets&&(i.morphTargets=!0),!0===this.skinning&&(i.skinning=!0),!1===this.visible&&(i.visible=!1),"{}"!==JSON.stringify(this.userData)&&(i.userData=this.userData),t){var n=r(e.textures),o=r(e.images);n.length>0&&(i.textures=n),o.length>0&&(i.images=o)}return i},clone:function(){return(new this.constructor).copy(this)},copy:function(e){this.name=e.name,this.fog=e.fog,this.lights=e.lights,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.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.overdraw=e.overdraw,this.visible=e.visible,this.userData=JSON.parse(JSON.stringify(e.userData)),this.clipShadows=e.clipShadows,this.clipIntersection=e.clipIntersection;var t=e.clippingPlanes,i=null;if(null!==t){var r=t.length;i=new Array(r);for(var n=0;n!==r;++n)i[n]=t[n].clone()}return this.clippingPlanes=i,this},dispose:function(){this.dispatchEvent({type:"dispose"})}}),yt.prototype=Object.create(gt.prototype),yt.prototype.constructor=yt,yt.prototype.isMeshDepthMaterial=!0,yt.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.depthPacking=e.depthPacking,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this},xt.prototype=Object.create(gt.prototype),xt.prototype.constructor=xt,xt.prototype.isMeshDistanceMaterial=!0,xt.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.referencePosition.copy(e.referencePosition),this.nearDistance=e.nearDistance,this.farDistance=e.farDistance,this.skinning=e.skinning,this.morphTargets=e.morphTargets,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this},Object.assign(bt.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,i=1/0,r=1/0,n=-1/0,o=-1/0,a=-1/0,s=0,c=e.length;sn&&(n=h),l>o&&(o=l),u>a&&(a=u)}return this.min.set(t,i,r),this.max.set(n,o,a),this},setFromBufferAttribute:function(e){for(var t=1/0,i=1/0,r=1/0,n=-1/0,o=-1/0,a=-1/0,s=0,c=e.count;sn&&(n=h),l>o&&(o=l),u>a&&(a=u)}return this.min.set(t,i,r),this.max.set(n,o,a),this},setFromPoints:function(e){this.makeEmpty();for(var t=0,i=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(t||new oe).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:(lt=new oe,function(e){return this.clampPoint(e.center,lt),lt.distanceToSquared(e.center)<=e.radius*e.radius}),intersectsPlane:function(e){var t,i;return e.normal.x>0?(t=e.normal.x*this.min.x,i=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,i=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,i+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,i+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,i+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,i+=e.normal.z*this.min.z),t<=e.constant&&i>=e.constant},clampPoint:function(e,t){return(t||new oe).copy(e).clamp(this.min,this.max)},distanceToPoint:function(){var e=new oe;return function(t){return e.copy(t).clamp(this.min,this.max).sub(t).length()}}(),getBoundingSphere:function(){var e=new oe;return function(t){var i=t||new wt;return this.getCenter(i.center),i.radius=.5*this.getSize(e).length(),i}}(),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:(ht=[new oe,new oe,new oe,new oe,new oe,new oe,new oe,new oe],function(e){return this.isEmpty()||(ht[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),ht[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),ht[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),ht[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),ht[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),ht[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),ht[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),ht[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(ht)),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)}}),Object.assign(wt.prototype,{set:function(e,t){return this.center.copy(e),this.radius=t,this},setFromPoints:(ut=new bt,function(e,t){var i=this.center;void 0!==t?i.copy(t):ut.setFromPoints(e).getCenter(i);for(var r=0,n=0,o=e.length;nthis.radius*this.radius&&(r.sub(this.center).normalize(),r.multiplyScalar(this.radius).add(this.center)),r},getBoundingBox:function(e){var t=e||new bt;return t.set(this.center,this.center),t.expandByScalar(this.radius),t},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}}),Object.assign(_t.prototype,{set:function(e,t){return this.normal.copy(e),this.constant=t,this},setComponents:function(e,t,i,r){return this.normal.set(e,t,i),this.constant=r,this},setFromNormalAndCoplanarPoint:function(e,t){return this.normal.copy(e),this.constant=-t.dot(this.normal),this},setFromCoplanarPoints:function(){var e=new oe,t=new oe;return function(i,r,n){var o=e.subVectors(n,r).cross(t.subVectors(i,r)).normalize();return this.setFromNormalAndCoplanarPoint(o,i),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(t||new oe).copy(this.normal).multiplyScalar(-this.distanceToPoint(e)).add(e)},intersectLine:function(){var e=new oe;return function(t,i){var r=i||new oe,n=t.delta(e),o=this.normal.dot(n);if(0===o)return 0===this.distanceToPoint(t.start)?r.copy(t.start):void 0;var a=-(t.start.dot(this.normal)+this.constant)/o;return a<0||a>1?void 0:r.copy(n).multiplyScalar(a).add(t.start)}}(),intersectsLine:function(e){var t=this.distanceToPoint(e.start),i=this.distanceToPoint(e.end);return t<0&&i>0||i<0&&t>0},intersectsBox:function(e){return e.intersectsPlane(this)},intersectsSphere:function(e){return e.intersectsPlane(this)},coplanarPoint:function(e){return(e||new oe).copy(this.normal).multiplyScalar(-this.constant)},applyMatrix4:function(){var e=new oe,t=new ae;return function(i,r){var n=r||t.getNormalMatrix(i),o=this.coplanarPoint(e).applyMatrix4(i),a=this.normal.applyMatrix3(n).normalize();return this.constant=-o.dot(a),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}}),Object.assign(Mt.prototype,{set:function(e,t,i,r,n,o){var a=this.planes;return a[0].copy(e),a[1].copy(t),a[2].copy(i),a[3].copy(r),a[4].copy(n),a[5].copy(o),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){for(var t=this.planes,i=0;i<6;i++)t[i].copy(e.planes[i]);return this},setFromMatrix:function(e){var t=this.planes,i=e.elements,r=i[0],n=i[1],o=i[2],a=i[3],s=i[4],c=i[5],h=i[6],l=i[7],u=i[8],p=i[9],d=i[10],f=i[11],m=i[12],v=i[13],g=i[14],y=i[15];return t[0].setComponents(a-r,l-s,f-u,y-m).normalize(),t[1].setComponents(a+r,l+s,f+u,y+m).normalize(),t[2].setComponents(a+n,l+c,f+p,y+v).normalize(),t[3].setComponents(a-n,l-c,f-p,y-v).normalize(),t[4].setComponents(a-o,l-h,f-d,y-g).normalize(),t[5].setComponents(a+o,l+h,f+d,y+g).normalize(),this},intersectsObject:(ft=new wt,function(e){var t=e.geometry;return null===t.boundingSphere&&t.computeBoundingSphere(),ft.copy(t.boundingSphere).applyMatrix4(e.matrixWorld),this.intersectsSphere(ft)}),intersectsSprite:function(){var e=new wt;return function(t){return e.center.set(0,0,0),e.radius=.7071067811865476,e.applyMatrix4(t.matrixWorld),this.intersectsSphere(e)}}(),intersectsSphere:function(e){for(var t=this.planes,i=e.center,r=-e.radius,n=0;n<6;n++){if(t[n].distanceToPoint(i)0?e.min.x:e.max.x,dt.x=r.normal.x>0?e.max.x:e.min.x,pt.y=r.normal.y>0?e.min.y:e.max.y,dt.y=r.normal.y>0?e.max.y:e.min.y,pt.z=r.normal.z>0?e.min.z:e.max.z,dt.z=r.normal.z>0?e.max.z:e.min.z;var n=r.distanceToPoint(pt),o=r.distanceToPoint(dt);if(n<0&&o<0)return!1}return!0}),containsPoint:function(e){for(var t=this.planes,i=0;i<6;i++)if(t[i].distanceToPoint(e)<0)return!1;return!0}}),St.RotationOrders=["XYZ","YZX","ZXY","XZY","YXZ","ZYX"],St.DefaultOrder="XYZ",Object.defineProperties(St.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(St.prototype,{isEuler:!0,set:function(e,t,i,r){return this._x=e,this._y=t,this._z=i,this._order=r||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,i){var r=te.clamp,n=e.elements,o=n[0],a=n[4],s=n[8],c=n[1],h=n[5],l=n[9],u=n[2],p=n[6],d=n[10];return"XYZ"===(t=t||this._order)?(this._y=Math.asin(r(s,-1,1)),Math.abs(s)<.99999?(this._x=Math.atan2(-l,d),this._z=Math.atan2(-a,o)):(this._x=Math.atan2(p,h),this._z=0)):"YXZ"===t?(this._x=Math.asin(-r(l,-1,1)),Math.abs(l)<.99999?(this._y=Math.atan2(s,d),this._z=Math.atan2(c,h)):(this._y=Math.atan2(-u,o),this._z=0)):"ZXY"===t?(this._x=Math.asin(r(p,-1,1)),Math.abs(p)<.99999?(this._y=Math.atan2(-u,d),this._z=Math.atan2(-a,h)):(this._y=0,this._z=Math.atan2(c,o))):"ZYX"===t?(this._y=Math.asin(-r(u,-1,1)),Math.abs(u)<.99999?(this._x=Math.atan2(p,d),this._z=Math.atan2(c,o)):(this._x=0,this._z=Math.atan2(-a,h))):"YZX"===t?(this._z=Math.asin(r(c,-1,1)),Math.abs(c)<.99999?(this._x=Math.atan2(-l,h),this._y=Math.atan2(-u,o)):(this._x=0,this._y=Math.atan2(s,d))):"XZY"===t?(this._z=Math.asin(-r(a,-1,1)),Math.abs(a)<.99999?(this._x=Math.atan2(p,h),this._y=Math.atan2(s,o)):(this._x=Math.atan2(-l,d),this._y=0)):console.warn("THREE.Euler: .setFromRotationMatrix() given unsupported order: "+t),this._order=t,!1!==i&&this.onChangeCallback(),this},setFromQuaternion:function(){var e=new re;return function(t,i,r){return e.makeRotationFromQuaternion(t),this.setFromRotationMatrix(e,i,r)}}(),setFromVector3:function(e,t){return this.set(e.x,e.y,e.z,t||this._order)},reorder:(mt=new ne,function(e){return mt.setFromEuler(this),this.setFromQuaternion(mt,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 oe(this._x,this._y,this._z)},onChange:function(e){return this.onChangeCallback=e,this},onChangeCallback:function(){}}),Object.assign(At.prototype,{set:function(e){this.mask=1<1){for(var t=0;t1){for(var t=0;t0){r.children=[];for(s=0;s0&&(i.geometries=u),p.length>0&&(i.materials=p),d.length>0&&(i.textures=d),f.length>0&&(i.images=f),a.length>0&&(i.shapes=a)}return i.object=r,i;function m(e){var t=[];for(var i in e){var r=e[i];delete r.metadata,t.push(r)}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 i=0;it&&(t=e[i]);return t}zt.prototype=Object.assign(Object.create(n.prototype),{constructor:zt,isGeometry:!0,applyMatrix:function(e){for(var t=(new ae).getNormalMatrix(e),i=0,r=this.vertices.length;i0)for(p=0;p0&&(this.normalsNeedUpdate=!0)},computeFlatVertexNormals:function(){var e,t,i;for(this.computeFaceNormals(),e=0,t=this.faces.length;e0&&(this.normalsNeedUpdate=!0)},computeMorphNormals:function(){var e,t,i,r,n;for(i=0,r=this.faces.length;i0&&(e+=t[i].distanceTo(t[i-1])),this.lineDistances[i]=e},computeBoundingBox:function(){null===this.boundingBox&&(this.boundingBox=new bt),this.boundingBox.setFromPoints(this.vertices)},computeBoundingSphere:function(){null===this.boundingSphere&&(this.boundingSphere=new wt),this.boundingSphere.setFromPoints(this.vertices)},merge:function(e,t,i){if(e&&e.isGeometry){var r,n=this.vertices.length,o=this.vertices,a=e.vertices,s=this.faces,c=e.faces,h=this.faceVertexUvs[0],l=e.faceVertexUvs[0],u=this.colors,p=e.colors;void 0===i&&(i=0),void 0!==t&&(r=(new ae).getNormalMatrix(t));for(var d=0,f=a.length;d=0;i--){var f=p[i];for(this.faces.splice(f,1),a=0,s=this.faceVertexUvs.length;a0,v=d.vertexNormals.length>0,g=1!==d.color.r||1!==d.color.g||1!==d.color.b,y=d.vertexColors.length>0,x=0;if(x=M(x,0,0),x=M(x,1,!0),x=M(x,2,!1),x=M(x,3,f),x=M(x,4,m),x=M(x,5,v),x=M(x,6,g),x=M(x,7,y),a.push(x),a.push(d.a,d.b,d.c),a.push(d.materialIndex),f){var b=this.faceVertexUvs[0][n];a.push(S(b[0]),S(b[1]),S(b[2]))}if(m&&a.push(E(d.normal)),v){var w=d.vertexNormals;a.push(E(w[0]),E(w[1]),E(w[2]))}if(g&&a.push(T(d.color)),y){var _=d.vertexColors;a.push(T(_[0]),T(_[1]),T(_[2]))}}function M(e,t,i){return i?e|1<0&&(e.data.colors=h),u.length>0&&(e.data.uvs=[u]),e.data.faces=a,e},clone:function(){return(new zt).copy(this)},copy:function(e){var t,i,r,n,o,a;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,i=s.length;t0,a=n[1]&&n[1].length>0,s=e.morphTargets,c=s.length;if(c>0){t=[];for(var h=0;h0){l=[];for(h=0;h0?1:-1,h.push(R.x,R.y,R.z),l.push(y/m),l.push(1-x/v),A+=1}}for(x=0;x1&&i.sort(yi),r.length>1&&r.sort(xi)}}}function wi(){var e={};return{get:function(t,i){var r=t.id+","+i.id,n=e[r];return void 0===n&&(n=new bi,e[r]=n),n},dispose:function(){e={}}}}function _i(e,t){return Math.abs(t[1])-Math.abs(e[1])}function Mi(e){var t={},i=new Float32Array(8);return{update:function(r,n,o,a){var s=r.morphTargetInfluences,c=s.length,h=t[n.id];if(void 0===h){h=[];for(var l=0;l65535?qt:Wt)(a,1),t.update(r,e.ELEMENT_ARRAY_BUFFER),n[i.id]=r,r}}}function Ai(){var e={};return{get:function(t){if(void 0!==e[t.id])return e[t.id];var i;switch(t.type){case"DirectionalLight":i={direction:new oe,color:new et,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie};break;case"SpotLight":i={position:new oe,direction:new oe,color:new et,distance:0,coneCos:0,penumbraCos:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie};break;case"PointLight":i={position:new oe,color:new et,distance:0,decay:0,shadow:!1,shadowBias:0,shadowRadius:1,shadowMapSize:new ie,shadowCameraNear:1,shadowCameraFar:1e3};break;case"HemisphereLight":i={direction:new oe,skyColor:new et,groundColor:new et};break;case"RectAreaLight":i={color:new et,position:new oe,halfWidth:new oe,halfHeight:new oe}}return e[t.id]=i,i}}}function Li(){var e=new Ai,t={hash:"",ambient:[0,0,0],directional:[],directionalShadowMap:[],directionalShadowMatrix:[],spot:[],spotShadowMap:[],spotShadowMatrix:[],rectArea:[],point:[],pointShadowMap:[],pointShadowMatrix:[],hemi:[]},i=new oe,r=new re,n=new re;return{setup:function(o,a,s){for(var c=0,h=0,l=0,u=0,p=0,d=0,f=0,m=0,v=s.matrixWorldInverse,g=0,y=o.length;g65535?qt:Wt)(e,1):this.index=e},addAttribute:function(e,t){return t&&t.isBufferAttribute||t&&t.isInterleavedBufferAttribute?"index"===e?(console.warn("THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute."),void this.setIndex(t)):(this.attributes[e]=t,this):(console.warn("THREE.BufferGeometry: .addAttribute() now expects ( name, attribute )."),void this.addAttribute(e,new kt(arguments[1],arguments[2])))},getAttribute:function(e){return this.attributes[e]},removeAttribute:function(e){return delete this.attributes[e],this},addGroup:function(e,t,i){this.groups.push({start:e,count:t,materialIndex:void 0!==i?i:0})},clearGroups:function(){this.groups=[]},setDrawRange:function(e,t){this.drawRange.start=e,this.drawRange.count=t},applyMatrix:function(e){var t=this.attributes.position;void 0!==t&&(e.applyToBufferAttribute(t),t.needsUpdate=!0);var i=this.attributes.normal;void 0!==i&&((new ae).getNormalMatrix(e).applyToBufferAttribute(i),i.needsUpdate=!0);return null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this},rotateX:function(){var e=new re;return function(t){return e.makeRotationX(t),this.applyMatrix(e),this}}(),rotateY:function(){var e=new re;return function(t){return e.makeRotationY(t),this.applyMatrix(e),this}}(),rotateZ:function(){var e=new re;return function(t){return e.makeRotationZ(t),this.applyMatrix(e),this}}(),translate:function(){var e=new re;return function(t,i,r){return e.makeTranslation(t,i,r),this.applyMatrix(e),this}}(),scale:function(){var e=new re;return function(t,i,r){return e.makeScale(t,i,r),this.applyMatrix(e),this}}(),lookAt:function(){var e=new Ot;return function(t){e.lookAt(t),e.updateMatrix(),this.applyMatrix(e.matrix)}}(),center:function(){this.computeBoundingBox();var e=this.boundingBox.getCenter().negate();return this.translate(e.x,e.y,e.z),e},setFromObject:function(e){var t=e.geometry;if(e.isPoints||e.isLine){var i=new Yt(3*t.vertices.length,3),r=new Yt(3*t.colors.length,3);if(this.addAttribute("position",i.copyVector3sArray(t.vertices)),this.addAttribute("color",r.copyColorsArray(t.colors)),t.lineDistances&&t.lineDistances.length===t.vertices.length){var n=new Yt(t.lineDistances.length,1);this.addAttribute("lineDistance",n.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=[],i=0,r=e.length;i0){var i=new Float32Array(3*e.normals.length);this.addAttribute("normal",new kt(i,3).copyVector3sArray(e.normals))}if(e.colors.length>0){var r=new Float32Array(3*e.colors.length);this.addAttribute("color",new kt(r,3).copyColorsArray(e.colors))}if(e.uvs.length>0){var n=new Float32Array(2*e.uvs.length);this.addAttribute("uv",new kt(n,2).copyVector2sArray(e.uvs))}if(e.uvs2.length>0){var o=new Float32Array(2*e.uvs2.length);this.addAttribute("uv2",new kt(o,2).copyVector2sArray(e.uvs2))}if(e.indices.length>0){var a=new(Kt(e.indices)>65535?Uint32Array:Uint16Array)(3*e.indices.length);this.setIndex(new kt(a,1).copyIndicesArray(e.indices))}for(var s in this.groups=e.groups,e.morphTargets){for(var c=[],h=e.morphTargets[s],l=0,u=h.length;l0){var f=new Yt(4*e.skinIndices.length,4);this.addAttribute("skinIndex",f.copyVector4sArray(e.skinIndices))}if(e.skinWeights.length>0){var m=new Yt(4*e.skinWeights.length,4);this.addAttribute("skinWeight",m.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 bt);var e=this.attributes.position;void 0!==e?this.boundingBox.setFromBufferAttribute(e):this.boundingBox.makeEmpty(),(isNaN(this.boundingBox.min.x)||isNaN(this.boundingBox.min.y)||isNaN(this.boundingBox.min.z))&&console.error('THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.',this)},computeBoundingSphere:function(){var e=new bt,t=new oe;return function(){null===this.boundingSphere&&(this.boundingSphere=new wt);var i=this.attributes.position;if(i){var r=this.boundingSphere.center;e.setFromBufferAttribute(i),e.getCenter(r);for(var n=0,o=0,a=i.count;o0&&(e.data.groups=JSON.parse(JSON.stringify(s)));var c=this.boundingSphere;return null!==c&&(e.data.boundingSphere={center:c.center.toArray(),radius:c.radius}),e},clone:function(){return(new ai).copy(this)},copy:function(e){var t,i,r;this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null,this.name=e.name;var n=e.index;null!==n&&this.setIndex(n.clone());var o=e.attributes;for(t in o){var a=o[t];this.addAttribute(t,a.clone())}var s=e.morphAttributes;for(t in s){var c=[],h=s[t];for(i=0,r=h.length;i0)if(o=h*l-u,s=c*d,(n=h*u-l)>=0)if(o>=-s)if(o<=s){var f=1/d;a=(n*=f)*(n+h*(o*=f)+2*l)+o*(h*n+o+2*u)+p}else o=c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;else o=-c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;else o<=-s?a=-(n=Math.max(0,-(-h*c+l)))*n+(o=n>0?-c:Math.min(Math.max(-c,-u),c))*(o+2*u)+p:o<=s?(n=0,a=(o=Math.min(Math.max(-c,-u),c))*(o+2*u)+p):a=-(n=Math.max(0,-(h*c+l)))*n+(o=n>0?c:Math.min(Math.max(-c,-u),c))*(o+2*u)+p;else o=h>0?-c:c,a=-(n=Math.max(0,-(h*o+l)))*n+o*(o+2*u)+p;return i&&i.copy(this.direction).multiplyScalar(n).add(this.origin),r&&r.copy(ei).multiplyScalar(o).add($t),a}),intersectSphere:function(){var e=new oe;return function(t,i){e.subVectors(t.center,this.origin);var r=e.dot(this.direction),n=e.dot(e)-r*r,o=t.radius*t.radius;if(n>o)return null;var a=Math.sqrt(o-n),s=r-a,c=r+a;return s<0&&c<0?null:s<0?this.at(c,i):this.at(s,i)}}(),intersectsSphere:function(e){return this.distanceToPoint(e.center)<=e.radius},distanceToPlane:function(e){var t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;var i=-(this.origin.dot(e.normal)+e.constant)/t;return i>=0?i:null},intersectPlane:function(e,t){var i=this.distanceToPlane(e);return null===i?null:this.at(i,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 i,r,n,o,a,s,c=1/this.direction.x,h=1/this.direction.y,l=1/this.direction.z,u=this.origin;return c>=0?(i=(e.min.x-u.x)*c,r=(e.max.x-u.x)*c):(i=(e.max.x-u.x)*c,r=(e.min.x-u.x)*c),h>=0?(n=(e.min.y-u.y)*h,o=(e.max.y-u.y)*h):(n=(e.max.y-u.y)*h,o=(e.min.y-u.y)*h),i>o||n>r?null:((n>i||i!=i)&&(i=n),(o=0?(a=(e.min.z-u.z)*l,s=(e.max.z-u.z)*l):(a=(e.max.z-u.z)*l,s=(e.min.z-u.z)*l),i>s||a>r?null:((a>i||i!=i)&&(i=a),(s=0?i:r,t)))},intersectsBox:(Qt=new oe,function(e){return null!==this.intersectBox(e,Qt)}),intersectTriangle:function(){var e=new oe,t=new oe,i=new oe,r=new oe;return function(n,o,a,s,c){t.subVectors(o,n),i.subVectors(a,n),r.crossVectors(t,i);var h,l=this.direction.dot(r);if(l>0){if(s)return null;h=1}else{if(!(l<0))return null;h=-1,l=-l}e.subVectors(this.origin,n);var u=h*this.direction.dot(i.crossVectors(e,i));if(u<0)return null;var p=h*this.direction.dot(t.cross(e));if(p<0)return null;if(u+p>l)return null;var d=-h*e.dot(r);return d<0?null:this.at(d/l,c)}}(),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)}}),Object.assign(fi.prototype,{set:function(e,t){return this.start.copy(e),this.end.copy(t),this},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.start.copy(e.start),this.end.copy(e.end),this},getCenter:function(e){return(e||new oe).addVectors(this.start,this.end).multiplyScalar(.5)},delta:function(e){return(e||new oe).subVectors(this.end,this.start)},distanceSq:function(){return this.start.distanceToSquared(this.end)},distance:function(){return this.start.distanceTo(this.end)},at:function(e,t){var i=t||new oe;return this.delta(i).multiplyScalar(e).add(this.start)},closestPointToPointParameter:(ii=new oe,ri=new oe,function(e,t){ii.subVectors(e,this.start),ri.subVectors(this.end,this.start);var i=ri.dot(ri),r=ri.dot(ii)/i;return t&&(r=te.clamp(r,0,1)),r}),closestPointToPoint:function(e,t,i){var r=this.closestPointToPointParameter(e,t),n=i||new oe;return this.delta(n).multiplyScalar(r).add(this.start)},applyMatrix4:function(e){return this.start.applyMatrix4(e),this.end.applyMatrix4(e),this},equals:function(e){return e.start.equals(this.start)&&e.end.equals(this.end)}}),Object.assign(mi,{normal:(ni=new oe,function(e,t,i,r){var n=r||new oe;n.subVectors(i,t),ni.subVectors(e,t),n.cross(ni);var o=n.lengthSq();return o>0?n.multiplyScalar(1/Math.sqrt(o)):n.set(0,0,0)}),barycoordFromPoint:function(){var e=new oe,t=new oe,i=new oe;return function(r,n,o,a,s){e.subVectors(a,n),t.subVectors(o,n),i.subVectors(r,n);var c=e.dot(e),h=e.dot(t),l=e.dot(i),u=t.dot(t),p=t.dot(i),d=c*u-h*h,f=s||new oe;if(0===d)return f.set(-2,-1,-1);var m=1/d,v=(u*l-h*p)*m,g=(c*p-h*l)*m;return f.set(1-v-g,g,v)}}(),containsPoint:function(){var e=new oe;return function(t,i,r,n){var o=mi.barycoordFromPoint(t,i,r,n,e);return o.x>=0&&o.y>=0&&o.x+o.y<=1}}()}),Object.assign(mi.prototype,{set:function(e,t,i){return this.a.copy(e),this.b.copy(t),this.c.copy(i),this},setFromPointsAndIndices:function(e,t,i,r){return this.a.copy(e[t]),this.b.copy(e[i]),this.c.copy(e[r]),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},area:function(){var e=new oe,t=new oe;return function(){return e.subVectors(this.c,this.b),t.subVectors(this.a,this.b),.5*e.cross(t).length()}}(),midpoint:function(e){return(e||new oe).addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)},normal:function(e){return mi.normal(this.a,this.b,this.c,e)},plane:function(e){return(e||new _t).setFromCoplanarPoints(this.a,this.b,this.c)},barycoordFromPoint:function(e,t){return mi.barycoordFromPoint(e,this.a,this.b,this.c,t)},containsPoint:function(e){return mi.containsPoint(e,this.a,this.b,this.c)},closestPointToPoint:function(){var e=new _t,t=[new fi,new fi,new fi],i=new oe,r=new oe;return function(n,o){var a=o||new oe,s=1/0;if(e.setFromCoplanarPoints(this.a,this.b,this.c),e.projectPoint(n,i),!0===this.containsPoint(i))a.copy(i);else{t[0].set(this.a,this.b),t[1].set(this.b,this.c),t[2].set(this.c,this.a);for(var c=0;c0){var a=n[o[0]];if(void 0!==a)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=a.length;e0)for(this.morphTargetInfluences=[],this.morphTargetDictionary={},e=0,t=s.length;ei.far?null:{distance:c,point:f.clone(),object:e}}function g(e,t,i,a,s,c,p,f){r.fromBufferAttribute(a,c),n.fromBufferAttribute(a,p),o.fromBufferAttribute(a,f);var g=v(e,e.material,t,i,r,n,o,d);return g&&(s&&(h.fromBufferAttribute(s,c),l.fromBufferAttribute(s,p),u.fromBufferAttribute(s,f),g.uv=m(d,r,n,o,h,l,u)),g.face=new Ut(c,p,f,mi.normal(r,n,o)),g.faceIndex=c),g}return function(p,f){var y,x=this.geometry,b=this.material,w=this.matrixWorld;if(void 0!==b&&(null===x.boundingSphere&&x.computeBoundingSphere(),i.copy(x.boundingSphere),i.applyMatrix4(w),!1!==p.ray.intersectsSphere(i)&&(e.getInverse(w),t.copy(p.ray).applyMatrix4(e),null===x.boundingBox||!1!==t.intersectsBox(x.boundingBox))))if(x.isBufferGeometry){var _,M,E,T,S,A=x.index,L=x.attributes.position,R=x.attributes.uv;if(null!==A)for(T=0,S=A.count;T0&&(O=F);for(var B=0,z=U.length;B/gm,(function(e,t){var i=rt[t];if(void 0===i)throw new Error("Can not resolve #include <"+t+">");return ji(i)}))}function Hi(e){return e.replace(/for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g,(function(e,t,i,r){for(var n="",o=parseInt(t);o0?e.gammaFactor:1,T=function(e,t,i){return[(e=e||{}).derivatives||t.envMapCubeUV||t.bumpMap||t.normalMap||t.flatShading?"#extension GL_OES_standard_derivatives : enable":"",(e.fragDepth||t.logarithmicDepthBuffer)&&i.get("EXT_frag_depth")?"#extension GL_EXT_frag_depth : enable":"",e.drawBuffers&&i.get("WEBGL_draw_buffers")?"#extension GL_EXT_draw_buffers : require":"",(e.shaderTextureLOD||t.envMap)&&i.get("EXT_shader_texture_lod")?"#extension GL_EXT_shader_texture_lod : enable":""].filter(Gi).join("\n")}(r.extensions,o,t),S=function(e){var t=[];for(var i in e){var r=e[i];!1!==r&&t.push("#define "+i+" "+r)}return t.join("\n")}(s),A=a.createProgram();r.isRawShaderMaterial?((f=[S].filter(Gi).join("\n")).length>0&&(f+="\n"),(b=[T,S].filter(Gi).join("\n")).length>0&&(b+="\n")):(f=["precision "+o.precision+" float;","precision "+o.precision+" int;","#define SHADER_NAME "+n.name,S,o.supportsVertexTextures?"#define VERTEX_TEXTURES":"","#define GAMMA_FACTOR "+E,"#define MAX_BONES "+o.maxBones,o.useFog&&o.fog?"#define USE_FOG":"",o.useFog&&o.fogExp?"#define FOG_EXP2":"",o.map?"#define USE_MAP":"",o.envMap?"#define USE_ENVMAP":"",o.envMap?"#define "+p:"",o.lightMap?"#define USE_LIGHTMAP":"",o.aoMap?"#define USE_AOMAP":"",o.emissiveMap?"#define USE_EMISSIVEMAP":"",o.bumpMap?"#define USE_BUMPMAP":"",o.normalMap?"#define USE_NORMALMAP":"",o.displacementMap&&o.supportsVertexTextures?"#define USE_DISPLACEMENTMAP":"",o.specularMap?"#define USE_SPECULARMAP":"",o.roughnessMap?"#define USE_ROUGHNESSMAP":"",o.metalnessMap?"#define USE_METALNESSMAP":"",o.alphaMap?"#define USE_ALPHAMAP":"",o.vertexColors?"#define USE_COLOR":"",o.flatShading?"#define FLAT_SHADED":"",o.skinning?"#define USE_SKINNING":"",o.useVertexTexture?"#define BONE_TEXTURE":"",o.morphTargets?"#define USE_MORPHTARGETS":"",o.morphNormals&&!1===o.flatShading?"#define USE_MORPHNORMALS":"",o.doubleSided?"#define DOUBLE_SIDED":"",o.flipSided?"#define FLIP_SIDED":"","#define NUM_CLIPPING_PLANES "+o.numClippingPlanes,o.shadowMapEnabled?"#define USE_SHADOWMAP":"",o.shadowMapEnabled?"#define "+l:"",o.sizeAttenuation?"#define USE_SIZEATTENUATION":"",o.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",o.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"","uniform mat4 modelMatrix;","uniform mat4 modelViewMatrix;","uniform mat4 projectionMatrix;","uniform mat4 viewMatrix;","uniform mat3 normalMatrix;","uniform vec3 cameraPosition;","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#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(Gi).join("\n"),b=[T,"precision "+o.precision+" float;","precision "+o.precision+" int;","#define SHADER_NAME "+n.name,S,o.alphaTest?"#define ALPHATEST "+o.alphaTest:"","#define GAMMA_FACTOR "+E,o.useFog&&o.fog?"#define USE_FOG":"",o.useFog&&o.fogExp?"#define FOG_EXP2":"",o.map?"#define USE_MAP":"",o.envMap?"#define USE_ENVMAP":"",o.envMap?"#define "+u:"",o.envMap?"#define "+p:"",o.envMap?"#define "+d:"",o.lightMap?"#define USE_LIGHTMAP":"",o.aoMap?"#define USE_AOMAP":"",o.emissiveMap?"#define USE_EMISSIVEMAP":"",o.bumpMap?"#define USE_BUMPMAP":"",o.normalMap?"#define USE_NORMALMAP":"",o.specularMap?"#define USE_SPECULARMAP":"",o.roughnessMap?"#define USE_ROUGHNESSMAP":"",o.metalnessMap?"#define USE_METALNESSMAP":"",o.alphaMap?"#define USE_ALPHAMAP":"",o.vertexColors?"#define USE_COLOR":"",o.gradientMap?"#define USE_GRADIENTMAP":"",o.flatShading?"#define FLAT_SHADED":"",o.doubleSided?"#define DOUBLE_SIDED":"",o.flipSided?"#define FLIP_SIDED":"","#define NUM_CLIPPING_PLANES "+o.numClippingPlanes,"#define UNION_CLIPPING_PLANES "+(o.numClippingPlanes-o.numClipIntersection),o.shadowMapEnabled?"#define USE_SHADOWMAP":"",o.shadowMapEnabled?"#define "+l:"",o.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",o.physicallyCorrectLights?"#define PHYSICALLY_CORRECT_LIGHTS":"",o.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",o.logarithmicDepthBuffer&&t.get("EXT_frag_depth")?"#define USE_LOGDEPTHBUF_EXT":"",o.envMap&&t.get("EXT_shader_texture_lod")?"#define TEXTURE_LOD_EXT":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;",0!==o.toneMapping?"#define TONE_MAPPING":"",0!==o.toneMapping?rt.tonemapping_pars_fragment:"",0!==o.toneMapping?ki("toneMapping",o.toneMapping):"",o.dithering?"#define DITHERING":"",o.outputEncoding||o.mapEncoding||o.envMapEncoding||o.emissiveMapEncoding?rt.encodings_pars_fragment:"",o.mapEncoding?zi("mapTexelToLinear",o.mapEncoding):"",o.envMapEncoding?zi("envMapTexelToLinear",o.envMapEncoding):"",o.emissiveMapEncoding?zi("emissiveMapTexelToLinear",o.emissiveMapEncoding):"",o.outputEncoding?(w="linearToOutputTexel",_=o.outputEncoding,M=Bi(_),"vec4 "+w+"( vec4 value ) { return LinearTo"+M[0]+M[1]+"; }"):"",o.depthPacking?"#define DEPTH_PACKING "+r.depthPacking:"","\n"].filter(Gi).join("\n")),c=Vi(c=ji(c),o),h=Vi(h=ji(h),o),r.isShaderMaterial||(c=Hi(c),h=Hi(h));var L=f+c,R=b+h,C=Ci(a,a.VERTEX_SHADER,L),P=Ci(a,a.FRAGMENT_SHADER,R);a.attachShader(A,C),a.attachShader(A,P),void 0!==r.index0AttributeName?a.bindAttribLocation(A,0,r.index0AttributeName):!0===o.morphTargets&&a.bindAttribLocation(A,0,"position"),a.linkProgram(A);var N,O,I=a.getProgramInfoLog(A),D=a.getShaderInfoLog(C),U=a.getShaderInfoLog(P),F=!0,B=!0;return!1===a.getProgramParameter(A,a.LINK_STATUS)?(F=!1,console.error("THREE.WebGLProgram: shader error: ",a.getError(),"gl.VALIDATE_STATUS",a.getProgramParameter(A,a.VALIDATE_STATUS),"gl.getProgramInfoLog",I,D,U)):""!==I?console.warn("THREE.WebGLProgram: gl.getProgramInfoLog()",I):""!==D&&""!==U||(B=!1),B&&(this.diagnostics={runnable:F,material:r,programLog:I,vertexShader:{log:D,prefix:f},fragmentShader:{log:U,prefix:b}}),a.deleteShader(C),a.deleteShader(P),this.getUniforms=function(){return void 0===N&&(N=new Qe(a,A,e)),N},this.getAttributes=function(){return void 0===O&&(O=function(e,t){for(var i={},r=e.getProgramParameter(t,e.ACTIVE_ATTRIBUTES),n=0;n0,maxBones:p,useVertexTexture:i.floatVertexTextures,morphTargets:t.morphTargets,morphNormals:t.morphNormals,maxMorphTargets:e.maxMorphTargets,maxMorphNormals:e.maxMorphNormals,numDirLights:r.directional.length,numPointLights:r.point.length,numSpotLights:r.spot.length,numRectAreaLights:r.rectArea.length,numHemiLights:r.hemi.length,numClippingPlanes:c,numClipIntersection:h,dithering:t.dithering,shadowMapEnabled:e.shadowMap.enabled&&l.receiveShadow&&o.length>0,shadowMapType:e.shadowMap.type,toneMapping:e.toneMapping,physicallyCorrectLights:e.physicallyCorrectLights,premultipliedAlpha:t.premultipliedAlpha,alphaTest:t.alphaTest,doubleSided:2===t.side,flipSided:1===t.side,depthPacking:void 0!==t.depthPacking&&t.depthPacking}},this.getProgramCode=function(t,i){var r=[];if(i.shaderID?r.push(i.shaderID):(r.push(t.fragmentShader),r.push(t.vertexShader)),void 0!==t.defines)for(var n in t.defines)r.push(n),r.push(t.defines[n]);for(var a=0;at||e.height>t){var i=t/Math.max(e.width,e.height),r=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return r.width=Math.floor(e.width*i),r.height=Math.floor(e.height*i),r.getContext("2d").drawImage(e,0,0,e.width,e.height,0,0,r.width,r.height),console.warn("THREE.WebGLRenderer: image is too big ("+e.width+"x"+e.height+"). Resized to "+r.width+"x"+r.height,e),r}return e}function l(e){return te.isPowerOfTwo(e.width)&&te.isPowerOfTwo(e.height)}function u(e,t){return e.generateMipmaps&&t&&e.minFilter!==M&&e.minFilter!==S}function p(t){return t===M||t===E||t===T?e.NEAREST:e.LINEAR}function d(t){var i=t.target;i.removeEventListener("dispose",d),function(t){var i=r.get(t);if(t.image&&i.__image__webglTextureCube)e.deleteTexture(i.__image__webglTextureCube);else{if(void 0===i.__webglInit)return;e.deleteTexture(i.__webglTexture)}r.remove(t)}(i),i.isVideoTexture&&delete c[i.id],a.textures--}function f(t){var i=t.target;i.removeEventListener("dispose",f),function(t){var i=r.get(t),n=r.get(t.texture);if(!t)return;void 0!==n.__webglTexture&&e.deleteTexture(n.__webglTexture);t.depthTexture&&t.depthTexture.dispose();if(t.isWebGLRenderTargetCube)for(var o=0;o<6;o++)e.deleteFramebuffer(i.__webglFramebuffer[o]),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer[o]);else e.deleteFramebuffer(i.__webglFramebuffer),i.__webglDepthbuffer&&e.deleteRenderbuffer(i.__webglDepthbuffer);r.remove(t.texture),r.remove(t)}(i),a.textures--}function m(t,p){var f=r.get(t);if(t.version>0&&f.__version!==t.version){var m=t.image;if(void 0===m)console.warn("THREE.WebGLRenderer: Texture marked for update but image is undefined",t);else{if(!1!==m.complete)return void function(t,r,p){void 0===t.__webglInit&&(t.__webglInit=!0,r.addEventListener("dispose",d),t.__webglTexture=e.createTexture(),r.isVideoTexture&&(c[r.id]=r),a.textures++);i.activeTexture(e.TEXTURE0+p),i.bindTexture(e.TEXTURE_2D,t.__webglTexture),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,r.flipY),e.pixelStorei(e.UNPACK_PREMULTIPLY_ALPHA_WEBGL,r.premultiplyAlpha),e.pixelStorei(e.UNPACK_ALIGNMENT,r.unpackAlignment);var f=h(r.image,n.maxTextureSize);(function(e){return e.wrapS!==w||e.wrapT!==w||e.minFilter!==M&&e.minFilter!==S})(r)&&!1===l(f)&&(f=function(e){if(e instanceof HTMLImageElement||e instanceof HTMLCanvasElement||e instanceof ImageBitmap){var t=document.createElementNS("http://www.w3.org/1999/xhtml","canvas");return t.width=te.floorPowerOfTwo(e.width),t.height=te.floorPowerOfTwo(e.height),t.getContext("2d").drawImage(e,0,0,t.width,t.height),console.warn("THREE.WebGLRenderer: image is not power of two ("+e.width+"x"+e.height+"). Resized to "+t.width+"x"+t.height,e),t}return e}(f));var m=l(f),g=o.convert(r.format),y=o.convert(r.type);v(e.TEXTURE_2D,r,m);var x,b=r.mipmaps;if(r.isDepthTexture){var _=e.DEPTH_COMPONENT;if(r.type===N){if(!s)throw new Error("Float Depth Texture only supported in WebGL2.0");_=e.DEPTH_COMPONENT32F}else s&&(_=e.DEPTH_COMPONENT16);r.format===F&&_===e.DEPTH_COMPONENT&&r.type!==C&&r.type!==P&&(console.warn("THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture."),r.type=C,y=o.convert(r.type)),r.format===B&&(_=e.DEPTH_STENCIL,r.type!==I&&(console.warn("THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture."),r.type=I,y=o.convert(r.type))),i.texImage2D(e.TEXTURE_2D,0,_,f.width,f.height,0,g,y,null)}else if(r.isDataTexture)if(b.length>0&&m){for(var E=0,T=b.length;E-1?i.compressedTexImage2D(e.TEXTURE_2D,E,g,x.width,x.height,0,x.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()"):i.texImage2D(e.TEXTURE_2D,E,g,x.width,x.height,0,g,y,x.data);else if(b.length>0&&m){for(E=0,T=b.length;E1||r.get(a).__currentAnisotropy)&&(e.texParameterf(i,c.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(a.anisotropy,n.getMaxAnisotropy())),r.get(a).__currentAnisotropy=a.anisotropy)}}function g(t,n,a,s){var c=o.convert(n.texture.format),h=o.convert(n.texture.type);i.texImage2D(s,0,c,n.width,n.height,0,c,h,null),e.bindFramebuffer(e.FRAMEBUFFER,t),e.framebufferTexture2D(e.FRAMEBUFFER,a,s,r.get(n.texture).__webglTexture,0),e.bindFramebuffer(e.FRAMEBUFFER,null)}function y(t,i){e.bindRenderbuffer(e.RENDERBUFFER,t),i.depthBuffer&&!i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_COMPONENT16,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.RENDERBUFFER,t)):i.depthBuffer&&i.stencilBuffer?(e.renderbufferStorage(e.RENDERBUFFER,e.DEPTH_STENCIL,i.width,i.height),e.framebufferRenderbuffer(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.RENDERBUFFER,t)):e.renderbufferStorage(e.RENDERBUFFER,e.RGBA4,i.width,i.height),e.bindRenderbuffer(e.RENDERBUFFER,null)}function x(t){var i=r.get(t),n=!0===t.isWebGLRenderTargetCube;if(t.depthTexture){if(n)throw new Error("target.depthTexture not supported in Cube render targets");!function(t,i){if(i&&i.isWebGLRenderTargetCube)throw new Error("Depth Texture with cube render targets is not supported");if(e.bindFramebuffer(e.FRAMEBUFFER,t),!i.depthTexture||!i.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");r.get(i.depthTexture).__webglTexture&&i.depthTexture.image.width===i.width&&i.depthTexture.image.height===i.height||(i.depthTexture.image.width=i.width,i.depthTexture.image.height=i.height,i.depthTexture.needsUpdate=!0),m(i.depthTexture,0);var n=r.get(i.depthTexture).__webglTexture;if(i.depthTexture.format===F)e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_ATTACHMENT,e.TEXTURE_2D,n,0);else{if(i.depthTexture.format!==B)throw new Error("Unknown depthTexture format");e.framebufferTexture2D(e.FRAMEBUFFER,e.DEPTH_STENCIL_ATTACHMENT,e.TEXTURE_2D,n,0)}}(i.__webglFramebuffer,t)}else if(n){i.__webglDepthbuffer=[];for(var o=0;o<6;o++)e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer[o]),i.__webglDepthbuffer[o]=e.createRenderbuffer(),y(i.__webglDepthbuffer[o],t)}else e.bindFramebuffer(e.FRAMEBUFFER,i.__webglFramebuffer),i.__webglDepthbuffer=e.createRenderbuffer(),y(i.__webglDepthbuffer,t);e.bindFramebuffer(e.FRAMEBUFFER,null)}this.setTexture2D=m,this.setTextureCube=function(t,s){var c=r.get(t);if(6===t.image.length)if(t.version>0&&c.__version!==t.version){c.__image__webglTextureCube||(t.addEventListener("dispose",d),c.__image__webglTextureCube=e.createTexture(),a.textures++),i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube),e.pixelStorei(e.UNPACK_FLIP_Y_WEBGL,t.flipY);for(var p=t&&t.isCompressedTexture,f=t.image[0]&&t.image[0].isDataTexture,m=[],g=0;g<6;g++)m[g]=p||f?f?t.image[g].image:t.image[g]:h(t.image[g],n.maxCubemapSize);var y=l(m[0]),x=o.convert(t.format),b=o.convert(t.type);v(e.TEXTURE_CUBE_MAP,t,y);for(g=0;g<6;g++)if(p)for(var w,_=m[g].mipmaps,M=0,E=_.length;M-1?i.compressedTexImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,x,w.width,w.height,0,w.data):console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()"):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,M,x,w.width,w.height,0,x,b,w.data);else f?i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,x,m[g].width,m[g].height,0,x,b,m[g].data):i.texImage2D(e.TEXTURE_CUBE_MAP_POSITIVE_X+g,0,x,x,b,m[g]);u(t,y)&&e.generateMipmap(e.TEXTURE_CUBE_MAP),c.__version=t.version,t.onUpdate&&t.onUpdate(t)}else i.activeTexture(e.TEXTURE0+s),i.bindTexture(e.TEXTURE_CUBE_MAP,c.__image__webglTextureCube)},this.setTextureCubeDynamic=function(t,n){i.activeTexture(e.TEXTURE0+n),i.bindTexture(e.TEXTURE_CUBE_MAP,r.get(t).__webglTexture)},this.setupRenderTarget=function(t){var n=r.get(t),o=r.get(t.texture);t.addEventListener("dispose",f),o.__webglTexture=e.createTexture(),a.textures++;var s=!0===t.isWebGLRenderTargetCube,c=l(t);if(s){n.__webglFramebuffer=[];for(var h=0;h<6;h++)n.__webglFramebuffer[h]=e.createFramebuffer()}else n.__webglFramebuffer=e.createFramebuffer();if(s){i.bindTexture(e.TEXTURE_CUBE_MAP,o.__webglTexture),v(e.TEXTURE_CUBE_MAP,t.texture,c);for(h=0;h<6;h++)g(n.__webglFramebuffer[h],t,e.COLOR_ATTACHMENT0,e.TEXTURE_CUBE_MAP_POSITIVE_X+h);u(t.texture,c)&&e.generateMipmap(e.TEXTURE_CUBE_MAP),i.bindTexture(e.TEXTURE_CUBE_MAP,null)}else i.bindTexture(e.TEXTURE_2D,o.__webglTexture),v(e.TEXTURE_2D,t.texture,c),g(n.__webglFramebuffer,t,e.COLOR_ATTACHMENT0,e.TEXTURE_2D),u(t.texture,c)&&e.generateMipmap(e.TEXTURE_2D),i.bindTexture(e.TEXTURE_2D,null);t.depthBuffer&&x(t)},this.updateRenderTargetMipmap=function(t){var n=t.texture;if(u(n,l(t))){var o=t.isWebGLRenderTargetCube?e.TEXTURE_CUBE_MAP:e.TEXTURE_2D,a=r.get(n).__webglTexture;i.bindTexture(o,a),e.generateMipmap(o),i.bindTexture(o,null)}},this.updateVideoTextures=function(){for(var e in c)c[e].update()}}function Yi(){var e={};return{get:function(t){var i=t.uuid,r=e[i];return void 0===r&&(r={},e[i]=r),r},remove:function(t){delete e[t.uuid]},clear:function(){e={}}}}function Zi(e,t,i){var r=new function(){var t=!1,i=new he,r=null,n=new he(0,0,0,0);return{setMask:function(i){r===i||t||(e.colorMask(i,i,i,i),r=i)},setLocked:function(e){t=e},setClear:function(t,r,o,a,s){!0===s&&(t*=a,r*=a,o*=a),i.set(t,r,o,a),!1===n.equals(i)&&(e.clearColor(t,r,o,a),n.copy(i))},reset:function(){t=!1,r=null,n.set(-1,0,0,0)}}},n=new function(){var t=!1,i=null,r=null,n=null;return{setTest:function(t){t?D(e.DEPTH_TEST):U(e.DEPTH_TEST)},setMask:function(r){i===r||t||(e.depthMask(r),i=r)},setFunc:function(t){if(r!==t){if(t)switch(t){case 0:e.depthFunc(e.NEVER);break;case 1:e.depthFunc(e.ALWAYS);break;case 2:e.depthFunc(e.LESS);break;case 3:default:e.depthFunc(e.LEQUAL);break;case 4:e.depthFunc(e.EQUAL);break;case 5:e.depthFunc(e.GEQUAL);break;case 6:e.depthFunc(e.GREATER);break;case 7:e.depthFunc(e.NOTEQUAL)}else e.depthFunc(e.LEQUAL);r=t}},setLocked:function(e){t=e},setClear:function(t){n!==t&&(e.clearDepth(t),n=t)},reset:function(){t=!1,i=null,r=null,n=null}}},o=new function(){var t=!1,i=null,r=null,n=null,o=null,a=null,s=null,c=null,h=null;return{setTest:function(t){t?D(e.STENCIL_TEST):U(e.STENCIL_TEST)},setMask:function(r){i===r||t||(e.stencilMask(r),i=r)},setFunc:function(t,i,a){r===t&&n===i&&o===a||(e.stencilFunc(t,i,a),r=t,n=i,o=a)},setOp:function(t,i,r){a===t&&s===i&&c===r||(e.stencilOp(t,i,r),a=t,s=i,c=r)},setLocked:function(e){t=e},setClear:function(t){h!==t&&(e.clearStencil(t),h=t)},reset:function(){t=!1,i=null,r=null,n=null,o=null,a=null,s=null,c=null,h=null}}},a=e.getParameter(e.MAX_VERTEX_ATTRIBS),s=new Uint8Array(a),c=new Uint8Array(a),h=new Uint8Array(a),l={},u=null,p=null,d=null,f=null,m=null,v=null,g=null,y=null,x=null,b=!1,w=null,_=null,M=null,E=null,T=null,S=e.getParameter(e.MAX_COMBINED_TEXTURE_IMAGE_UNITS),A=parseFloat(/^WebGL\ ([0-9])/.exec(e.getParameter(e.VERSION))[1]),L=parseFloat(A)>=1,R=null,C={},P=new he,N=new he;function O(t,i,r){var n=new Uint8Array(4),o=e.createTexture();e.bindTexture(t,o),e.texParameteri(t,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(t,e.TEXTURE_MAG_FILTER,e.NEAREST);for(var a=0;a0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.HIGH_FLOAT).precision>0)return"highp";t="mediump"}return"mediump"===t&&e.getShaderPrecisionFormat(e.VERTEX_SHADER,e.MEDIUM_FLOAT).precision>0&&e.getShaderPrecisionFormat(e.FRAGMENT_SHADER,e.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}var o=void 0!==i.precision?i.precision:"highp",a=n(o);a!==o&&(console.warn("THREE.WebGLRenderer:",o,"not supported, using",a,"instead."),o=a);var s=!0===i.logarithmicDepthBuffer,c=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS),h=e.getParameter(e.MAX_VERTEX_TEXTURE_IMAGE_UNITS),l=e.getParameter(e.MAX_TEXTURE_SIZE),u=e.getParameter(e.MAX_CUBE_MAP_TEXTURE_SIZE),p=e.getParameter(e.MAX_VERTEX_ATTRIBS),d=e.getParameter(e.MAX_VERTEX_UNIFORM_VECTORS),f=e.getParameter(e.MAX_VARYING_VECTORS),m=e.getParameter(e.MAX_FRAGMENT_UNIFORM_VECTORS),v=h>0,g=!!t.get("OES_texture_float");return{getMaxAnisotropy:function(){if(void 0!==r)return r;var i=t.get("EXT_texture_filter_anisotropic");return r=null!==i?e.getParameter(i.MAX_TEXTURE_MAX_ANISOTROPY_EXT):0},getMaxPrecision:n,precision:o,logarithmicDepthBuffer:s,maxTextures:c,maxVertexTextures:h,maxTextureSize:l,maxCubemapSize:u,maxAttributes:p,maxVertexUniforms:d,maxVaryings:f,maxFragmentUniforms:m,vertexTextures:v,floatFragmentTextures:g,floatVertexTextures:v&&g}}function Ki(e,t,i,r){It.call(this),this.type="PerspectiveCamera",this.fov=void 0!==e?e:50,this.zoom=1,this.near=void 0!==i?i:.1,this.far=void 0!==r?r:2e3,this.focus=10,this.aspect=void 0!==t?t:1,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}function Qi(e){Ki.call(this),this.cameras=e||[]}function $i(e){var t=this,i=null,r=null,n=null;"undefined"!=typeof window&&"VRFrameData"in window&&(r=new window.VRFrameData);var o=new re,a=new Ki;a.bounds=new he(0,0,.5,1),a.layers.enable(1);var s=new Ki;s.bounds=new he(.5,0,.5,1),s.layers.enable(2);var c,h,l=new Qi([a,s]);function u(){if(null!==i&&i.isPresenting){var r=i.getEyeParameters("left"),n=r.renderWidth,o=r.renderHeight;h=e.getPixelRatio(),c=e.getSize(),e.setDrawingBufferSize(2*n,o,1)}else t.enabled&&e.setDrawingBufferSize(c.width,c.height,h)}l.layers.enable(1),l.layers.enable(2),"undefined"!=typeof window&&window.addEventListener("vrdisplaypresentchange",u,!1),this.enabled=!1,this.getDevice=function(){return i},this.setDevice=function(e){void 0!==e&&(i=e)},this.setPoseTarget=function(e){void 0!==e&&(n=e)},this.getCamera=function(e){if(null===i)return e;i.depthNear=e.near,i.depthFar=e.far,i.getFrameData(r);var t=r.pose,c=null!==n?n:e;if(null!==t.position?c.position.fromArray(t.position):c.position.set(0,0,0),null!==t.orientation&&c.quaternion.fromArray(t.orientation),c.updateMatrixWorld(),!1===i.isPresenting)return e;a.near=e.near,s.near=e.near,a.far=e.far,s.far=e.far,l.matrixWorld.copy(e.matrixWorld),l.matrixWorldInverse.copy(e.matrixWorldInverse),a.matrixWorldInverse.fromArray(r.leftViewMatrix),s.matrixWorldInverse.fromArray(r.rightViewMatrix);var h=c.parent;null!==h&&(o.getInverse(h.matrixWorld),a.matrixWorldInverse.multiply(o),s.matrixWorldInverse.multiply(o)),a.matrixWorld.getInverse(a.matrixWorldInverse),s.matrixWorld.getInverse(s.matrixWorldInverse),a.projectionMatrix.fromArray(r.leftProjectionMatrix),s.projectionMatrix.fromArray(r.rightProjectionMatrix),l.projectionMatrix.copy(a.projectionMatrix);var u=i.getLayers();if(u.length){var p=u[0];null!==p.leftBounds&&4===p.leftBounds.length&&a.bounds.fromArray(p.leftBounds),null!==p.rightBounds&&4===p.rightBounds.length&&s.bounds.fromArray(p.rightBounds)}return l},this.submitFrame=function(){i&&i.isPresenting&&i.submitFrame()},this.dispose=function(){"undefined"!=typeof window&&window.removeEventListener("vrdisplaypresentchange",u)}}function er(e){var t={};return{get:function(i){if(void 0!==t[i])return t[i];var r;switch(i){case"WEBGL_depth_texture":r=e.getExtension("WEBGL_depth_texture")||e.getExtension("MOZ_WEBGL_depth_texture")||e.getExtension("WEBKIT_WEBGL_depth_texture");break;case"EXT_texture_filter_anisotropic":r=e.getExtension("EXT_texture_filter_anisotropic")||e.getExtension("MOZ_EXT_texture_filter_anisotropic")||e.getExtension("WEBKIT_EXT_texture_filter_anisotropic");break;case"WEBGL_compressed_texture_s3tc":r=e.getExtension("WEBGL_compressed_texture_s3tc")||e.getExtension("MOZ_WEBGL_compressed_texture_s3tc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");break;case"WEBGL_compressed_texture_pvrtc":r=e.getExtension("WEBGL_compressed_texture_pvrtc")||e.getExtension("WEBKIT_WEBGL_compressed_texture_pvrtc");break;case"WEBGL_compressed_texture_etc1":r=e.getExtension("WEBGL_compressed_texture_etc1");break;default:r=e.getExtension(i)}return null===r&&console.warn("THREE.WebGLRenderer: "+i+" extension not supported."),t[i]=r,r}}}function tr(){var e=this,t=null,i=0,r=!1,n=!1,o=new _t,a=new ae,s={value:null,needsUpdate:!1};function c(){s.value!==t&&(s.value=t,s.needsUpdate=i>0),e.numPlanes=i,e.numIntersection=0}function h(t,i,r,n){var c=null!==t?t.length:0,h=null;if(0!==c){if(h=s.value,!0!==n||null===h){var l=r+4*c,u=i.matrixWorldInverse;a.getNormalMatrix(u),(null===h||h.length=0){var h=n[s];if(void 0!==h){var l=h.normalized,u=h.itemSize,p=w.get(h);if(void 0===p)continue;var d=p.buffer,f=p.type,g=p.bytesPerElement;if(h.isInterleavedBufferAttribute){var x=h.data,b=x.stride,_=h.offset;x&&x.isInstancedInterleavedBuffer?(y.enableAttributeAndDivisor(c,x.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=x.meshPerAttribute*x.count)):y.enableAttribute(c),m.bindBuffer(m.ARRAY_BUFFER,d),m.vertexAttribPointer(c,u,f,l,b*g,(r*b+_)*g)}else h.isInstancedBufferAttribute?(y.enableAttributeAndDivisor(c,h.meshPerAttribute),void 0===i.maxInstancedCount&&(i.maxInstancedCount=h.meshPerAttribute*h.count)):y.enableAttribute(c),m.bindBuffer(m.ARRAY_BUFFER,d),m.vertexAttribPointer(c,u,f,l,0,r*u*g)}else if(void 0!==a){var M=a[s];if(void 0!==M)switch(M.length){case 2:m.vertexAttrib2fv(c,M);break;case 3:m.vertexAttrib3fv(c,M);break;case 4:m.vertexAttrib4fv(c,M);break;default:m.vertexAttrib1fv(c,M)}}}}y.disableUnusedAttributes()}(r,s,i),null!==u&&m.bindBuffer(m.ELEMENT_ARRAY_BUFFER,l.buffer));var g=0;null!==u?g=u.count:void 0!==p&&(g=p.count);var x=i.drawRange.start*d,b=i.drawRange.count*d,M=null!==o?o.start*d:0,E=null!==o?o.count*d:1/0,T=Math.max(x,M),S=Math.min(g,x+b,M+E)-1,A=Math.max(0,S-T+1);if(0!==A){if(n.isMesh)if(!0===r.wireframe)y.setLineWidth(r.wireframeLinewidth*me()),f.setMode(m.LINES);else switch(n.drawMode){case 0:f.setMode(m.TRIANGLES);break;case 1:f.setMode(m.TRIANGLE_STRIP);break;case 2:f.setMode(m.TRIANGLE_FAN)}else if(n.isLine){var R=r.linewidth;void 0===R&&(R=1),y.setLineWidth(R*me()),n.isLineSegments?f.setMode(m.LINES):n.isLineLoop?f.setMode(m.LINE_LOOP):f.setMode(m.LINE_STRIP)}else n.isPoints&&f.setMode(m.POINTS);i&&i.isInstancedBufferGeometry?i.maxInstancedCount>0&&f.renderInstances(i,T,A):f.render(T,A)}},this.compile=function(e,t){l.length=0,u.length=0,e.traverse((function(e){e.isLight&&(l.push(e),e.castShadow&&u.push(e))})),E.setup(l,u,t),e.traverse((function(t){if(t.material)if(Array.isArray(t.material))for(var i=0;i=0&&e.numSupportedMorphTargets++}if(e.morphNormals){e.numSupportedMorphNormals=0;for(l=0;l=0&&e.numSupportedMorphNormals++}var p=r.shader.uniforms;(e.isShaderMaterial||e.isRawShaderMaterial)&&!0!==e.clipping||(r.numClippingPlanes=ae.numPlanes,r.numIntersection=ae.numIntersection,p.clippingPlanes=ae.uniform),r.fog=t,r.lightsHash=E.state.hash,e.lights&&(p.ambientLightColor.value=E.state.ambient,p.directionalLights.value=E.state.directional,p.spotLights.value=E.state.spot,p.rectAreaLights.value=E.state.rectArea,p.pointLights.value=E.state.point,p.hemisphereLights.value=E.state.hemi,p.directionalShadowMap.value=E.state.directionalShadowMap,p.directionalShadowMatrix.value=E.state.directionalShadowMatrix,p.spotShadowMap.value=E.state.spotShadowMap,p.spotShadowMatrix.value=E.state.spotShadowMatrix,p.pointShadowMap.value=E.state.pointShadowMap,p.pointShadowMatrix.value=E.state.pointShadowMatrix);var d=r.program.getUniforms(),f=Qe.seqWithValue(d.seq,p);r.uniformsList=f}function Ne(e,t,i,r){Z=0;var n=x.get(i);if(se&&(ce||e!==H)){var o=e===H&&i.id===V;ae.setState(i.clippingPlanes,i.clipIntersection,i.clipShadows,e,n,o)}!1===i.needsUpdate&&(void 0===n.program||i.fog&&n.fog!==t||i.lights&&n.lightsHash!==E.state.hash?i.needsUpdate=!0:void 0===n.numClippingPlanes||n.numClippingPlanes===ae.numPlanes&&n.numIntersection===ae.numIntersection||(i.needsUpdate=!0)),i.needsUpdate&&(Pe(i,t,r),i.needsUpdate=!1);var a,s,c=!1,h=!1,l=!1,u=n.program,p=u.getUniforms(),d=n.shader.uniforms;if(y.useProgram(u.program)&&(c=!0,h=!0,l=!0),i.id!==V&&(V=i.id,h=!0),c||e!==H){if(p.setValue(m,"projectionMatrix",e.projectionMatrix),g.logarithmicDepthBuffer&&p.setValue(m,"logDepthBufFC",2/(Math.log(e.far+1)/Math.LN2)),H!==(W||e)&&(H=W||e,h=!0,l=!0),i.isShaderMaterial||i.isMeshPhongMaterial||i.isMeshStandardMaterial||i.envMap){var f=p.map.cameraPosition;void 0!==f&&f.setValue(m,ue.setFromMatrixPosition(e.matrixWorld))}(i.isMeshPhongMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial||i.skinning)&&p.setValue(m,"viewMatrix",e.matrixWorldInverse)}if(i.skinning){p.setOptional(m,r,"bindMatrix"),p.setOptional(m,r,"bindMatrixInverse");var v=r.skeleton;if(v){var b=v.bones;if(g.floatVertexTextures){if(void 0===v.boneTexture){var w=Math.sqrt(4*b.length);w=te.ceilPowerOfTwo(w),w=Math.max(w,4);var _=new Float32Array(w*w*4);_.set(v.boneMatrices);var M=new pe(_,w,w,U,N);v.boneMatrices=_,v.boneTexture=M,v.boneTextureSize=w}p.setValue(m,"boneTexture",v.boneTexture),p.setValue(m,"boneTextureSize",v.boneTextureSize)}else p.setOptional(m,v,"boneMatrices")}}return h&&(p.setValue(m,"toneMappingExposure",B.toneMappingExposure),p.setValue(m,"toneMappingWhitePoint",B.toneMappingWhitePoint),i.lights&&(s=l,(a=d).ambientLightColor.needsUpdate=s,a.directionalLights.needsUpdate=s,a.pointLights.needsUpdate=s,a.spotLights.needsUpdate=s,a.rectAreaLights.needsUpdate=s,a.hemisphereLights.needsUpdate=s),t&&i.fog&&function(e,t){e.fogColor.value=t.color,t.isFog?(e.fogNear.value=t.near,e.fogFar.value=t.far):t.isFogExp2&&(e.fogDensity.value=t.density)}(d,t),i.isMeshBasicMaterial?Oe(d,i):i.isMeshLambertMaterial?(Oe(d,i),function(e,t){t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap)}(d,i)):i.isMeshPhongMaterial?(Oe(d,i),i.isMeshToonMaterial?function(e,t){Ie(e,t),t.gradientMap&&(e.gradientMap.value=t.gradientMap)}(d,i):Ie(d,i)):i.isMeshStandardMaterial?(Oe(d,i),i.isMeshPhysicalMaterial?function(e,t){e.clearCoat.value=t.clearCoat,e.clearCoatRoughness.value=t.clearCoatRoughness,De(e,t)}(d,i):De(d,i)):i.isMeshDepthMaterial?(Oe(d,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(d,i)):i.isMeshDistanceMaterial?(Oe(d,i),function(e,t){t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias);e.referencePosition.value.copy(t.referencePosition),e.nearDistance.value=t.nearDistance,e.farDistance.value=t.farDistance}(d,i)):i.isMeshNormalMaterial?(Oe(d,i),function(e,t){t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale);t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale));t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}(d,i)):i.isLineBasicMaterial?(function(e,t){e.diffuse.value=t.color,e.opacity.value=t.opacity}(d,i),i.isLineDashedMaterial&&function(e,t){e.dashSize.value=t.dashSize,e.totalSize.value=t.dashSize+t.gapSize,e.scale.value=t.scale}(d,i)):i.isPointsMaterial?function(e,t){if(e.diffuse.value=t.color,e.opacity.value=t.opacity,e.size.value=t.size*Q,e.scale.value=.5*K,e.map.value=t.map,null!==t.map){if(!0===t.map.matrixAutoUpdate){var i=t.map.offset,r=t.map.repeat,n=t.map.rotation,o=t.map.center;t.map.matrix.setUvTransform(i.x,i.y,r.x,r.y,n,o.x,o.y)}e.uvTransform.value.copy(t.map.matrix)}}(d,i):i.isShadowMaterial&&(d.color.value=i.color,d.opacity.value=i.opacity),void 0!==d.ltcMat&&(d.ltcMat.value=tt.LTC_MAT_TEXTURE),void 0!==d.ltcMag&&(d.ltcMag.value=tt.LTC_MAG_TEXTURE),Qe.upload(m,n.uniformsList,d,B)),p.setValue(m,"modelViewMatrix",r.modelViewMatrix),p.setValue(m,"normalMatrix",r.normalMatrix),p.setValue(m,"modelMatrix",r.matrixWorld),u}function Oe(e,t){var i;if(e.opacity.value=t.opacity,t.color&&(e.diffuse.value=t.color),t.emissive&&e.emissive.value.copy(t.emissive).multiplyScalar(t.emissiveIntensity),t.map&&(e.map.value=t.map),t.alphaMap&&(e.alphaMap.value=t.alphaMap),t.specularMap&&(e.specularMap.value=t.specularMap),t.envMap&&(e.envMap.value=t.envMap,e.flipEnvMap.value=t.envMap&&t.envMap.isCubeTexture?-1:1,e.reflectivity.value=t.reflectivity,e.refractionRatio.value=t.refractionRatio),t.lightMap&&(e.lightMap.value=t.lightMap,e.lightMapIntensity.value=t.lightMapIntensity),t.aoMap&&(e.aoMap.value=t.aoMap,e.aoMapIntensity.value=t.aoMapIntensity),t.map?i=t.map:t.specularMap?i=t.specularMap:t.displacementMap?i=t.displacementMap:t.normalMap?i=t.normalMap:t.bumpMap?i=t.bumpMap:t.roughnessMap?i=t.roughnessMap:t.metalnessMap?i=t.metalnessMap:t.alphaMap?i=t.alphaMap:t.emissiveMap&&(i=t.emissiveMap),void 0!==i){if(i.isWebGLRenderTarget&&(i=i.texture),!0===i.matrixAutoUpdate){var r=i.offset,n=i.repeat,o=i.rotation,a=i.center;i.matrix.setUvTransform(r.x,r.y,n.x,n.y,o,a.x,a.y)}e.uvTransform.value.copy(i.matrix)}}function Ie(e,t){e.specular.value=t.specular,e.shininess.value=Math.max(t.shininess,1e-4),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale)),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias)}function De(e,t){e.roughness.value=t.roughness,e.metalness.value=t.metalness,t.roughnessMap&&(e.roughnessMap.value=t.roughnessMap),t.metalnessMap&&(e.metalnessMap.value=t.metalnessMap),t.emissiveMap&&(e.emissiveMap.value=t.emissiveMap),t.bumpMap&&(e.bumpMap.value=t.bumpMap,e.bumpScale.value=t.bumpScale),t.normalMap&&(e.normalMap.value=t.normalMap,e.normalScale.value.copy(t.normalScale)),t.displacementMap&&(e.displacementMap.value=t.displacementMap,e.displacementScale.value=t.displacementScale,e.displacementBias.value=t.displacementBias),t.envMap&&(e.envMapIntensity.value=t.envMapIntensity)}this.animate=function(e){Se=e,function(){if(!Te){var e=ye.getDevice();e&&e.isPresenting?e.requestAnimationFrame(Ae):window.requestAnimationFrame(Ae),Te=!0}}()},this.render=function(e,t,i,r){if(t&&t.isCamera){if(!z){j="",V=-1,H=null,!0===e.autoUpdate&&e.updateMatrixWorld(),null===t.parent&&t.updateMatrixWorld(),ye.enabled&&(t=ye.getCamera(t)),le.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),ne.setFromMatrix(le),l.length=0,u.length=0,d.length=0,f.length=0,ce=this.localClippingEnabled,se=ae.init(this.clippingPlanes,ce,t),(p=S.get(e,t)).init(),Le(e,t,B.sortObjects),!0===B.sortObjects&&p.sort(),b.updateVideoTextures(),se&&ae.beginShadows(),xe.render(u,e,t),E.setup(l,u,t),se&&ae.endShadows(),fe.frame++,fe.calls=0,fe.vertices=0,fe.faces=0,fe.points=0,void 0===i&&(i=null),this.setRenderTarget(i),A.render(p,e,t,r);var n=p.opaque,o=p.transparent;if(e.overrideMaterial){var a=e.overrideMaterial;n.length&&Re(n,e,t,a),o.length&&Re(o,e,t,a)}else n.length&&Re(n,e,t),o.length&&Re(o,e,t);D.render(d,e,t),I.render(f,e,t,X),i&&b.updateRenderTargetMipmap(i),y.buffers.depth.setTest(!0),y.buffers.depth.setMask(!0),y.buffers.color.setMask(!0),y.setPolygonOffset(!1),ye.enabled&&ye.submitFrame()}}else console.error("THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.")},this.setFaceCulling=function(e,t){y.setCullFace(e),y.setFlipSided(0===t)},this.allocTextureUnit=function(){var e=Z;return e>=g.maxTextures&&console.warn("THREE.WebGLRenderer: Trying to use "+e+" texture units while this GPU supports only "+g.maxTextures),Z+=1,e},this.setTexture2D=(Ee=!1,function(e,t){e&&e.isWebGLRenderTarget&&(Ee||(console.warn("THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead."),Ee=!0),e=e.texture),b.setTexture2D(e,t)}),this.setTexture=function(){var e=!1;return function(t,i){e||(console.warn("THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead."),e=!0),b.setTexture2D(t,i)}}(),this.setTextureCube=function(){var e=!1;return function(t,i){t&&t.isWebGLRenderTargetCube&&(e||(console.warn("THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead."),e=!0),t=t.texture),t&&t.isCubeTexture||Array.isArray(t.image)&&6===t.image.length?b.setTextureCube(t,i):b.setTextureCubeDynamic(t,i)}}(),this.getRenderTarget=function(){return k},this.setRenderTarget=function(e){k=e,e&&void 0===x.get(e).__webglFramebuffer&&b.setupRenderTarget(e);var t=null,i=!1;if(e){var r=x.get(e).__webglFramebuffer;e.isWebGLRenderTargetCube?(t=r[e.activeCubeFace],i=!0):t=r,X.copy(e.viewport),q.copy(e.scissor),Y=e.scissorTest}else X.copy($).multiplyScalar(Q),q.copy(ee).multiplyScalar(Q),Y=ie;if(G!==t&&(m.bindFramebuffer(m.FRAMEBUFFER,t),G=t),y.viewport(X),y.scissor(q),y.setScissorTest(Y),i){var n=x.get(e.texture);m.framebufferTexture2D(m.FRAMEBUFFER,m.COLOR_ATTACHMENT0,m.TEXTURE_CUBE_MAP_POSITIVE_X+e.activeCubeFace,n.__webglTexture,e.activeMipMapLevel)}},this.readRenderTargetPixels=function(e,t,i,r,n,o){if(e&&e.isWebGLRenderTarget){var a=x.get(e).__webglFramebuffer;if(a){var s=!1;a!==G&&(m.bindFramebuffer(m.FRAMEBUFFER,a),s=!0);try{var c=e.texture,h=c.format,l=c.type;if(h!==U&&F.convert(h)!==m.getParameter(m.IMPLEMENTATION_COLOR_READ_FORMAT))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!(l===R||F.convert(l)===m.getParameter(m.IMPLEMENTATION_COLOR_READ_TYPE)||l===N&&(v.get("OES_texture_float")||v.get("WEBGL_color_buffer_float"))||l===O&&v.get("EXT_color_buffer_half_float")))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");m.checkFramebufferStatus(m.FRAMEBUFFER)===m.FRAMEBUFFER_COMPLETE?t>=0&&t<=e.width-r&&i>=0&&i<=e.height-n&&m.readPixels(t,i,r,n,F.convert(h),F.convert(l),o):console.error("THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.")}finally{s&&m.bindFramebuffer(m.FRAMEBUFFER,G)}}}else console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.")}}function nr(e,t){this.name="",this.color=new et(e),this.density=void 0!==t?t:25e-5}function or(e,t,i){this.name="",this.color=new et(e),this.near=void 0!==t?t:1,this.far=void 0!==i?i:1e3}function ar(){Ot.call(this),this.type="Scene",this.background=null,this.fog=null,this.overrideMaterial=null,this.autoUpdate=!0}function sr(e,t,i,r,n){Ot.call(this),this.lensFlares=[],this.positionScreen=new oe,this.customUpdateCallback=void 0,void 0!==e&&this.add(e,t,i,r,n)}function cr(e){gt.call(this),this.type="SpriteMaterial",this.color=new et(16777215),this.map=null,this.rotation=0,this.fog=!1,this.lights=!1,this.setValues(e)}function hr(e){Ot.call(this),this.type="Sprite",this.material=void 0!==e?e:new cr}function lr(){Ot.call(this),this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]}})}function ur(e,t){if(e=e||[],this.bones=e.slice(0),this.boneMatrices=new Float32Array(16*this.bones.length),void 0===t)this.calculateInverses();else if(this.bones.length===t.length)this.boneInverses=t.slice(0);else{console.warn("THREE.Skeleton boneInverses is the wrong length."),this.boneInverses=[];for(var i=0,r=this.bones.length;i=0?(p=e(g-h,v,p),d.subVectors(u,p)):(p=e(g+h,v,p),d.subVectors(p,u)),v-h>=0?(p=e(g,v-h,p),f.subVectors(u,p)):(p=e(g,v+h,p),f.subVectors(p,u)),l.crossVectors(d,f).normalize(),s.push(l.x,l.y,l.z),c.push(g,v)}}for(r=0;r.9&&a<.1&&(t<.2&&(o[e+0]+=1),i<.2&&(o[e+2]+=1),r<.2&&(o[e+4]+=1))}}()}(),this.addAttribute("position",new Yt(n,3)),this.addAttribute("normal",new Yt(n.slice(),3)),this.addAttribute("uv",new Yt(o,2)),0===r?this.computeVertexNormals():this.normalizeNormals()}function Rr(e,t){zt.call(this),this.type="TetrahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Cr(e,t)),this.mergeVertices()}function Cr(e,t){Lr.call(this,[1,1,1,-1,-1,1,-1,1,-1,1,-1,-1],[2,1,0,0,3,2,1,3,0,2,3,1],e,t),this.type="TetrahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Pr(e,t){zt.call(this),this.type="OctahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Nr(e,t)),this.mergeVertices()}function Nr(e,t){Lr.call(this,[1,0,0,-1,0,0,0,1,0,0,-1,0,0,0,1,0,0,-1],[0,2,4,0,4,3,0,3,5,0,5,2,1,2,5,1,5,3,1,3,4,1,4,2],e,t),this.type="OctahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Or(e,t){zt.call(this),this.type="IcosahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Ir(e,t)),this.mergeVertices()}function Ir(e,t){var i=(1+Math.sqrt(5))/2,r=[-1,i,0,1,i,0,-1,-i,0,1,-i,0,0,-1,i,0,1,i,0,-1,-i,0,1,-i,i,0,-1,i,0,1,-i,0,-1,-i,0,1];Lr.call(this,r,[0,11,5,0,5,1,0,1,7,0,7,10,0,10,11,1,5,9,5,11,4,11,10,2,10,7,6,7,1,8,3,9,4,3,4,2,3,2,6,3,6,8,3,8,9,4,9,5,2,4,11,6,2,10,8,6,7,9,8,1],e,t),this.type="IcosahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Dr(e,t){zt.call(this),this.type="DodecahedronGeometry",this.parameters={radius:e,detail:t},this.fromBufferGeometry(new Ur(e,t)),this.mergeVertices()}function Ur(e,t){var i=(1+Math.sqrt(5))/2,r=1/i,n=[-1,-1,-1,-1,-1,1,-1,1,-1,-1,1,1,1,-1,-1,1,-1,1,1,1,-1,1,1,1,0,-r,-i,0,-r,i,0,r,-i,0,r,i,-r,-i,0,-r,i,0,r,-i,0,r,i,0,-i,0,-r,i,0,-r,-i,0,r,i,0,r];Lr.call(this,n,[3,11,7,3,7,15,3,15,13,7,19,17,7,17,6,7,6,15,17,4,8,17,8,10,17,10,6,8,0,16,8,16,2,8,2,10,0,12,1,0,1,18,0,18,16,6,10,2,6,2,13,6,13,15,2,16,18,2,18,3,2,3,13,18,1,9,18,9,11,18,11,3,4,14,12,4,12,0,4,0,8,11,9,5,11,5,19,11,19,7,19,5,14,19,14,4,19,4,17,1,12,14,1,14,5,1,5,9],e,t),this.type="DodecahedronBufferGeometry",this.parameters={radius:e,detail:t}}function Fr(e,t,i,r,n,o){zt.call(this),this.type="TubeGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},void 0!==o&&console.warn("THREE.TubeGeometry: taper has been removed.");var a=new Br(e,t,i,r,n);this.tangents=a.tangents,this.normals=a.normals,this.binormals=a.binormals,this.fromBufferGeometry(a),this.mergeVertices()}function Br(e,t,i,r,n){ai.call(this),this.type="TubeBufferGeometry",this.parameters={path:e,tubularSegments:t,radius:i,radialSegments:r,closed:n},t=t||64,i=i||1,r=r||8,n=n||!1;var o=e.computeFrenetFrames(t,n);this.tangents=o.tangents,this.normals=o.normals,this.binormals=o.binormals;var a,s,c=new oe,h=new oe,l=new ie,u=new oe,p=[],d=[],f=[],m=[];function v(n){u=e.getPointAt(n/t,u);var a=o.normals[n],l=o.binormals[n];for(s=0;s<=r;s++){var f=s/r*Math.PI*2,m=Math.sin(f),v=-Math.cos(f);h.x=v*a.x+m*l.x,h.y=v*a.y+m*l.y,h.z=v*a.z+m*l.z,h.normalize(),d.push(h.x,h.y,h.z),c.x=u.x+i*h.x,c.y=u.y+i*h.y,c.z=u.z+i*h.z,p.push(c.x,c.y,c.z)}}!function(){for(a=0;ai)){var r=e.ray.origin.distanceTo(Pi);re.far||t.push({distance:r,point:Pi.clone(),face:null,object:this})}}),clone:function(){return new this.constructor(this.material).copy(this)}}),lr.prototype=Object.assign(Object.create(Ot.prototype),{constructor:lr,copy:function(e){Ot.prototype.copy.call(this,e,!1);for(var t=e.levels,i=0,r=t.length;i1){e.setFromMatrixPosition(i.matrixWorld),t.setFromMatrixPosition(this.matrixWorld);var n=e.distanceTo(t);r[0].object.visible=!0;for(var o=1,a=r.length;o=r[o].distance;o++)r[o-1].object.visible=!1,r[o].object.visible=!0;for(;oa))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}else for(g=0,y=m.length/3-1;ga))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}else if(s.isGeometry){var w=s.vertices,_=w.length;for(g=0;g<_-1;g+=d){var M;if(!(t.distanceSqToSegment(w[g],w[g+1],p,u)>a))p.applyMatrix4(this.matrixWorld),(M=r.ray.origin.distanceTo(p))r.far||n.push({distance:M,point:u.clone().applyMatrix4(this.matrixWorld),index:g,face:null,faceIndex:null,object:this})}}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),vr.prototype=Object.assign(Object.create(mr.prototype),{constructor:vr,isLineSegments:!0}),gr.prototype=Object.assign(Object.create(mr.prototype),{constructor:gr,isLineLoop:!0}),yr.prototype=Object.create(gt.prototype),yr.prototype.constructor=yr,yr.prototype.isPointsMaterial=!0,yr.prototype.copy=function(e){return gt.prototype.copy.call(this,e),this.color.copy(e.color),this.map=e.map,this.size=e.size,this.sizeAttenuation=e.sizeAttenuation,this},xr.prototype=Object.assign(Object.create(Ot.prototype),{constructor:xr,isPoints:!0,raycast:function(){var e=new re,t=new di,i=new wt;return function(r,n){var o=this,a=this.geometry,s=this.matrixWorld,c=r.params.Points.threshold;if(null===a.boundingSphere&&a.computeBoundingSphere(),i.copy(a.boundingSphere),i.applyMatrix4(s),i.radius+=c,!1!==r.ray.intersectsSphere(i)){e.getInverse(s),t.copy(r.ray).applyMatrix4(e);var h=c/((this.scale.x+this.scale.y+this.scale.z)/3),l=h*h,u=new oe;if(a.isBufferGeometry){var p=a.index,d=a.attributes.position.array;if(null!==p)for(var f=p.array,m=0,v=f.length;mr.far)return;n.push({distance:h,distanceToRay:Math.sqrt(a),point:c.clone(),index:i,face:null,object:o})}}}}(),clone:function(){return new this.constructor(this.geometry,this.material).copy(this)}}),br.prototype=Object.assign(Object.create(Ot.prototype),{constructor:br,isGroup:!0}),wr.prototype=Object.assign(Object.create(ce.prototype),{constructor:wr,isVideoTexture:!0,update:function(){var e=this.image;e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}),_r.prototype=Object.create(ce.prototype),_r.prototype.constructor=_r,_r.prototype.isCompressedTexture=!0,Mr.prototype=Object.create(ce.prototype),Mr.prototype.constructor=Mr,Mr.prototype.isDepthTexture=!0,Er.prototype=Object.create(ai.prototype),Er.prototype.constructor=Er,Tr.prototype=Object.create(zt.prototype),Tr.prototype.constructor=Tr,Sr.prototype=Object.create(ai.prototype),Sr.prototype.constructor=Sr,Ar.prototype=Object.create(zt.prototype),Ar.prototype.constructor=Ar,Lr.prototype=Object.create(ai.prototype),Lr.prototype.constructor=Lr,Rr.prototype=Object.create(zt.prototype),Rr.prototype.constructor=Rr,Cr.prototype=Object.create(Lr.prototype),Cr.prototype.constructor=Cr,Pr.prototype=Object.create(zt.prototype),Pr.prototype.constructor=Pr,Nr.prototype=Object.create(Lr.prototype),Nr.prototype.constructor=Nr,Or.prototype=Object.create(zt.prototype),Or.prototype.constructor=Or,Ir.prototype=Object.create(Lr.prototype),Ir.prototype.constructor=Ir,Dr.prototype=Object.create(zt.prototype),Dr.prototype.constructor=Dr,Ur.prototype=Object.create(Lr.prototype),Ur.prototype.constructor=Ur,Fr.prototype=Object.create(zt.prototype),Fr.prototype.constructor=Fr,Br.prototype=Object.create(ai.prototype),Br.prototype.constructor=Br,zr.prototype=Object.create(zt.prototype),zr.prototype.constructor=zr,kr.prototype=Object.create(ai.prototype),kr.prototype.constructor=kr,Gr.prototype=Object.create(zt.prototype),Gr.prototype.constructor=Gr,Vr.prototype=Object.create(ai.prototype),Vr.prototype.constructor=Vr;var jr=function(e,t,i){i=i||2;var r,n,o,a,s,c,h,l=t&&t.length,u=l?t[0]*i:e.length,p=Hr(e,0,u,i,!0),d=[];if(!p)return d;if(l&&(p=function(e,t,i,r){var n,o,a,s=[];for(n=0,o=t.length;n80*i){r=o=e[0],n=a=e[1];for(var f=i;fo&&(o=s),c>a&&(a=c);h=0!==(h=Math.max(o-r,a-n))?1/h:0}return Xr(p,d,i,r,n,h),d};function Hr(e,t,i,r,n){var o,a;if(n===function(e,t,i,r){for(var n=0,o=t,a=i-r;o0)for(o=t;o=t;o-=r)a=hn(o,e[o],e[o+1],a);return a&&on(a,a.next)&&(ln(a),a=a.next),a}function Wr(e,t){if(!e)return e;t||(t=e);var i,r=e;do{if(i=!1,r.steiner||!on(r,r.next)&&0!==nn(r.prev,r,r.next))r=r.next;else{if(ln(r),(r=t=r.prev)===r.next)break;i=!0}}while(i||r!==t);return t}function Xr(e,t,i,r,n,o,a){if(e){!a&&o&&function(e,t,i,r){var n=e;do{null===n.z&&(n.z=$r(n.x,n.y,t,i,r)),n.prevZ=n.prev,n.nextZ=n.next,n=n.next}while(n!==e);n.prevZ.nextZ=null,n.prevZ=null,function(e){var t,i,r,n,o,a,s,c,h=1;do{for(i=e,e=null,o=null,a=0;i;){for(a++,r=i,s=0,t=0;t0||c>0&&r;)0!==s&&(0===c||!r||i.z<=r.z)?(n=i,i=i.nextZ,s--):(n=r,r=r.nextZ,c--),o?o.nextZ=n:e=n,n.prevZ=o,o=n;i=r}o.nextZ=null,h*=2}while(a>1)}(n)}(e,r,n,o);for(var s,c,h=e;e.prev!==e.next;)if(s=e.prev,c=e.next,o?Yr(e,r,n,o):qr(e))t.push(s.i/i),t.push(e.i/i),t.push(c.i/i),ln(e),e=c.next,h=c.next;else if((e=c)===h){a?1===a?Xr(e=Zr(e,t,i),t,i,r,n,o,2):2===a&&Jr(e,t,i,r,n,o):Xr(Wr(e),t,i,r,n,o,1);break}}}function qr(e){var t=e.prev,i=e,r=e.next;if(nn(t,i,r)>=0)return!1;for(var n=e.next.next;n!==e.prev;){if(tn(t.x,t.y,i.x,i.y,r.x,r.y,n.x,n.y)&&nn(n.prev,n,n.next)>=0)return!1;n=n.next}return!0}function Yr(e,t,i,r){var n=e.prev,o=e,a=e.next;if(nn(n,o,a)>=0)return!1;for(var s=n.xo.x?n.x>a.x?n.x:a.x:o.x>a.x?o.x:a.x,l=n.y>o.y?n.y>a.y?n.y:a.y:o.y>a.y?o.y:a.y,u=$r(s,c,t,i,r),p=$r(h,l,t,i,r),d=e.nextZ;d&&d.z<=p;){if(d!==e.prev&&d!==e.next&&tn(n.x,n.y,o.x,o.y,a.x,a.y,d.x,d.y)&&nn(d.prev,d,d.next)>=0)return!1;d=d.nextZ}for(d=e.prevZ;d&&d.z>=u;){if(d!==e.prev&&d!==e.next&&tn(n.x,n.y,o.x,o.y,a.x,a.y,d.x,d.y)&&nn(d.prev,d,d.next)>=0)return!1;d=d.prevZ}return!0}function Zr(e,t,i){var r=e;do{var n=r.prev,o=r.next.next;!on(n,o)&&an(n,r,r.next,o)&&sn(n,o)&&sn(o,n)&&(t.push(n.i/i),t.push(r.i/i),t.push(o.i/i),ln(r),ln(r.next),r=e=o),r=r.next}while(r!==e);return r}function Jr(e,t,i,r,n,o){var a=e;do{for(var s=a.next.next;s!==a.prev;){if(a.i!==s.i&&rn(a,s)){var c=cn(a,s);return a=Wr(a,a.next),c=Wr(c,c.next),Xr(a,t,i,r,n,o),void Xr(c,t,i,r,n,o)}s=s.next}a=a.next}while(a!==e)}function Kr(e,t){return e.x-t.x}function Qr(e,t){if(t=function(e,t){var i,r=t,n=e.x,o=e.y,a=-1/0;do{if(o<=r.y&&o>=r.next.y&&r.next.y!==r.y){var s=r.x+(o-r.y)*(r.next.x-r.x)/(r.next.y-r.y);if(s<=n&&s>a){if(a=s,s===n){if(o===r.y)return r;if(o===r.next.y)return r.next}i=r.x=r.x&&r.x>=l&&n!==r.x&&tn(oi.x)&&sn(r,e)&&(i=r,p=c),r=r.next;return i}(e,t),t){var i=cn(t,e);Wr(i,i.next)}}function $r(e,t,i,r,n){return(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=32767*(e-i)*n)|e<<8))|e<<4))|e<<2))|e<<1))|(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=32767*(t-r)*n)|t<<8))|t<<4))|t<<2))|t<<1))<<1}function en(e){var t=e,i=e;do{t.x=0&&(e-a)*(r-s)-(i-a)*(t-s)>=0&&(i-a)*(o-s)-(n-a)*(r-s)>=0}function rn(e,t){return e.next.i!==t.i&&e.prev.i!==t.i&&!function(e,t){var i=e;do{if(i.i!==e.i&&i.next.i!==e.i&&i.i!==t.i&&i.next.i!==t.i&&an(i,i.next,e,t))return!0;i=i.next}while(i!==e);return!1}(e,t)&&sn(e,t)&&sn(t,e)&&function(e,t){var i=e,r=!1,n=(e.x+t.x)/2,o=(e.y+t.y)/2;do{i.y>o!=i.next.y>o&&i.next.y!==i.y&&n<(i.next.x-i.x)*(o-i.y)/(i.next.y-i.y)+i.x&&(r=!r),i=i.next}while(i!==e);return r}(e,t)}function nn(e,t,i){return(t.y-e.y)*(i.x-t.x)-(t.x-e.x)*(i.y-t.y)}function on(e,t){return e.x===t.x&&e.y===t.y}function an(e,t,i,r){return!!(on(e,t)&&on(i,r)||on(e,r)&&on(i,t))||nn(e,t,i)>0!=nn(e,t,r)>0&&nn(i,r,e)>0!=nn(i,r,t)>0}function sn(e,t){return nn(e.prev,e,e.next)<0?nn(e,t,e.next)>=0&&nn(e,e.prev,t)>=0:nn(e,t,e.prev)<0||nn(e,e.next,t)<0}function cn(e,t){var i=new un(e.i,e.x,e.y),r=new un(t.i,t.x,t.y),n=e.next,o=t.prev;return e.next=t,t.prev=e,i.next=n,n.prev=i,r.next=i,i.prev=r,o.next=r,r.prev=o,r}function hn(e,t,i,r){var n=new un(e,t,i);return r?(n.next=r.next,n.prev=r,r.next.prev=n,r.next=n):(n.prev=n,n.next=n),n}function ln(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ)}function un(e,t,i){this.i=e,this.x=t,this.y=i,this.prev=null,this.next=null,this.z=null,this.prevZ=null,this.nextZ=null,this.steiner=!1}var pn={area:function(e){for(var t=e.length,i=0,r=t-1,n=0;n2&&e[t-1].equals(e[0])&&e.pop()}function r(e,t){for(var i=0;i0)&&f.push(w,_,E),(c!==i-1||h0&&g(!0),t>0&&g(!1)),this.setIndex(h),this.addAttribute("position",new Yt(l,3)),this.addAttribute("normal",new Yt(u,3)),this.addAttribute("uv",new Yt(p,2))}function Rn(e,t,i,r,n,o,a){An.call(this,0,e,t,i,r,n,o,a),this.type="ConeGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:o,thetaLength:a}}function Cn(e,t,i,r,n,o,a){Ln.call(this,0,e,t,i,r,n,o,a),this.type="ConeBufferGeometry",this.parameters={radius:e,height:t,radialSegments:i,heightSegments:r,openEnded:n,thetaStart:o,thetaLength:a}}function Pn(e,t,i,r){zt.call(this),this.type="CircleGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},this.fromBufferGeometry(new Nn(e,t,i,r)),this.mergeVertices()}function Nn(e,t,i,r){ai.call(this),this.type="CircleBufferGeometry",this.parameters={radius:e,segments:t,thetaStart:i,thetaLength:r},e=e||1,t=void 0!==t?Math.max(3,t):8,i=void 0!==i?i:0,r=void 0!==r?r:2*Math.PI;var n,o,a=[],s=[],c=[],h=[],l=new oe,u=new ie;for(s.push(0,0,0),c.push(0,0,1),h.push(.5,.5),o=0,n=3;o<=t;o++,n+=3){var p=i+o/t*r;l.x=e*Math.cos(p),l.y=e*Math.sin(p),s.push(l.x,l.y,l.z),c.push(0,0,1),u.x=(s[n]/e+1)/2,u.y=(s[n+1]/e+1)/2,h.push(u.x,u.y)}for(n=1;n<=t;n++)a.push(n,n+1,0);this.setIndex(a),this.addAttribute("position",new Yt(s,3)),this.addAttribute("normal",new Yt(c,3)),this.addAttribute("uv",new Yt(h,2))}dn.prototype=Object.create(zt.prototype),dn.prototype.constructor=dn,fn.prototype=Object.create(ai.prototype),fn.prototype.constructor=fn,fn.prototype.getArrays=function(){var e=this.getAttribute("position"),t=e?Array.prototype.slice.call(e.array):[],i=this.getAttribute("uv"),r=i?Array.prototype.slice.call(i.array):[],n=this.index;return{position:t,uv:r,index:n?Array.prototype.slice.call(n.array):[]}},fn.prototype.addShapeList=function(e,t){var i=e.length;t.arrays=this.getArrays();for(var r=0;rNumber.EPSILON){var p=Math.sqrt(l),d=Math.sqrt(c*c+h*h),f=t.x-s/p,m=t.y+a/p,v=((i.x-h/d-f)*h-(i.y+c/d-m)*c)/(a*h-s*c),g=(r=f+a*v-e.x)*r+(n=m+s*v-e.y)*n;if(g<=2)return new ie(r,n);o=Math.sqrt(g/2)}else{var y=!1;a>Number.EPSILON?c>Number.EPSILON&&(y=!0):a<-Number.EPSILON?c<-Number.EPSILON&&(y=!0):Math.sign(s)===Math.sign(h)&&(y=!0),y?(r=-s,n=a,o=Math.sqrt(l)):(r=a,n=s,o=Math.sqrt(l/2))}return new ie(r/o,n/o)}for(var G=[],V=0,j=C.length,H=j-1,W=V+1;V=0;N--){for(I=N/y,D=v*Math.cos(I*Math.PI/2),O=g*Math.sin(I*Math.PI/2),V=0,j=C.length;V=0;){i=V,(r=V-1)<0&&(r=e.length-1);var n=0,o=w+2*y;for(n=0;n0||0===e.search(/^data\:image\/jpeg/);n.format=r?D:U,n.needsUpdate=!0,void 0!==t&&t(n)}),i,r),n},setCrossOrigin:function(e){return this.crossOrigin=e,this},setPath:function(e){return this.path=e,this}}),Object.assign(eo.prototype,{getPoint:function(){return console.warn("THREE.Curve: .getPoint() not implemented."),null},getPointAt:function(e,t){var i=this.getUtoTmapping(e);return this.getPoint(i,t)},getPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPoint(i/e));return t},getSpacedPoints:function(e){void 0===e&&(e=5);for(var t=[],i=0;i<=e;i++)t.push(this.getPointAt(i/e));return t},getLength:function(){var e=this.getLengths();return e[e.length-1]},getLengths:function(e){if(void 0===e&&(e=this.arcLengthDivisions),this.cacheArcLengths&&this.cacheArcLengths.length===e+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;var t,i,r=[],n=this.getPoint(0),o=0;for(r.push(0),i=1;i<=e;i++)o+=(t=this.getPoint(i/e)).distanceTo(n),r.push(o),n=t;return this.cacheArcLengths=r,r},updateArcLengths:function(){this.needsUpdate=!0,this.getLengths()},getUtoTmapping:function(e,t){var i,r=this.getLengths(),n=0,o=r.length;i=t||e*r[o-1];for(var a,s=0,c=o-1;s<=c;)if((a=r[n=Math.floor(s+(c-s)/2)]-i)<0)s=n+1;else{if(!(a>0)){c=n;break}c=n-1}if(r[n=c]===i)return n/(o-1);var h=r[n];return(n+(i-h)/(r[n+1]-h))/(o-1)},getTangent:function(e){var t=1e-4,i=e-t,r=e+t;i<0&&(i=0),r>1&&(r=1);var n=this.getPoint(i);return this.getPoint(r).clone().sub(n).normalize()},getTangentAt:function(e){var t=this.getUtoTmapping(e);return this.getTangent(t)},computeFrenetFrames:function(e,t){var i,r,n,o=new oe,a=[],s=[],c=[],h=new oe,l=new re;for(i=0;i<=e;i++)r=i/e,a[i]=this.getTangentAt(r),a[i].normalize();s[0]=new oe,c[0]=new oe;var u=Number.MAX_VALUE,p=Math.abs(a[0].x),d=Math.abs(a[0].y),f=Math.abs(a[0].z);for(p<=u&&(u=p,o.set(1,0,0)),d<=u&&(u=d,o.set(0,1,0)),f<=u&&o.set(0,0,1),h.crossVectors(a[0],o).normalize(),s[0].crossVectors(a[0],h),c[0].crossVectors(a[0],s[0]),i=1;i<=e;i++)s[i]=s[i-1].clone(),c[i]=c[i-1].clone(),h.crossVectors(a[i-1],a[i]),h.length()>Number.EPSILON&&(h.normalize(),n=Math.acos(te.clamp(a[i-1].dot(a[i]),-1,1)),s[i].applyMatrix4(l.makeRotationAxis(h,n))),c[i].crossVectors(a[i],s[i]);if(!0===t)for(n=Math.acos(te.clamp(s[0].dot(s[e]),-1,1)),n/=e,a[0].dot(h.crossVectors(s[0],s[e]))>0&&(n=-n),i=1;i<=e;i++)s[i].applyMatrix4(l.makeRotationAxis(a[i],n*i)),c[i].crossVectors(a[i],s[i]);return{tangents:a,normals:s,binormals:c}},clone:function(){return(new this.constructor).copy(this)},copy:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this},toJSON:function(){var e={metadata:{version:4.5,type:"Curve",generator:"Curve.toJSON"}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e},fromJSON:function(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}}),to.prototype=Object.create(eo.prototype),to.prototype.constructor=to,to.prototype.isEllipseCurve=!0,to.prototype.getPoint=function(e,t){for(var i=t||new ie,r=2*Math.PI,n=this.aEndAngle-this.aStartAngle,o=Math.abs(n)r;)n-=r;n0?0:(Math.floor(Math.abs(l)/s.length)+1)*s.length:0===u&&l===c-1&&(l=c-2,u=1),this.closed||l>0?i=s[(l-1)%c]:(no.subVectors(s[0],s[1]).add(s[0]),i=no),r=s[l%c],n=s[(l+1)%c],this.closed||l+2r.length-2?r.length-1:o+1],l=r[o>r.length-3?r.length-1:o+2];return i.set(ho(a,s.x,c.x,h.x,l.x),ho(a,s.y,c.y,h.y,l.y)),i},xo.prototype.copy=function(e){eo.prototype.copy.call(this,e),this.points=[];for(var t=0,i=e.points.length;t=t){var n=i[r]-t,o=this.curves[r],a=o.getLength(),s=0===a?0:1-n/a;return o.getPointAt(s)}r++}return null},getLength:function(){var e=this.getCurveLengths();return e[e.length-1]},updateArcLengths:function(){this.needsUpdate=!0,this.cacheLengths=null,this.getCurveLengths()},getCurveLengths:function(){if(this.cacheLengths&&this.cacheLengths.length===this.curves.length)return this.cacheLengths;for(var e=[],t=0,i=0,r=this.curves.length;i1&&!i[i.length-1].equals(i[0])&&i.push(i[0]),i},copy:function(e){eo.prototype.copy.call(this,e),this.curves=[];for(var t=0,i=e.curves.length;t0){var h=c.getPoint(0);h.equals(this.currentPoint)||this.lineTo(h.x,h.y)}this.curves.push(c);var l=c.getPoint(1);this.currentPoint.copy(l)},copy:function(e){return wo.prototype.copy.call(this,e),this.currentPoint.copy(e.currentPoint),this},toJSON:function(){var e=wo.prototype.toJSON.call(this);return e.currentPoint=this.currentPoint.toArray(),e},fromJSON:function(e){return wo.prototype.fromJSON.call(this,e),this.currentPoint.fromArray(e.currentPoint),this}}),Mo.prototype=Object.assign(Object.create(_o.prototype),{constructor:Mo,getPointsHoles:function(e){for(var t=[],i=0,r=this.holes.length;i=n)break e;var s=t[1];e=(n=t[--i-1]))break t}o=i,i=0}for(;i>>1;et;)--o;if(++o,0!==n||o!==r){n>=o&&(n=(o=Math.max(o,1))-1);var a=this.getValueSize();this.times=Ho.arraySlice(i,n,o),this.values=Ho.arraySlice(this.values,n*a,o*a)}return this},validate:function(){var e=!0,t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);var i=this.times,r=this.values,n=i.length;0===n&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);for(var o=null,a=0;a!==n;a++){var s=i[a];if("number"==typeof s&&isNaN(s)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,a,s),e=!1;break}if(null!==o&&o>s){console.error("THREE.KeyframeTrack: Out of order keys.",this,a,s,o),e=!1;break}o=s}if(void 0!==r&&Ho.isTypedArray(r)){a=0;for(var c=r.length;a!==c;++a){var h=r[a];if(isNaN(h)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,a,h),e=!1;break}}}return e},optimize:function(){for(var e=this.times,t=this.values,i=this.getValueSize(),r=this.getInterpolation()===Z,n=1,o=e.length-1,a=1;a0){e[n]=e[o];for(f=o*i,m=n*i,p=0;p!==i;++p)t[m+p]=t[f+p];++n}return n!==e.length&&(this.times=Ho.arraySlice(e,0,n),this.values=Ho.arraySlice(t,0,n*i)),this}}),Xo.prototype=Object.assign(Object.create(Wo.prototype),{constructor:Xo,ValueTypeName:"vector"}),Object.assign(qo,{parse:function(e){for(var t=[],i=e.tracks,r=1/(e.fps||1),n=0,o=i.length;n!==o;++n)t.push(Wo.parse(i[n]).scale(r));return new qo(e.name,e.duration,t)},toJSON:function(e){for(var t=[],i=e.tracks,r={name:e.name,duration:e.duration,tracks:t},n=0,o=i.length;n!==o;++n)t.push(Wo.toJSON(i[n]));return r},CreateFromMorphTargetSequence:function(e,t,i,r){for(var n=t.length,o=[],a=0;a1){var h=r[u=c[1]];h||(r[u]=h=[]),h.push(s)}}var l=[];for(var u in r)l.push(qo.CreateFromMorphTargetSequence(u,r[u],t,i));return l},parseAnimation:function(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;for(var i=function(e,t,i,r,n){if(0!==i.length){var o=[],a=[];Ho.flattenJSON(i,o,a,r),0!==o.length&&n.push(new e(t,o,a))}},r=[],n=e.name||"default",o=e.length||-1,a=e.fps||30,s=e.hierarchy||[],c=0;c1?e.skinWeights[r+1]:0,s=i>2?e.skinWeights[r+2]:0,c=i>3?e.skinWeights[r+3]:0;t.skinWeights.push(new he(o,a,s,c))}if(e.skinIndices)for(r=0,n=e.skinIndices.length;r1?e.skinIndices[r+1]:0,u=i>2?e.skinIndices[r+2]:0,p=i>3?e.skinIndices[r+3]:0;t.skinIndices.push(new he(h,l,u,p))}t.bones=e.bones,t.bones&&t.bones.length>0&&(t.skinWeights.length!==t.skinIndices.length||t.skinIndices.length!==t.vertices.length)&&console.warn("When skinning, number of vertices ("+t.vertices.length+"), skinIndices ("+t.skinIndices.length+"), and skinWeights ("+t.skinWeights.length+") should match.")}(e,i),function(e,t){var i=e.scale;if(void 0!==e.morphTargets)for(var r=0,n=e.morphTargets.length;r0){console.warn('THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.');var l=t.faces,u=e.morphColors[0].colors;for(r=0,n=l.length;r0&&(t.animations=i)}(e,i),i.computeFaceNormals(),i.computeBoundingSphere(),void 0===e.materials||0===e.materials.length?{geometry:i}:{geometry:i,materials:ta.prototype.initMaterials(e.materials,t,this.crossOrigin)}}}),Object.assign(na.prototype,{load:function(e,t,i,r){""===this.texturePath&&(this.texturePath=e.substring(0,e.lastIndexOf("/")+1));var n=this;new Yn(n.manager).load(e,(function(i){var o=null;try{o=JSON.parse(i)}catch(t){return void 0!==r&&r(t),void console.error("THREE:ObjectLoader: Can't parse "+e+".",t.message)}var a=o.metadata;void 0!==a&&void 0!==a.type&&"geometry"!==a.type.toLowerCase()?n.parse(o,t):console.error("THREE.ObjectLoader: Can't load "+e+". Use THREE.JSONLoader instead.")}),i,r)},setTexturePath:function(e){this.texturePath=e},setCrossOrigin:function(e){this.crossOrigin=e},parse:function(e,t){var i=this.parseShape(e.shapes),r=this.parseGeometries(e.geometries,i),n=this.parseImages(e.images,(function(){void 0!==t&&t(s)})),o=this.parseTextures(e.textures,n),a=this.parseMaterials(e.materials,o),s=this.parseObject(e.object,r,a);return e.animations&&(s.animations=this.parseAnimations(e.animations)),void 0!==e.images&&0!==e.images.length||void 0!==t&&t(s),s},parseShape:function(e){var t={};if(void 0!==e)for(var i=0,r=e.length;i0){var o=new Kn(new Wn(t));o.setCrossOrigin(this.crossOrigin);for(var a=0,s=e.length;a0?new dr(s,c):new vi(s,c);break;case"LOD":n=new lr;break;case"Line":n=new mr(o(t.geometry),a(t.material),t.mode);break;case"LineLoop":n=new gr(o(t.geometry),a(t.material));break;case"LineSegments":n=new vr(o(t.geometry),a(t.material));break;case"PointCloud":case"Points":n=new xr(o(t.geometry),a(t.material));break;case"Sprite":n=new hr(a(t.material));break;case"Group":n=new br;break;default:n=new Ot}if(n.uuid=t.uuid,void 0!==t.name&&(n.name=t.name),void 0!==t.matrix?(e.fromArray(t.matrix),e.decompose(n.position,n.quaternion,n.scale)):(void 0!==t.position&&n.position.fromArray(t.position),void 0!==t.rotation&&n.rotation.fromArray(t.rotation),void 0!==t.quaternion&&n.quaternion.fromArray(t.quaternion),void 0!==t.scale&&n.scale.fromArray(t.scale)),void 0!==t.castShadow&&(n.castShadow=t.castShadow),void 0!==t.receiveShadow&&(n.receiveShadow=t.receiveShadow),t.shadow&&(void 0!==t.shadow.bias&&(n.shadow.bias=t.shadow.bias),void 0!==t.shadow.radius&&(n.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&&n.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&&(n.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&&(n.visible=t.visible),void 0!==t.userData&&(n.userData=t.userData),void 0!==t.children)for(var h=t.children,l=0;lNumber.EPSILON){if(h<0&&(a=t[o],c=-c,s=t[n],h=-h),e.ys.y)continue;if(e.y===a.y){if(e.x===a.x)return!0}else{var l=h*(e.x-a.x)-c*(e.y-a.y);if(0===l)return!0;if(l<0)continue;r=!r}}else{if(e.y!==a.y)continue;if(s.x<=e.x&&e.x<=a.x||a.x<=e.x&&e.x<=s.x)return!0}}return r}var n=pn.isClockWise,o=this.subPaths;if(0===o.length)return[];if(!0===t)return i(o);var a,s,c,h=[];if(1===o.length)return s=o[0],(c=new Mo).curves=s.curves,h.push(c),h;var l=!n(o[0].getPoints());l=e?!l:l;var u,p,d=[],f=[],m=[],v=0;f[v]=void 0,m[v]=[];for(var g=0,y=o.length;g1){for(var x=!1,b=[],w=0,_=f.length;w<_;w++)d[w]=[];for(w=0,_=f.length;w<_;w++)for(var M=m[w],E=0;E0&&(x||(m=d))}g=0;for(var L=f.length;g0){this.source.connect(this.filters[0]);for(var e=1,t=this.filters.length;e0){this.source.disconnect(this.filters[0]);for(var e=1,t=this.filters.length;e=.5)for(var o=0;o!==n;++o)e[t+o]=e[i+o]},_slerp:function(e,t,i,r){ne.slerpFlat(e,t,e,t,e,i,r)},_lerp:function(e,t,i,r,n){for(var o=1-r,a=0;a!==n;++a){var s=t+a;e[s]=e[s]*o+e[i+a]*r}}}),Object.assign(Ba.prototype,{getValue:function(e,t){this.bind();var i=this._targetGroup.nCachedObjects_,r=this._bindings[i];void 0!==r&&r.getValue(e,t)},setValue:function(e,t){for(var i=this._bindings,r=this._targetGroup.nCachedObjects_,n=i.length;r!==n;++r)i[r].setValue(e,t)},bind:function(){for(var e=this._bindings,t=this._targetGroup.nCachedObjects_,i=e.length;t!==i;++t)e[t].bind()},unbind:function(){for(var e=this._bindings,t=this._targetGroup.nCachedObjects_,i=e.length;t!==i;++t)e[t].unbind()}}),Object.assign(za,{Composite:Ba,create:function(e,t,i){return e&&e.isAnimationObjectGroup?new za.Composite(e,t,i):new za(e,t,i)},sanitizeNodeName:function(e){return e.replace(/\s/g,"_").replace(/[^\w-]/g,"")},parseTrackName:(Ma=new RegExp("^"+/((?:[\w-]+[\/:])*)/.source+/([\w-\.]+)?/.source+/(?:\.([\w-]+)(?:\[(.+)\])?)?/.source+/\.([\w-]+)(?:\[(.+)\])?/.source+"$"),Ea=["material","materials","bones"],function(e){var t=Ma.exec(e);if(!t)throw new Error("PropertyBinding: Cannot parse trackName: "+e);var i={nodeName:t[2],objectName:t[3],objectIndex:t[4],propertyName:t[5],propertyIndex:t[6]},r=i.nodeName&&i.nodeName.lastIndexOf(".");if(void 0!==r&&-1!==r){var n=i.nodeName.substring(r+1);-1!==Ea.indexOf(n)&&(i.nodeName=i.nodeName.substring(0,r),i.objectName=n)}if(null===i.propertyName||0===i.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+e);return i}),findNode:function(e,t){if(!t||""===t||"root"===t||"."===t||-1===t||t===e.name||t===e.uuid)return e;if(e.skeleton){var i=function(e){for(var i=0;i0;)if(o===e[a])return r;n(t)}}Object.assign(d.prototype,{subscribe:function(e,t,i){var r=this,n=this._target,o=this._emitter,a=this._listeners,s=function(){var r=u.apply(null,arguments),a={data:r,name:t,original:e};if(i){var s=i.call(n,a);!1!==s&&o.emit.apply(o,[a.name].concat(r))}else o.emit.apply(o,[t].concat(r))};if(a[e])throw Error("Event '"+e+"' is already listening");this._listenersCount++,o._newListener&&o._removeListener&&!r._onNewListener?(this._onNewListener=function(i){i===t&&null===a[e]&&(a[e]=s,r._on.call(n,e,s))},o.on("newListener",this._onNewListener),this._onRemoveListener=function(i){i===t&&!o.hasListeners(i)&&a[e]&&(a[e]=null,r._off.call(n,e,s))},a[e]=null,o.on("removeListener",this._onRemoveListener)):(a[e]=s,r._on.call(n,e,s))},unsubscribe:function(e){var t,i,r,n=this,o=this._listeners,a=this._emitter,c=this._off,h=this._target;if(e&&"string"!=typeof e)throw TypeError("event must be a string");function l(){n._onNewListener&&(a.off("newListener",n._onNewListener),a.off("removeListener",n._onRemoveListener),n._onNewListener=null,n._onRemoveListener=null);var e=b.call(a,n);a._observers.splice(e,1)}if(e){if(!(t=o[e]))return;c.call(h,e,t),delete o[e],--this._listenersCount||l()}else{for(r=(i=s(o)).length;r-- >0;)e=i[r],c.call(h,e,o[e]);this._listeners={},this._listenersCount=0,l()}}});var g=v(["function"]),y=v(["object","function"]);function x(e,t,i){var r,n,o,a=0,s=new e((function(c,h,l){function u(){n&&(n=null),a&&(clearTimeout(a),a=0)}i=f(i,{timeout:0,overload:!1},{timeout:function(e,t){return("number"!=typeof(e*=1)||e<0||!Number.isFinite(e))&&t("timeout must be a positive number"),e}}),r=!i.overload&&"function"==typeof e.prototype.cancel&&"function"==typeof l;var p=function(e){u(),c(e)},d=function(e){u(),h(e)};r?t(p,d,l):(n=[function(e){d(e||Error("canceled"))}],t(p,d,(function(e){if(o)throw Error("Unable to subscribe on cancel event asynchronously");if("function"!=typeof e)throw TypeError("onCancel callback must be a function");n.push(e)})),o=!0),i.timeout>0&&(a=setTimeout((function(){var e=Error("timeout");e.code="ETIMEDOUT",a=0,s.cancel(e),h(e)}),i.timeout))}));return r||(s.cancel=function(e){if(n){for(var t=n.length,i=1;i0;)"_listeners"!==(d=y[c])&&(x=w(e,t,i[d],r+1,n))&&(b?b.push.apply(b,x):b=x);return b}if("**"===_){for((g=r+1===n||r+2===n&&"*"===M)&&i._listeners&&(b=w(e,t,i,n,n)),c=(y=s(i)).length;c-- >0;)"_listeners"!==(d=y[c])&&("*"===d||"**"===d?(i[d]._listeners&&!g&&(x=w(e,t,i[d],n,n))&&(b?b.push.apply(b,x):b=x),x=w(e,t,i[d],r,n)):x=w(e,t,i[d],d===M?r+2:r,n),x&&(b?b.push.apply(b,x):b=x));return b}i[_]&&(b=w(e,t,i[_],r+1,n))}if((f=i["*"])&&w(e,t,f,r+1,n),m=i["**"])if(r0;)"_listeners"!==(d=y[c])&&(d===M?w(e,t,m[d],r+2,n):d===_?w(e,t,m[d],r+1,n):((v={})[d]=m[d],w(e,t,{"**":v},r+1,n)));else m._listeners?w(e,t,m,n,n):m["*"]&&m["*"]._listeners&&w(e,t,m["*"],n,n);return b}function _(e,t,i){var r,n,o=0,a=0,s=this.delimiter,c=s.length;if("string"==typeof e)if(-1!==(r=e.indexOf(s))){n=new Array(5);do{n[o++]=e.slice(a,r),a=r+c}while(-1!==(r=e.indexOf(s,a)));n[o++]=e.slice(a)}else n=[e],o=1;else n=e,o=e.length;if(o>1)for(r=0;r+10&&u._listeners.length>this._maxListeners&&(u._listeners.warned=!0,l.call(this,u._listeners.length,h))):u._listeners=t,!0;return!0}function M(e,t,i,r){for(var n,o,a,c,h=s(e),l=h.length,u=e._listeners;l-- >0;)n=e[o=h[l]],a="_listeners"===o?i:i?i.concat(o):[o],c=r||"symbol"==typeof o,u&&t.push(c?a:a.join(this.delimiter)),"object"==typeof n&&M.call(this,n,t,a,c);return t}function E(e){for(var t,i,r,n=s(e),o=n.length;o-- >0;)(t=e[i=n[o]])&&(r=!0,"_listeners"===i||E(t)||delete e[i]);return r}function T(e,t,i){this.emitter=e,this.event=t,this.listener=i}function S(t,i,n){if(!0===n)s=!0;else if(!1===n)o=!0;else{if(!n||"object"!=typeof n)throw TypeError("options should be an object or true");var o=n.async,s=n.promisify,c=n.nextTick,h=n.objectify}if(o||c||s){var l=i,u=i._origin||i;if(c&&!r)throw Error("process.nextTick is not supported");s===e&&(s="AsyncFunction"===i.constructor.name),i=function(){var e=arguments,t=this,i=this.event;return s?c?Promise.resolve():new Promise((function(e){a(e)})).then((function(){return t.event=i,l.apply(t,e)})):(c?process.nextTick:a)((function(){t.event=i,l.apply(t,e)}))},i._async=!0,i._origin=u}return[i,h?new T(this,t,i):this]}function A(e){this._events={},this._newListener=!1,this._removeListener=!1,this.verboseMemoryLeak=!1,h.call(this,e)}T.prototype.off=function(){return this.emitter.off(this.event,this.listener),this},A.EventEmitter2=A,A.prototype.listenTo=function(t,r,n){if("object"!=typeof t)throw TypeError("target musts be an object");var o=this;function a(e){if("object"!=typeof e)throw TypeError("events must be an object");var i,r=n.reducers,a=b.call(o,t);i=-1===a?new d(o,t,n):o._observers[a];for(var c,h=s(e),l=h.length,u="function"==typeof r,p=0;p0;)r=i[n],e&&r._target!==e||(r.unsubscribe(t),o=!0);return o},A.prototype.delimiter=".",A.prototype.setMaxListeners=function(t){t!==e&&(this._maxListeners=t,this._conf||(this._conf={}),this._conf.maxListeners=t)},A.prototype.getMaxListeners=function(){return this._maxListeners},A.prototype.event="",A.prototype.once=function(e,t,i){return this._once(e,t,!1,i)},A.prototype.prependOnceListener=function(e,t,i){return this._once(e,t,!0,i)},A.prototype._once=function(e,t,i,r){return this._many(e,1,t,i,r)},A.prototype.many=function(e,t,i,r){return this._many(e,t,i,!1,r)},A.prototype.prependMany=function(e,t,i,r){return this._many(e,t,i,!0,r)},A.prototype._many=function(e,t,i,r,n){var o=this;if("function"!=typeof i)throw new Error("many only accepts instances of Function");function a(){return 0==--t&&o.off(e,a),i.apply(this,arguments)}return a._origin=i,this._on(e,a,r,n)},A.prototype.emit=function(){if(!this._events&&!this._all)return!1;this._events||c.call(this);var e,t,i,r,o,a,s=arguments[0],h=this.wildcard;if("newListener"===s&&!this._newListener&&!this._events.newListener)return!1;if(h&&(e=s,"newListener"!==s&&"removeListener"!==s&&"object"==typeof s)){if(i=s.length,n)for(r=0;r3)for(t=new Array(u-1),o=1;o3)for(i=new Array(p-1),a=1;a0&&this._events[t].length>this._maxListeners&&(this._events[t].warned=!0,l.call(this,this._events[t].length,t))):this._events[t]=i,a)},A.prototype.off=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");var r,n=[];if(this.wildcard){var o="string"==typeof e?e.split(this.delimiter):e.slice();if(!(n=w.call(this,null,o,this.listenerTree,0)))return this}else{if(!this._events[e])return this;r=this._events[e],n.push({_listeners:r})}for(var a=0;a0){for(i=0,r=(t=this._all).length;i0;)"function"==typeof(r=c[i[o]])?n.push(r):n.push.apply(n,r);return n}if(this.wildcard){if(!(a=this.listenerTree))return[];var h=[],l="string"==typeof t?t.split(this.delimiter):t.slice();return w.call(this,h,l,a,0),h}return c&&(r=c[t])?"function"==typeof r?[r]:r:[]},A.prototype.eventNames=function(e){var t=this._events;return this.wildcard?M.call(this,this.listenerTree,[],null,e):t?s(t):[]},A.prototype.listenerCount=function(e){return this.listeners(e).length},A.prototype.hasListeners=function(t){if(this.wildcard){var i=[],r="string"==typeof t?t.split(this.delimiter):t.slice();return w.call(this,i,r,this.listenerTree,0),i.length>0}var n=this._events,o=this._all;return!!(o&&o.length||n&&(t===e?s(n).length:n[t]))},A.prototype.listenersAny=function(){return this._all?this._all:[]},A.prototype.waitFor=function(t,i){var r=this,n=typeof i;return"number"===n?i={timeout:i}:"function"===n&&(i={filter:i}),x((i=f(i,{timeout:0,filter:e,handleError:!1,Promise:Promise,overload:!1},{filter:g,Promise:m})).Promise,(function(e,n,o){function a(){var o=i.filter;if(!o||o.apply(r,arguments))if(r.off(t,a),i.handleError){var s=arguments[0];s?n(s):e(u.apply(null,arguments).slice(1))}else e(u.apply(null,arguments))}o((function(){r.off(t,a)})),r._on(t,a,!1)}),{timeout:i.timeout,overload:i.overload})};var L=A.prototype;Object.defineProperties(A,{defaultMaxListeners:{get:function(){return L._maxListeners},set:function(e){if("number"!=typeof e||e<0||Number.isNaN(e))throw TypeError("n must be a non-negative number");L._maxListeners=e},enumerable:!0},once:{value:function(e,t,i){return x((i=f(i,{Promise:Promise,timeout:0,overload:!1},{Promise:m})).Promise,(function(i,r,n){var o;if("function"==typeof e.addEventListener)return o=function(){i(u.apply(null,arguments))},n((function(){e.removeEventListener(t,o)})),void e.addEventListener(t,o,{once:!0});var a,s=function(){a&&e.removeListener("error",a),i(u.apply(null,arguments))};"error"!==t&&(a=function(i){e.removeListener(t,s),r(i)},e.once("error",a)),n((function(){a&&e.removeListener("error",a),e.removeListener(t,s)})),e.once(t,s)}),{timeout:i.timeout,overload:i.overload})},writable:!0,configurable:!0}}),Object.defineProperties(L,{_maxListeners:{value:10,writable:!0,configurable:!0},_observers:{value:null,writable:!0,configurable:!0}}),Ws.exports=A}();var qs=Hs(Xs.exports);class Ys extends qs{constructor(e){super(),e=e||{},this.message=e.message,this.feedbackTopic=e.feedbackTopic,this.tfClient=e.tfClient,this.menuFontSize=e.menuFontSize||"0.8em",this.name=this.message.name,this.header=this.message.header,this.controls=this.message.controls,this.menuEntries=this.message.menu_entries,this.dragging=!1,this.timeoutHandle=null,this.tfTransform=new r.Transform,this.pose=new r.Pose,this.setPoseFromClientBound=this.setPoseFromClient.bind(this),this.onMouseDownBound=this.onMouseDown.bind(this),this.onMouseUpBound=this.onMouseUp.bind(this),this.onButtonClickBound=this.onButtonClick.bind(this),this.onMenuSelectBound=this.onMenuSelect.bind(this),this.setPoseFromServer(this.message.pose),this.tfUpdateBound=this.tfUpdate.bind(this)}subscribeTf(){0===this.message.header.stamp.secs&&0===this.message.header.stamp.nsecs&&this.tfClient.subscribe(this.message.header.frame_id,this.tfUpdateBound)}unsubscribeTf(){this.tfClient.unsubscribe(this.message.header.frame_id,this.tfUpdateBound)}emitServerPoseUpdate(){var e=new r.Pose(this.pose);e.applyTransform(this.tfTransform),this.emit("pose",e)}setPoseFromServer(e){this.pose=new r.Pose(e),this.emitServerPoseUpdate()}tfUpdate(e){this.tfTransform=new r.Transform(e),this.emitServerPoseUpdate()}setPoseFromClient(e){this.pose=new r.Pose(e);var t=this.tfTransform.clone();t.rotation.invert(),t.translation.multiplyQuaternion(t.rotation),t.translation.x*=-1,t.translation.y*=-1,t.translation.z*=-1,this.pose.applyTransform(t),this.sendFeedback(1,void 0,0,e.controlName),this.dragging&&(this.timeoutHandle&&clearTimeout(this.timeoutHandle),this.timeoutHandle=setTimeout(this.setPoseFromClient.bind(this,e),250))}onButtonClick(e){this.sendFeedback(3,e.clickPosition,0,e.controlName)}onMouseDown(e){this.sendFeedback(4,e.clickPosition,0,e.controlName),this.dragging=!0}onMouseUp(e){this.sendFeedback(5,e.clickPosition,0,e.controlName),this.dragging=!1,this.timeoutHandle&&clearTimeout(this.timeoutHandle)}onMenuSelect(e){this.sendFeedback(2,void 0,e.id,e.controlName)}sendFeedback(e,t,i,r){var n=void 0!==t;t=t||{x:0,y:0,z:0};var o={header:this.header,client_id:this.clientID,marker_name:this.name,control_name:r,event_type:e,pose:this.pose,mouse_point:t,mouse_point_valid:n,menu_entry_id:i};this.feedbackTopic.publish(o)}}class Zs extends Ss.Object3D{constructor(e){super(),e=e||{};var t=this;this.tfClient=e.tfClient,this.frameID=e.frameID;var i=e.object;this.pose=e.pose||new r.Pose,this.visible=!1,this.add(i),this.updatePose(this.pose),this.tfUpdate=function(e){var i=new r.Transform(e),n=new r.Pose(t.pose);n.applyTransform(i),t.updatePose(n),t.visible=!0},this.tfClient.subscribe(this.frameID,this.tfUpdate)}updatePose(e){this.position.set(e.position.x,e.position.y,e.position.z),this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.updateMatrixWorld(!0)}unsubscribeTf(){this.tfClient.unsubscribe(this.frameID,this.tfUpdate)}}class Js extends Ss.ArrowHelper{constructor(e){var t=(e=e||{}).origin||new Ss.Vector3(0,0,0),i=e.direction||new Ss.Vector3(1,0,0),r=e.length||1;e.headLength,e.shaftDiameter,e.headDiameter,e.material||new Ss.MeshBasicMaterial,super(i,t,r,16711680)}dispose(){void 0!==this.line&&(this.line.material.dispose(),this.line.geometry.dispose()),void 0!==this.cone&&(this.cone.material.dispose(),this.cone.geometry.dispose())}}class Ks extends Ss.Object3D{constructor(e){super();var t=this,i=(e=e||{}).shaftRadius||.008,r=e.headRadius||.023,n=e.headLength||.1,o=e.scale||1,a=e.lineType||"full",s=e.lineDashLength||.1;function c(e){var r=new Ss.Color;r.setRGB(e.x,e.y,e.z);var n=new Ss.MeshBasicMaterial({color:r.getHex()}),o=new Ss.Vector3;o.crossVectors(e,new Ss.Vector3(0,-1,0));var c=new Ss.Quaternion;c.setFromAxisAngle(o,.5*Math.PI);var h,l=new Ss.Mesh(t.headGeom,n);if(l.position.copy(e),l.position.multiplyScalar(.95),l.quaternion.copy(c),l.updateMatrix(),t.add(l),"dashed"===a)for(var u=s,p=0;u/2+3*u*p+u/2<=1;++p){var d=new Ss.CylinderGeometry(i,i,u);(h=new Ss.Mesh(d,n)).position.copy(e),h.position.multiplyScalar(u/2+3*u*p),h.quaternion.copy(c),h.updateMatrix(),t.add(h)}else"full"===a?((h=new Ss.Mesh(t.lineGeom,n)).position.copy(e),h.position.multiplyScalar(.45),h.quaternion.copy(c),h.updateMatrix(),t.add(h)):console.warn("[Axes]: Unsupported line type. Not drawing any axes.")}this.scale.set(o,o,o),this.lineGeom=new Ss.CylinderGeometry(i,i,1-n),this.headGeom=new Ss.CylinderGeometry(0,r,n),c(new Ss.Vector3(1,0,0)),c(new Ss.Vector3(0,1,0)),c(new Ss.Vector3(0,0,1))}}class Qs extends Ss.Object3D{constructor(e){var t=(e=e||{}).num_cells||10,i=e.color||"#cccccc",r=e.lineWidth||1,n=e.cellSize||1;super();for(var o=new Ss.LineBasicMaterial({color:i,linewidth:r}),a=0;a<=t;++a){var s=n*t/2,c=s-a*n,h=new Ss.Geometry;h.vertices.push(new Ss.Vector3(-s,c,0),new Ss.Vector3(s,c,0));var l=new Ss.Geometry;l.vertices.push(new Ss.Vector3(c,-s,0),new Ss.Vector3(c,s,0)),this.add(new Ss.Line(h,o)),this.add(new Ss.Line(l,o))}}}class $s extends Ss.Mesh{constructor(e){var t=(e=e||{}).message,i=e.opacity||1,r=e.color||{r:255,g:255,b:255,a:255},n=t.info,o=n.origin,a=n.width,s=n.height,c=new Ss.PlaneBufferGeometry(a,s),h=new Uint8Array(a*s*4),l=new Ss.DataTexture(h,a,s,Ss.RGBAFormat);l.flipY=!0,l.minFilter=Ss.NearestFilter,l.magFilter=Ss.NearestFilter,l.needsUpdate=!0;var u=new Ss.MeshBasicMaterial({map:l,transparent:i<1,opacity:i});u.side=Ss.DoubleSide,super(c,u),Object.assign(this,e),this.quaternion.copy(new Ss.Quaternion(o.orientation.x,o.orientation.y,o.orientation.z,o.orientation.w)),this.position.x=a*n.resolution/2+o.position.x,this.position.y=s*n.resolution/2+o.position.y,this.position.z=o.position.z,this.scale.x=n.resolution,this.scale.y=n.resolution;var p=t.data;this.color=r,this.material=u,this.texture=l;for(var d=0;d{const t="read"+e.kind,i="get"+e.kind;this[t]=()=>{if(this._cursor+e.width>this.length)throw new Error("Cannot read data stream. Overflow. Len="+this.length+" crsr="+this._cursor);const t=this._dataView[i](this._cursor,this.isLittleEndian);return this._cursor+=e.width,t}})),Object.defineProperty(this,"isEnd",{get:()=>this.cursor>=this.data.length}),this}class ac{constructor(e){this.resolution=void 0!==e.resolution?e.resolution:1,this.color=new Ss.Color(void 0!==e.color?e.color:"green"),this.opacity=void 0!==e.opacity?e.opacity:1,this.voxelRenderMode=void 0!==e.voxelRenderMode?e.voxelRenderMode:tc,this._rootNode=null,this._treeDepth=16,this._treeMaxKeyVal=32768,this._BINARY_UNALLOCATED=0,this._BINARY_LEAF_FREE=1,this._BINARY_LEAF_OCCUPIED=2,this._BINARY_HAS_CHILDREN=3,this._BINARY_CHILD_BUILD_TABLE={},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE]=function(e){e.value=this._defaultFreeValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED]=function(e){e.value=this._defaultOccupiedValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN]=function(e){e.value=null},this._FACES=[{normal:[-1,0,0],vertices:[[0,1,0],[0,0,0],[0,1,1],[0,0,1]],childIndex:[1,3,5,7]},{normal:[1,0,0],vertices:[[1,1,1],[1,0,1],[1,1,0],[1,0,0]],childIndex:[0,2,4,6]},{normal:[0,-1,0],vertices:[[1,0,1],[0,0,1],[1,0,0],[0,0,0]],childIndex:[2,3,6,7]},{normal:[0,1,0],vertices:[[0,1,1],[1,1,1],[0,1,0],[1,1,0]],childIndex:[0,1,4,5]},{normal:[0,0,-1],vertices:[[1,0,0],[0,0,0],[1,1,0],[0,1,0]],childIndex:[4,5,6,7]},{normal:[0,0,1],vertices:[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],childIndex:[0,1,2,3]}],this.nodeSizeTable=new Array(this._treeDepth);let t=this.resolution;for(let e=this._treeDepth-1;e>=0;--e)this.nodeSizeTable[e]=t,t*=2;this._defaultOccupiedValue=!0,this._defaultFreeValue=!1,this.object=null}searchAtDepth(e,t){t=void 0!==t&&t>0?t:this._treeDepth;const i=this._adjustKeyAtDepth(e,t),r=this._treeDepth-t;let n=this._rootNode;for(let e=this._treeDepth-1;e>=r;--e){const t=this._computeChildIdx(i,e);if(!n.hasChildAt(t))return n.hasChildren()?null:n;n=n.getChildAt(t)}return n}_computeCoordFromKey(e){return e.map((e=>this.resolution*(e-this._treeMaxKeyVal)))}_computeChildIdx(e,t){let i=0;return e[0]&1<(e-this._treeMaxKeyVal>>i<0;){let e=i.pop();const r=t.readUint16();let n=8;for(;0!==n;){--n;const t=(r&3<<2*n)>>2*n;if(t!==this._BINARY_UNALLOCATED){let r=this._newNode();this._BINARY_CHILD_BUILD_TABLE[t].bind(this)(r),e.createChildNodeAt(r,n),t===this._BINARY_HAS_CHILDREN&&i.push(r)}}}}read(e){null!==this._rootNode&&delete this._rootNode,this._rootNode=this._newNode();let t=new oc(e,!0),i=new Array;for(i.push(this._rootNode);i.length>0;){let e=i.pop();this._readNodeData(t,e);const r=t.readUint8();let n=8;for(;0!==n;){--n;if(r&1<0;){let i=t.pop();if(i.node.isLeafNode())e(i.node,i.key,i.depth-1);else for(let e=0;e<8;++e)if(i.node.hasChildAt(e)){const r=this._computeKeyFromChildIdx(e,i.key,i.depth);t.push({node:i.node.getChildAt(e),depth:i.depth+1,key:r})}}}_obtainColor(e){return this.color}_checkOccupied(e){return!1!==e.value}_buildFaces(){let e={vertices:[],indices:[],normals:[],colors:[],_insertFace:function(e,t,i,r){const n=this.vertices.length/3;e.vertices.forEach((function(e){this.vertices.push(t[0]+e[0]*i,t[1]+e[1]*i,t[2]+e[2]*i)}));const o=[r.r,r.g,r.b];this.colors.push(...o,...o,...o,...o),this.normals.push(...e.normal,...e.normal,...e.normal,...e.normal),this.indices.push(n,n+1,n+2,n+2,n+1,n+3)},_checkNeighborsTouchingFace:function(e,t,i){let r=new Array;for(r.push(t);0!==r.length;){const t=r.pop();t.hasChildren()&&e.childIndex.forEach((function(e){if(!t.hasChildAt(e))return!0;{const n=t.getChildAt(e),o=this._checkOccupied(t);(o&&i===ROS3D.OcTreeVoxelRenderMode.OCCUPIED||!o&&i===ic)&&r.push(n)}}))}return!1}};return this._traverseLeaves(((t,i,r)=>{const n=this._computeCoordFromKey(i),o=this.nodeSizeTable[r],a=this._treeDepth-r,s=this._checkOccupied(t);(s||this.voxelRenderMode!==tc)&&(s&&this.voxelRenderMode===ic||this._FACES.forEach((function(s){const c=[i[0]+s.normal[0]*a*a,i[1]+s.normal[1]*a*a,i[2]+s.normal[2]*a*a],h=this.searchAtDepth(c);null===h?e._insertFace(s,n,o,this._obtainColor(t)):rnew Ss.Color(e))):[{r:0,g:0,b:128},{r:0,g:255,b:0},{r:255,g:255,b:0},{r:255,g:128,b:0},{r:255,g:0,b:0}],this.paletteScale=void 0!==e.paletteScale?e.paletteScale:1}_readNodeData(e,t){t.value=e.readFloat32()}_obtainColor(e){if(this.useFlatColoring)return this.color;const t=1/(1+Math.exp(-e.value*this.paletteScale))*this.palette.length,i=Math.trunc(t),r=t-i;return i<0?this.palette[0]:i>=this.palette.length-1?this.palette[this.palette.length-1]:{r:r*this.palette[i].r+(1-r)*this.palette[i+1].r,g:r*this.palette[i].g+(1-r)*this.palette[i+1].g,b:r*this.palette[i].b+(1-r)*this.palette[i+1].b}}_checkOccupied(e){return e.value>=this.occupancyThreshold}}class cc extends sc{constructor(e){super(e),this.useOwnColor=void 0!==e.palette&&e.colorMode===nc}_readNodeData(e,t){t.value=e.readFloat32(),t.color={r:e.readUint8(),g:e.readUint8(),b:e.readUint8()}}_obtainColor(e){return this.useOwnColor?e.color:sc.prototype._obtainColor.call(this,e)}}class hc extends Ss.Object3D{constructor(e){super(),this.options=e||{},this.ros=e.ros,this.topicName=e.topic||"/particlecloud",this.tfClient=e.tfClient,this.color=e.color||13369599,this.length=e.length||1,this.rootObject=e.rootObject||new Ss.Object3D,this.keep=e.keep||1,this.sns=[],this.rosTopic=void 0,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Odometry"}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){this.sns.length>=this.keep&&(this.sns[0].unsubscribeTf(),this.rootObject.remove(this.sns[0]),this.sns.shift()),this.options.origin=new Ss.Vector3(e.pose.pose.position.x,e.pose.pose.position.y,e.pose.pose.position.z);var t=new Ss.Quaternion(e.pose.pose.orientation.x,e.pose.pose.orientation.y,e.pose.pose.orientation.z,e.pose.pose.orientation.w);this.options.direction=new Ss.Vector3(1,0,0),this.options.direction.applyQuaternion(t),this.options.material=new Ss.MeshBasicMaterial({color:this.color});var i=new Ns(this.options);this.sns.push(new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:i})),this.rootObject.add(this.sns[this.sns.length-1])}}class lc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/path",this.tfClient=e.tfClient,this.color=e.color||13369599,this.rootObject=e.rootObject||new Ss.Object3D,this.sn=null,this.line=null,this.rosTopic=void 0,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Path"}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){null!==this.sn&&(this.sn.unsubscribeTf(),this.rootObject.remove(this.sn));for(var t=new Ss.Geometry,i=0;i=e.range_min&&n<=e.range_max){var o=e.angle_min+r*e.angle_increment;this.points.positions.array[i++]=n*Math.cos(o),this.points.positions.array[i++]=n*Math.sin(o),this.points.positions.array[i++]=0}}this.points.update(i/3)}}}class yc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/gps/fix",this.rootObject=e.rootObject||new Ss.Object3D,this.object3d=e.object3d||new Ss.Object3D;var t=e.material||{};this.altitudeNaN=e.altitudeNaN||0,this.keep=e.keep||100,this.convert=e.convert||function(e,t,i){return new Ss.Vector3(e,t,i)},this.count=0,this.next1=0,this.next2=this.keep,this.geom=new Ss.BufferGeometry,this.vertices=new Ss.BufferAttribute(new Float32Array(6*this.keep),3),this.geom.addAttribute("position",this.vertices),this.material=t.isMaterial?t:new Ss.LineBasicMaterial(t),this.line=new Ss.Line(this.geom,this.material),this.rootObject.add(this.object3d),this.rootObject.add(this.line),this.rosTopic=void 0,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"sensor_msgs/NavSatFix"}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){var t=isNaN(e.altitude)?this.altitudeNaN:e.altitude,i=this.convert(e.longitude,e.latitude,t);this.object3d.position.copy(i),this.object3d.updateMatrixWorld(!0),this.vertices.array[3*this.next1]=i.x,this.vertices.array[3*this.next1+1]=i.y,this.vertices.array[3*this.next1+2]=i.z,this.vertices.array[3*this.next2]=i.x,this.vertices.array[3*this.next2+1]=i.y,this.vertices.array[3*this.next2+2]=i.z,this.vertices.needsUpdate=!0,this.next1=(this.next1+1)%this.keep,this.next2=this.next1+this.keep,this.count=Math.min(this.count+1,this.keep),this.geom.setDrawRange(this.next2-this.count,this.count)}}function xc(e,t,i,r){var n,o=0,a=0,s=0,c=e.length,h=t.length,l=((r=r||1)-1)*(i=i||h)*8;for(n=0;n=8&&(a-=8,t[s++]=o>>>a&255,s%i==0&&(n+=Math.ceil((l-a)/6),(a%=8)>0&&(o=xc.e[e.charAt(n)])));return Math.floor(s/i)}xc.S="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",xc.e={};for(var bc=0;bc<64;bc++)xc.e[xc.S.charAt(bc)]=bc;class wc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/points",this.throttle_rate=e.throttle_rate||null,this.compression=e.compression||"cbor",this.max_pts=e.max_pts||1e4,this.points=new vc(e),this.rosTopic=void 0,this.buffer=null,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"sensor_msgs/PointCloud2",throttle_rate:this.throttle_rate,queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){if(this.points.setup(e.header.frame_id,e.point_step,e.fields)){var t,i=this.points.pointRatio,r=this.max_pts*e.point_step;e.data.buffer?(this.buffer=e.data.slice(0,Math.min(e.data.byteLength,r)),t=Math.min(e.height*e.width/i,this.points.positions.array.length/3)):((!this.buffer||this.buffer.byteLength0?(r=d[0].object,p.intersection=this.lastIntersection=d[0]):r=this.fallbackTarget,r!==this.lastTarget&&e.type.match(/mouse/)){var f=this.notify(r,"mouseover",p);0===f?this.notify(this.lastTarget,"mouseout",p):1===f&&(r=this.fallbackTarget)!==this.lastTarget&&(this.notify(r,"mouseover",p),this.notify(this.lastTarget,"mouseout",p))}r!==this.lastTarget&&e.type.match(/touch/)&&(this.notify(r,e.type,p)?(this.notify(this.lastTarget,"touchleave",p),this.notify(this.lastTarget,"touchend",p)):(r=this.fallbackTarget)!==this.lastTarget&&(this.notify(this.lastTarget,"touchmove",p),this.notify(this.lastTarget,"touchend",p)));this.notify(r,e.type,p),"mousedown"!==e.type&&"touchstart"!==e.type&&"touchmove"!==e.type||(this.dragging=!0),this.lastTarget=r}notify(e,t,i){for(i.type=t,i.cancelBubble=!1,i.continueBubble=!1,i.stopPropagation=function(){i.cancelBubble=!0},i.continuePropagation=function(){i.continueBubble=!0},i.currentTarget=e;i.currentTarget;){if(i.currentTarget.dispatchEvent&&i.currentTarget.dispatchEvent instanceof Function){if(i.currentTarget.dispatchEvent(i),i.cancelBubble)return this.dispatchEvent(i),0;if(i.continueBubble)return 2}i.currentTarget=i.currentTarget.parent}return 1}}class Sc extends Ss.EventDispatcher{constructor(e){super();var t=this,i=(e=e||{}).scene;this.camera=e.camera,this.center=new Ss.Vector3,this.userZoom=!0,this.userZoomSpeed=e.userZoomSpeed||1,this.userRotate=!0,this.userRotateSpeed=e.userRotateSpeed||1,this.autoRotate=e.autoRotate,this.autoRotateSpeed=e.autoRotateSpeed||2,this.displayPanAndZoomFrame=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,this.lineTypePanAndZoomFrame=e.dashedPanAndZoomFrame||"full",this.camera.up=new Ss.Vector3(0,0,1);var r=1800,n=new Ss.Vector2,o=new Ss.Vector2,a=new Ss.Vector2,s=new Ss.Vector2,c=new Ss.Vector2,h=new Ss.Vector2,l=new Ss.Vector3,u=new Ss.Vector3,p=new Ss.Vector3,d=new Ss.Vector3,f=new Array(2),m=new Array(2);this.phiDelta=0,this.thetaDelta=0,this.scale=1,this.lastPosition=new Ss.Vector3;var v=-1,g=0,y=1,x=2,b=v;function w(e,t,i){var r=new Ss.Vector3;new Ss.Vector3;r.subVectors(t,e.origin);var n=e.direction.dot(i);if(Math.abs(n)0?t.zoomIn():t.zoomOut(),this.showAxes()}}this.axes=new Ks({shaftRadius:.025,headRadius:.07,headLength:.2,lineType:this.lineTypePanAndZoomFrame}),this.displayPanAndZoomFrame&&(i.add(this.axes),this.axes.traverse((function(e){e.visible=!1}))),this.addEventListener("mousedown",(function(e){var i=e.domEvent;switch(i.preventDefault(),i.button){case 0:b=g,n.set(i.clientX,i.clientY);break;case 1:b=x,u=new Ss.Vector3(0,0,1);var r=(new Ss.Matrix4).extractRotation(this.camera.matrix);u.applyMatrix4(r),l=t.center.clone(),p=t.camera.position.clone(),d=w(e.mouseRay,l,u);break;case 2:b=y,s.set(i.clientX,i.clientY)}this.showAxes()})),this.addEventListener("mouseup",(function(e){t.userRotate&&(b=v)})),this.addEventListener("mousemove",(function(e){var i=e.domEvent;if(b===g)o.set(i.clientX,i.clientY),a.subVectors(o,n),t.rotateLeft(2*Math.PI*a.x/r*t.userRotateSpeed),t.rotateUp(2*Math.PI*a.y/r*t.userRotateSpeed),n.copy(o),this.showAxes();else if(b===y)c.set(i.clientX,i.clientY),h.subVectors(c,s),h.y>0?t.zoomIn():t.zoomOut(),s.copy(c),this.showAxes();else if(b===x){var f=w(e.mouseRay,t.center,u);if(!f)return;var m=(new Ss.Vector3).subVectors(d.clone(),f.clone());t.center.addVectors(l.clone(),m.clone()),t.camera.position.addVectors(p.clone(),m.clone()),t.update(),t.camera.updateMatrixWorld(),this.showAxes()}})),this.addEventListener("touchstart",(function(e){var i=e.domEvent;switch(i.touches.length){case 1:b=g,n.set(i.touches[0].pageX-window.scrollX,i.touches[0].pageY-window.scrollY);break;case 2:b=v,u=new Ss.Vector3(0,0,1);var r=(new Ss.Matrix4).extractRotation(this.camera.matrix);u.applyMatrix4(r),l=t.center.clone(),p=t.camera.position.clone(),d=w(e.mouseRay,l,u),f[0]=new Ss.Vector2(i.touches[0].pageX,i.touches[0].pageY),f[1]=new Ss.Vector2(i.touches[1].pageX,i.touches[1].pageY),m[0]=new Ss.Vector2(0,0),m[1]=new Ss.Vector2(0,0)}this.showAxes(),i.preventDefault()})),this.addEventListener("touchmove",(function(e){var i=e.domEvent;if(b===g)o.set(i.touches[0].pageX-window.scrollX,i.touches[0].pageY-window.scrollY),a.subVectors(o,n),t.rotateLeft(2*Math.PI*a.x/r*t.userRotateSpeed),t.rotateUp(2*Math.PI*a.y/r*t.userRotateSpeed),n.copy(o),this.showAxes();else{if(m[0].set(f[0].x-i.touches[0].pageX,f[0].y-i.touches[0].pageY),m[1].set(f[1].x-i.touches[1].pageX,f[1].y-i.touches[1].pageY),m[0].lengthSq()>10&&m[1].lengthSq()>10&&(f[0].set(i.touches[0].pageX,i.touches[0].pageY),f[1].set(i.touches[1].pageX,i.touches[1].pageY),m[0].dot(m[1])>0&&b!==y?b=x:m[0].dot(m[1])<0&&b!==x&&(b=y),b===y)){var s=new Ss.Vector2;s.subVectors(f[0],f[1]),m[0].dot(s)<0&&m[1].dot(s)>0?t.zoomOut():m[0].dot(s)>0&&m[1].dot(s)<0&&t.zoomIn()}if(b===x){var c=w(e.mouseRay,t.center,u);if(!c)return;var h=(new Ss.Vector3).subVectors(d.clone(),c.clone());t.center.addVectors(l.clone(),h.clone()),t.camera.position.addVectors(p.clone(),h.clone()),t.update(),t.camera.updateMatrixWorld()}this.showAxes(),i.preventDefault()}})),this.addEventListener("touchend",(function(e){var t=e.domEvent;1===t.touches.length&&b!==g?(b=g,n.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY)):b=v})),this.addEventListener("mousewheel",_),this.addEventListener("DOMMouseScroll",_)}showAxes(){var e=this;this.axes.traverse((function(e){e.visible=!0})),this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout((function(){e.axes.traverse((function(e){e.visible=!1})),e.hideTimeout=!1}),1e3)}rotateLeft(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta-=e}rotateRight(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta+=e}rotateUp(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta-=e}rotateDown(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta+=e}zoomIn(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale/=e}zoomOut(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale*=e}update(){var e=this.camera.position,t=e.clone().sub(this.center),i=Math.atan2(t.y,t.x),r=Math.atan2(Math.sqrt(t.y*t.y+t.x*t.x),t.z);this.autoRotate&&this.rotateLeft(2*Math.PI/60/60*this.autoRotateSpeed),i+=this.thetaDelta,r+=this.phiDelta;var n=1e-6;r=Math.max(n,Math.min(Math.PI-n,r));var o=t.length();t.set(o*Math.sin(r)*Math.cos(i),o*Math.sin(r)*Math.sin(i),o*Math.cos(r)),t.multiplyScalar(this.scale),e.copy(this.center).add(t),this.camera.lookAt(this.center),o=t.length(),this.axes.position.copy(this.center),this.axes.scale.set(.05*o,.05*o,.05*o),this.axes.updateMatrixWorld(!0),this.thetaDelta=0,this.phiDelta=0,this.scale=1,this.lastPosition.distanceTo(this.camera.position)>0&&(this.dispatchEvent({type:"change"}),this.lastPosition.copy(this.camera.position))}}return e.Arrow=Ns,e.Arrow2=Js,e.Axes=Ks,e.ColorOcTree=cc,e.DepthCloud=Ps,e.Grid=Qs,e.Highlighter=Ec,e.INTERACTIVE_MARKER_BUTTON=2,e.INTERACTIVE_MARKER_BUTTON_CLICK=3,e.INTERACTIVE_MARKER_FIXED=1,e.INTERACTIVE_MARKER_INHERIT=0,e.INTERACTIVE_MARKER_KEEP_ALIVE=0,e.INTERACTIVE_MARKER_MENU=1,e.INTERACTIVE_MARKER_MENU_SELECT=2,e.INTERACTIVE_MARKER_MOUSE_DOWN=4,e.INTERACTIVE_MARKER_MOUSE_UP=5,e.INTERACTIVE_MARKER_MOVE_3D=7,e.INTERACTIVE_MARKER_MOVE_AXIS=3,e.INTERACTIVE_MARKER_MOVE_PLANE=4,e.INTERACTIVE_MARKER_MOVE_ROTATE=6,e.INTERACTIVE_MARKER_MOVE_ROTATE_3D=9,e.INTERACTIVE_MARKER_NONE=0,e.INTERACTIVE_MARKER_POSE_UPDATE=1,e.INTERACTIVE_MARKER_ROTATE_3D=8,e.INTERACTIVE_MARKER_ROTATE_AXIS=5,e.INTERACTIVE_MARKER_VIEW_FACING=2,e.InteractiveMarker=js,e.InteractiveMarkerClient=class{constructor(e){e=e||{},this.ros=e.ros,this.tfClient=e.tfClient,this.topicName=e.topic,this.path=e.path||"/",this.camera=e.camera,this.rootObject=e.rootObject||new Ss.Object3D,this.loader=e.loader,this.menuFontSize=e.menuFontSize||"0.8em",this.interactiveMarkers={},this.updateTopic=null,this.feedbackTopic=null,this.topicName&&this.subscribe(this.topicName)}subscribe(e){this.unsubscribe(),this.updateTopic=new r.Topic({ros:this.ros,name:e+"/tunneled/update",messageType:"visualization_msgs/InteractiveMarkerUpdate",compression:"png"}),this.updateTopic.subscribe(this.processUpdate.bind(this)),this.feedbackTopic=new r.Topic({ros:this.ros,name:e+"/feedback",messageType:"visualization_msgs/InteractiveMarkerFeedback",compression:"png"}),this.feedbackTopic.advertise(),this.initService=new r.Service({ros:this.ros,name:e+"/tunneled/get_init",serviceType:"demo_interactive_markers/GetInit"});var t=new r.ServiceRequest({});this.initService.callService(t,this.processInit.bind(this))}unsubscribe(){for(var e in this.updateTopic&&this.updateTopic.unsubscribe(this.processUpdate),this.feedbackTopic&&this.feedbackTopic.unadvertise(),this.interactiveMarkers)this.eraseIntMarker(e);this.interactiveMarkers={}}processInit(e){var t=e.msg;for(var i in t.erases=[],this.interactiveMarkers)t.erases.push(i);t.poses=[],this.processUpdate(t)}processUpdate(e){var t=this;e.erases.forEach((function(e){t.eraseIntMarker(e)})),e.poses.forEach((function(e){var i=t.interactiveMarkers[e.name];i&&i.setPoseFromServer(e.pose)})),e.markers.forEach((function(e){var i=t.interactiveMarkers[e.name];i&&t.eraseIntMarker(i.name);var r=new Ys({message:e,feedbackTopic:t.feedbackTopic,tfClient:t.tfClient,menuFontSize:t.menuFontSize});t.interactiveMarkers[e.name]=r;var n=new js({handle:r,camera:t.camera,path:t.path,loader:t.loader});n.name=e.name,t.rootObject.add(n),r.on("pose",(function(e){n.onServerSetPose({pose:e})})),n.addEventListener("user-pose-change",r.setPoseFromClientBound),n.addEventListener("user-mousedown",r.onMouseDownBound),n.addEventListener("user-mouseup",r.onMouseUpBound),n.addEventListener("user-button-click",r.onButtonClickBound),n.addEventListener("menu-select",r.onMenuSelectBound),r.subscribeTf()}))}eraseIntMarker(e){if(this.interactiveMarkers[e]){var t=this.rootObject.getObjectByName(e);this.rootObject.remove(t);var i=this.interactiveMarkers[e];i.unsubscribeTf(),t.removeEventListener("user-pose-change",i.setPoseFromClientBound),t.removeEventListener("user-mousedown",i.onMouseDownBound),t.removeEventListener("user-mouseup",i.onMouseUpBound),t.removeEventListener("user-button-click",i.onButtonClickBound),t.removeEventListener("menu-select",i.onMenuSelectBound),delete this.interactiveMarkers[e],t.dispose()}}},e.InteractiveMarkerControl=Gs,e.InteractiveMarkerHandle=Ys,e.InteractiveMarkerMenu=Vs,e.LaserScan=gc,e.MARKER_ARROW=0,e.MARKER_CUBE=1,e.MARKER_CUBE_LIST=6,e.MARKER_CYLINDER=3,e.MARKER_LINE_LIST=5,e.MARKER_LINE_STRIP=4,e.MARKER_MESH_RESOURCE=10,e.MARKER_POINTS=8,e.MARKER_SPHERE=2,e.MARKER_SPHERE_LIST=7,e.MARKER_TEXT_VIEW_FACING=9,e.MARKER_TRIANGLE_LIST=11,e.Marker=ks,e.MarkerArrayClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.path=e.path||"/",this.markers={},this.rosTopic=void 0,this.subscribe()}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/MarkerArray",compression:"png"}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){e.markers.forEach(function(e){var t=e.ns+e.id;if(0===e.action){var i=!1;if(t in this.markers&&((i=this.markers[t].children[0].update(e))||this.removeMarker(t)),!i){var r=new ks({message:e,path:this.path});this.markers[t]=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:r}),this.rootObject.add(this.markers[t])}}else if(1===e.action)console.warn('Received marker message with deprecated action identifier "1"');else if(2===e.action)this.removeMarker(t);else if(3===e.action){for(var n in this.markers)this.removeMarker(n);this.markers={}}else console.warn('Received marker message with unknown action identifier "'+e.action+'"')}.bind(this)),this.emit("change")}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}removeMarker(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((e=>{e.dispose()})),delete this.markers[e])}},e.MarkerClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.path=e.path||"/",this.lifetime=e.lifetime||0,this.markers={},this.rosTopic=void 0,this.updatedTime={},this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}checkTime(e){if((new Date).getTime()-this.updatedTime[e]>this.lifetime)this.removeMarker(e),this.emit("change");else{var t=this;setTimeout((function(){t.checkTime(e)}),100)}}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/Marker",compression:"png"}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){var t=e.ns+e.id,i=this.markers[t];if(this.updatedTime[t]=(new Date).getTime(),i?this.removeMarker(t):this.lifetime&&this.checkTime(e.ns+e.id),0===e.action){var r=new ks({message:e,path:this.path});this.markers[t]=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:r}),this.rootObject.add(this.markers[t])}this.emit("change")}removeMarker(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((e=>{e.dispose()})),delete this.markers[e])}},e.MeshLoader=Fs,e.MeshResource=Bs,e.MouseHandler=Tc,e.NavSatFix=yc,e.OcTree=sc,e.OcTreeClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/octomap",this.compression=e.compression||"cbor",this.continuous=e.continuous,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.offsetPose=e.offsetPose||new r.Pose,this.options={},void 0!==e.color&&(this.options.color=e.color),void 0!==e.opacity&&(this.options.opacity=e.opacity),void 0!==e.colorMode&&(this.options.colorMode=e.colorMode),void 0!==e.palette&&(this.options.palette=e.palette),void 0!==e.paletteScale&&(this.options.paletteScale=e.palette),void 0!==e.voxelRenderMode&&(this.options.voxelRenderMode=e.voxelRenderMode),this.currentMap=null,this.rosTopic=void 0,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"octomap_msgs/Octomap",queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){this.currentMap&&this.currentMap.tfClient&&this.currentMap.unsubscribeTf(),this._processMessagePrivate(e),this.continuous||this.rosTopic.unsubscribe(this.processMessage)}_loadOcTree(e){return new Promise(function(t,i){const r=Object.assign({resolution:e.resolution},this.options);let n=null;if(e.binary)n=new ac(r),n.readBinary(e.data);else{const t={OcTree:sc,ColorOcTree:cc};e.id in t&&(console.log(e.id,t),n=new t[e.id](r),n.read(e.data))}n.buildGeometry(),t(n)}.bind(this))}_processMessagePrivate(e){this._loadOcTree(e).then(function(t){const i=this.sceneNode;this.tfClient?(this.currentMap=t,this.sceneNode=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:t.object,pose:this.offsetPose})):(this.sceneNode=t.object,this.currentMap=t),this.rootObject.remove(i),this.rootObject.add(this.sceneNode),this.emit("change")}.bind(this))}},e.OccupancyGrid=$s,e.OccupancyGridClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/map",this.compression=e.compression||"cbor",this.continuous=e.continuous,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.offsetPose=e.offsetPose||new r.Pose,this.color=e.color||{r:255,g:255,b:255},this.opacity=e.opacity||1,this.currentGrid=null,this.rosTopic=void 0,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"nav_msgs/OccupancyGrid",queue_length:1,compression:this.compression}),this.sceneNode=null,this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){this.currentGrid&&(this.tfClient?(this.sceneNode.unsubscribeTf(),this.sceneNode.remove(this.currentGrid)):this.rootObject.remove(this.currentGrid),this.currentGrid.dispose());var t=new $s({message:e,color:this.color,opacity:this.opacity});this.tfClient?(this.currentGrid=t,null===this.sceneNode?(this.sceneNode=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:t,pose:this.offsetPose}),this.rootObject.add(this.sceneNode)):this.sceneNode.add(this.currentGrid)):(this.sceneNode=this.currentGrid=t,this.rootObject.add(this.currentGrid)),this.emit("change"),this.continuous||this.rosTopic.unsubscribe(this.processMessage)}},e.Odometry=hc,e.OrbitControls=Sc,e.Path=lc,e.Point=uc,e.PointCloud2=wc,e.Points=vc,e.Polygon=pc,e.Pose=dc,e.PoseArray=fc,e.PoseWithCovariance=mc,e.SceneNode=Zs,e.TFAxes=_c,e.TriangleList=zs,e.Urdf=Mc,e.UrdfClient=class{constructor(e){var t=this,i=(e=e||{}).ros;this.param=e.param||"robot_description",this.path=e.path||"/",this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.tfPrefix=e.tfPrefix||"",this.loader=e.loader,new r.Param({ros:i,name:this.param}).get((function(e){var i=new r.UrdfModel({string:e});t.urdf=new Mc({urdfModel:i,path:t.path,tfClient:t.tfClient,tfPrefix:t.tfPrefix,loader:t.loader}),t.rootObject.add(t.urdf)}))}},e.Viewer=class{constructor(e){var t=(e=e||{}).divID,i=e.elem,r=e.width,n=e.height,o=e.background||"#111111",a=e.antialias,s=e.intensity||.66,c=e.near||.01,h=e.far||1e3,l=e.alpha||1,u=e.cameraPose||{x:3,y:3,z:3},p=e.cameraZoomSpeed||.5,d=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,f=e.lineTypePanAndZoomFrame||"full";this.renderer=new Ss.WebGLRenderer({antialias:a,alpha:!0}),this.renderer.setClearColor(parseInt(o.replace("#","0x"),16),l),this.renderer.sortObjects=!1,this.renderer.setSize(r,n),this.renderer.shadowMap.enabled=!1,this.renderer.autoClear=!1,this.scene=new Ss.Scene,this.camera=new Ss.PerspectiveCamera(40,r/n,c,h),this.camera.position.x=u.x,this.camera.position.y=u.y,this.camera.position.z=u.z,this.cameraControls=new Sc({scene:this.scene,camera:this.camera,displayPanAndZoomFrame:d,lineTypePanAndZoomFrame:f}),this.cameraControls.userZoomSpeed=p,this.scene.add(new Ss.AmbientLight(5592405)),this.directionalLight=new Ss.DirectionalLight(16777215,s),this.scene.add(this.directionalLight),this.selectableObjects=new Ss.Group,this.scene.add(this.selectableObjects);var m=new Tc({renderer:this.renderer,camera:this.camera,rootObject:this.selectableObjects,fallbackTarget:this.cameraControls});this.highlighter=new Ec({mouseHandler:m}),this.stopped=!0,this.animationRequestId=void 0,(i||document.getElementById(t)).appendChild(this.renderer.domElement),this.start()}start(){this.stopped=!1,this.draw()}draw(){this.stopped||(this.cameraControls.update(),this.directionalLight.position.normalize(),this.renderer.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera),this.highlighter.renderHighlights(this.scene,this.renderer,this.camera),this.animationRequestId=requestAnimationFrame(this.draw.bind(this)))}stop(){this.stopped||cancelAnimationFrame(this.animationRequestId),this.stopped=!0}addObject(e,t){t?this.selectableObjects.add(e):this.scene.add(e)}resize(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t)}},e.closestAxisPoint=Cs,e.findClosestPoint=Rs,e.intersectPlane=Ls,e.makeColorMaterial=As,Object.defineProperty(e,"__esModule",{value:!0}),e}({},ROSLIB); + */Ws=Xs,function(e){var t=Object.hasOwnProperty,i=Array.isArray?Array.isArray:function(e){return"[object Array]"===Object.prototype.toString.call(e)},r="object"==typeof process&&"function"==typeof process.nextTick,n="function"==typeof Symbol,o="object"==typeof Reflect,a="function"==typeof setImmediate?setImmediate:setTimeout,s=n?o&&"function"==typeof Reflect.ownKeys?Reflect.ownKeys:function(e){var t=Object.getOwnPropertyNames(e);return t.push.apply(t,Object.getOwnPropertySymbols(e)),t}:Object.keys;function c(){this._events={},this._conf&&h.call(this,this._conf)}function h(t){t&&(this._conf=t,t.delimiter&&(this.delimiter=t.delimiter),t.maxListeners!==e&&(this._maxListeners=t.maxListeners),t.wildcard&&(this.wildcard=t.wildcard),t.newListener&&(this._newListener=t.newListener),t.removeListener&&(this._removeListener=t.removeListener),t.verboseMemoryLeak&&(this.verboseMemoryLeak=t.verboseMemoryLeak),t.ignoreErrors&&(this.ignoreErrors=t.ignoreErrors),this.wildcard&&(this.listenerTree={}))}function l(e,t){var i="(node) warning: possible EventEmitter memory leak detected. "+e+" listeners added. Use emitter.setMaxListeners() to increase limit.";if(this.verboseMemoryLeak&&(i+=" Event name: "+t+"."),"undefined"!=typeof process&&process.emitWarning){var r=new Error(i);r.name="MaxListenersExceededWarning",r.emitter=this,r.count=e,process.emitWarning(r)}else console.error(i),console.trace&&console.trace()}var u=function(e,t,i){var r=arguments.length;switch(r){case 0:return[];case 1:return[e];case 2:return[e,t];case 3:return[e,t,i];default:for(var n=new Array(r);r--;)n[r]=arguments[r];return n}};function p(t,i){for(var r={},n=t.length,o=i?i.length:0,a=0;a0;)if(o===e[a])return r;n(t)}}Object.assign(d.prototype,{subscribe:function(e,t,i){var r=this,n=this._target,o=this._emitter,a=this._listeners,s=function(){var r=u.apply(null,arguments),a={data:r,name:t,original:e};if(i){var s=i.call(n,a);!1!==s&&o.emit.apply(o,[a.name].concat(r))}else o.emit.apply(o,[t].concat(r))};if(a[e])throw Error("Event '"+e+"' is already listening");this._listenersCount++,o._newListener&&o._removeListener&&!r._onNewListener?(this._onNewListener=function(i){i===t&&null===a[e]&&(a[e]=s,r._on.call(n,e,s))},o.on("newListener",this._onNewListener),this._onRemoveListener=function(i){i===t&&!o.hasListeners(i)&&a[e]&&(a[e]=null,r._off.call(n,e,s))},a[e]=null,o.on("removeListener",this._onRemoveListener)):(a[e]=s,r._on.call(n,e,s))},unsubscribe:function(e){var t,i,r,n=this,o=this._listeners,a=this._emitter,c=this._off,h=this._target;if(e&&"string"!=typeof e)throw TypeError("event must be a string");function l(){n._onNewListener&&(a.off("newListener",n._onNewListener),a.off("removeListener",n._onRemoveListener),n._onNewListener=null,n._onRemoveListener=null);var e=b.call(a,n);a._observers.splice(e,1)}if(e){if(!(t=o[e]))return;c.call(h,e,t),delete o[e],--this._listenersCount||l()}else{for(r=(i=s(o)).length;r-- >0;)e=i[r],c.call(h,e,o[e]);this._listeners={},this._listenersCount=0,l()}}});var g=v(["function"]),y=v(["object","function"]);function x(e,t,i){var r,n,o,a=0,s=new e((function(c,h,l){function u(){n&&(n=null),a&&(clearTimeout(a),a=0)}i=f(i,{timeout:0,overload:!1},{timeout:function(e,t){return("number"!=typeof(e*=1)||e<0||!Number.isFinite(e))&&t("timeout must be a positive number"),e}}),r=!i.overload&&"function"==typeof e.prototype.cancel&&"function"==typeof l;var p=function(e){u(),c(e)},d=function(e){u(),h(e)};r?t(p,d,l):(n=[function(e){d(e||Error("canceled"))}],t(p,d,(function(e){if(o)throw Error("Unable to subscribe on cancel event asynchronously");if("function"!=typeof e)throw TypeError("onCancel callback must be a function");n.push(e)})),o=!0),i.timeout>0&&(a=setTimeout((function(){var e=Error("timeout");e.code="ETIMEDOUT",a=0,s.cancel(e),h(e)}),i.timeout))}));return r||(s.cancel=function(e){if(n){for(var t=n.length,i=1;i0;)"_listeners"!==(d=y[c])&&(x=w(e,t,i[d],r+1,n))&&(b?b.push.apply(b,x):b=x);return b}if("**"===_){for((g=r+1===n||r+2===n&&"*"===M)&&i._listeners&&(b=w(e,t,i,n,n)),c=(y=s(i)).length;c-- >0;)"_listeners"!==(d=y[c])&&("*"===d||"**"===d?(i[d]._listeners&&!g&&(x=w(e,t,i[d],n,n))&&(b?b.push.apply(b,x):b=x),x=w(e,t,i[d],r,n)):x=w(e,t,i[d],d===M?r+2:r,n),x&&(b?b.push.apply(b,x):b=x));return b}i[_]&&(b=w(e,t,i[_],r+1,n))}if((f=i["*"])&&w(e,t,f,r+1,n),m=i["**"])if(r0;)"_listeners"!==(d=y[c])&&(d===M?w(e,t,m[d],r+2,n):d===_?w(e,t,m[d],r+1,n):((v={})[d]=m[d],w(e,t,{"**":v},r+1,n)));else m._listeners?w(e,t,m,n,n):m["*"]&&m["*"]._listeners&&w(e,t,m["*"],n,n);return b}function _(e,t,i){var r,n,o=0,a=0,s=this.delimiter,c=s.length;if("string"==typeof e)if(-1!==(r=e.indexOf(s))){n=new Array(5);do{n[o++]=e.slice(a,r),a=r+c}while(-1!==(r=e.indexOf(s,a)));n[o++]=e.slice(a)}else n=[e],o=1;else n=e,o=e.length;if(o>1)for(r=0;r+10&&u._listeners.length>this._maxListeners&&(u._listeners.warned=!0,l.call(this,u._listeners.length,h))):u._listeners=t,!0;return!0}function M(e,t,i,r){for(var n,o,a,c,h=s(e),l=h.length,u=e._listeners;l-- >0;)n=e[o=h[l]],a="_listeners"===o?i:i?i.concat(o):[o],c=r||"symbol"==typeof o,u&&t.push(c?a:a.join(this.delimiter)),"object"==typeof n&&M.call(this,n,t,a,c);return t}function E(e){for(var t,i,r,n=s(e),o=n.length;o-- >0;)(t=e[i=n[o]])&&(r=!0,"_listeners"===i||E(t)||delete e[i]);return r}function T(e,t,i){this.emitter=e,this.event=t,this.listener=i}function S(t,i,n){if(!0===n)s=!0;else if(!1===n)o=!0;else{if(!n||"object"!=typeof n)throw TypeError("options should be an object or true");var o=n.async,s=n.promisify,c=n.nextTick,h=n.objectify}if(o||c||s){var l=i,u=i._origin||i;if(c&&!r)throw Error("process.nextTick is not supported");s===e&&(s="AsyncFunction"===i.constructor.name),i=function(){var e=arguments,t=this,i=this.event;return s?c?Promise.resolve():new Promise((function(e){a(e)})).then((function(){return t.event=i,l.apply(t,e)})):(c?process.nextTick:a)((function(){t.event=i,l.apply(t,e)}))},i._async=!0,i._origin=u}return[i,h?new T(this,t,i):this]}function A(e){this._events={},this._newListener=!1,this._removeListener=!1,this.verboseMemoryLeak=!1,h.call(this,e)}T.prototype.off=function(){return this.emitter.off(this.event,this.listener),this},A.EventEmitter2=A,A.prototype.listenTo=function(t,r,n){if("object"!=typeof t)throw TypeError("target musts be an object");var o=this;function a(e){if("object"!=typeof e)throw TypeError("events must be an object");var i,r=n.reducers,a=b.call(o,t);i=-1===a?new d(o,t,n):o._observers[a];for(var c,h=s(e),l=h.length,u="function"==typeof r,p=0;p0;)r=i[n],e&&r._target!==e||(r.unsubscribe(t),o=!0);return o},A.prototype.delimiter=".",A.prototype.setMaxListeners=function(t){t!==e&&(this._maxListeners=t,this._conf||(this._conf={}),this._conf.maxListeners=t)},A.prototype.getMaxListeners=function(){return this._maxListeners},A.prototype.event="",A.prototype.once=function(e,t,i){return this._once(e,t,!1,i)},A.prototype.prependOnceListener=function(e,t,i){return this._once(e,t,!0,i)},A.prototype._once=function(e,t,i,r){return this._many(e,1,t,i,r)},A.prototype.many=function(e,t,i,r){return this._many(e,t,i,!1,r)},A.prototype.prependMany=function(e,t,i,r){return this._many(e,t,i,!0,r)},A.prototype._many=function(e,t,i,r,n){var o=this;if("function"!=typeof i)throw new Error("many only accepts instances of Function");function a(){return 0==--t&&o.off(e,a),i.apply(this,arguments)}return a._origin=i,this._on(e,a,r,n)},A.prototype.emit=function(){if(!this._events&&!this._all)return!1;this._events||c.call(this);var e,t,i,r,o,a,s=arguments[0],h=this.wildcard;if("newListener"===s&&!this._newListener&&!this._events.newListener)return!1;if(h&&(e=s,"newListener"!==s&&"removeListener"!==s&&"object"==typeof s)){if(i=s.length,n)for(r=0;r3)for(t=new Array(u-1),o=1;o3)for(i=new Array(p-1),a=1;a0&&this._events[t].length>this._maxListeners&&(this._events[t].warned=!0,l.call(this,this._events[t].length,t))):this._events[t]=i,a)},A.prototype.off=function(e,t){if("function"!=typeof t)throw new Error("removeListener only takes instances of Function");var r,n=[];if(this.wildcard){var o="string"==typeof e?e.split(this.delimiter):e.slice();if(!(n=w.call(this,null,o,this.listenerTree,0)))return this}else{if(!this._events[e])return this;r=this._events[e],n.push({_listeners:r})}for(var a=0;a0){for(i=0,r=(t=this._all).length;i0;)"function"==typeof(r=c[i[o]])?n.push(r):n.push.apply(n,r);return n}if(this.wildcard){if(!(a=this.listenerTree))return[];var h=[],l="string"==typeof t?t.split(this.delimiter):t.slice();return w.call(this,h,l,a,0),h}return c&&(r=c[t])?"function"==typeof r?[r]:r:[]},A.prototype.eventNames=function(e){var t=this._events;return this.wildcard?M.call(this,this.listenerTree,[],null,e):t?s(t):[]},A.prototype.listenerCount=function(e){return this.listeners(e).length},A.prototype.hasListeners=function(t){if(this.wildcard){var i=[],r="string"==typeof t?t.split(this.delimiter):t.slice();return w.call(this,i,r,this.listenerTree,0),i.length>0}var n=this._events,o=this._all;return!!(o&&o.length||n&&(t===e?s(n).length:n[t]))},A.prototype.listenersAny=function(){return this._all?this._all:[]},A.prototype.waitFor=function(t,i){var r=this,n=typeof i;return"number"===n?i={timeout:i}:"function"===n&&(i={filter:i}),x((i=f(i,{timeout:0,filter:e,handleError:!1,Promise:Promise,overload:!1},{filter:g,Promise:m})).Promise,(function(e,n,o){function a(){var o=i.filter;if(!o||o.apply(r,arguments))if(r.off(t,a),i.handleError){var s=arguments[0];s?n(s):e(u.apply(null,arguments).slice(1))}else e(u.apply(null,arguments))}o((function(){r.off(t,a)})),r._on(t,a,!1)}),{timeout:i.timeout,overload:i.overload})};var L=A.prototype;Object.defineProperties(A,{defaultMaxListeners:{get:function(){return L._maxListeners},set:function(e){if("number"!=typeof e||e<0||Number.isNaN(e))throw TypeError("n must be a non-negative number");L._maxListeners=e},enumerable:!0},once:{value:function(e,t,i){return x((i=f(i,{Promise:Promise,timeout:0,overload:!1},{Promise:m})).Promise,(function(i,r,n){var o;if("function"==typeof e.addEventListener)return o=function(){i(u.apply(null,arguments))},n((function(){e.removeEventListener(t,o)})),void e.addEventListener(t,o,{once:!0});var a,s=function(){a&&e.removeListener("error",a),i(u.apply(null,arguments))};"error"!==t&&(a=function(i){e.removeListener(t,s),r(i)},e.once("error",a)),n((function(){a&&e.removeListener("error",a),e.removeListener(t,s)})),e.once(t,s)}),{timeout:i.timeout,overload:i.overload})},writable:!0,configurable:!0}}),Object.defineProperties(L,{_maxListeners:{value:10,writable:!0,configurable:!0},_observers:{value:null,writable:!0,configurable:!0}}),Ws.exports=A}();var qs=Hs(Xs.exports);class Ys extends qs{constructor(e){super(),e=e||{},this.message=e.message,this.feedbackTopic=e.feedbackTopic,this.tfClient=e.tfClient,this.menuFontSize=e.menuFontSize||"0.8em",this.name=this.message.name,this.header=this.message.header,this.controls=this.message.controls,this.menuEntries=this.message.menu_entries,this.dragging=!1,this.timeoutHandle=null,this.tfTransform=new r.Transform,this.pose=new r.Pose,this.setPoseFromClientBound=this.setPoseFromClient.bind(this),this.onMouseDownBound=this.onMouseDown.bind(this),this.onMouseUpBound=this.onMouseUp.bind(this),this.onButtonClickBound=this.onButtonClick.bind(this),this.onMenuSelectBound=this.onMenuSelect.bind(this),this.setPoseFromServer(this.message.pose),this.tfUpdateBound=this.tfUpdate.bind(this)}subscribeTf(){0===this.message.header.stamp.secs&&0===this.message.header.stamp.nsecs&&this.tfClient.subscribe(this.message.header.frame_id,this.tfUpdateBound)}unsubscribeTf(){this.tfClient.unsubscribe(this.message.header.frame_id,this.tfUpdateBound)}emitServerPoseUpdate(){var e=new r.Pose(this.pose);e.applyTransform(this.tfTransform),this.emit("pose",e)}setPoseFromServer(e){this.pose=new r.Pose(e),this.emitServerPoseUpdate()}tfUpdate(e){this.tfTransform=new r.Transform(e),this.emitServerPoseUpdate()}setPoseFromClient(e){this.pose=new r.Pose(e);var t=this.tfTransform.clone();t.rotation.invert(),t.translation.multiplyQuaternion(t.rotation),t.translation.x*=-1,t.translation.y*=-1,t.translation.z*=-1,this.pose.applyTransform(t),this.sendFeedback(1,void 0,0,e.controlName),this.dragging&&(this.timeoutHandle&&clearTimeout(this.timeoutHandle),this.timeoutHandle=setTimeout(this.setPoseFromClient.bind(this,e),250))}onButtonClick(e){this.sendFeedback(3,e.clickPosition,0,e.controlName)}onMouseDown(e){this.sendFeedback(4,e.clickPosition,0,e.controlName),this.dragging=!0}onMouseUp(e){this.sendFeedback(5,e.clickPosition,0,e.controlName),this.dragging=!1,this.timeoutHandle&&clearTimeout(this.timeoutHandle)}onMenuSelect(e){this.sendFeedback(2,void 0,e.id,e.controlName)}sendFeedback(e,t,i,r){var n=void 0!==t;t=t||{x:0,y:0,z:0};var o={header:this.header,client_id:this.clientID,marker_name:this.name,control_name:r,event_type:e,pose:this.pose,mouse_point:t,mouse_point_valid:n,menu_entry_id:i};this.feedbackTopic.publish(o)}}class Zs extends Ss.Object3D{constructor(e){super(),e=e||{};var t=this;this.tfClient=e.tfClient,this.frameID=e.frameID;var i=e.object;this.pose=e.pose||new r.Pose,this.visible=!1,this.add(i),this.updatePose(this.pose),this.tfUpdate=function(e){var i=new r.Transform(e),n=new r.Pose(t.pose);n.applyTransform(i),t.updatePose(n),t.visible=!0},this.tfClient.subscribe(this.frameID,this.tfUpdate)}updatePose(e){this.position.set(e.position.x,e.position.y,e.position.z),this.quaternion.set(e.orientation.x,e.orientation.y,e.orientation.z,e.orientation.w),this.updateMatrixWorld(!0)}unsubscribeTf(){this.tfClient.unsubscribe(this.frameID,this.tfUpdate)}}class Js extends Ss.ArrowHelper{constructor(e){var t=(e=e||{}).origin||new Ss.Vector3(0,0,0),i=e.direction||new Ss.Vector3(1,0,0),r=e.length||1;e.headLength,e.shaftDiameter,e.headDiameter,e.material||new Ss.MeshBasicMaterial,super(i,t,r,16711680)}dispose(){void 0!==this.line&&(this.line.material.dispose(),this.line.geometry.dispose()),void 0!==this.cone&&(this.cone.material.dispose(),this.cone.geometry.dispose())}}class Ks extends Ss.Object3D{constructor(e){super();var t=this,i=(e=e||{}).shaftRadius||.008,r=e.headRadius||.023,n=e.headLength||.1,o=e.scale||1,a=e.lineType||"full",s=e.lineDashLength||.1;function c(e){var r=new Ss.Color;r.setRGB(e.x,e.y,e.z);var n=new Ss.MeshBasicMaterial({color:r.getHex()}),o=new Ss.Vector3;o.crossVectors(e,new Ss.Vector3(0,-1,0));var c=new Ss.Quaternion;c.setFromAxisAngle(o,.5*Math.PI);var h,l=new Ss.Mesh(t.headGeom,n);if(l.position.copy(e),l.position.multiplyScalar(.95),l.quaternion.copy(c),l.updateMatrix(),t.add(l),"dashed"===a)for(var u=s,p=0;u/2+3*u*p+u/2<=1;++p){var d=new Ss.CylinderGeometry(i,i,u);(h=new Ss.Mesh(d,n)).position.copy(e),h.position.multiplyScalar(u/2+3*u*p),h.quaternion.copy(c),h.updateMatrix(),t.add(h)}else"full"===a?((h=new Ss.Mesh(t.lineGeom,n)).position.copy(e),h.position.multiplyScalar(.45),h.quaternion.copy(c),h.updateMatrix(),t.add(h)):console.warn("[Axes]: Unsupported line type. Not drawing any axes.")}this.scale.set(o,o,o),this.lineGeom=new Ss.CylinderGeometry(i,i,1-n),this.headGeom=new Ss.CylinderGeometry(0,r,n),c(new Ss.Vector3(1,0,0)),c(new Ss.Vector3(0,1,0)),c(new Ss.Vector3(0,0,1))}}class Qs extends Ss.Object3D{constructor(e){var t=(e=e||{}).num_cells||10,i=e.color||"#cccccc",r=e.lineWidth||1,n=e.cellSize||1;super();for(var o=new Ss.LineBasicMaterial({color:i,linewidth:r}),a=0;a<=t;++a){var s=n*t/2,c=s-a*n,h=new Ss.Geometry;h.vertices.push(new Ss.Vector3(-s,c,0),new Ss.Vector3(s,c,0));var l=new Ss.Geometry;l.vertices.push(new Ss.Vector3(c,-s,0),new Ss.Vector3(c,s,0)),this.add(new Ss.Line(h,o)),this.add(new Ss.Line(l,o))}}}class $s extends Ss.Mesh{constructor(e){var t=(e=e||{}).message,i=e.opacity||1,r=e.color||{r:255,g:255,b:255,a:255},n=t.info,o=n.origin,a=n.width,s=n.height,c=new Ss.PlaneBufferGeometry(a,s),h=new Uint8Array(a*s*4),l=new Ss.DataTexture(h,a,s,Ss.RGBAFormat);l.flipY=!0,l.minFilter=Ss.NearestFilter,l.magFilter=Ss.NearestFilter,l.needsUpdate=!0;var u=new Ss.MeshBasicMaterial({map:l,transparent:i<1,opacity:i});u.side=Ss.DoubleSide,super(c,u),Object.assign(this,e),this.quaternion.copy(new Ss.Quaternion(o.orientation.x,o.orientation.y,o.orientation.z,o.orientation.w)),this.position.x=a*n.resolution/2+o.position.x,this.position.y=s*n.resolution/2+o.position.y,this.position.z=o.position.z,this.scale.x=n.resolution,this.scale.y=n.resolution;var p=t.data;this.color=r,this.material=u,this.texture=l;for(var d=0;d{const t="read"+e.kind,i="get"+e.kind;this[t]=()=>{if(this._cursor+e.width>this.length)throw new Error("Cannot read data stream. Overflow. Len="+this.length+" crsr="+this._cursor);const t=this._dataView[i](this._cursor,this.isLittleEndian);return this._cursor+=e.width,t}})),Object.defineProperty(this,"isEnd",{get:()=>this.cursor>=this.data.length}),this}class ac{constructor(e){this.resolution=void 0!==e.resolution?e.resolution:1,this.color=new Ss.Color(void 0!==e.color?e.color:"green"),this.opacity=void 0!==e.opacity?e.opacity:1,this.voxelRenderMode=void 0!==e.voxelRenderMode?e.voxelRenderMode:tc,this._rootNode=null,this._treeDepth=16,this._treeMaxKeyVal=32768,this._BINARY_UNALLOCATED=0,this._BINARY_LEAF_FREE=1,this._BINARY_LEAF_OCCUPIED=2,this._BINARY_HAS_CHILDREN=3,this._BINARY_CHILD_BUILD_TABLE={},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE]=function(e){e.value=this._defaultFreeValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED]=function(e){e.value=this._defaultOccupiedValue},this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN]=function(e){e.value=null},this._FACES=[{normal:[-1,0,0],vertices:[[0,1,0],[0,0,0],[0,1,1],[0,0,1]],childIndex:[1,3,5,7]},{normal:[1,0,0],vertices:[[1,1,1],[1,0,1],[1,1,0],[1,0,0]],childIndex:[0,2,4,6]},{normal:[0,-1,0],vertices:[[1,0,1],[0,0,1],[1,0,0],[0,0,0]],childIndex:[2,3,6,7]},{normal:[0,1,0],vertices:[[0,1,1],[1,1,1],[0,1,0],[1,1,0]],childIndex:[0,1,4,5]},{normal:[0,0,-1],vertices:[[1,0,0],[0,0,0],[1,1,0],[0,1,0]],childIndex:[4,5,6,7]},{normal:[0,0,1],vertices:[[0,0,1],[1,0,1],[0,1,1],[1,1,1]],childIndex:[0,1,2,3]}],this.nodeSizeTable=new Array(this._treeDepth);let t=this.resolution;for(let e=this._treeDepth-1;e>=0;--e)this.nodeSizeTable[e]=t,t*=2;this._defaultOccupiedValue=!0,this._defaultFreeValue=!1,this.object=null}searchAtDepth(e,t){t=void 0!==t&&t>0?t:this._treeDepth;const i=this._adjustKeyAtDepth(e,t),r=this._treeDepth-t;let n=this._rootNode;for(let e=this._treeDepth-1;e>=r;--e){const t=this._computeChildIdx(i,e);if(!n.hasChildAt(t))return n.hasChildren()?null:n;n=n.getChildAt(t)}return n}_computeCoordFromKey(e){return e.map((e=>this.resolution*(e-this._treeMaxKeyVal)))}_computeChildIdx(e,t){let i=0;return e[0]&1<(e-this._treeMaxKeyVal>>i<0;){let e=i.pop();const r=t.readUint16();let n=8;for(;0!==n;){--n;const t=(r&3<<2*n)>>2*n;if(t!==this._BINARY_UNALLOCATED){let r=this._newNode();this._BINARY_CHILD_BUILD_TABLE[t].bind(this)(r),e.createChildNodeAt(r,n),t===this._BINARY_HAS_CHILDREN&&i.push(r)}}}}read(e){null!==this._rootNode&&delete this._rootNode,this._rootNode=this._newNode();let t=new oc(e,!0),i=new Array;for(i.push(this._rootNode);i.length>0;){let e=i.pop();this._readNodeData(t,e);const r=t.readUint8();let n=8;for(;0!==n;){--n;if(r&1<0;){let i=t.pop();if(i.node.isLeafNode())e(i.node,i.key,i.depth-1);else for(let e=0;e<8;++e)if(i.node.hasChildAt(e)){const r=this._computeKeyFromChildIdx(e,i.key,i.depth);t.push({node:i.node.getChildAt(e),depth:i.depth+1,key:r})}}}_obtainColor(e){return this.color}_checkOccupied(e){return!1!==e.value}_buildFaces(){let e={vertices:[],indices:[],normals:[],colors:[],_insertFace:function(e,t,i,r){const n=this.vertices.length/3;e.vertices.forEach((function(e){this.vertices.push(t[0]+e[0]*i,t[1]+e[1]*i,t[2]+e[2]*i)}));const o=[r.r,r.g,r.b];this.colors.push(...o,...o,...o,...o),this.normals.push(...e.normal,...e.normal,...e.normal,...e.normal),this.indices.push(n,n+1,n+2,n+2,n+1,n+3)},_checkNeighborsTouchingFace:function(e,t,i){let r=new Array;for(r.push(t);0!==r.length;){const t=r.pop();t.hasChildren()&&e.childIndex.forEach((function(e){if(!t.hasChildAt(e))return!0;{const n=t.getChildAt(e),o=this._checkOccupied(t);(o&&i===ROS3D.OcTreeVoxelRenderMode.OCCUPIED||!o&&i===ic)&&r.push(n)}}))}return!1}};return this._traverseLeaves(((t,i,r)=>{const n=this._computeCoordFromKey(i),o=this.nodeSizeTable[r],a=this._treeDepth-r,s=this._checkOccupied(t);(s||this.voxelRenderMode!==tc)&&(s&&this.voxelRenderMode===ic||this._FACES.forEach((function(s){const c=[i[0]+s.normal[0]*a*a,i[1]+s.normal[1]*a*a,i[2]+s.normal[2]*a*a],h=this.searchAtDepth(c);null===h?e._insertFace(s,n,o,this._obtainColor(t)):rnew Ss.Color(e))):[{r:0,g:0,b:128},{r:0,g:255,b:0},{r:255,g:255,b:0},{r:255,g:128,b:0},{r:255,g:0,b:0}],this.paletteScale=void 0!==e.paletteScale?e.paletteScale:1}_readNodeData(e,t){t.value=e.readFloat32()}_obtainColor(e){if(this.useFlatColoring)return this.color;const t=1/(1+Math.exp(-e.value*this.paletteScale))*this.palette.length,i=Math.trunc(t),r=t-i;return i<0?this.palette[0]:i>=this.palette.length-1?this.palette[this.palette.length-1]:{r:r*this.palette[i].r+(1-r)*this.palette[i+1].r,g:r*this.palette[i].g+(1-r)*this.palette[i+1].g,b:r*this.palette[i].b+(1-r)*this.palette[i+1].b}}_checkOccupied(e){return e.value>=this.occupancyThreshold}}class cc extends sc{constructor(e){super(e),this.useOwnColor=void 0!==e.palette&&e.colorMode===nc}_readNodeData(e,t){t.value=e.readFloat32(),t.color={r:e.readUint8(),g:e.readUint8(),b:e.readUint8()}}_obtainColor(e){return this.useOwnColor?e.color:sc.prototype._obtainColor.call(this,e)}}class hc extends Ss.Object3D{constructor(e){super(),this.options=e||{},this.ros=e.ros,this.topicName=e.topic||"/particlecloud",this.tfClient=e.tfClient,this.color=e.color||13369599,this.length=e.length||1,this.rootObject=e.rootObject||new Ss.Object3D,this.keep=e.keep||1,this.sns=[],this.rosTopic=void 0,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Odometry"}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){this.sns.length>=this.keep&&(this.sns[0].unsubscribeTf(),this.rootObject.remove(this.sns[0]),this.sns.shift()),this.options.origin=new Ss.Vector3(e.pose.pose.position.x,e.pose.pose.position.y,e.pose.pose.position.z);var t=new Ss.Quaternion(e.pose.pose.orientation.x,e.pose.pose.orientation.y,e.pose.pose.orientation.z,e.pose.pose.orientation.w);this.options.direction=new Ss.Vector3(1,0,0),this.options.direction.applyQuaternion(t),this.options.material=new Ss.MeshBasicMaterial({color:this.color});var i=new Ns(this.options);this.sns.push(new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:i})),this.rootObject.add(this.sns[this.sns.length-1])}}class lc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/path",this.tfClient=e.tfClient,this.color=e.color||13369599,this.rootObject=e.rootObject||new Ss.Object3D,this.sn=null,this.line=null,this.rosTopic=void 0,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"nav_msgs/Path"}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){null!==this.sn&&(this.sn.unsubscribeTf(),this.rootObject.remove(this.sn));for(var t=new Ss.Geometry,i=0;i=e.range_min&&n<=e.range_max){var o=e.angle_min+r*e.angle_increment;this.points.positions.array[i++]=n*Math.cos(o),this.points.positions.array[i++]=n*Math.sin(o),this.points.positions.array[i++]=0}}this.points.update(i/3)}}}class yc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/gps/fix",this.rootObject=e.rootObject||new Ss.Object3D,this.object3d=e.object3d||new Ss.Object3D;var t=e.material||{};this.altitudeNaN=e.altitudeNaN||0,this.keep=e.keep||100,this.convert=e.convert||function(e,t,i){return new Ss.Vector3(e,t,i)},this.count=0,this.next1=0,this.next2=this.keep,this.geom=new Ss.BufferGeometry,this.vertices=new Ss.BufferAttribute(new Float32Array(6*this.keep),3),this.geom.addAttribute("position",this.vertices),this.material=t.isMaterial?t:new Ss.LineBasicMaterial(t),this.line=new Ss.Line(this.geom,this.material),this.rootObject.add(this.object3d),this.rootObject.add(this.line),this.rosTopic=void 0,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,queue_length:1,messageType:"sensor_msgs/NavSatFix"}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){var t=isNaN(e.altitude)?this.altitudeNaN:e.altitude,i=this.convert(e.longitude,e.latitude,t);this.object3d.position.copy(i),this.object3d.updateMatrixWorld(!0),this.vertices.array[3*this.next1]=i.x,this.vertices.array[3*this.next1+1]=i.y,this.vertices.array[3*this.next1+2]=i.z,this.vertices.array[3*this.next2]=i.x,this.vertices.array[3*this.next2+1]=i.y,this.vertices.array[3*this.next2+2]=i.z,this.vertices.needsUpdate=!0,this.next1=(this.next1+1)%this.keep,this.next2=this.next1+this.keep,this.count=Math.min(this.count+1,this.keep),this.geom.setDrawRange(this.next2-this.count,this.count)}}function xc(e,t,i,r){var n,o=0,a=0,s=0,c=e.length,h=t.length,l=((r=r||1)-1)*(i=i||h)*8;for(n=0;n=8&&(a-=8,t[s++]=o>>>a&255,s%i==0&&(n+=Math.ceil((l-a)/6),(a%=8)>0&&(o=xc.e[e.charAt(n)])));return Math.floor(s/i)}xc.S="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",xc.e={};for(var bc=0;bc<64;bc++)xc.e[xc.S.charAt(bc)]=bc;class wc extends Ss.Object3D{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/points",this.throttle_rate=e.throttle_rate||null,this.compression=e.compression||"cbor",this.max_pts=e.max_pts||1e4,this.points=new vc(e),this.rosTopic=void 0,this.buffer=null,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"sensor_msgs/PointCloud2",throttle_rate:this.throttle_rate,queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){if(this.points.setup(e.header.frame_id,e.point_step,e.fields)){var t,i=this.points.pointRatio,r=this.max_pts*e.point_step;e.data.buffer?(this.buffer=e.data.slice(0,Math.min(e.data.byteLength,r)),t=Math.min(e.height*e.width/i,this.points.positions.array.length/3)):((!this.buffer||this.buffer.byteLength0?(r=d[0].object,p.intersection=this.lastIntersection=d[0]):r=this.fallbackTarget,r!==this.lastTarget&&e.type.match(/mouse/)){var f=this.notify(r,"mouseover",p);0===f?this.notify(this.lastTarget,"mouseout",p):1===f&&(r=this.fallbackTarget)!==this.lastTarget&&(this.notify(r,"mouseover",p),this.notify(this.lastTarget,"mouseout",p))}r!==this.lastTarget&&e.type.match(/touch/)&&(this.notify(r,e.type,p)?(this.notify(this.lastTarget,"touchleave",p),this.notify(this.lastTarget,"touchend",p)):(r=this.fallbackTarget)!==this.lastTarget&&(this.notify(this.lastTarget,"touchmove",p),this.notify(this.lastTarget,"touchend",p)));this.notify(r,e.type,p),"mousedown"!==e.type&&"touchstart"!==e.type&&"touchmove"!==e.type||(this.dragging=!0),this.lastTarget=r}notify(e,t,i){for(i.type=t,i.cancelBubble=!1,i.continueBubble=!1,i.stopPropagation=function(){i.cancelBubble=!0},i.continuePropagation=function(){i.continueBubble=!0},i.currentTarget=e;i.currentTarget;){if(i.currentTarget.dispatchEvent&&i.currentTarget.dispatchEvent instanceof Function){if(i.currentTarget.dispatchEvent(i),i.cancelBubble)return this.dispatchEvent(i),0;if(i.continueBubble)return 2}i.currentTarget=i.currentTarget.parent}return 1}}class Sc extends Ss.EventDispatcher{constructor(e){super();var t=this,i=(e=e||{}).scene;this.camera=e.camera,this.center=new Ss.Vector3,this.userZoom=!0,this.userZoomSpeed=e.userZoomSpeed||1,this.userRotate=!0,this.userRotateSpeed=e.userRotateSpeed||1,this.autoRotate=e.autoRotate,this.autoRotateSpeed=e.autoRotateSpeed||2,this.displayPanAndZoomFrame=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,this.lineTypePanAndZoomFrame=e.dashedPanAndZoomFrame||"full",this.camera.up=new Ss.Vector3(0,0,1);var r=1800,n=new Ss.Vector2,o=new Ss.Vector2,a=new Ss.Vector2,s=new Ss.Vector2,c=new Ss.Vector2,h=new Ss.Vector2,l=new Ss.Vector3,u=new Ss.Vector3,p=new Ss.Vector3,d=new Ss.Vector3,f=new Array(2),m=new Array(2);this.phiDelta=0,this.thetaDelta=0,this.scale=1,this.lastPosition=new Ss.Vector3;var v=-1,g=0,y=1,x=2,b=v;function w(e,t,i){var r=new Ss.Vector3;new Ss.Vector3;r.subVectors(t,e.origin);var n=e.direction.dot(i);if(Math.abs(n)0?t.zoomIn():t.zoomOut(),this.showAxes()}}this.axes=new Ks({shaftRadius:.025,headRadius:.07,headLength:.2,lineType:this.lineTypePanAndZoomFrame}),this.displayPanAndZoomFrame&&(i.add(this.axes),this.axes.traverse((function(e){e.visible=!1}))),this.addEventListener("mousedown",(function(e){var i=e.domEvent;switch(i.preventDefault(),i.button){case 0:b=g,n.set(i.clientX,i.clientY);break;case 1:b=x,u=new Ss.Vector3(0,0,1);var r=(new Ss.Matrix4).extractRotation(this.camera.matrix);u.applyMatrix4(r),l=t.center.clone(),p=t.camera.position.clone(),d=w(e.mouseRay,l,u);break;case 2:b=y,s.set(i.clientX,i.clientY)}this.showAxes()})),this.addEventListener("mouseup",(function(e){t.userRotate&&(b=v)})),this.addEventListener("mousemove",(function(e){var i=e.domEvent;if(b===g)o.set(i.clientX,i.clientY),a.subVectors(o,n),t.rotateLeft(2*Math.PI*a.x/r*t.userRotateSpeed),t.rotateUp(2*Math.PI*a.y/r*t.userRotateSpeed),n.copy(o),this.showAxes();else if(b===y)c.set(i.clientX,i.clientY),h.subVectors(c,s),h.y>0?t.zoomIn():t.zoomOut(),s.copy(c),this.showAxes();else if(b===x){var f=w(e.mouseRay,t.center,u);if(!f)return;var m=(new Ss.Vector3).subVectors(d.clone(),f.clone());t.center.addVectors(l.clone(),m.clone()),t.camera.position.addVectors(p.clone(),m.clone()),t.update(),t.camera.updateMatrixWorld(),this.showAxes()}})),this.addEventListener("touchstart",(function(e){var i=e.domEvent;switch(i.touches.length){case 1:b=g,n.set(i.touches[0].pageX-window.scrollX,i.touches[0].pageY-window.scrollY);break;case 2:b=v,u=new Ss.Vector3(0,0,1);var r=(new Ss.Matrix4).extractRotation(this.camera.matrix);u.applyMatrix4(r),l=t.center.clone(),p=t.camera.position.clone(),d=w(e.mouseRay,l,u),f[0]=new Ss.Vector2(i.touches[0].pageX,i.touches[0].pageY),f[1]=new Ss.Vector2(i.touches[1].pageX,i.touches[1].pageY),m[0]=new Ss.Vector2(0,0),m[1]=new Ss.Vector2(0,0)}this.showAxes(),i.preventDefault()})),this.addEventListener("touchmove",(function(e){var i=e.domEvent;if(b===g)o.set(i.touches[0].pageX-window.scrollX,i.touches[0].pageY-window.scrollY),a.subVectors(o,n),t.rotateLeft(2*Math.PI*a.x/r*t.userRotateSpeed),t.rotateUp(2*Math.PI*a.y/r*t.userRotateSpeed),n.copy(o),this.showAxes();else{if(m[0].set(f[0].x-i.touches[0].pageX,f[0].y-i.touches[0].pageY),m[1].set(f[1].x-i.touches[1].pageX,f[1].y-i.touches[1].pageY),m[0].lengthSq()>10&&m[1].lengthSq()>10&&(f[0].set(i.touches[0].pageX,i.touches[0].pageY),f[1].set(i.touches[1].pageX,i.touches[1].pageY),m[0].dot(m[1])>0&&b!==y?b=x:m[0].dot(m[1])<0&&b!==x&&(b=y),b===y)){var s=new Ss.Vector2;s.subVectors(f[0],f[1]),m[0].dot(s)<0&&m[1].dot(s)>0?t.zoomOut():m[0].dot(s)>0&&m[1].dot(s)<0&&t.zoomIn()}if(b===x){var c=w(e.mouseRay,t.center,u);if(!c)return;var h=(new Ss.Vector3).subVectors(d.clone(),c.clone());t.center.addVectors(l.clone(),h.clone()),t.camera.position.addVectors(p.clone(),h.clone()),t.update(),t.camera.updateMatrixWorld()}this.showAxes(),i.preventDefault()}})),this.addEventListener("touchend",(function(e){var t=e.domEvent;1===t.touches.length&&b!==g?(b=g,n.set(t.touches[0].pageX-window.scrollX,t.touches[0].pageY-window.scrollY)):b=v})),this.addEventListener("mousewheel",_),this.addEventListener("DOMMouseScroll",_)}showAxes(){var e=this;this.axes.traverse((function(e){e.visible=!0})),this.hideTimeout&&clearTimeout(this.hideTimeout),this.hideTimeout=setTimeout((function(){e.axes.traverse((function(e){e.visible=!1})),e.hideTimeout=!1}),1e3)}rotateLeft(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta-=e}rotateRight(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.thetaDelta+=e}rotateUp(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta-=e}rotateDown(e){void 0===e&&(e=2*Math.PI/60/60*this.autoRotateSpeed),this.phiDelta+=e}zoomIn(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale/=e}zoomOut(e){void 0===e&&(e=Math.pow(.95,this.userZoomSpeed)),this.scale*=e}update(){var e=this.camera.position,t=e.clone().sub(this.center),i=Math.atan2(t.y,t.x),r=Math.atan2(Math.sqrt(t.y*t.y+t.x*t.x),t.z);this.autoRotate&&this.rotateLeft(2*Math.PI/60/60*this.autoRotateSpeed),i+=this.thetaDelta,r+=this.phiDelta;var n=1e-6;r=Math.max(n,Math.min(Math.PI-n,r));var o=t.length();t.set(o*Math.sin(r)*Math.cos(i),o*Math.sin(r)*Math.sin(i),o*Math.cos(r)),t.multiplyScalar(this.scale),e.copy(this.center).add(t),this.camera.lookAt(this.center),o=t.length(),this.axes.position.copy(this.center),this.axes.scale.set(.05*o,.05*o,.05*o),this.axes.updateMatrixWorld(!0),this.thetaDelta=0,this.phiDelta=0,this.scale=1,this.lastPosition.distanceTo(this.camera.position)>0&&(this.dispatchEvent({type:"change"}),this.lastPosition.copy(this.camera.position))}}return e.Arrow=Ns,e.Arrow2=Js,e.Axes=Ks,e.ColorOcTree=cc,e.DepthCloud=Ps,e.Grid=Qs,e.Highlighter=Ec,e.INTERACTIVE_MARKER_BUTTON=2,e.INTERACTIVE_MARKER_BUTTON_CLICK=3,e.INTERACTIVE_MARKER_FIXED=1,e.INTERACTIVE_MARKER_INHERIT=0,e.INTERACTIVE_MARKER_KEEP_ALIVE=0,e.INTERACTIVE_MARKER_MENU=1,e.INTERACTIVE_MARKER_MENU_SELECT=2,e.INTERACTIVE_MARKER_MOUSE_DOWN=4,e.INTERACTIVE_MARKER_MOUSE_UP=5,e.INTERACTIVE_MARKER_MOVE_3D=7,e.INTERACTIVE_MARKER_MOVE_AXIS=3,e.INTERACTIVE_MARKER_MOVE_PLANE=4,e.INTERACTIVE_MARKER_MOVE_ROTATE=6,e.INTERACTIVE_MARKER_MOVE_ROTATE_3D=9,e.INTERACTIVE_MARKER_NONE=0,e.INTERACTIVE_MARKER_POSE_UPDATE=1,e.INTERACTIVE_MARKER_ROTATE_3D=8,e.INTERACTIVE_MARKER_ROTATE_AXIS=5,e.INTERACTIVE_MARKER_VIEW_FACING=2,e.InteractiveMarker=js,e.InteractiveMarkerClient=class{constructor(e){e=e||{},this.ros=e.ros,this.tfClient=e.tfClient,this.topicName=e.topic,this.path=e.path||"/",this.camera=e.camera,this.rootObject=e.rootObject||new Ss.Object3D,this.loader=e.loader,this.menuFontSize=e.menuFontSize||"0.8em",this.interactiveMarkers={},this.updateTopic=null,this.feedbackTopic=null,this.topicName&&this.subscribe(this.topicName)}subscribe(e){this.unsubscribe(),this.updateTopic=new r.Topic({ros:this.ros,name:e+"/tunneled/update",messageType:"visualization_msgs/InteractiveMarkerUpdate",compression:"png"}),this.updateTopic.subscribe(this.processUpdate.bind(this)),this.feedbackTopic=new r.Topic({ros:this.ros,name:e+"/feedback",messageType:"visualization_msgs/InteractiveMarkerFeedback",compression:"png"}),this.feedbackTopic.advertise(),this.initService=new r.Service({ros:this.ros,name:e+"/tunneled/get_init",serviceType:"demo_interactive_markers/GetInit"});var t=new r.ServiceRequest({});this.initService.callService(t,this.processInit.bind(this))}unsubscribe(){for(var e in this.updateTopic&&this.updateTopic.unsubscribe(this.processUpdate),this.feedbackTopic&&this.feedbackTopic.unadvertise(),this.interactiveMarkers)this.eraseIntMarker(e);this.interactiveMarkers={}}processInit(e){var t=e.msg;for(var i in t.erases=[],this.interactiveMarkers)t.erases.push(i);t.poses=[],this.processUpdate(t)}processUpdate(e){var t=this;e.erases.forEach((function(e){t.eraseIntMarker(e)})),e.poses.forEach((function(e){var i=t.interactiveMarkers[e.name];i&&i.setPoseFromServer(e.pose)})),e.markers.forEach((function(e){var i=t.interactiveMarkers[e.name];i&&t.eraseIntMarker(i.name);var r=new Ys({message:e,feedbackTopic:t.feedbackTopic,tfClient:t.tfClient,menuFontSize:t.menuFontSize});t.interactiveMarkers[e.name]=r;var n=new js({handle:r,camera:t.camera,path:t.path,loader:t.loader});n.name=e.name,t.rootObject.add(n),r.on("pose",(function(e){n.onServerSetPose({pose:e})})),n.addEventListener("user-pose-change",r.setPoseFromClientBound),n.addEventListener("user-mousedown",r.onMouseDownBound),n.addEventListener("user-mouseup",r.onMouseUpBound),n.addEventListener("user-button-click",r.onButtonClickBound),n.addEventListener("menu-select",r.onMenuSelectBound),r.subscribeTf()}))}eraseIntMarker(e){if(this.interactiveMarkers[e]){var t=this.rootObject.getObjectByName(e);this.rootObject.remove(t);var i=this.interactiveMarkers[e];i.unsubscribeTf(),t.removeEventListener("user-pose-change",i.setPoseFromClientBound),t.removeEventListener("user-mousedown",i.onMouseDownBound),t.removeEventListener("user-mouseup",i.onMouseUpBound),t.removeEventListener("user-button-click",i.onButtonClickBound),t.removeEventListener("menu-select",i.onMenuSelectBound),delete this.interactiveMarkers[e],t.dispose()}}},e.InteractiveMarkerControl=Gs,e.InteractiveMarkerHandle=Ys,e.InteractiveMarkerMenu=Vs,e.LaserScan=gc,e.MARKER_ARROW=0,e.MARKER_CUBE=1,e.MARKER_CUBE_LIST=6,e.MARKER_CYLINDER=3,e.MARKER_LINE_LIST=5,e.MARKER_LINE_STRIP=4,e.MARKER_MESH_RESOURCE=10,e.MARKER_POINTS=8,e.MARKER_SPHERE=2,e.MARKER_SPHERE_LIST=7,e.MARKER_TEXT_VIEW_FACING=9,e.MARKER_TRIANGLE_LIST=11,e.Marker=ks,e.MarkerArrayClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.path=e.path||"/",this.markers={},this.rosTopic=void 0,this.subscribe()}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/MarkerArray",compression:"png"}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){e.markers.forEach(function(e){var t=e.ns+e.id;if(0===e.action){var i=!1;if(t in this.markers&&((i=this.markers[t].children[0].update(e))||this.removeMarker(t)),!i){var r=new ks({message:e,path:this.path});this.markers[t]=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:r}),this.rootObject.add(this.markers[t])}}else if(1===e.action)console.warn('Received marker message with deprecated action identifier "1"');else if(2===e.action)this.removeMarker(t);else if(3===e.action){for(var n in this.markers)this.removeMarker(n);this.markers={}}else console.warn('Received marker message with unknown action identifier "'+e.action+'"')}.bind(this)),this.emit("change")}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}removeMarker(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((e=>{e.dispose()})),delete this.markers[e])}},e.MarkerClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.path=e.path||"/",this.lifetime=e.lifetime||0,this.markers={},this.rosTopic=void 0,this.updatedTime={},this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}checkTime(e){if((new Date).getTime()-this.updatedTime[e]>this.lifetime)this.removeMarker(e),this.emit("change");else{var t=this;setTimeout((function(){t.checkTime(e)}),100)}}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"visualization_msgs/Marker",compression:"png"}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){var t=e.ns+e.id,i=this.markers[t];if(this.updatedTime[t]=(new Date).getTime(),i?this.removeMarker(t):this.lifetime&&this.checkTime(e.ns+e.id),0===e.action){var r=new ks({message:e,path:this.path});this.markers[t]=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:r}),this.rootObject.add(this.markers[t])}this.emit("change")}removeMarker(e){var t=this.markers[e];t&&(t.unsubscribeTf(),this.rootObject.remove(t),t.children.forEach((e=>{e.dispose()})),delete this.markers[e])}},e.MeshLoader=Fs,e.MeshResource=Bs,e.MouseHandler=Tc,e.NavSatFix=yc,e.OcTree=sc,e.OcTreeClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/octomap",this.compression=e.compression||"cbor",this.continuous=e.continuous,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.offsetPose=e.offsetPose||new r.Pose,this.options={},void 0!==e.color&&(this.options.color=e.color),void 0!==e.opacity&&(this.options.opacity=e.opacity),void 0!==e.colorMode&&(this.options.colorMode=e.colorMode),void 0!==e.palette&&(this.options.palette=e.palette),void 0!==e.paletteScale&&(this.options.paletteScale=e.palette),void 0!==e.voxelRenderMode&&(this.options.voxelRenderMode=e.voxelRenderMode),this.currentMap=null,this.rosTopic=void 0,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"octomap_msgs/Octomap",queue_length:1,compression:this.compression}),this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){this.currentMap&&this.currentMap.tfClient&&this.currentMap.unsubscribeTf(),this._processMessagePrivate(e),this.continuous||this.rosTopic.unsubscribe(this.processMessage)}_loadOcTree(e){return new Promise(function(t,i){const r=Object.assign({resolution:e.resolution},this.options);let n=null;if(e.binary)n=new ac(r),n.readBinary(e.data);else{const t={OcTree:sc,ColorOcTree:cc};e.id in t&&(console.log(e.id,t),n=new t[e.id](r),n.read(e.data))}n.buildGeometry(),t(n)}.bind(this))}_processMessagePrivate(e){this._loadOcTree(e).then(function(t){const i=this.sceneNode;this.tfClient?(this.currentMap=t,this.sceneNode=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:t.object,pose:this.offsetPose})):(this.sceneNode=t.object,this.currentMap=t),this.rootObject.remove(i),this.rootObject.add(this.sceneNode),this.emit("change")}.bind(this))}},e.OccupancyGrid=$s,e.OccupancyGridClient=class extends qs{constructor(e){super(),e=e||{},this.ros=e.ros,this.topicName=e.topic||"/map",this.compression=e.compression||"cbor",this.continuous=e.continuous,this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.offsetPose=e.offsetPose||new r.Pose,this.color=e.color||{r:255,g:255,b:255},this.opacity=e.opacity||1,this.currentGrid=null,this.rosTopic=void 0,this.subscribe()}unsubscribe(){this.rosTopic&&this.rosTopic.unsubscribe(this.processMessage)}subscribe(){this.unsubscribe(),this.rosTopic=new r.Topic({ros:this.ros,name:this.topicName,messageType:"nav_msgs/OccupancyGrid",queue_length:1,compression:this.compression}),this.sceneNode=null,this.rosTopic.subscribe(this.processMessage.bind(this))}processMessage(e){this.currentGrid&&(this.tfClient?(this.sceneNode.unsubscribeTf(),this.sceneNode.remove(this.currentGrid)):this.rootObject.remove(this.currentGrid),this.currentGrid.dispose());var t=new $s({message:e,color:this.color,opacity:this.opacity});this.tfClient?(this.currentGrid=t,null===this.sceneNode?(this.sceneNode=new Zs({frameID:e.header.frame_id,tfClient:this.tfClient,object:t,pose:this.offsetPose}),this.rootObject.add(this.sceneNode)):this.sceneNode.add(this.currentGrid)):(this.sceneNode=this.currentGrid=t,this.rootObject.add(this.currentGrid)),this.emit("change"),this.continuous||this.rosTopic.unsubscribe(this.processMessage)}},e.Odometry=hc,e.OrbitControls=Sc,e.Path=lc,e.Point=uc,e.PointCloud2=wc,e.Points=vc,e.Polygon=pc,e.Pose=dc,e.PoseArray=fc,e.PoseWithCovariance=mc,e.SceneNode=Zs,e.TFAxes=_c,e.TriangleList=zs,e.Urdf=Mc,e.UrdfClient=class{constructor(e){var t=this,i=(e=e||{}).ros;this.param=e.param||"robot_description",this.path=e.path||"/",this.tfClient=e.tfClient,this.rootObject=e.rootObject||new Ss.Object3D,this.tfPrefix=e.tfPrefix||"",this.loader=e.loader,new r.Param({ros:i,name:this.param}).get((function(e){var i=new r.UrdfModel({string:e});t.urdf=new Mc({urdfModel:i,path:t.path,tfClient:t.tfClient,tfPrefix:t.tfPrefix,loader:t.loader}),t.rootObject.add(t.urdf)}))}},e.Viewer=class{constructor(e){var t=(e=e||{}).divID,i=e.elem,r=e.width,n=e.height,o=e.background||"#111111",a=e.antialias,s=e.intensity||.66,c=e.near||.01,h=e.far||1e3,l=e.alpha||1,u=e.cameraPose||{x:3,y:3,z:3},p=e.cameraZoomSpeed||.5,d=void 0===e.displayPanAndZoomFrame||!!e.displayPanAndZoomFrame,f=e.lineTypePanAndZoomFrame||"full";this.renderer=new Ss.WebGLRenderer({antialias:a,alpha:!0}),this.renderer.setClearColor(parseInt(o.replace("#","0x"),16),l),this.renderer.sortObjects=!1,this.renderer.setSize(r,n),this.renderer.shadowMap.enabled=!1,this.renderer.autoClear=!1,this.scene=new Ss.Scene,this.camera=new Ss.PerspectiveCamera(40,r/n,c,h),this.camera.position.x=u.x,this.camera.position.y=u.y,this.camera.position.z=u.z,this.cameraControls=new Sc({scene:this.scene,camera:this.camera,displayPanAndZoomFrame:d,lineTypePanAndZoomFrame:f}),this.cameraControls.userZoomSpeed=p,this.scene.add(new Ss.AmbientLight(5592405)),this.directionalLight=new Ss.DirectionalLight(16777215,s),this.scene.add(this.directionalLight),this.selectableObjects=new Ss.Group,this.scene.add(this.selectableObjects);var m=new Tc({renderer:this.renderer,camera:this.camera,rootObject:this.selectableObjects,fallbackTarget:this.cameraControls});this.highlighter=new Ec({mouseHandler:m}),this.stopped=!0,this.animationRequestId=void 0,(i||document.getElementById(t)).appendChild(this.renderer.domElement),this.start()}start(){this.stopped=!1,this.draw()}draw(){this.stopped||(this.cameraControls.update(),this.directionalLight.position.normalize(),this.renderer.clear(!0,!0,!0),this.renderer.render(this.scene,this.camera),this.highlighter.renderHighlights(this.scene,this.renderer,this.camera),this.animationRequestId=requestAnimationFrame(this.draw.bind(this)))}stop(){this.stopped||cancelAnimationFrame(this.animationRequestId),this.stopped=!0}addObject(e,t){t?this.selectableObjects.add(e):this.scene.add(e)}resize(e,t){this.camera.aspect=e/t,this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t)}},e.closestAxisPoint=Cs,e.findClosestPoint=Rs,e.intersectPlane=Ls,e.makeColorMaterial=As,Object.defineProperty(e,"__esModule",{value:!0}),e}({},ROSLIB); diff --git a/examples/mappa.py b/examples/mappa.py new file mode 100644 index 00000000..8bcc92cd --- /dev/null +++ b/examples/mappa.py @@ -0,0 +1,33 @@ +import rclpy +from rclpy.node import Node +from nav_msgs.msg import OccupancyGrid + +class MapPublisher(Node): + def __init__(self): + super().__init__('map_publisher') + self.publisher_ = self.create_publisher(OccupancyGrid, '/map', 10) + self.timer_ = self.create_timer(1.0, self.publish_map) # Publicar cada 1 segundo + self.map_ = OccupancyGrid() + self.map_.header.frame_id = 'map' + self.map_.info.width = 100 # Ancho del mapa + self.map_.info.height = 100 # Alto del mapa + self.map_.info.resolution = 0.1 # Resolución del mapa (metros/píxel) + self.map_.data = [0] * (self.map_.info.width * self.map_.info.height) # Datos de ocupación del mapa + + def publish_map(self): + # Generar datos realistas del mapa (aquí puedes inventar tus propios datos) + for i in range(len(self.map_.data)): + self.map_.data[i] = 100 # Valor de ocupación máximo (totalmente ocupado) + + self.publisher_.publish(self.map_) + +def main(args=None): + rclpy.init(args=args) + publisher = MapPublisher() + rclpy.spin(publisher) + publisher.destroy_node() + rclpy.shutdown() + +if __name__ == '__main__': + main() + diff --git a/examples/markers.html b/examples/markers.html index 6f63852e..8fc984c4 100644 --- a/examples/markers.html +++ b/examples/markers.html @@ -32,7 +32,7 @@ angularThres : 0.01, transThres : 0.01, rate : 10.0, - fixedFrame : '/my_frame' + fixedFrame : 'my_frame' }); // Setup the marker client. diff --git a/examples/nubepun.py b/examples/nubepun.py new file mode 100644 index 00000000..6cfcf8ef --- /dev/null +++ b/examples/nubepun.py @@ -0,0 +1,156 @@ +import rclpy +import random +from rclpy.node import Node +from sensor_msgs.msg import PointCloud2, PointField +from std_msgs.msg import Header +import struct + +import struct + +class PointCloud2Publisher(Node): + def __init__(self): + super().__init__('pointcloud2_publisher') + self.publisher_ = self.create_publisher(PointCloud2, '/camera/depth_registered/points', 10) + self.timer_ = self.create_timer(1.0, self.publish_pointcloud) + self.get_logger().info('PointCloud2 Publisher Node has been started.') + + def publish_pointcloud(self): + # Create the PointCloud2 message + pointcloud_msg = PointCloud2() + pointcloud_msg.header = Header() + pointcloud_msg.header.frame_id = 'camera_link' + + # Populate the fields of the PointCloud2 message + pointcloud_msg.fields.append(PointField(name='x', offset=0, datatype=PointField.FLOAT32, count=1)) + pointcloud_msg.fields.append(PointField(name='y', offset=4, datatype=PointField.FLOAT32, count=1)) + pointcloud_msg.fields.append(PointField(name='z', offset=8, datatype=PointField.FLOAT32, count=1)) + + # Populate the point data of the PointCloud2 message + pointcloud_msg.point_step = 12 + pointcloud_msg.is_dense = True + pointcloud_msg.is_bigendian = True + + pointcloud_msg.height = 15 + pointcloud_msg.width = 20 + + pointcloud_msg.row_step = pointcloud_msg.width * pointcloud_msg.point_step + n = pointcloud_msg.height * pointcloud_msg.width + + points = [] # Empty array to store the points + + #Para tener puntos fijos y comparar con los mensajes + points.append(1.1) + points.append(1.1) + points.append(1.1) + points.append(2.2) + points.append(2.2) + points.append(2.2) + points.append(3.3) + points.append(3.3) + points.append(3.3) + n = n - 3 + + for _ in range(n): + x= random.uniform(0.0, 10.0) # Create a point as a list [x, y, z] + points.append(x) + y = random.uniform(0.0, 10.0) + points.append(y) + z = random.uniform(0.0, 10.0) + # point = (x, y, z) + points.append(z) # Add the point to the points array + + # # Create a buffer to store the point data + # buffer = [] + # for point in points: + # buffer.extend(struct.pack('fff', *point)) + + # Convert the buffer to bytes + pointcloud_msg.data = list(b''.join(struct.pack('f', f) for f in points)) + + # Publish the PointCloud2 message + self.publisher_.publish(pointcloud_msg) + +def main(args=None): + rclpy.init(args=args) + pointcloud_publisher = PointCloud2Publisher() + rclpy.spin(pointcloud_publisher) + pointcloud_publisher.destroy_node() + rclpy.shutdown() + +if __name__ == '__main__': + main() + + +'''import struct + +# Lista de floats +floats = [1.23, 4.56, 7.89, 8.52] + +# Conversión a lista de bytes +msg.data = list(b''.join(struct.pack('f', f) for f in floats)) + +# Imprimir el resultado +print(byte_list) +''' + + + + +# import rclpy +# from rclpy.node import Node +# from sensor_msgs.msg import PointCloud2, PointField +# import numpy as np + +# class PointCloudPublisher(Node): +# def __init__(self): +# super().__init__('point_cloud_publisher') +# self.publisher_ = self.create_publisher(PointCloud2, '/camera/depth_registered/points', 10) + +# def publish_point_cloud(self): +# # Create the PointCloud2 message +# cloud_msg = PointCloud2() + +# # Set the header information +# cloud_msg.header.stamp = self.get_clock().now().to_msg() +# cloud_msg.header.frame_id = 'camera_link' # Set the appropriate frame ID + +# # Define the fields of the PointCloud2 message +# fields = [ +# PointField(name='x', offset=0, datatype=PointField.FLOAT32, count=1), +# PointField(name='y', offset=4, datatype=PointField.FLOAT32, count=1), +# PointField(name='z', offset=8, datatype=PointField.FLOAT32, count=1), +# ] +# cloud_msg.fields = fields + +# cloud_msg.point_step = 12 +# cloud_msg.row_step = pointcloud_msg.width * pointcloud_msg.point_step +# cloud_msg.is_dense = True + +# cloud_msg.height = 30 +# cloud_msg.width = 30 + +# # Generate a sample point cloud data +# points = [(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)] # Replace with your actual point cloud data + +# # Convert the points to a numpy array +# point_array = np.array(points, dtype=np.float32) + +# # Set the point cloud data +# cloud_msg.data = point_array.tobytes() +# cloud_msg.width = point_array.shape[0] +# cloud_msg.height = 1 +# cloud_msg.point_step = 12 # 3 fields * 4 bytes (float32) +# cloud_msg.row_step = cloud_msg.point_step * cloud_msg.width + +# # Publish the PointCloud2 message +# self.publisher_.publish(cloud_msg) +# self.get_logger().info('Published PointCloud2 message') + +# def main(args=None): +# rclpy.init(args=args) +# point_cloud_publisher = PointCloudPublisher() +# point_cloud_publisher.publish_point_cloud() +# rclpy.shutdown() + +# if __name__ == '__main__': +# main() diff --git a/examples/pointcloud2.html b/examples/pointcloud2.html index ed0caa46..4ac4f801 100644 --- a/examples/pointcloud2.html +++ b/examples/pointcloud2.html @@ -15,7 +15,8 @@ function init() { // Connect to ROS. var ros = new ROSLIB.Ros({ - url : 'ws://localhost:9090' + url : 'ws://localhost:9090', + groovyCompatibility: false }); // Create the main viewer. @@ -23,7 +24,7 @@ divID : 'viewer', width : 800, height : 600, - antialias : true + antialias : true, }); // Setup a client to listen to TFs. @@ -32,7 +33,7 @@ angularThres : 0.01, transThres : 0.01, rate : 10.0, - fixedFrame : '/camera_link' + fixedFrame : 'camera_link' }); var cloudClient = new ROS3D.PointCloud2({ diff --git a/examples/pyesfera.py b/examples/pyesfera.py new file mode 100644 index 00000000..b73124ef --- /dev/null +++ b/examples/pyesfera.py @@ -0,0 +1,45 @@ +import rclpy +from rclpy.node import Node +from visualization_msgs.msg import Marker +from geometry_msgs.msg import Point + +class MarkerPublisherNode(Node): + def __init__(self): + super().__init__('marker_publisher') + self.publisher_ = self.create_publisher(Marker, '/visualization_marker', 10) + self.timer_ = self.create_timer(1.0, self.publish_marker) + self.get_logger().info('Marker Publisher Node has been started.') + + def publish_marker(self): + marker_msg = Marker() + marker_msg.header.frame_id = 'my_frame' + marker_msg.type = Marker.SPHERE + marker_msg.action = Marker.ADD + marker_msg.pose.position.x = 0.0 + marker_msg.pose.position.y = 0.0 + marker_msg.pose.position.z = 0.0 + marker_msg.pose.orientation.w = 1.0 + + # Tamaño de la esfera de 2 metros de diámetro + diameter = 2.0 + marker_msg.scale.x = diameter + marker_msg.scale.y = diameter + marker_msg.scale.z = diameter + + marker_msg.color.r = 1.0 + marker_msg.color.g = 0.0 + marker_msg.color.b = 0.0 + marker_msg.color.a = 1.0 + marker_msg.lifetime.sec = 0 + + self.publisher_.publish(marker_msg) + +def main(args=None): + rclpy.init(args=args) + marker_publisher = MarkerPublisherNode() + rclpy.spin(marker_publisher) + marker_publisher.destroy_node() + rclpy.shutdown() + +if __name__ == '__main__': + main() diff --git a/package-lock.json b/package-lock.json index 1b1f5579..ad95f3ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.1.0", "license": "BSD-3-Clause", "dependencies": { - "eventemitter2": "^6.4.0", + "eventemitter2": "^6.4.9", "roslib": "^1.0.0", "three": "^0.89.0" }, @@ -2392,9 +2392,9 @@ } }, "node_modules/eventemitter2": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz", - "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" }, "node_modules/eventemitter3": { "version": "4.0.7", @@ -9797,9 +9797,9 @@ "dev": true }, "eventemitter2": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.5.tgz", - "integrity": "sha512-bXE7Dyc1i6oQElDG0jMRZJrRAn9QR2xyyFGmBdZleNmyQX0FqGYmhZIrIrpPfm/w//LTo4tVQGOGQcGCb5q9uw==" + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" }, "eventemitter3": { "version": "4.0.7", @@ -10541,7 +10541,7 @@ "version": "git+ssh://git@github.com/RobotWebTools/grunt-pipe.git#d0937a52726f8f73df5d6d704d0519473150fb0e", "integrity": "sha512-DPgn249Wea0hGLV8SHUGHk7Wdk9r4rY/L3tRHPSrYFRsCV9o8jR0P31wUXCEz2u5ci/0JEJ7eLn1jtYJ2+wS1g==", "dev": true, - "from": "grunt-pipe@git+https://github.com/RobotWebTools/grunt-pipe.git#d0937a52726f8f73df5d6d704d0519473150fb0e", + "from": "grunt-pipe@git+https://github.com/RobotWebTools/grunt-pipe.git", "requires": { "cheerio": "^1.0.0-rc.12" } diff --git a/package.json b/package.json index 78ca8b58..6681cb48 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "main": "./build/ros3d.cjs.js", "module": "./build/ros3d.esm.js", "dependencies": { - "eventemitter2": "^6.4.0", + "eventemitter2": "^6.4.9", "roslib": "^1.0.0", "three": "^0.89.0" }, diff --git a/src/markers/MarkerClient.js b/src/markers/MarkerClient.js index 8ef922d8..2e729c2c 100644 --- a/src/markers/MarkerClient.js +++ b/src/markers/MarkerClient.js @@ -64,7 +64,8 @@ ROS3D.MarkerClient.prototype.subscribe = function(){ ros : this.ros, name : this.topicName, messageType : 'visualization_msgs/Marker', - compression : 'png' + compression : 'cbor' + // compression : 'png' }); this.rosTopic.subscribe(this.processMessage.bind(this)); }; From e3990153214d5cbe30aad34a0b3313f3b0b0b427 Mon Sep 17 00:00:00 2001 From: atobaruela-ibrobotics Date: Wed, 28 Jun 2023 08:34:41 +0200 Subject: [PATCH 2/5] Cambiados formatos predeterminados de png a cbor en Markers --- build/ros3d.js | 4 ++-- examples/pointcloud2.html | 4 ++-- src/interactivemarkers/InteractiveMarkerClient.js | 6 ++++-- src/markers/MarkerArrayClient.js | 3 ++- src/markers/MarkerClient.js | 2 +- src/visualization/SceneNode.js | 4 ++-- 6 files changed, 13 insertions(+), 10 deletions(-) diff --git a/build/ros3d.js b/build/ros3d.js index ad2cfdd0..e7a48329 100644 --- a/build/ros3d.js +++ b/build/ros3d.js @@ -55622,8 +55622,8 @@ var ROS3D = (function (exports, ROSLIB) { ros : this.ros, name : this.topicName, messageType : 'visualization_msgs/Marker', - compression : 'cbor' - // compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.rosTopic.subscribe(this.processMessage.bind(this)); }; diff --git a/examples/pointcloud2.html b/examples/pointcloud2.html index 4ac4f801..a5fd8e2d 100644 --- a/examples/pointcloud2.html +++ b/examples/pointcloud2.html @@ -33,14 +33,14 @@ angularThres : 0.01, transThres : 0.01, rate : 10.0, - fixedFrame : 'camera_link' + fixedFrame : 'laser_data_frame' }); var cloudClient = new ROS3D.PointCloud2({ ros: ros, tfClient: tfClient, rootObject: viewer.scene, - topic: '/camera/depth_registered/points', + topic: '/os1/points', material: { size: 0.05, color: 0xff00ff } }); } diff --git a/src/interactivemarkers/InteractiveMarkerClient.js b/src/interactivemarkers/InteractiveMarkerClient.js index 50a28770..852f7999 100644 --- a/src/interactivemarkers/InteractiveMarkerClient.js +++ b/src/interactivemarkers/InteractiveMarkerClient.js @@ -53,7 +53,8 @@ ROS3D.InteractiveMarkerClient.prototype.subscribe = function(topic) { ros : this.ros, name : topic + '/tunneled/update', messageType : 'visualization_msgs/InteractiveMarkerUpdate', - compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.updateTopic.subscribe(this.processUpdate.bind(this)); @@ -61,7 +62,8 @@ ROS3D.InteractiveMarkerClient.prototype.subscribe = function(topic) { ros : this.ros, name : topic + '/feedback', messageType : 'visualization_msgs/InteractiveMarkerFeedback', - compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.feedbackTopic.advertise(); diff --git a/src/markers/MarkerArrayClient.js b/src/markers/MarkerArrayClient.js index 45657957..5619171e 100644 --- a/src/markers/MarkerArrayClient.js +++ b/src/markers/MarkerArrayClient.js @@ -44,7 +44,8 @@ ROS3D.MarkerArrayClient.prototype.subscribe = function(){ ros : this.ros, name : this.topicName, messageType : 'visualization_msgs/MarkerArray', - compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.rosTopic.subscribe(this.processMessage.bind(this)); }; diff --git a/src/markers/MarkerClient.js b/src/markers/MarkerClient.js index 2e729c2c..627922cc 100644 --- a/src/markers/MarkerClient.js +++ b/src/markers/MarkerClient.js @@ -64,8 +64,8 @@ ROS3D.MarkerClient.prototype.subscribe = function(){ ros : this.ros, name : this.topicName, messageType : 'visualization_msgs/Marker', - compression : 'cbor' // compression : 'png' + compression : 'cbor' }); this.rosTopic.subscribe(this.processMessage.bind(this)); }; diff --git a/src/visualization/SceneNode.js b/src/visualization/SceneNode.js index 55d15c4f..7d4fc1bd 100644 --- a/src/visualization/SceneNode.js +++ b/src/visualization/SceneNode.js @@ -25,7 +25,7 @@ ROS3D.SceneNode = function(options) { this.pose = options.pose || new ROSLIB.Pose(); // Do not render this object until we receive a TF update - this.visible = false; + this.visible = false; // Si se cambia a true visualiza sin TF update // add the model this.add(object); @@ -43,7 +43,7 @@ ROS3D.SceneNode = function(options) { // update the world that.updatePose(poseTransformed); - that.visible = true; + that.visible = true; }; // listen for TF updates From 0127492ec171b622aaf7dbe9dbec71fdd52abe5f Mon Sep 17 00:00:00 2001 From: atobaruela-ibrobotics Date: Thu, 29 Jun 2023 14:32:58 +0200 Subject: [PATCH 3/5] cambios para compression c_bor --- build/ros3d.js | 2 +- examples/continuousmap.html | 3 ++- examples/markers.html | 3 ++- examples/nubepun.py | 4 ++-- examples/pointcloud2.html | 4 ++-- examples/urdf.html | 3 ++- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/build/ros3d.js b/build/ros3d.js index e7a48329..4e67fa81 100644 --- a/build/ros3d.js +++ b/build/ros3d.js @@ -55394,7 +55394,7 @@ var ROS3D = (function (exports, ROSLIB) { this.pose = options.pose || new ROSLIB__namespace.Pose(); // Do not render this object until we receive a TF update - this.visible = true; + this.visible = false; // add the model this.add(object); diff --git a/examples/continuousmap.html b/examples/continuousmap.html index bc81d8d5..d6713186 100644 --- a/examples/continuousmap.html +++ b/examples/continuousmap.html @@ -15,7 +15,8 @@ function init() { // Connect to ROS. var ros = new ROSLIB.Ros({ - url : 'ws://localhost:9090' + url : 'ws://localhost:9090', + groovyCompatibility: false }); // Create the main viewer. diff --git a/examples/markers.html b/examples/markers.html index 8fc984c4..b5c5aaad 100644 --- a/examples/markers.html +++ b/examples/markers.html @@ -15,7 +15,8 @@ function init() { // Connect to ROS. var ros = new ROSLIB.Ros({ - url : 'ws://localhost:9090' + url : 'ws://localhost:9090', + groovyCompatibility: false, }); // Create the main viewer. diff --git a/examples/nubepun.py b/examples/nubepun.py index 6cfcf8ef..6047ab4c 100644 --- a/examples/nubepun.py +++ b/examples/nubepun.py @@ -10,7 +10,7 @@ class PointCloud2Publisher(Node): def __init__(self): super().__init__('pointcloud2_publisher') - self.publisher_ = self.create_publisher(PointCloud2, '/camera/depth_registered/points', 10) + self.publisher_ = self.create_publisher(PointCloud2, '/os1/points', 10) self.timer_ = self.create_timer(1.0, self.publish_pointcloud) self.get_logger().info('PointCloud2 Publisher Node has been started.') @@ -18,7 +18,7 @@ def publish_pointcloud(self): # Create the PointCloud2 message pointcloud_msg = PointCloud2() pointcloud_msg.header = Header() - pointcloud_msg.header.frame_id = 'camera_link' + pointcloud_msg.header.frame_id = 'laser_data_frame' # Populate the fields of the PointCloud2 message pointcloud_msg.fields.append(PointField(name='x', offset=0, datatype=PointField.FLOAT32, count=1)) diff --git a/examples/pointcloud2.html b/examples/pointcloud2.html index a5fd8e2d..535e9ed6 100644 --- a/examples/pointcloud2.html +++ b/examples/pointcloud2.html @@ -16,7 +16,7 @@ // Connect to ROS. var ros = new ROSLIB.Ros({ url : 'ws://localhost:9090', - groovyCompatibility: false + groovyCompatibility: false, }); // Create the main viewer. @@ -33,7 +33,7 @@ angularThres : 0.01, transThres : 0.01, rate : 10.0, - fixedFrame : 'laser_data_frame' + fixedFrame : 'base_link' }); var cloudClient = new ROS3D.PointCloud2({ diff --git a/examples/urdf.html b/examples/urdf.html index 18c3167f..365eb933 100644 --- a/examples/urdf.html +++ b/examples/urdf.html @@ -18,7 +18,8 @@ function init() { // Connect to ROS. var ros = new ROSLIB.Ros({ - url : 'ws://localhost:9090' + url : 'ws://localhost:9090', + groovyCompatibility: false, }); // Create the main viewer. From a110580b1cdf014a0593a925eab5496842ba4e67 Mon Sep 17 00:00:00 2001 From: atobaruela-ibrobotics Date: Thu, 29 Jun 2023 14:36:14 +0200 Subject: [PATCH 4/5] =?UTF-8?q?Para=20react=20parece=20hacer=20falta=20toc?= =?UTF-8?q?ar=20ros3d.esm.js=20y=20por=20si=20acaso=20he=20adaptado=20tamb?= =?UTF-8?q?i=C3=A9n=20a=20cbor=20este=20archivo=20y=20los=20necesarios=20d?= =?UTF-8?q?entro=20de=20la=20carpeta=20src-esm,=20que=20son=20similares=20?= =?UTF-8?q?a=20los=20de=20src?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build/ros3d.esm.js | 12 +- src-esm/Ros3D.js | 181 ++++++ src-esm/depthcloud/DepthCloud.js | 333 ++++++++++ src-esm/index.js | 50 ++ .../interactivemarkers/InteractiveMarker.js | 371 ++++++++++++ .../InteractiveMarkerClient.js | 218 +++++++ .../InteractiveMarkerControl.js | 277 +++++++++ .../InteractiveMarkerHandle.js | 200 ++++++ .../InteractiveMarkerMenu.js | 185 ++++++ src-esm/markers/Marker.js | 499 +++++++++++++++ src-esm/markers/MarkerArrayClient.js | 124 ++++ src-esm/markers/MarkerClient.js | 123 ++++ src-esm/models/Arrow.js | 103 ++++ src-esm/models/Arrow2.js | 71 +++ src-esm/models/Axes.js | 103 ++++ src-esm/models/Grid.js | 52 ++ src-esm/models/MeshLoader.js | 138 +++++ src-esm/models/MeshResource.js | 51 ++ src-esm/models/TriangleList.js | 82 +++ src-esm/navigation/ColorOcTree.js | 31 + src-esm/navigation/OcTree.js | 77 +++ src-esm/navigation/OcTreeBase.js | 567 ++++++++++++++++++ src-esm/navigation/OcTreeBaseNode.js | 42 ++ src-esm/navigation/OcTreeClient.js | 185 ++++++ src-esm/navigation/OccupancyGrid.js | 131 ++++ src-esm/navigation/OccupancyGridClient.js | 123 ++++ src-esm/navigation/Odometry.js | 93 +++ src-esm/navigation/Path.js | 86 +++ src-esm/navigation/Point.js | 81 +++ src-esm/navigation/Polygon.js | 89 +++ src-esm/navigation/Pose.js | 89 +++ src-esm/navigation/PoseArray.js | 108 ++++ src-esm/navigation/PoseWithCovariance.js | 85 +++ src-esm/sensors/LaserScan.js | 79 +++ src-esm/sensors/NavSatFix.js | 101 ++++ src-esm/sensors/PointCloud2.js | 144 +++++ src-esm/sensors/Points.js | 124 ++++ src-esm/sensors/TFAxes.js | 58 ++ src-esm/urdf/Urdf.js | 141 +++++ src-esm/urdf/UrdfClient.js | 66 ++ src-esm/visualization/SceneNode.js | 73 +++ src-esm/visualization/Viewer.js | 188 ++++++ .../visualization/interaction/Highlighter.js | 144 +++++ .../visualization/interaction/MouseHandler.js | 226 +++++++ .../interaction/OrbitControls.js | 522 ++++++++++++++++ 45 files changed, 6822 insertions(+), 4 deletions(-) create mode 100644 src-esm/Ros3D.js create mode 100644 src-esm/depthcloud/DepthCloud.js create mode 100644 src-esm/index.js create mode 100644 src-esm/interactivemarkers/InteractiveMarker.js create mode 100644 src-esm/interactivemarkers/InteractiveMarkerClient.js create mode 100644 src-esm/interactivemarkers/InteractiveMarkerControl.js create mode 100644 src-esm/interactivemarkers/InteractiveMarkerHandle.js create mode 100644 src-esm/interactivemarkers/InteractiveMarkerMenu.js create mode 100644 src-esm/markers/Marker.js create mode 100644 src-esm/markers/MarkerArrayClient.js create mode 100644 src-esm/markers/MarkerClient.js create mode 100644 src-esm/models/Arrow.js create mode 100644 src-esm/models/Arrow2.js create mode 100644 src-esm/models/Axes.js create mode 100644 src-esm/models/Grid.js create mode 100644 src-esm/models/MeshLoader.js create mode 100644 src-esm/models/MeshResource.js create mode 100644 src-esm/models/TriangleList.js create mode 100644 src-esm/navigation/ColorOcTree.js create mode 100644 src-esm/navigation/OcTree.js create mode 100644 src-esm/navigation/OcTreeBase.js create mode 100644 src-esm/navigation/OcTreeBaseNode.js create mode 100644 src-esm/navigation/OcTreeClient.js create mode 100644 src-esm/navigation/OccupancyGrid.js create mode 100644 src-esm/navigation/OccupancyGridClient.js create mode 100644 src-esm/navigation/Odometry.js create mode 100644 src-esm/navigation/Path.js create mode 100644 src-esm/navigation/Point.js create mode 100644 src-esm/navigation/Polygon.js create mode 100644 src-esm/navigation/Pose.js create mode 100644 src-esm/navigation/PoseArray.js create mode 100644 src-esm/navigation/PoseWithCovariance.js create mode 100644 src-esm/sensors/LaserScan.js create mode 100644 src-esm/sensors/NavSatFix.js create mode 100644 src-esm/sensors/PointCloud2.js create mode 100644 src-esm/sensors/Points.js create mode 100644 src-esm/sensors/TFAxes.js create mode 100644 src-esm/urdf/Urdf.js create mode 100644 src-esm/urdf/UrdfClient.js create mode 100644 src-esm/visualization/SceneNode.js create mode 100644 src-esm/visualization/Viewer.js create mode 100644 src-esm/visualization/interaction/Highlighter.js create mode 100644 src-esm/visualization/interaction/MouseHandler.js create mode 100644 src-esm/visualization/interaction/OrbitControls.js diff --git a/build/ros3d.esm.js b/build/ros3d.esm.js index 83a73a22..462700f2 100644 --- a/build/ros3d.esm.js +++ b/build/ros3d.esm.js @@ -55084,7 +55084,8 @@ InteractiveMarkerClient.prototype.subscribe = function subscribe (topic) { ros : this.ros, name : topic + '/tunneled/update', messageType : 'visualization_msgs/InteractiveMarkerUpdate', - compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.updateTopic.subscribe(this.processUpdate.bind(this)); @@ -55092,7 +55093,8 @@ InteractiveMarkerClient.prototype.subscribe = function subscribe (topic) { ros : this.ros, name : topic + '/feedback', messageType : 'visualization_msgs/InteractiveMarkerFeedback', - compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.feedbackTopic.advertise(); @@ -55330,7 +55332,8 @@ var MarkerArrayClient = /*@__PURE__*/(function (EventEmitter2) { ros : this.ros, name : this.topicName, messageType : 'visualization_msgs/MarkerArray', - compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.rosTopic.subscribe(this.processMessage.bind(this)); }; @@ -55449,7 +55452,8 @@ var MarkerClient = /*@__PURE__*/(function (EventEmitter2) { ros : this.ros, name : this.topicName, messageType : 'visualization_msgs/Marker', - compression : 'png' + // compression : 'png' + compression : 'cbor' }); this.rosTopic.subscribe(this.processMessage.bind(this)); }; diff --git a/src-esm/Ros3D.js b/src-esm/Ros3D.js new file mode 100644 index 00000000..d6dc762c --- /dev/null +++ b/src-esm/Ros3D.js @@ -0,0 +1,181 @@ +import THREE from '../shims/three/core.js'; + +/** + * @fileOverview + * @author Russell Toris - rctoris@wpi.edu + * @author David Gossow - dgossow@willowgarage.com + */ + +var ROS3D = ROS3D || { + /** + * @default + * @description Library version + */ + REVISION : '1.1.0' +}; + +// Marker types +export var MARKER_ARROW = 0; +export var MARKER_CUBE = 1; +export var MARKER_SPHERE = 2; +export var MARKER_CYLINDER = 3; +export var MARKER_LINE_STRIP = 4; +export var MARKER_LINE_LIST = 5; +export var MARKER_CUBE_LIST = 6; +export var MARKER_SPHERE_LIST = 7; +export var MARKER_POINTS = 8; +export var MARKER_TEXT_VIEW_FACING = 9; +export var MARKER_MESH_RESOURCE = 10; +export var MARKER_TRIANGLE_LIST = 11; + +// Interactive marker feedback types +export var INTERACTIVE_MARKER_KEEP_ALIVE = 0; +export var INTERACTIVE_MARKER_POSE_UPDATE = 1; +export var INTERACTIVE_MARKER_MENU_SELECT = 2; +export var INTERACTIVE_MARKER_BUTTON_CLICK = 3; +export var INTERACTIVE_MARKER_MOUSE_DOWN = 4; +export var INTERACTIVE_MARKER_MOUSE_UP = 5; + +// Interactive marker control types +export var INTERACTIVE_MARKER_NONE = 0; +export var INTERACTIVE_MARKER_MENU = 1; +export var INTERACTIVE_MARKER_BUTTON = 2; +export var INTERACTIVE_MARKER_MOVE_AXIS = 3; +export var INTERACTIVE_MARKER_MOVE_PLANE = 4; +export var INTERACTIVE_MARKER_ROTATE_AXIS = 5; +export var INTERACTIVE_MARKER_MOVE_ROTATE = 6; +export var INTERACTIVE_MARKER_MOVE_3D = 7; +export var INTERACTIVE_MARKER_ROTATE_3D = 8; +export var INTERACTIVE_MARKER_MOVE_ROTATE_3D = 9; + +// Interactive marker rotation behavior +export var INTERACTIVE_MARKER_INHERIT = 0; +export var INTERACTIVE_MARKER_FIXED = 1; +export var INTERACTIVE_MARKER_VIEW_FACING = 2; + +/** + * @function makeColorMaterial + * @description Create a THREE material based on the given RGBA values. + * + * @param r - the red value + * @param g - the green value + * @param b - the blue value + * @param a - the alpha value + * @returns the THREE material + */ +export var makeColorMaterial = function(r, g, b, a) { + var color = new THREE.Color(); + color.setRGB(r, g, b); + if (a <= 0.99) { + return new THREE.MeshBasicMaterial({ + color : color.getHex(), + opacity : a + 0.1, + transparent : true, + depthWrite : true, + blendSrc : THREE.SrcAlphaFactor, + blendDst : THREE.OneMinusSrcAlphaFactor, + blendEquation : THREE.ReverseSubtractEquation, + blending : THREE.NormalBlending + }); + } else { + return new THREE.MeshPhongMaterial({ + color : color.getHex(), + opacity : a, + blending : THREE.NormalBlending + }); + } +}; + +/** + * @function intersectPlane + * @description Return the intersection between the mouseray and the plane. + * + * @param mouseRay - the mouse ray + * @param planeOrigin - the origin of the plane + * @param planeNormal - the normal of the plane + * @returns the intersection point + */ +export var intersectPlane = function(mouseRay, planeOrigin, planeNormal) { + var vector = new THREE.Vector3(); + var intersectPoint = new THREE.Vector3(); + vector.subVectors(planeOrigin, mouseRay.origin); + var dot = mouseRay.direction.dot(planeNormal); + + // bail if ray and plane are parallel + if (Math.abs(dot) < mouseRay.precision) { + return undefined; + } + + // calc distance to plane + var scalar = planeNormal.dot(vector) / dot; + + intersectPoint.addVectors(mouseRay.origin, mouseRay.direction.clone().multiplyScalar(scalar)); + return intersectPoint; +}; + +/** + * @function findClosestPoint + * @description Find the closest point on targetRay to any point on mouseRay. Math taken from + * http://paulbourke.net/geometry/lineline3d/ + * + * @param targetRay - the target ray to use + * @param mouseRay - the mouse ray + * @param the closest point between the two rays + */ +export var findClosestPoint = function(targetRay, mouseRay) { + var v13 = new THREE.Vector3(); + v13.subVectors(targetRay.origin, mouseRay.origin); + var v43 = mouseRay.direction.clone(); + var v21 = targetRay.direction.clone(); + var d1343 = v13.dot(v43); + var d4321 = v43.dot(v21); + var d1321 = v13.dot(v21); + var d4343 = v43.dot(v43); + var d2121 = v21.dot(v21); + + var denom = d2121 * d4343 - d4321 * d4321; + // check within a delta + if (Math.abs(denom) <= 0.0001) { + return undefined; + } + var numer = d1343 * d4321 - d1321 * d4343; + + var mua = numer / denom; + return mua; +}; + +/** + * @function closestAxisPoint + * @description Find the closest point between the axis and the mouse. + * + * @param axisRay - the ray from the axis + * @param camera - the camera to project from + * @param mousePos - the mouse position + * @returns the closest axis point + */ +export var closestAxisPoint = function(axisRay, camera, mousePos) { + // project axis onto screen + var o = axisRay.origin.clone(); + o.project(camera); + var o2 = axisRay.direction.clone().add(axisRay.origin); + o2.project(camera); + + // d is the axis vector in screen space (d = o2-o) + var d = o2.clone().sub(o); + + // t is the 2d ray param of perpendicular projection of mousePos onto o + var tmp = new THREE.Vector2(); + // (t = (mousePos - o) * d / (d*d)) + var t = tmp.subVectors(mousePos, o).dot(d) / d.dot(d); + + // mp is the final 2d-projected mouse pos (mp = o + d*t) + var mp = new THREE.Vector2(); + mp.addVectors(o, d.clone().multiplyScalar(t)); + + // go back to 3d by shooting a ray + var vector = new THREE.Vector3(mp.x, mp.y, 0.5); + vector.unproject(camera); + var mpRay = new THREE.Ray(camera.position, vector.sub(camera.position).normalize()); + + return findClosestPoint(axisRay, mpRay); +}; diff --git a/src-esm/depthcloud/DepthCloud.js b/src-esm/depthcloud/DepthCloud.js new file mode 100644 index 00000000..76e503ec --- /dev/null +++ b/src-esm/depthcloud/DepthCloud.js @@ -0,0 +1,333 @@ +import THREE from '../../shims/three/core.js'; + +/** + * @fileOverview + * @author Julius Kammerl - jkammerl@willowgarage.com + */ + +export class DepthCloud extends THREE.Object3D { + + /** + * The DepthCloud object. + * + * @constructor + * @param options - object with following keys: + * + * * url - the URL of the stream + * * streamType (optional) - the stream type: mjpeg or vp8 video (defaults to vp8) + * * f (optional) - the camera's focal length (defaults to standard Kinect calibration) + * * maxDepthPerTile (optional) - the factor with which we control the desired depth range (defaults to 1.0) + * * pointSize (optional) - point size (pixels) for rendered point cloud + * * width (optional) - width of the video stream + * * height (optional) - height of the video stream + * * whiteness (optional) - blends rgb values to white (0..100) + * * varianceThreshold (optional) - threshold for variance filter, used for compression artifact removal + */ + constructor(options) { + super(); + options = options || {}; + + this.url = options.url; + this.streamType = options.streamType || 'vp8'; + this.f = options.f || 526; + this.maxDepthPerTile = options.maxDepthPerTile || 1.0; + this.pointSize = options.pointSize || 3; + this.width = options.width || 1024; + this.height = options.height || 1024; + this.resolutionFactor = Math.max(this.width, this.height) / 1024; + this.whiteness = options.whiteness || 0; + this.varianceThreshold = options.varianceThreshold || 0.000016667; + + this.isMjpeg = this.streamType.toLowerCase() === 'mjpeg'; + + this.video = document.createElement(this.isMjpeg ? 'img' : 'video'); + this.video.crossOrigin = 'Anonymous'; + this.video.addEventListener(this.isMjpeg ? 'load' : 'loadedmetadata', this.metaLoaded.bind(this), false); + + if (!this.isMjpeg) { + this.video.loop = true; + } + + this.video.src = this.url; + this.video.setAttribute('crossorigin', 'Anonymous'); + + // define custom shaders + this.vertex_shader = [ + 'uniform sampler2D map;', + '', + 'uniform float width;', + 'uniform float height;', + 'uniform float nearClipping, farClipping;', + '', + 'uniform float pointSize;', + 'uniform float zOffset;', + '', + 'uniform float focallength;', + 'uniform float maxDepthPerTile;', + 'uniform float resolutionFactor;', + '', + 'varying vec2 vUvP;', + 'varying vec2 colorP;', + '', + 'varying float depthVariance;', + 'varying float maskVal;', + '', + 'float sampleDepth(vec2 pos)', + ' {', + ' float depth;', + ' ', + ' vec2 vUv = vec2( pos.x / (width*2.0), pos.y / (height*2.0)+0.5 );', + ' vec2 vUv2 = vec2( pos.x / (width*2.0)+0.5, pos.y / (height*2.0)+0.5 );', + ' ', + ' vec4 depthColor = texture2D( map, vUv );', + ' ', + ' depth = ( depthColor.r + depthColor.g + depthColor.b ) / 3.0 ;', + ' ', + ' if (depth>0.99)', + ' {', + ' vec4 depthColor2 = texture2D( map, vUv2 );', + ' float depth2 = ( depthColor2.r + depthColor2.g + depthColor2.b ) / 3.0 ;', + ' depth = 0.99+depth2;', + ' }', + ' ', + ' return depth;', + ' }', + '', + 'float median(float a, float b, float c)', + ' {', + ' float r=a;', + ' ', + ' if ( (a0.5) || (vUvP.y<0.5) || (vUvP.y>0.0))', + ' {', + ' vec2 smp = decodeDepth(vec2(position.x, position.y));', + ' float depth = smp.x;', + ' depthVariance = smp.y;', + ' ', + ' float z = -depth;', + ' ', + ' pos = vec4(', + ' ( position.x / width - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength) * -1.0,', + ' ( position.y / height - 0.5 ) * z * 0.5 * maxDepthPerTile * resolutionFactor * (1000.0/focallength),', + ' (- z + zOffset / 1000.0) * maxDepthPerTile,', + ' 1.0);', + ' ', + ' vec2 maskP = vec2( position.x / (width*2.0), position.y / (height*2.0) );', + ' vec4 maskColor = texture2D( map, maskP );', + ' maskVal = ( maskColor.r + maskColor.g + maskColor.b ) / 3.0 ;', + ' }', + ' ', + ' gl_PointSize = pointSize;', + ' gl_Position = projectionMatrix * modelViewMatrix * pos;', + ' ', + '}' + ].join('\n'); + + this.fragment_shader = [ + 'uniform sampler2D map;', + 'uniform float varianceThreshold;', + 'uniform float whiteness;', + '', + 'varying vec2 vUvP;', + 'varying vec2 colorP;', + '', + 'varying float depthVariance;', + 'varying float maskVal;', + '', + '', + 'void main() {', + ' ', + ' vec4 color;', + ' ', + ' if ( (depthVariance>varianceThreshold) || (maskVal>0.5) ||(vUvP.x<0.0)|| (vUvP.x>0.5) || (vUvP.y<0.5) || (vUvP.y>1.0))', + ' { ', + ' discard;', + ' }', + ' else ', + ' {', + ' color = texture2D( map, colorP );', + ' ', + ' float fader = whiteness /100.0;', + ' ', + ' color.r = color.r * (1.0-fader)+ fader;', + ' ', + ' color.g = color.g * (1.0-fader)+ fader;', + ' ', + ' color.b = color.b * (1.0-fader)+ fader;', + ' ', + ' color.a = 1.0;//smoothstep( 20000.0, -20000.0, gl_FragCoord.z / gl_FragCoord.w );', + ' }', + ' ', + ' gl_FragColor = vec4( color.r, color.g, color.b, color.a );', + ' ', + '}' + ].join('\n'); + }; + + /** + * Callback called when video metadata is ready + */ + metaLoaded() { + this.metaLoaded = true; + this.initStreamer(); + }; + + /** + * Callback called when video metadata is ready + */ + initStreamer() { + + if (this.metaLoaded) { + this.texture = new THREE.Texture(this.video); + this.geometry = new THREE.Geometry(); + + for (var i = 0, l = this.width * this.height; i < l; i++) { + + var vertex = new THREE.Vector3(); + vertex.x = (i % this.width); + vertex.y = Math.floor(i / this.width); + + this.geometry.vertices.push(vertex); + } + + this.material = new THREE.ShaderMaterial({ + uniforms : { + 'map' : { + type : 't', + value : this.texture + }, + 'width' : { + type : 'f', + value : this.width + }, + 'height' : { + type : 'f', + value : this.height + }, + 'focallength' : { + type : 'f', + value : this.f + }, + 'pointSize' : { + type : 'f', + value : this.pointSize + }, + 'zOffset' : { + type : 'f', + value : 0 + }, + 'whiteness' : { + type : 'f', + value : this.whiteness + }, + 'varianceThreshold' : { + type : 'f', + value : this.varianceThreshold + }, + 'maxDepthPerTile': { + type : 'f', + value : this.maxDepthPerTile + }, + 'resolutionFactor': { + type : 'f', + value : this.resolutionFactor + }, + }, + vertexShader : this.vertex_shader, + fragmentShader : this.fragment_shader + }); + + this.mesh = new THREE.ParticleSystem(this.geometry, this.material); + this.mesh.position.x = 0; + this.mesh.position.y = 0; + this.add(this.mesh); + + var that = this; + + setInterval(function() { + if (that.isMjpeg || that.video.readyState === that.video.HAVE_ENOUGH_DATA) { + that.texture.needsUpdate = true; + } + }, 1000 / 30); + } + }; + + /** + * Start video playback + */ + startStream() { + if (!this.isMjpeg) { + this.video.play(); + } + }; + + /** + * Stop video playback + */ + stopStream() { + if (!this.isMjpeg) { + this.video.pause(); + } + }; +} diff --git a/src-esm/index.js b/src-esm/index.js new file mode 100644 index 00000000..edc9160f --- /dev/null +++ b/src-esm/index.js @@ -0,0 +1,50 @@ + +export * from './Ros3D' + +export * from './depthcloud/DepthCloud' + +export * from './interactivemarkers/InteractiveMarker' +export * from './interactivemarkers/InteractiveMarkerClient' +export * from './interactivemarkers/InteractiveMarkerControl' +export * from './interactivemarkers/InteractiveMarkerHandle' +export * from './interactivemarkers/InteractiveMarkerMenu' + +export * from './markers/Marker' +export * from './markers/MarkerArrayClient' +export * from './markers/MarkerClient' + +export * from './models/Arrow' +export * from './models/Arrow2' +export * from './models/Axes' +export * from './models/Grid' +export * from './models/MeshLoader' +export * from './models/MeshResource' +export * from './models/TriangleList' + +export * from './navigation/OccupancyGrid' +export * from './navigation/OccupancyGridClient' +export * from './navigation/OcTree' +export * from './navigation/ColorOcTree' +export * from './navigation/OcTreeClient' +export * from './navigation/Odometry' +export * from './navigation/Path' +export * from './navigation/Point' +export * from './navigation/Polygon' +export * from './navigation/Pose' +export * from './navigation/PoseArray' +export * from './navigation/PoseWithCovariance' + +export * from './sensors/LaserScan' +export * from './sensors/NavSatFix' +export * from './sensors/Points' +export * from './sensors/PointCloud2' +export * from './sensors/TFAxes' + +export * from './urdf/Urdf' +export * from './urdf/UrdfClient' + +export * from './visualization/interaction/Highlighter' +export * from './visualization/interaction/MouseHandler' +export * from './visualization/interaction/OrbitControls' +export * from './visualization/SceneNode' +export * from './visualization/Viewer' diff --git a/src-esm/interactivemarkers/InteractiveMarker.js b/src-esm/interactivemarkers/InteractiveMarker.js new file mode 100644 index 00000000..daed0cba --- /dev/null +++ b/src-esm/interactivemarkers/InteractiveMarker.js @@ -0,0 +1,371 @@ +import THREE from '../../shims/three/core.js'; + +import { InteractiveMarkerControl } from './InteractiveMarkerControl' +import { InteractiveMarkerMenu } from './InteractiveMarkerMenu' +import { closestAxisPoint, intersectPlane } from '../Ros3D' + +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ + +export class InteractiveMarker extends THREE.Object3D { + + /** + * The main interactive marker object. + * + * @constructor + * @param options - object with following keys: + * + * * handle - the ROS3D.InteractiveMarkerHandle for this marker + * * camera - the main camera associated with the viewer for this marker + * * path (optional) - the base path to any meshes that will be loaded + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + */ + constructor(options) { + super(); + + var that = this; + options = options || {}; + var handle = options.handle; + this.name = handle.name; + var camera = options.camera; + var path = options.path || '/'; + var loader = options.loader; + this.dragging = false; + + // set the initial pose + this.onServerSetPose({ + pose : handle.pose + }); + + // information on where the drag started + this.dragStart = { + position : new THREE.Vector3(), + orientation : new THREE.Quaternion(), + positionWorld : new THREE.Vector3(), + orientationWorld : new THREE.Quaternion(), + event3d : {} + }; + + // add each control message + handle.controls.forEach(function(controlMessage) { + that.add(new InteractiveMarkerControl({ + parent : that, + handle : handle, + message : controlMessage, + camera : camera, + path : path, + loader : loader + })); + }); + + // check for any menus + if (handle.menuEntries.length > 0) { + this.menu = new InteractiveMarkerMenu({ + menuEntries : handle.menuEntries, + menuFontSize : handle.menuFontSize + }); + + // forward menu select events + this.menu.addEventListener('menu-select', function(event) { + that.dispatchEvent(event); + }); + } + }; + + /** + * Show the interactive marker menu associated with this marker. + * + * @param control - the control to use + * @param event - the event that caused this + */ + showMenu(control, event) { + if (this.menu) { + this.menu.show(control, event); + } + }; + + /** + * Move the axis based on the given event information. + * + * @param control - the control to use + * @param origAxis - the origin of the axis + * @param event3d - the event that caused this + */ + moveAxis(control, origAxis, event3d) { + if (this.dragging) { + var currentControlOri = control.currentControlOri; + var axis = origAxis.clone().applyQuaternion(currentControlOri); + // get move axis in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var axisWorld = axis.clone().applyQuaternion(this.dragStart.orientationWorld.clone()); + + var axisRay = new THREE.Ray(originWorld, axisWorld); + + // find closest point to mouse on axis + var t = closestAxisPoint(axisRay, event3d.camera, event3d.mousePos); + + // offset from drag start position + var p = new THREE.Vector3(); + p.addVectors(this.dragStart.position, axis.clone().applyQuaternion(this.dragStart.orientation) + .multiplyScalar(t)); + this.setPosition(control, p); + + + event3d.stopPropagation(); + } + }; + + + /** + * Move with respect to the plane based on the contorl and event. + * + * @param control - the control to use + * @param origNormal - the normal of the origin + * @param event3d - the event that caused this + */ + move3d(control, origNormal, event3d) { + // by default, move in a plane + if (this.dragging) { + + if(control.isShift){ + // this doesn't work + // // use the camera position and the marker position to determine the axis + // var newAxis = control.camera.position.clone(); + // newAxis.sub(this.position); + // // now mimic same steps constructor uses to create origAxis + // var controlOri = new THREE.Quaternion(newAxis.x, newAxis.y, + // newAxis.z, 1); + // controlOri.normalize(); + // var controlAxis = new THREE.Vector3(1, 0, 0); + // controlAxis.applyQuaternion(controlOri); + // origAxis = controlAxis; + }else{ + // we want to use the origin plane that is closest to the camera + var cameraVector = control.camera.getWorldDirection(); + var x = Math.abs(cameraVector.x); + var y = Math.abs(cameraVector.y); + var z = Math.abs(cameraVector.z); + var controlOri = new THREE.Quaternion(1, 0, 0, 1); + if(y > x && y > z){ + // orientation for the control + controlOri = new THREE.Quaternion(0, 0, 1, 1); + }else if(z > x && z > y){ + // orientation for the control + controlOri = new THREE.Quaternion(0, 1, 0, 1); + } + controlOri.normalize(); + + // transform x axis into local frame + origNormal = new THREE.Vector3(1, 0, 0); + origNormal.applyQuaternion(controlOri); + this.movePlane(control, origNormal, event3d); + } + } + }; + + /** + * Move with respect to the plane based on the contorl and event. + * + * @param control - the control to use + * @param origNormal - the normal of the origin + * @param event3d - the event that caused this + */ + movePlane(control, origNormal, event3d) { + if (this.dragging) { + var currentControlOri = control.currentControlOri; + var normal = origNormal.clone().applyQuaternion(currentControlOri); + // get plane params in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var normalWorld = normal.clone().applyQuaternion(this.dragStart.orientationWorld); + + // intersect mouse ray with plane + var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); + + // offset from drag start position + var p = new THREE.Vector3(); + p.subVectors(intersection, originWorld); + p.add(this.dragStart.positionWorld); + this.setPosition(control, p); + event3d.stopPropagation(); + } + }; + + /** + * Rotate based on the control and event given. + * + * @param control - the control to use + * @param origOrientation - the orientation of the origin + * @param event3d - the event that caused this + */ + rotateAxis(control, origOrientation, event3d) { + if (this.dragging) { + control.updateMatrixWorld(); + + var currentControlOri = control.currentControlOri; + var orientation = currentControlOri.clone().multiply(origOrientation.clone()); + + var normal = (new THREE.Vector3(1, 0, 0)).applyQuaternion(orientation); + + // get plane params in world coords + var originWorld = this.dragStart.event3d.intersection.point; + var normalWorld = normal.applyQuaternion(this.dragStart.orientationWorld); + + // intersect mouse ray with plane + var intersection = intersectPlane(event3d.mouseRay, originWorld, normalWorld); + + // offset local origin to lie on intersection plane + var normalRay = new THREE.Ray(this.dragStart.positionWorld, normalWorld); + var rotOrigin = intersectPlane(normalRay, originWorld, normalWorld); + + // rotates from world to plane coords + var orientationWorld = this.dragStart.orientationWorld.clone().multiply(orientation); + var orientationWorldInv = orientationWorld.clone().inverse(); + + // rotate original and current intersection into local coords + intersection.sub(rotOrigin); + intersection.applyQuaternion(orientationWorldInv); + + var origIntersection = this.dragStart.event3d.intersection.point.clone(); + origIntersection.sub(rotOrigin); + origIntersection.applyQuaternion(orientationWorldInv); + + // compute relative 2d angle + var a1 = Math.atan2(intersection.y, intersection.z); + var a2 = Math.atan2(origIntersection.y, origIntersection.z); + var a = a2 - a1; + + var rot = new THREE.Quaternion(); + rot.setFromAxisAngle(normal, a); + + // rotate + this.setOrientation(control, rot.multiply(this.dragStart.orientationWorld)); + + // offset from drag start position + event3d.stopPropagation(); + } + }; + + /** + * Dispatch the given event type. + * + * @param type - the type of event + * @param control - the control to use + */ + feedbackEvent(type, control) { + this.dispatchEvent({ + type : type, + position : this.position.clone(), + orientation : this.quaternion.clone(), + controlName : control.name + }); + }; + + /** + * Start a drag action. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + startDrag(control, event3d) { + if (event3d.domEvent.button === 0) { + event3d.stopPropagation(); + this.dragging = true; + this.updateMatrixWorld(true); + var scale = new THREE.Vector3(); + this.matrixWorld + .decompose(this.dragStart.positionWorld, this.dragStart.orientationWorld, scale); + this.dragStart.position = this.position.clone(); + this.dragStart.orientation = this.quaternion.clone(); + this.dragStart.event3d = event3d; + + this.feedbackEvent('user-mousedown', control); + } + }; + + /** + * Stop a drag action. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + stopDrag(control, event3d) { + if (event3d.domEvent.button === 0) { + event3d.stopPropagation(); + this.dragging = false; + this.dragStart.event3d = {}; + this.onServerSetPose(this.bufferedPoseEvent); + this.bufferedPoseEvent = undefined; + + this.feedbackEvent('user-mouseup', control); + } + }; + + /** + * Handle a button click. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + buttonClick(control, event3d) { + event3d.stopPropagation(); + this.feedbackEvent('user-button-click', control); + }; + + /** + * Handle a user pose change for the position. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + setPosition(control, position) { + this.position.copy(position); + this.feedbackEvent('user-pose-change', control); + }; + + /** + * Handle a user pose change for the orientation. + * + * @param control - the control to use + * @param event3d - the event that caused this + */ + setOrientation(control, orientation) { + orientation.normalize(); + this.quaternion.copy(orientation); + this.feedbackEvent('user-pose-change', control); + }; + + /** + * Update the marker based when the pose is set from the server. + * + * @param event - the event that caused this + */ + onServerSetPose(event) { + if (event !== undefined) { + // don't update while dragging + if (this.dragging) { + this.bufferedPoseEvent = event; + } else { + var pose = event.pose; + this.position.copy(pose.position); + this.quaternion.copy(pose.orientation); + this.updateMatrixWorld(true); + } + } + }; + + /** + * Free memory of elements in this marker. + */ + dispose() { + var that = this; + this.children.forEach(function(intMarkerControl) { + intMarkerControl.children.forEach(function(marker) { + marker.dispose(); + intMarkerControl.remove(marker); + }); + that.remove(intMarkerControl); + }); + }; +} diff --git a/src-esm/interactivemarkers/InteractiveMarkerClient.js b/src-esm/interactivemarkers/InteractiveMarkerClient.js new file mode 100644 index 00000000..ee326c8b --- /dev/null +++ b/src-esm/interactivemarkers/InteractiveMarkerClient.js @@ -0,0 +1,218 @@ +import THREE from '../../shims/three/core.js'; +import * as ROSLIB from 'roslib'; + +import { InteractiveMarkerHandle } from './InteractiveMarkerHandle' +import { InteractiveMarker } from './InteractiveMarker' + +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ + +export class InteractiveMarkerClient { + + /** + * A client for an interactive marker topic. + * + * @constructor + * @param options - object with following keys: + * + * * ros - a handle to the ROS connection + * * tfClient - a handle to the TF client + * * topic (optional) - the topic to subscribe to, like '/basic_controls', if not provided use subscribe() to start message receiving + * * path (optional) - the base path to any meshes that will be loaded + * * camera - the main camera associated with the viewer for this marker client + * * rootObject (optional) - the root THREE 3D object to render to + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + * * menuFontSize (optional) - the menu font size + */ + constructor(options) { + var that = this; + options = options || {}; + this.ros = options.ros; + this.tfClient = options.tfClient; + this.topicName = options.topic; + this.path = options.path || '/'; + this.camera = options.camera; + this.rootObject = options.rootObject || new THREE.Object3D(); + this.loader = options.loader; + this.menuFontSize = options.menuFontSize || '0.8em'; + + this.interactiveMarkers = {}; + this.updateTopic = null; + this.feedbackTopic = null; + + // check for an initial topic + if (this.topicName) { + this.subscribe(this.topicName); + } + }; + + /** + * Subscribe to the given interactive marker topic. This will unsubscribe from any current topics. + * + * @param topic - the topic to subscribe to, like '/basic_controls' + */ + subscribe(topic) { + // unsubscribe to the other topics + this.unsubscribe(); + + this.updateTopic = new ROSLIB.Topic({ + ros : this.ros, + name : topic + '/tunneled/update', + messageType : 'visualization_msgs/InteractiveMarkerUpdate', + // compression : 'png' + compression : 'cbor' + }); + this.updateTopic.subscribe(this.processUpdate.bind(this)); + + this.feedbackTopic = new ROSLIB.Topic({ + ros : this.ros, + name : topic + '/feedback', + messageType : 'visualization_msgs/InteractiveMarkerFeedback', + // compression : 'png' + compression : 'cbor' + }); + this.feedbackTopic.advertise(); + + this.initService = new ROSLIB.Service({ + ros : this.ros, + name : topic + '/tunneled/get_init', + serviceType : 'demo_interactive_markers/GetInit' + }); + var request = new ROSLIB.ServiceRequest({}); + this.initService.callService(request, this.processInit.bind(this)); + }; + + /** + * Unsubscribe from the current interactive marker topic. + */ + unsubscribe() { + if (this.updateTopic) { + this.updateTopic.unsubscribe(this.processUpdate); + } + if (this.feedbackTopic) { + this.feedbackTopic.unadvertise(); + } + // erase all markers + for (var intMarkerName in this.interactiveMarkers) { + this.eraseIntMarker(intMarkerName); + } + this.interactiveMarkers = {}; + }; + + /** + * Process the given interactive marker initialization message. + * + * @param initMessage - the interactive marker initialization message to process + */ + processInit(initMessage) { + var message = initMessage.msg; + + // erase any old markers + message.erases = []; + for (var intMarkerName in this.interactiveMarkers) { + message.erases.push(intMarkerName); + } + message.poses = []; + + // treat it as an update + this.processUpdate(message); + }; + + /** + * Process the given interactive marker update message. + * + * @param initMessage - the interactive marker update message to process + */ + processUpdate(message) { + var that = this; + + // erase any markers + message.erases.forEach(function(name) { + that.eraseIntMarker(name); + }); + + // updates marker poses + message.poses.forEach(function(poseMessage) { + var marker = that.interactiveMarkers[poseMessage.name]; + if (marker) { + marker.setPoseFromServer(poseMessage.pose); + } + }); + + // add new markers + message.markers.forEach(function(msg) { + // get rid of anything with the same name + var oldhandle = that.interactiveMarkers[msg.name]; + if (oldhandle) { + that.eraseIntMarker(oldhandle.name); + } + + // create the handle + var handle = new InteractiveMarkerHandle({ + message : msg, + feedbackTopic : that.feedbackTopic, + tfClient : that.tfClient, + menuFontSize : that.menuFontSize + }); + that.interactiveMarkers[msg.name] = handle; + + // create the actual marker + var intMarker = new InteractiveMarker({ + handle : handle, + camera : that.camera, + path : that.path, + loader : that.loader + }); + // add it to the scene + intMarker.name = msg.name; + that.rootObject.add(intMarker); + + // listen for any pose updates from the server + handle.on('pose', function(pose) { + intMarker.onServerSetPose({ + pose : pose + }); + }); + + // add bound versions of UI handlers + intMarker.addEventListener('user-pose-change', handle.setPoseFromClientBound); + intMarker.addEventListener('user-mousedown', handle.onMouseDownBound); + intMarker.addEventListener('user-mouseup', handle.onMouseUpBound); + intMarker.addEventListener('user-button-click', handle.onButtonClickBound); + intMarker.addEventListener('menu-select', handle.onMenuSelectBound); + + // now listen for any TF changes + handle.subscribeTf(); + }); + }; + + /** + * Erase the interactive marker with the given name. + * + * @param intMarkerName - the interactive marker name to delete + */ + eraseIntMarker(intMarkerName) { + if (this.interactiveMarkers[intMarkerName]) { + // remove the object + var targetIntMarker = this.rootObject.getObjectByName(intMarkerName); + this.rootObject.remove(targetIntMarker); + // unsubscribe from TF topic! + var handle = this.interactiveMarkers[intMarkerName]; + handle.unsubscribeTf(); + + // remove all other listeners + + targetIntMarker.removeEventListener('user-pose-change', handle.setPoseFromClientBound); + targetIntMarker.removeEventListener('user-mousedown', handle.onMouseDownBound); + targetIntMarker.removeEventListener('user-mouseup', handle.onMouseUpBound); + targetIntMarker.removeEventListener('user-button-click', handle.onButtonClickBound); + targetIntMarker.removeEventListener('menu-select', handle.onMenuSelectBound); + + // remove the handle from the map - after leaving this function's scope, there should be no references to the handle + delete this.interactiveMarkers[intMarkerName]; + targetIntMarker.dispose(); + } + }; +} diff --git a/src-esm/interactivemarkers/InteractiveMarkerControl.js b/src-esm/interactivemarkers/InteractiveMarkerControl.js new file mode 100644 index 00000000..7753ebae --- /dev/null +++ b/src-esm/interactivemarkers/InteractiveMarkerControl.js @@ -0,0 +1,277 @@ +import THREE from '../../shims/three/core.js'; +import * as ROSLIB from 'roslib'; + +import { INTERACTIVE_MARKER_MOVE_ROTATE_3D, INTERACTIVE_MARKER_MOVE_3D, INTERACTIVE_MARKER_MOVE_AXIS, INTERACTIVE_MARKER_ROTATE_AXIS, INTERACTIVE_MARKER_MOVE_PLANE, INTERACTIVE_MARKER_BUTTON, INTERACTIVE_MARKER_NONE, INTERACTIVE_MARKER_INHERIT, INTERACTIVE_MARKER_FIXED, INTERACTIVE_MARKER_VIEW_FACING } from '../Ros3D' +import { Marker } from '../markers/Marker' + +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ + +export class InteractiveMarkerControl extends THREE.Object3D { + + /** + * The main marker control object for an interactive marker. + * + * @constructor + * @param options - object with following keys: + * + * * parent - the parent of this control + * * message - the interactive marker control message + * * camera - the main camera associated with the viewer for this marker client + * * path (optional) - the base path to any meshes that will be loaded + * * loader (optional) - the Collada loader to use (e.g., an instance of ROS3D.COLLADA_LOADER) + */ + constructor(options) { + super(); + var that = this; + + options = options || {}; + this.parent = options.parent; + var handle = options.handle; + var message = options.message; + this.message = message; + this.name = message.name; + this.camera = options.camera; + this.path = options.path || '/'; + this.loader = options.loader; + this.dragging = false; + this.startMousePos = new THREE.Vector2(); + this.isShift = false; + + + // orientation for the control + var controlOri = new THREE.Quaternion(message.orientation.x, message.orientation.y, + message.orientation.z, message.orientation.w); + controlOri.normalize(); + + // transform x axis into local frame + var controlAxis = new THREE.Vector3(1, 0, 0); + controlAxis.applyQuaternion(controlOri); + + this.currentControlOri = new THREE.Quaternion(); + + // determine mouse interaction + switch (message.interaction_mode) { + case INTERACTIVE_MARKER_MOVE_ROTATE_3D: + case INTERACTIVE_MARKER_MOVE_3D: + this.addEventListener('mousemove', this.parent.move3d.bind(this.parent, this, controlAxis)); + break; + case INTERACTIVE_MARKER_MOVE_AXIS: + this.addEventListener('mousemove', this.parent.moveAxis.bind(this.parent, this, controlAxis)); + this.addEventListener('touchmove', this.parent.moveAxis.bind(this.parent, this, controlAxis)); + break; + case INTERACTIVE_MARKER_ROTATE_AXIS: + this + .addEventListener('mousemove', this.parent.rotateAxis.bind(this.parent, this, controlOri)); + break; + case INTERACTIVE_MARKER_MOVE_PLANE: + this + .addEventListener('mousemove', this.parent.movePlane.bind(this.parent, this, controlAxis)); + break; + case INTERACTIVE_MARKER_BUTTON: + this.addEventListener('click', this.parent.buttonClick.bind(this.parent, this)); + break; + default: + break; + } + + /** + * Install default listeners for highlighting / dragging. + * + * @param event - the event to stop + */ + function stopPropagation(event) { + event.stopPropagation(); + } + + // check the mode + if (message.interaction_mode !== INTERACTIVE_MARKER_NONE) { + this.addEventListener('mousedown', this.parent.startDrag.bind(this.parent, this)); + this.addEventListener('mouseup', this.parent.stopDrag.bind(this.parent, this)); + this.addEventListener('contextmenu', this.parent.showMenu.bind(this.parent, this)); + this.addEventListener('mouseup', function(event3d) { + if (that.startMousePos.distanceToSquared(event3d.mousePos) === 0) { + event3d.type = 'contextmenu'; + that.dispatchEvent(event3d); + } + }); + this.addEventListener('mouseover', stopPropagation); + this.addEventListener('mouseout', stopPropagation); + this.addEventListener('click', stopPropagation); + this.addEventListener('mousedown', function(event3d) { + that.startMousePos = event3d.mousePos; + }); + + // touch support + this.addEventListener('touchstart', function(event3d) { + if (event3d.domEvent.touches.length === 1) { + event3d.type = 'mousedown'; + event3d.domEvent.button = 0; + that.dispatchEvent(event3d); + } + }); + this.addEventListener('touchmove', function(event3d) { + if (event3d.domEvent.touches.length === 1) { + event3d.type = 'mousemove'; + event3d.domEvent.button = 0; + that.dispatchEvent(event3d); + } + }); + this.addEventListener('touchend', function(event3d) { + if (event3d.domEvent.touches.length === 0) { + event3d.domEvent.button = 0; + event3d.type = 'mouseup'; + that.dispatchEvent(event3d); + event3d.type = 'click'; + that.dispatchEvent(event3d); + } + }); + + window.addEventListener('keydown', function(event){ + if(event.keyCode === 16){ + that.isShift = true; + } + }); + window.addEventListener('keyup', function(event){ + if(event.keyCode === 16){ + that.isShift = false; + } + }); + } + + // rotation behavior + var rotInv = new THREE.Quaternion(); + var posInv = this.parent.position.clone().multiplyScalar(-1); + switch (message.orientation_mode) { + case INTERACTIVE_MARKER_INHERIT: + rotInv = this.parent.quaternion.clone().inverse(); + break; + case INTERACTIVE_MARKER_FIXED: + break; + case INTERACTIVE_MARKER_VIEW_FACING: + break; + default: + console.error('Unkown orientation mode: ' + message.orientation_mode); + break; + } + + // temporary TFClient to get transformations from InteractiveMarker + // frame to potential child Marker frames + var localTfClient = new ROSLIB.TFClient({ + ros : handle.tfClient.ros, + fixedFrame : handle.message.header.frame_id, + serverName : handle.tfClient.serverName + }); + + // create visuals (markers) + message.markers.forEach(function(markerMsg) { + var addMarker = function(transformMsg) { + var markerHelper = new Marker({ + message : markerMsg, + path : that.path, + loader : that.loader + }); + + // if transformMsg isn't null, this was called by TFClient + if (transformMsg !== null) { + // get the current pose as a ROSLIB.Pose... + var newPose = new ROSLIB.Pose({ + position : markerHelper.position, + orientation : markerHelper.quaternion + }); + // so we can apply the transform provided by the TFClient + newPose.applyTransform(new ROSLIB.Transform(transformMsg)); + + // get transform between parent marker's location and its frame + // apply it to sub-marker position to get sub-marker position + // relative to parent marker + var transformMarker = new Marker({ + message : markerMsg, + path : that.path, + loader : that.loader + }); + transformMarker.position.add(posInv); + transformMarker.position.applyQuaternion(rotInv); + transformMarker.quaternion.multiplyQuaternions(rotInv, transformMarker.quaternion); + var translation = new THREE.Vector3(transformMarker.position.x, transformMarker.position.y, transformMarker.position.z); + var transform = new ROSLIB.Transform({ + translation : translation, + orientation : transformMarker.quaternion + }); + + // apply that transform too + newPose.applyTransform(transform); + + markerHelper.setPose(newPose); + + markerHelper.updateMatrixWorld(); + // we only need to set the pose once - at least, this is what RViz seems to be doing, might change in the future + localTfClient.unsubscribe(markerMsg.header.frame_id); + } + + // add the marker + that.add(markerHelper); + }; + + // If the marker is not relative to the parent marker's position, + // ask the *local* TFClient for the transformation from the + // InteractiveMarker frame to the sub-Marker frame + if (markerMsg.header.frame_id !== '') { + localTfClient.subscribe(markerMsg.header.frame_id, addMarker); + } + // If not, just add the marker without changing its pose + else { + addMarker(null); + } + }); + }; + + updateMatrixWorld(force) { + var that = this; + var message = this.message; + switch (message.orientation_mode) { + case INTERACTIVE_MARKER_INHERIT: + super.updateMatrixWorld(force); + that.currentControlOri.copy(that.quaternion); + that.currentControlOri.normalize(); + break; + case INTERACTIVE_MARKER_FIXED: + that.quaternion.copy(that.parent.quaternion.clone().inverse()); + that.updateMatrix(); + that.matrixWorldNeedsUpdate = true; + super.updateMatrixWorld(force); + that.currentControlOri.copy(that.quaternion); + break; + case INTERACTIVE_MARKER_VIEW_FACING: + that.camera.updateMatrixWorld(); + var cameraRot = new THREE.Matrix4().extractRotation(that.camera.matrixWorld); + + var ros2Gl = new THREE.Matrix4(); + var r90 = Math.PI * 0.5; + var rv = new THREE.Euler(-r90, 0, r90); + ros2Gl.makeRotationFromEuler(rv); + + var worldToLocal = new THREE.Matrix4(); + worldToLocal.getInverse(that.parent.matrixWorld); + + cameraRot.multiplyMatrices(cameraRot, ros2Gl); + cameraRot.multiplyMatrices(worldToLocal, cameraRot); + + that.currentControlOri.setFromRotationMatrix(cameraRot); + + // check the orientation + if (!message.independent_marker_orientation) { + that.quaternion.copy(that.currentControlOri); + that.updateMatrix(); + that.matrixWorldNeedsUpdate = true; + } + super.updateMatrixWorld(force); + break; + default: + console.error('Unkown orientation mode: ' + message.orientation_mode); + break; + } + }; +} diff --git a/src-esm/interactivemarkers/InteractiveMarkerHandle.js b/src-esm/interactivemarkers/InteractiveMarkerHandle.js new file mode 100644 index 00000000..c4cc5bf9 --- /dev/null +++ b/src-esm/interactivemarkers/InteractiveMarkerHandle.js @@ -0,0 +1,200 @@ +import * as ROSLIB from 'roslib'; +import EventEmitter2 from 'eventemitter2'; + +import { INTERACTIVE_MARKER_POSE_UPDATE, INTERACTIVE_MARKER_BUTTON_CLICK, INTERACTIVE_MARKER_MOUSE_DOWN, INTERACTIVE_MARKER_MOUSE_UP, INTERACTIVE_MARKER_MENU_SELECT } from '../Ros3D' + +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ + +export class InteractiveMarkerHandle extends EventEmitter2 { + + /** + * Handle with signals for a single interactive marker. + * + * Emits the following events: + * + * * 'pose' - emitted when a new pose comes from the server + * + * @constructor + * @param options - object with following keys: + * + * * message - the interactive marker message + * * feedbackTopic - the ROSLIB.Topic associated with the feedback + * * tfClient - a handle to the TF client to use + * * menuFontSize (optional) - the menu font size + */ + constructor(options) { + super(); + options = options || {}; + this.message = options.message; + this.feedbackTopic = options.feedbackTopic; + this.tfClient = options.tfClient; + this.menuFontSize = options.menuFontSize || '0.8em'; + this.name = this.message.name; + this.header = this.message.header; + this.controls = this.message.controls; + this.menuEntries = this.message.menu_entries; + this.dragging = false; + this.timeoutHandle = null; + this.tfTransform = new ROSLIB.Transform(); + this.pose = new ROSLIB.Pose(); + + this.setPoseFromClientBound = this.setPoseFromClient.bind(this); + this.onMouseDownBound = this.onMouseDown.bind(this); + this.onMouseUpBound = this.onMouseUp.bind(this); + this.onButtonClickBound = this.onButtonClick.bind(this); + this.onMenuSelectBound = this.onMenuSelect.bind(this); + + // start by setting the pose + this.setPoseFromServer(this.message.pose); + this.tfUpdateBound = this.tfUpdate.bind(this); + }; + + /** + * Subscribe to the TF associated with this interactive marker. + */ + subscribeTf() { + // subscribe to tf updates if frame-fixed + if (this.message.header.stamp.secs === 0.0 && this.message.header.stamp.nsecs === 0.0) { + this.tfClient.subscribe(this.message.header.frame_id, this.tfUpdateBound); + } + }; + + unsubscribeTf() { + this.tfClient.unsubscribe(this.message.header.frame_id, this.tfUpdateBound); + }; + + /** + * Emit the new pose that has come from the server. + */ + emitServerPoseUpdate() { + var poseTransformed = new ROSLIB.Pose(this.pose); + poseTransformed.applyTransform(this.tfTransform); + this.emit('pose', poseTransformed); + }; + + /** + * Update the pose based on the pose given by the server. + * + * @param poseMsg - the pose given by the server + */ + setPoseFromServer(poseMsg) { + this.pose = new ROSLIB.Pose(poseMsg); + this.emitServerPoseUpdate(); + }; + + /** + * Update the pose based on the TF given by the server. + * + * @param transformMsg - the TF given by the server + */ + tfUpdate(transformMsg) { + this.tfTransform = new ROSLIB.Transform(transformMsg); + this.emitServerPoseUpdate(); + }; + + /** + * Set the pose from the client based on the given event. + * + * @param event - the event to base the change off of + */ + setPoseFromClient(event) { + // apply the transform + this.pose = new ROSLIB.Pose(event); + var inv = this.tfTransform.clone(); + inv.rotation.invert(); + inv.translation.multiplyQuaternion(inv.rotation); + inv.translation.x *= -1; + inv.translation.y *= -1; + inv.translation.z *= -1; + this.pose.applyTransform(inv); + + // send feedback to the server + this.sendFeedback(INTERACTIVE_MARKER_POSE_UPDATE, undefined, 0, event.controlName); + + // keep sending pose feedback until the mouse goes up + if (this.dragging) { + if (this.timeoutHandle) { + clearTimeout(this.timeoutHandle); + } + this.timeoutHandle = setTimeout(this.setPoseFromClient.bind(this, event), 250); + } + }; + + /** + * Send the button click feedback to the server. + * + * @param event - the event associated with the button click + */ + onButtonClick(event) { + this.sendFeedback(INTERACTIVE_MARKER_BUTTON_CLICK, event.clickPosition, 0, + event.controlName); + }; + + /** + * Send the mousedown feedback to the server. + * + * @param event - the event associated with the mousedown + */ + onMouseDown(event) { + this.sendFeedback(INTERACTIVE_MARKER_MOUSE_DOWN, event.clickPosition, 0, event.controlName); + this.dragging = true; + }; + + /** + * Send the mouseup feedback to the server. + * + * @param event - the event associated with the mouseup + */ + onMouseUp(event) { + this.sendFeedback(INTERACTIVE_MARKER_MOUSE_UP, event.clickPosition, 0, event.controlName); + this.dragging = false; + if (this.timeoutHandle) { + clearTimeout(this.timeoutHandle); + } + }; + + /** + * Send the menu select feedback to the server. + * + * @param event - the event associated with the menu select + */ + onMenuSelect(event) { + this.sendFeedback(INTERACTIVE_MARKER_MENU_SELECT, undefined, event.id, event.controlName); + }; + + /** + * Send feedback to the interactive marker server. + * + * @param eventType - the type of event that happened + * @param clickPosition (optional) - the position in ROS space the click happened + * @param menuEntryID (optional) - the menu entry ID that is associated + * @param controlName - the name of the control + */ + sendFeedback(eventType, clickPosition, + menuEntryID, controlName) { + + // check for the click position + var mousePointValid = clickPosition !== undefined; + clickPosition = clickPosition || { + x : 0, + y : 0, + z : 0 + }; + + var feedback = { + header : this.header, + client_id : this.clientID, + marker_name : this.name, + control_name : controlName, + event_type : eventType, + pose : this.pose, + mouse_point : clickPosition, + mouse_point_valid : mousePointValid, + menu_entry_id : menuEntryID + }; + this.feedbackTopic.publish(feedback); + }; +} diff --git a/src-esm/interactivemarkers/InteractiveMarkerMenu.js b/src-esm/interactivemarkers/InteractiveMarkerMenu.js new file mode 100644 index 00000000..539ae6fd --- /dev/null +++ b/src-esm/interactivemarkers/InteractiveMarkerMenu.js @@ -0,0 +1,185 @@ +import THREE from '../../shims/three/core.js'; + +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ + +export class InteractiveMarkerMenu extends THREE.EventDispatcher { + + /** + * A menu for an interactive marker. This will be overlayed on the canvas. + * + * @constructor + * @param options - object with following keys: + * + * * menuEntries - the menu entries to add + * * className (optional) - a custom CSS class for the menu div + * * entryClassName (optional) - a custom CSS class for the menu entry + * * overlayClassName (optional) - a custom CSS class for the menu overlay + * * menuFontSize (optional) - the menu font size + */ + constructor(options) { + super(); + var that = this; + options = options || {}; + var menuEntries = options.menuEntries; + var className = options.className || 'default-interactive-marker-menu'; + var entryClassName = options.entryClassName || 'default-interactive-marker-menu-entry'; + var overlayClassName = options.overlayClassName || 'default-interactive-marker-overlay'; + var menuFontSize = options.menuFontSize || '0.8em'; + + // holds the menu tree + var allMenus = []; + allMenus[0] = { + children : [] + }; + + + // create the CSS for this marker if it has not been created + if (document.getElementById('default-interactive-marker-menu-css') === null) { + var style = document.createElement('style'); + style.id = 'default-interactive-marker-menu-css'; + style.type = 'text/css'; + style.innerHTML = '.default-interactive-marker-menu {' + 'background-color: #444444;' + + 'border: 1px solid #888888;' + 'border: 1px solid #888888;' + 'padding: 0px 0px 0px 0px;' + + 'color: #FFFFFF;' + 'font-family: sans-serif;' + 'font-size: ' + menuFontSize +';' + 'z-index: 1002;' + + '}' + '.default-interactive-marker-menu ul {' + 'padding: 0px 0px 5px 0px;' + + 'margin: 0px;' + 'list-style-type: none;' + '}' + + '.default-interactive-marker-menu ul li div {' + '-webkit-touch-callout: none;' + + '-webkit-user-select: none;' + '-khtml-user-select: none;' + '-moz-user-select: none;' + + '-ms-user-select: none;' + 'user-select: none;' + 'cursor: default;' + + 'padding: 3px 10px 3px 10px;' + '}' + '.default-interactive-marker-menu-entry:hover {' + + ' background-color: #666666;' + ' cursor: pointer;' + '}' + + '.default-interactive-marker-menu ul ul {' + ' font-style: italic;' + + ' padding-left: 10px;' + '}' + '.default-interactive-marker-overlay {' + + ' position: absolute;' + ' top: 0%;' + ' left: 0%;' + ' width: 100%;' + + ' height: 100%;' + ' background-color: black;' + ' z-index: 1001;' + + ' -moz-opacity: 0.0;' + ' opacity: .0;' + ' filter: alpha(opacity = 0);' + '}'; + document.getElementsByTagName('head')[0].appendChild(style); + } + + // place the menu in a div + this.menuDomElem = document.createElement('div'); + this.menuDomElem.style.position = 'absolute'; + this.menuDomElem.className = className; + this.menuDomElem.addEventListener('contextmenu', function(event) { + event.preventDefault(); + }); + + // create the overlay DOM + this.overlayDomElem = document.createElement('div'); + this.overlayDomElem.className = overlayClassName; + + this.hideListener = this.hide.bind(this); + this.overlayDomElem.addEventListener('contextmenu', this.hideListener); + this.overlayDomElem.addEventListener('click', this.hideListener); + this.overlayDomElem.addEventListener('touchstart', this.hideListener); + + // parse all entries and link children to parents + var i, entry, id; + for ( i = 0; i < menuEntries.length; i++) { + entry = menuEntries[i]; + id = entry.id; + allMenus[id] = { + title : entry.title, + id : id, + children : [] + }; + } + for ( i = 0; i < menuEntries.length; i++) { + entry = menuEntries[i]; + id = entry.id; + var menu = allMenus[id]; + var parent = allMenus[entry.parent_id]; + parent.children.push(menu); + } + + function emitMenuSelect(menuEntry, domEvent) { + this.dispatchEvent({ + type : 'menu-select', + domEvent : domEvent, + id : menuEntry.id, + controlName : this.controlName + }); + this.hide(domEvent); + } + + /** + * Create the HTML UL element for the menu and link it to the parent. + * + * @param parentDomElem - the parent DOM element + * @param parentMenu - the parent menu + */ + function makeUl(parentDomElem, parentMenu) { + + var ulElem = document.createElement('ul'); + parentDomElem.appendChild(ulElem); + + var children = parentMenu.children; + + for ( var i = 0; i < children.length; i++) { + var liElem = document.createElement('li'); + var divElem = document.createElement('div'); + divElem.appendChild(document.createTextNode(children[i].title)); + ulElem.appendChild(liElem); + liElem.appendChild(divElem); + + if (children[i].children.length > 0) { + makeUl(liElem, children[i]); + divElem.addEventListener('click', that.hide.bind(that)); + divElem.addEventListener('touchstart', that.hide.bind(that)); + } else { + divElem.addEventListener('click', emitMenuSelect.bind(that, children[i])); + divElem.addEventListener('touchstart', emitMenuSelect.bind(that, children[i])); + divElem.className = 'default-interactive-marker-menu-entry'; + } + } + + } + + // construct DOM element + makeUl(this.menuDomElem, allMenus[0]); + }; + + /** + * Shoe the menu DOM element. + * + * @param control - the control for the menu + * @param event - the event that caused this + */ + show(control, event) { + if (event && event.preventDefault) { + event.preventDefault(); + } + + this.controlName = control.name; + + // position it on the click + if (event.domEvent.changedTouches !== undefined) { + // touch click + this.menuDomElem.style.left = event.domEvent.changedTouches[0].pageX + 'px'; + this.menuDomElem.style.top = event.domEvent.changedTouches[0].pageY + 'px'; + } else { + // mouse click + this.menuDomElem.style.left = event.domEvent.clientX + 'px'; + this.menuDomElem.style.top = event.domEvent.clientY + 'px'; + } + document.body.appendChild(this.overlayDomElem); + document.body.appendChild(this.menuDomElem); + }; + + /** + * Hide the menu DOM element. + * + * @param event (optional) - the event that caused this + */ + hide(event) { + if (event && event.preventDefault) { + event.preventDefault(); + } + + document.body.removeChild(this.overlayDomElem); + document.body.removeChild(this.menuDomElem); + }; +} diff --git a/src-esm/markers/Marker.js b/src-esm/markers/Marker.js new file mode 100644 index 00000000..14b582ec --- /dev/null +++ b/src-esm/markers/Marker.js @@ -0,0 +1,499 @@ +import THREE from '../../shims/three/core.js'; + +import { makeColorMaterial, MARKER_ARROW, MARKER_CUBE, MARKER_SPHERE, MARKER_CYLINDER, MARKER_LINE_STRIP, MARKER_LINE_LIST, MARKER_CUBE_LIST, MARKER_SPHERE_LIST, MARKER_POINTS, MARKER_TEXT_VIEW_FACING, MARKER_MESH_RESOURCE, MARKER_TRIANGLE_LIST } from '../Ros3D' +import { Arrow } from '../models/Arrow' +import { MeshResource } from '../models/MeshResource' +import { TriangleList } from '../models/TriangleList' + +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + * @author Russell Toris - rctoris@wpi.edu + */ + +export class Marker extends THREE.Object3D { + + /** + * A Marker can convert a ROS marker message into a THREE object. + * + * @constructor + * @param options - object with following keys: + * + * * path - the base path or URL for any mesh files that will be loaded for this marker + * * message - the marker message + */ + constructor(options) { + super(); + + options = options || {}; + var path = options.path || '/'; + var message = options.message; + + // check for a trailing '/' + if (path.substr(path.length - 1) !== '/') { + path += '/'; + } + + if(message.scale) { + this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + } + else { + this.msgScale = [1,1,1]; + } + this.msgColor = message.color; + this.msgMesh = undefined; + + // set the pose and get the color + this.setPose(message.pose); + var colorMaterial = makeColorMaterial(this.msgColor.r, + this.msgColor.g, this.msgColor.b, this.msgColor.a); + + // create the object based on the type + switch (message.type) { + case MARKER_ARROW: + // get the sizes for the arrow + var len = message.scale.x; + var headLength = len * 0.23; + var headDiameter = message.scale.y; + var shaftDiameter = headDiameter * 0.5; + + // determine the points + var direction, p1 = null; + if (message.points.length === 2) { + p1 = new THREE.Vector3(message.points[0].x, message.points[0].y, message.points[0].z); + var p2 = new THREE.Vector3(message.points[1].x, message.points[1].y, message.points[1].z); + direction = p1.clone().negate().add(p2); + // direction = p2 - p1; + len = direction.length(); + headDiameter = message.scale.y; + shaftDiameter = message.scale.x; + + if (message.scale.z !== 0.0) { + headLength = message.scale.z; + } + } + + // add the marker + this.add(new Arrow({ + direction : direction, + origin : p1, + length : len, + headLength : headLength, + shaftDiameter : shaftDiameter, + headDiameter : headDiameter, + material : colorMaterial + })); + break; + case MARKER_CUBE: + // set the cube dimensions + var cubeGeom = new THREE.BoxGeometry(message.scale.x, message.scale.y, message.scale.z); + this.add(new THREE.Mesh(cubeGeom, colorMaterial)); + break; + case MARKER_SPHERE: + // set the sphere dimensions + var sphereGeom = new THREE.SphereGeometry(0.5); + var sphereMesh = new THREE.Mesh(sphereGeom, colorMaterial); + sphereMesh.scale.x = message.scale.x; + sphereMesh.scale.y = message.scale.y; + sphereMesh.scale.z = message.scale.z; + this.add(sphereMesh); + break; + case MARKER_CYLINDER: + // set the cylinder dimensions + var cylinderGeom = new THREE.CylinderGeometry(0.5, 0.5, 1, 16, 1, false); + var cylinderMesh = new THREE.Mesh(cylinderGeom, colorMaterial); + cylinderMesh.quaternion.setFromAxisAngle(new THREE.Vector3(1, 0, 0), Math.PI * 0.5); + cylinderMesh.scale.set(message.scale.x, message.scale.z, message.scale.y); + this.add(cylinderMesh); + break; + case MARKER_LINE_STRIP: + var lineStripGeom = new THREE.Geometry(); + var lineStripMaterial = new THREE.LineBasicMaterial({ + linewidth : message.scale.x + }); + + // add the points + var j; + for ( j = 0; j < message.points.length; j++) { + var pt = new THREE.Vector3(); + pt.x = message.points[j].x; + pt.y = message.points[j].y; + pt.z = message.points[j].z; + lineStripGeom.vertices.push(pt); + } + + // determine the colors for each + if (message.colors.length === message.points.length) { + lineStripMaterial.vertexColors = true; + for ( j = 0; j < message.points.length; j++) { + var clr = new THREE.Color(); + clr.setRGB(message.colors[j].r, message.colors[j].g, message.colors[j].b); + lineStripGeom.colors.push(clr); + } + } else { + lineStripMaterial.color.setRGB(message.color.r, message.color.g, message.color.b); + } + + // add the line + this.add(new THREE.Line(lineStripGeom, lineStripMaterial)); + break; + case MARKER_LINE_LIST: + var lineListGeom = new THREE.Geometry(); + var lineListMaterial = new THREE.LineBasicMaterial({ + linewidth : message.scale.x + }); + + // add the points + var k; + for ( k = 0; k < message.points.length; k++) { + var v = new THREE.Vector3(); + v.x = message.points[k].x; + v.y = message.points[k].y; + v.z = message.points[k].z; + lineListGeom.vertices.push(v); + } + + // determine the colors for each + if (message.colors.length === message.points.length) { + lineListMaterial.vertexColors = true; + for ( k = 0; k < message.points.length; k++) { + var c = new THREE.Color(); + c.setRGB(message.colors[k].r, message.colors[k].g, message.colors[k].b); + lineListGeom.colors.push(c); + } + } else { + lineListMaterial.color.setRGB(message.color.r, message.color.g, message.color.b); + } + + // add the line + this.add(new THREE.LineSegments(lineListGeom, lineListMaterial)); + break; + case MARKER_CUBE_LIST: + // holds the main object + var object = new THREE.Object3D(); + + // check if custom colors should be used + var numPoints = message.points.length; + var createColors = (numPoints === message.colors.length); + // do not render giant lists + var stepSize = Math.ceil(numPoints / 1250); + + // add the points + var p, cube, curColor, newMesh; + for (p = 0; p < numPoints; p+=stepSize) { + cube = new THREE.BoxGeometry(message.scale.x, message.scale.y, message.scale.z); + + // check the color + if(createColors) { + curColor = makeColorMaterial(message.colors[p].r, message.colors[p].g, message.colors[p].b, message.colors[p].a); + } else { + curColor = colorMaterial; + } + + newMesh = new THREE.Mesh(cube, curColor); + newMesh.position.x = message.points[p].x; + newMesh.position.y = message.points[p].y; + newMesh.position.z = message.points[p].z; + object.add(newMesh); + } + + this.add(object); + break; + case MARKER_SPHERE_LIST: + // holds the main object + var sphereObject = new THREE.Object3D(); + + // check if custom colors should be used + var numSpherePoints = message.points.length; + var createSphereColors = (numSpherePoints === message.colors.length); + // do not render giant lists + var sphereStepSize = Math.ceil(numSpherePoints / 1250); + + // add the points + var q, sphere, curSphereColor, newSphereMesh; + for (q = 0; q < numSpherePoints; q+=sphereStepSize) { + sphere = new THREE.SphereGeometry(0.5, 8, 8); + + // check the color + if(createSphereColors) { + curSphereColor = makeColorMaterial(message.colors[q].r, message.colors[q].g, message.colors[q].b, message.colors[q].a); + } else { + curSphereColor = colorMaterial; + } + + newSphereMesh = new THREE.Mesh(sphere, curSphereColor); + newSphereMesh.scale.x = message.scale.x; + newSphereMesh.scale.y = message.scale.y; + newSphereMesh.scale.z = message.scale.z; + newSphereMesh.position.x = message.points[q].x; + newSphereMesh.position.y = message.points[q].y; + newSphereMesh.position.z = message.points[q].z; + sphereObject.add(newSphereMesh); + } + this.add(sphereObject); + break; + case MARKER_POINTS: + // for now, use a particle system for the lists + var geometry = new THREE.Geometry(); + var material = new THREE.PointsMaterial({ + size : message.scale.x + }); + + // add the points + var i; + for ( i = 0; i < message.points.length; i++) { + var vertex = new THREE.Vector3(); + vertex.x = message.points[i].x; + vertex.y = message.points[i].y; + vertex.z = message.points[i].z; + geometry.vertices.push(vertex); + } + + // determine the colors for each + if (message.colors.length === message.points.length) { + material.vertexColors = true; + for ( i = 0; i < message.points.length; i++) { + var color = new THREE.Color(); + color.setRGB(message.colors[i].r, message.colors[i].g, message.colors[i].b); + geometry.colors.push(color); + } + } else { + material.color.setRGB(message.color.r, message.color.g, message.color.b); + } + + // add the particle system + this.add(new THREE.Points(geometry, material)); + break; + case MARKER_TEXT_VIEW_FACING: + // only work on non-empty text + if (message.text.length > 0) { + // Use a THREE.Sprite to always be view-facing + // ( code from http://stackoverflow.com/a/27348780 ) + var textColor = this.msgColor; + + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + var textHeight = 100; + var fontString = 'normal ' + textHeight + 'px sans-serif'; + context.font = fontString; + var metrics = context.measureText( message.text ); + var textWidth = metrics.width; + + canvas.width = textWidth; + // To account for overhang (like the letter 'g'), make the canvas bigger + // The non-text portion is transparent anyway + canvas.height = 1.5 * textHeight; + + // this does need to be set again + context.font = fontString; + context.fillStyle = 'rgba(' + + Math.round(255 * textColor.r) + ', ' + + Math.round(255 * textColor.g) + ', ' + + Math.round(255 * textColor.b) + ', ' + + textColor.a + ')'; + context.textAlign = 'left'; + context.textBaseline = 'middle'; + context.fillText( message.text, 0, canvas.height/2); + + var texture = new THREE.Texture(canvas); + texture.needsUpdate = true; + + var spriteMaterial = new THREE.SpriteMaterial({ + map: texture, + // NOTE: This is needed for THREE.js r61, unused in r70 + useScreenCoordinates: false }); + var sprite = new THREE.Sprite( spriteMaterial ); + var textSize = message.scale.x; + sprite.scale.set(textWidth / canvas.height * textSize, textSize, 1); + + this.add(sprite); } + break; + case MARKER_MESH_RESOURCE: + // load and add the mesh + var meshColorMaterial = null; + if(message.color.r !== 0 || message.color.g !== 0 || + message.color.b !== 0 || message.color.a !== 0) { + meshColorMaterial = colorMaterial; + } + this.msgMesh = message.mesh_resource.substr(10); + var meshResource = new MeshResource({ + path : path, + resource : this.msgMesh, + material : meshColorMaterial, + }); + this.add(meshResource); + break; + case MARKER_TRIANGLE_LIST: + // create the list of triangles + var tri = new TriangleList({ + material : colorMaterial, + vertices : message.points, + colors : message.colors + }); + tri.scale.set(message.scale.x, message.scale.y, message.scale.z); + this.add(tri); + break; + default: + console.error('Currently unsupported marker type: ' + message.type); + break; + } + }; + + /** + * Set the pose of this marker to the given values. + * + * @param pose - the pose to set for this marker + */ + setPose(pose) { + // set position information + this.position.x = pose.position.x; + this.position.y = pose.position.y; + this.position.z = pose.position.z; + + // set the rotation + this.quaternion.set(pose.orientation.x, pose.orientation.y, + pose.orientation.z, pose.orientation.w); + this.quaternion.normalize(); + + // update the world + this.updateMatrixWorld(); + }; + + /** + * Update this marker. + * + * @param message - the marker message + * @return true on success otherwhise false is returned + */ + update(message) { + // set the pose and get the color + this.setPose(message.pose); + + // Update color + if(message.color.r !== this.msgColor.r || + message.color.g !== this.msgColor.g || + message.color.b !== this.msgColor.b || + message.color.a !== this.msgColor.a) + { + var colorMaterial = makeColorMaterial( + message.color.r, message.color.g, + message.color.b, message.color.a); + + switch (message.type) { + case MARKER_LINE_STRIP: + case MARKER_LINE_LIST: + case MARKER_POINTS: + break; + case MARKER_ARROW: + case MARKER_CUBE: + case MARKER_SPHERE: + case MARKER_CYLINDER: + case MARKER_TRIANGLE_LIST: + case MARKER_TEXT_VIEW_FACING: + this.traverse (function (child){ + if (child instanceof THREE.Mesh) { + child.material = colorMaterial; + } + }); + break; + case MARKER_MESH_RESOURCE: + var meshColorMaterial = null; + if(message.color.r !== 0 || message.color.g !== 0 || + message.color.b !== 0 || message.color.a !== 0) { + meshColorMaterial = this.colorMaterial; + } + this.traverse (function (child){ + if (child instanceof THREE.Mesh) { + child.material = meshColorMaterial; + } + }); + break; + case MARKER_CUBE_LIST: + case MARKER_SPHERE_LIST: + // TODO Support to update color for MARKER_CUBE_LIST & MARKER_SPHERE_LIST + return false; + default: + return false; + } + + this.msgColor = message.color; + } + + // Update geometry + var scaleChanged = + Math.abs(this.msgScale[0] - message.scale.x) > 1.0e-6 || + Math.abs(this.msgScale[1] - message.scale.y) > 1.0e-6 || + Math.abs(this.msgScale[2] - message.scale.z) > 1.0e-6; + this.msgScale = [message.scale.x, message.scale.y, message.scale.z]; + + switch (message.type) { + case MARKER_CUBE: + case MARKER_SPHERE: + case MARKER_CYLINDER: + if(scaleChanged) { + return false; + } + break; + case MARKER_TEXT_VIEW_FACING: + if(scaleChanged || this.text !== message.text) { + return false; + } + break; + case MARKER_MESH_RESOURCE: + var meshResource = message.mesh_resource.substr(10); + if(meshResource !== this.msgMesh) { + return false; + } + if(scaleChanged) { + return false; + } + break; + case MARKER_ARROW: + case MARKER_LINE_STRIP: + case MARKER_LINE_LIST: + case MARKER_CUBE_LIST: + case MARKER_SPHERE_LIST: + case MARKER_POINTS: + case MARKER_TRIANGLE_LIST: + // TODO: Check if geometry changed + return false; + default: + break; + } + + return true; + }; + + /* + * Free memory of elements in this marker. + */ + dispose() { + this.children.forEach(function(element) { + if (element instanceof MeshResource) { + element.children.forEach(function(scene) { + if (scene.material !== undefined) { + scene.material.dispose(); + } + scene.children.forEach(function(mesh) { + if (mesh.geometry !== undefined) { + mesh.geometry.dispose(); + } + if (mesh.material !== undefined) { + mesh.material.dispose(); + } + scene.remove(mesh); + }); + element.remove(scene); + }); + } else { + if (element.geometry !== undefined) { + element.geometry.dispose(); + } + if (element.material !== undefined) { + element.material.dispose(); + } + } + element.parent.remove(element); + }); + }; +} diff --git a/src-esm/markers/MarkerArrayClient.js b/src-esm/markers/MarkerArrayClient.js new file mode 100644 index 00000000..85adcbb3 --- /dev/null +++ b/src-esm/markers/MarkerArrayClient.js @@ -0,0 +1,124 @@ +import THREE from '../../shims/three/core.js'; +import EventEmitter2 from 'eventemitter2'; +import * as ROSLIB from 'roslib'; + +import { Marker } from './Marker' +import { SceneNode } from '../visualization/SceneNode' + +/** + * @fileOverview + * @author Russell Toris - rctoris@wpi.edu + * @author Nils Berg - berg.nils@gmail.com + */ + +export class MarkerArrayClient extends EventEmitter2 { + + /** + * A MarkerArray client that listens to a given topic. + * + * Emits the following events: + * + * * 'change' - there was an update or change in the MarkerArray + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add the markers to + * * path (optional) - the base path to any meshes that will be loaded + */ + constructor(options) { + super(); + options = options || {}; + this.ros = options.ros; + this.topicName = options.topic; + this.tfClient = options.tfClient; + this.rootObject = options.rootObject || new THREE.Object3D(); + this.path = options.path || '/'; + + // Markers that are displayed (Map ns+id--Marker) + this.markers = {}; + this.rosTopic = undefined; + + this.subscribe(); + }; + + subscribe(){ + this.unsubscribe(); + + // subscribe to MarkerArray topic + this.rosTopic = new ROSLIB.Topic({ + ros : this.ros, + name : this.topicName, + messageType : 'visualization_msgs/MarkerArray', + //compression : 'png' + compression : 'cbor' + }); + this.rosTopic.subscribe(this.processMessage.bind(this)); + }; + + processMessage(arrayMessage){ + arrayMessage.markers.forEach(function(message) { + var key = message.ns + message.id; + if(message.action === 0) { + var updated = false; + if(key in this.markers) { // "MODIFY" + updated = this.markers[key].children[0].update(message); + if(!updated) { // "REMOVE" + this.removeMarker(key); + } + } + if(!updated) { // "ADD" + var newMarker = new Marker({ + message : message, + path : this.path, + }); + this.markers[key] = new SceneNode({ + frameID : message.header.frame_id, + tfClient : this.tfClient, + object : newMarker + }); + this.rootObject.add(this.markers[key]); + } + } + else if(message.action === 1) { // "DEPRECATED" + console.warn('Received marker message with deprecated action identifier "1"'); + } + else if(message.action === 2) { // "DELETE" + this.removeMarker(key); + } + else if(message.action === 3) { // "DELETE ALL" + for (var m in this.markers){ + this.removeMarker(m); + } + this.markers = {}; + } + else { + console.warn('Received marker message with unknown action identifier "'+message.action+'"'); + } + }.bind(this)); + + this.emit('change'); + }; + + unsubscribe(){ + if(this.rosTopic){ + this.rosTopic.unsubscribe(this.processMessage); + } + }; + + removeMarker(key) { + var oldNode = this.markers[key]; + if(!oldNode) { + return; + } + oldNode.unsubscribeTf(); + this.rootObject.remove(oldNode); + oldNode.children.forEach(child => { + child.dispose(); + }); + delete(this.markers[key]); + }; +} diff --git a/src-esm/markers/MarkerClient.js b/src-esm/markers/MarkerClient.js new file mode 100644 index 00000000..ec0f13b3 --- /dev/null +++ b/src-esm/markers/MarkerClient.js @@ -0,0 +1,123 @@ +import THREE from '../../shims/three/core.js'; +import EventEmitter2 from 'eventemitter2'; +import * as ROSLIB from 'roslib'; + +import { Marker } from './Marker' +import { SceneNode } from '../visualization/SceneNode' + +/** + * @fileOverview + * @author Russell Toris - rctoris@wpi.edu + */ + +export class MarkerClient extends EventEmitter2 { + + /** + * A marker client that listens to a given marker topic. + * + * Emits the following events: + * + * * 'change' - there was an update or change in the marker + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add this marker to + * * path (optional) - the base path to any meshes that will be loaded + * * lifetime - the lifetime of marker + */ + constructor(options) { + super(); + options = options || {}; + this.ros = options.ros; + this.topicName = options.topic; + this.tfClient = options.tfClient; + this.rootObject = options.rootObject || new THREE.Object3D(); + this.path = options.path || '/'; + this.lifetime = options.lifetime || 0; + + // Markers that are displayed (Map ns+id--Marker) + this.markers = {}; + this.rosTopic = undefined; + this.updatedTime = {}; + + this.subscribe(); + }; + + unsubscribe(){ + if(this.rosTopic){ + this.rosTopic.unsubscribe(this.processMessage); + } + }; + + checkTime(name){ + var curTime = new Date().getTime(); + if (curTime - this.updatedTime[name] > this.lifetime) { + this.removeMarker(name); + this.emit('change'); + } else { + var that = this; + setTimeout(function() {that.checkTime(name);}, + 100); + } + }; + + subscribe(){ + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros : this.ros, + name : this.topicName, + messageType : 'visualization_msgs/Marker', + // compression : 'png' + compression : 'cbor' + }); + this.rosTopic.subscribe(this.processMessage.bind(this)); + }; + + processMessage(message){ + // remove old marker from Three.Object3D children buffer + var key = message.ns + message.id; + var oldNode = this.markers[key]; + this.updatedTime[key] = new Date().getTime(); + if (oldNode) { + this.removeMarker(key); + + } else if (this.lifetime) { + this.checkTime(message.ns + message.id); + } + + if (message.action === 0) { // "ADD" or "MODIFY" + var newMarker = new Marker({ + message : message, + path : this.path, + }); + + this.markers[key] = new SceneNode({ + frameID : message.header.frame_id, + tfClient : this.tfClient, + object : newMarker + }); + this.rootObject.add(this.markers[key]); + } + + this.emit('change'); + }; + + removeMarker(key) { + var oldNode = this.markers[key]; + if(!oldNode) { + return; + } + oldNode.unsubscribeTf(); + this.rootObject.remove(oldNode); + oldNode.children.forEach(child => { + child.dispose(); + }); + delete(this.markers[key]); + }; +} diff --git a/src-esm/models/Arrow.js b/src-esm/models/Arrow.js new file mode 100644 index 00000000..35ba3836 --- /dev/null +++ b/src-esm/models/Arrow.js @@ -0,0 +1,103 @@ +import THREE from '../../shims/three/core.js'; + +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ + +export class Arrow extends THREE.Mesh { + + /** + * A Arrow is a THREE object that can be used to display an arrow model. + * + * @constructor + * @param options - object with following keys: + * + * * origin (optional) - the origin of the arrow + * * direction (optional) - the direction vector of the arrow + * * length (optional) - the length of the arrow + * * headLength (optional) - the head length of the arrow + * * shaftDiameter (optional) - the shaft diameter of the arrow + * * headDiameter (optional) - the head diameter of the arrow + * * material (optional) - the material to use for this arrow + */ + constructor(options) { + options = options || {}; + var origin = options.origin || new THREE.Vector3(0, 0, 0); + var direction = options.direction || new THREE.Vector3(1, 0, 0); + var length = options.length || 1; + var headLength = options.headLength || 0.2; + var shaftDiameter = options.shaftDiameter || 0.05; + var headDiameter = options.headDiameter || 0.1; + var material = options.material || new THREE.MeshBasicMaterial(); + + var shaftLength = length - headLength; + + // create and merge geometry + var geometry = new THREE.CylinderGeometry(shaftDiameter * 0.5, shaftDiameter * 0.5, shaftLength, + 12, 1); + var m = new THREE.Matrix4(); + m.setPosition(new THREE.Vector3(0, shaftLength * 0.5, 0)); + geometry.applyMatrix(m); + + // create the head + var coneGeometry = new THREE.CylinderGeometry(0, headDiameter * 0.5, headLength, 12, 1); + m.setPosition(new THREE.Vector3(0, shaftLength + (headLength * 0.5), 0)); + coneGeometry.applyMatrix(m); + + // put the arrow together + geometry.merge(coneGeometry); + + super(geometry, material); + + this.position.copy(origin); + this.setDirection(direction); + }; + + /** + * Set the direction of this arrow to that of the given vector. + * + * @param direction - the direction to set this arrow + */ + setDirection(direction) { + var axis = new THREE.Vector3(); + if(direction.x === 0 && direction.z === 0){ + axis.set(1, 0, 0); + } else { + axis.set(0, 1, 0).cross(direction); + } + var radians = Math.acos(new THREE.Vector3(0, 1, 0).dot(direction.clone().normalize())); + this.matrix = new THREE.Matrix4().makeRotationAxis(axis.normalize(), radians); + this.rotation.setFromRotationMatrix(this.matrix, this.rotation.order); + }; + + /** + * Set this arrow to be the given length. + * + * @param length - the new length of the arrow + */ + setLength(length) { + this.scale.set(length, length, length); + }; + + /** + * Set the color of this arrow to the given hex value. + * + * @param hex - the hex value of the color to use + */ + setColor(hex) { + this.material.color.setHex(hex); + }; + + /* + * Free memory of elements in this marker. + */ + dispose() { + if (this.geometry !== undefined) { + this.geometry.dispose(); + } + if (this.material !== undefined) { + this.material.dispose(); + } + }; +} diff --git a/src-esm/models/Arrow2.js b/src-esm/models/Arrow2.js new file mode 100644 index 00000000..54220fb5 --- /dev/null +++ b/src-esm/models/Arrow2.js @@ -0,0 +1,71 @@ +import THREE from '../../shims/three/core.js'; + +/** + * @fileOverview + * @author Jihoon Lee - lee@magazino.eu + */ + +export class Arrow2 extends THREE.ArrowHelper { + + /** + * A Arrow is a THREE object that can be used to display an arrow model using ArrowHelper + * + * @constructor + * @param options - object with following keys: + * + * * origin (optional) - the origin of the arrow + * * direction (optional) - the direction vector of the arrow + * * length (optional) - the length of the arrow + * * headLength (optional) - the head length of the arrow + * * shaftDiameter (optional) - the shaft diameter of the arrow + * * headDiameter (optional) - the head diameter of the arrow + * * material (optional) - the material to use for this arrow + */ + constructor(options) { + options = options || {}; + var origin = options.origin || new THREE.Vector3(0, 0, 0); + var direction = options.direction || new THREE.Vector3(1, 0, 0); + var length = options.length || 1; + var headLength = options.headLength || 0.2; + var shaftDiameter = options.shaftDiameter || 0.05; + var headDiameter = options.headDiameter || 0.1; + var material = options.material || new THREE.MeshBasicMaterial(); + + super(direction, origin, length, 0xff0000); + + }; + + + /* + * Free memory of elements in this object. + */ + dispose() { + if (this.line !== undefined) { + this.line.material.dispose(); + this.line.geometry.dispose(); + } + if (this.cone!== undefined) { + this.cone.material.dispose(); + this.cone.geometry.dispose(); + } + }; + + /* + setLength( length, headLength, headWidth ) { + if ( headLength === undefined ) { + headLength = 0.2 * length; + } + if ( headWidth === undefined ) { + headWidth = 0.2 * headLength; + } + + this.line.scale.set( 1, Math.max( 0, length), 1 ); + this.line.updateMatrix(); + + this.cone.scale.set( headWidth, headLength, headWidth ); + this.cone.position.y = length; + this.cone.updateMatrix(); + + }; + */ +} diff --git a/src-esm/models/Axes.js b/src-esm/models/Axes.js new file mode 100644 index 00000000..ca7d44dd --- /dev/null +++ b/src-esm/models/Axes.js @@ -0,0 +1,103 @@ +import THREE from '../../shims/three/core.js'; + +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ + +export class Axes extends THREE.Object3D { + + /** + * An Axes object can be used to display the axis of a particular coordinate frame. + * + * @constructor + * @param options - object with following keys: + * + * * shaftRadius (optional) - the radius of the shaft to render + * * headRadius (optional) - the radius of the head to render + * * headLength (optional) - the length of the head to render + * * scale (optional) - the scale of the frame (defaults to 1.0) + * * lineType (optional) - the line type for the axes. Supported line types: + * 'dashed' and 'full'. + * * lineDashLength (optional) - the length of the dashes, relative to the length of the axis. + * Maximum value is 1, which means the dash length is + * equal to the length of the axis. Parameter only applies when + * lineType is set to dashed. + */ + constructor(options) { + super(); + var that = this; + options = options || {}; + var shaftRadius = options.shaftRadius || 0.008; + var headRadius = options.headRadius || 0.023; + var headLength = options.headLength || 0.1; + var scaleArg = options.scale || 1.0; + var lineType = options.lineType || 'full'; + var lineDashLength = options.lineDashLength || 0.1; + + + this.scale.set(scaleArg, scaleArg, scaleArg); + + // create the cylinders for the objects + this.lineGeom = new THREE.CylinderGeometry(shaftRadius, shaftRadius, 1.0 - headLength); + this.headGeom = new THREE.CylinderGeometry(0, headRadius, headLength); + + /** + * Adds an axis marker to this axes object. + * + * @param axis - the 3D vector representing the axis to add + */ + function addAxis(axis) { + // set the color of the axis + var color = new THREE.Color(); + color.setRGB(axis.x, axis.y, axis.z); + var material = new THREE.MeshBasicMaterial({ + color : color.getHex() + }); + + // setup the rotation information + var rotAxis = new THREE.Vector3(); + rotAxis.crossVectors(axis, new THREE.Vector3(0, -1, 0)); + var rot = new THREE.Quaternion(); + rot.setFromAxisAngle(rotAxis, 0.5 * Math.PI); + + // create the arrow + var arrow = new THREE.Mesh(that.headGeom, material); + arrow.position.copy(axis); + arrow.position.multiplyScalar(0.95); + arrow.quaternion.copy(rot); + arrow.updateMatrix(); + that.add(arrow); + + // create the line + var line; + if (lineType === 'dashed') { + var l = lineDashLength; + for (var i = 0; (l / 2 + 3 * l * i + l / 2) <= 1; ++i) { + var geom = new THREE.CylinderGeometry(shaftRadius, shaftRadius, l); + line = new THREE.Mesh(geom, material); + line.position.copy(axis); + // Make spacing between dashes equal to 1.5 times the dash length. + line.position.multiplyScalar(l / 2 + 3 * l * i); + line.quaternion.copy(rot); + line.updateMatrix(); + that.add(line); + } + } else if (lineType === 'full') { + line = new THREE.Mesh(that.lineGeom, material); + line.position.copy(axis); + line.position.multiplyScalar(0.45); + line.quaternion.copy(rot); + line.updateMatrix(); + that.add(line); + } else { + console.warn('[Axes]: Unsupported line type. Not drawing any axes.'); + } + } + + // add the three markers to the axes + addAxis(new THREE.Vector3(1, 0, 0)); + addAxis(new THREE.Vector3(0, 1, 0)); + addAxis(new THREE.Vector3(0, 0, 1)); + }; +} diff --git a/src-esm/models/Grid.js b/src-esm/models/Grid.js new file mode 100644 index 00000000..9669a92d --- /dev/null +++ b/src-esm/models/Grid.js @@ -0,0 +1,52 @@ +import THREE from '../../shims/three/core.js'; + +/** + * @fileOverview + * @author Russell Toris - rctoris@wpi.edu + */ + +export class Grid extends THREE.Object3D { + + /** + * Create a grid object. + * + * @constructor + * @param options - object with following keys: + * + * * num_cells (optional) - The number of cells of the grid + * * color (optional) - the line color of the grid, like '#cccccc' + * * lineWidth (optional) - the width of the lines in the grid + * * cellSize (optional) - The length, in meters, of the side of each cell + */ + constructor(options) { + options = options || {}; + var num_cells = options.num_cells || 10; + var color = options.color || '#cccccc'; + var lineWidth = options.lineWidth || 1; + var cellSize = options.cellSize || 1; + + super(); + + var material = new THREE.LineBasicMaterial({ + color: color, + linewidth: lineWidth + }); + + for (var i = 0; i <= num_cells; ++i) { + var edge = cellSize * num_cells / 2; + var position = edge - (i * cellSize); + var geometryH = new THREE.Geometry(); + geometryH.vertices.push( + new THREE.Vector3( -edge, position, 0 ), + new THREE.Vector3( edge, position, 0 ) + ); + var geometryV = new THREE.Geometry(); + geometryV.vertices.push( + new THREE.Vector3( position, -edge, 0 ), + new THREE.Vector3( position, edge, 0 ) + ); + this.add(new THREE.Line(geometryH, material)); + this.add(new THREE.Line(geometryV, material)); + } + }; +} diff --git a/src-esm/models/MeshLoader.js b/src-esm/models/MeshLoader.js new file mode 100644 index 00000000..16a0fe80 --- /dev/null +++ b/src-esm/models/MeshLoader.js @@ -0,0 +1,138 @@ +import THREE from '../../shims/three/core.js'; +import '../../shims/three/STLLoader.js'; +import '../../shims/three/OBJLoader.js'; +import '../../shims/three/MTLLoader.js'; +import '../../shims/three/ColladaLoader.js'; + +/** + * @fileOverview + * @author Jose Rojas - jrojas@redlinesolutions.co + */ + + /** + * MeshLoader is a singleton factory class for using various helper classes to + * load mesh files of different types. + * + * It consists of one dictionary property 'loaders'. The dictionary keys consist + * of the file extension for each supported loader type. The dictionary values + * are functions used to construct the loader objects. The functions have the + * following parameters: + * + * * meshRes - the MeshResource that will contain the loaded mesh + * * uri - the uri path to the mesh file + * @returns loader object + */ +export var MeshLoader = { + onError: function(error) { + console.error(error); + }, + loaders: { + 'dae': function(meshRes, uri, options) { + const material = options.material; + const loader = new THREE.ColladaLoader(options.loader); + loader.log = function(message) { + if (meshRes.warnings) { + console.warn(message); + } + }; + loader.load( + uri, + function colladaReady(collada) { + // check for a scale factor in ColladaLoader2 + // add a texture to anything that is missing one + if(material !== null) { + collada.scene.traverse(function(child) { + if(child instanceof THREE.Mesh) { + if(child.material === undefined) { + child.material = material; + } + } + }); + } + + meshRes.add(collada.scene); + }, + /*onProgress=*/null, + MeshLoader.onError); + return loader; + }, + + 'obj': function(meshRes, uri, options) { + const material = options.material; + const loader = new THREE.OBJLoader(options.loader); + loader.log = function(message) { + if (meshRes.warnings) { + console.warn(message); + } + }; + + //Reload the mesh again after materials have been loaded + // @todo: this should be improved so that the file doesn't need to be + // reloaded however that would involve more changes within the OBJLoader. + function onMaterialsLoaded(loader, materials) { + loader. + setMaterials(materials). + load( + uri, + function OBJMaterialsReady(obj) { + // add the container group + meshRes.add(obj); + }, + null, + MeshLoader.onError); + } + + loader.load( + uri, + function OBJFileReady(obj) { + + const baseUri = THREE.LoaderUtils.extractUrlBase( uri ); + + if (obj.materialLibraries.length) { + // load the material libraries + const materialUri = obj.materialLibraries[0]; + new THREE.MTLLoader(options.loader).setPath(baseUri).load( + materialUri, + function(materials) { + materials.preload(); + onMaterialsLoaded(loader, materials); + }, + null, + MeshLoader.onError + ); + } else { + // add the container group + meshRes.add(obj); + } + + }, + /*onProgress=*/null, + MeshLoader.onError + ); + return loader; + }, + + 'stl': function(meshRes, uri, options) { + const material = options.material; + const loader = new THREE.STLLoader(options.loader); + { + loader.load(uri, + function ( geometry ) { + geometry.computeFaceNormals(); + var mesh; + if(material !== null) { + mesh = new THREE.Mesh( geometry, material ); + } else { + mesh = new THREE.Mesh( geometry, + new THREE.MeshBasicMaterial( { color: 0x999999 } ) ); + } + meshRes.add(mesh); + }, + /*onProgress=*/null, + MeshLoader.onError); + } + return loader; + } + + } + }; diff --git a/src-esm/models/MeshResource.js b/src-esm/models/MeshResource.js new file mode 100644 index 00000000..d6f91502 --- /dev/null +++ b/src-esm/models/MeshResource.js @@ -0,0 +1,51 @@ +import THREE from '../../shims/three/core.js'; + +import { MeshLoader } from './MeshLoader' + +/** + * @fileOverview + * @author Jihoon Lee - jihoonlee.in@gmail.com + * @author Russell Toris - rctoris@wpi.edu + */ + +export class MeshResource extends THREE.Object3D { + + /** + * A MeshResource is an THREE object that will load from a external mesh file. Currently loads + * Collada files. + * + * @constructor + * @param options - object with following keys: + * + * * path (optional) - the base path to the associated models that will be loaded + * * resource - the resource file name to load + * * material (optional) - the material to use for the object + * * warnings (optional) - if warnings should be printed + */ + constructor(options) { + super(); + var that = this; + options = options || {}; + var path = options.path || '/'; + var resource = options.resource; + var material = options.material || null; + this.warnings = options.warnings; + + + // check for a trailing '/' + if (path.substr(path.length - 1) !== '/') { + path += '/'; + } + + var uri = path + resource; + var fileType = uri.substr(-3).toLowerCase(); + + // check the type + var loaderFunc = MeshLoader.loaders[fileType]; + if (loaderFunc) { + loaderFunc(this, uri, options); + } else { + console.warn('Unsupported loader for file type: \'' + fileType + '\''); + } + }; +} diff --git a/src-esm/models/TriangleList.js b/src-esm/models/TriangleList.js new file mode 100644 index 00000000..0ccc3647 --- /dev/null +++ b/src-esm/models/TriangleList.js @@ -0,0 +1,82 @@ +import THREE from '../../shims/three/core.js'; + +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + */ + +export class TriangleList extends THREE.Object3D { + + /** + * A TriangleList is a THREE object that can be used to display a list of triangles as a geometry. + * + * @constructor + * @param options - object with following keys: + * + * * material (optional) - the material to use for the object + * * vertices - the array of vertices to use + * * colors - the associated array of colors to use + */ + constructor(options) { + options = options || {}; + var material = options.material || new THREE.MeshBasicMaterial(); + var vertices = options.vertices; + var colors = options.colors; + + super(); + + // set the material to be double sided + material.side = THREE.DoubleSide; + + // construct the geometry + var geometry = new THREE.Geometry(); + for (i = 0; i < vertices.length; i++) { + geometry.vertices.push(new THREE.Vector3(vertices[i].x, vertices[i].y, vertices[i].z)); + } + + // set the colors + var i, j; + if (colors.length === vertices.length) { + // use per-vertex color + for (i = 0; i < vertices.length; i += 3) { + var faceVert = new THREE.Face3(i, i + 1, i + 2); + for (j = i * 3; j < i * 3 + 3; i++) { + var color = new THREE.Color(); + color.setRGB(colors[i].r, colors[i].g, colors[i].b); + faceVert.vertexColors.push(color); + } + geometry.faces.push(faceVert); + } + material.vertexColors = THREE.VertexColors; + } else if (colors.length === vertices.length / 3) { + // use per-triangle color + for (i = 0; i < vertices.length; i += 3) { + var faceTri = new THREE.Face3(i, i + 1, i + 2); + faceTri.color.setRGB(colors[i / 3].r, colors[i / 3].g, colors[i / 3].b); + geometry.faces.push(faceTri); + } + material.vertexColors = THREE.FaceColors; + } else { + // use marker color + for (i = 0; i < vertices.length; i += 3) { + var face = new THREE.Face3(i, i + 1, i + 2); + geometry.faces.push(face); + } + } + + geometry.computeBoundingBox(); + geometry.computeBoundingSphere(); + geometry.computeFaceNormals(); + + this.add(new THREE.Mesh(geometry, material)); + }; + + /** + * Set the color of this object to the given hex value. + * + * @param hex - the hex value of the color to set + */ + setColor(hex) { + this.mesh.material.color.setHex(hex); + }; +} diff --git a/src-esm/navigation/ColorOcTree.js b/src-esm/navigation/ColorOcTree.js new file mode 100644 index 00000000..b3de341f --- /dev/null +++ b/src-esm/navigation/ColorOcTree.js @@ -0,0 +1,31 @@ +import { OcTree } from './OcTree' +import { OcTreeColorMode } from './OcTreeBase' + +export class ColorOcTree extends OcTree { + + /** + * @fileOverview + * @author Peter Sari - sari@photoneo.com + */ + + constructor(options) { + super(options); + this.useOwnColor = (typeof options.palette !== 'undefined') && options.colorMode === OcTreeColorMode.COLOR; + }; + + + _readNodeData(dataStream, node) { + node.value = dataStream.readFloat32(); // occupancy + node.color = { + r: dataStream.readUint8(), // red + g: dataStream.readUint8(), // green + b: dataStream.readUint8(), // blue + }; + + }; + + _obtainColor(node) { + if (!this.useOwnColor) { return OcTree.prototype._obtainColor.call(this, node); } + return node.color; + }; +} diff --git a/src-esm/navigation/OcTree.js b/src-esm/navigation/OcTree.js new file mode 100644 index 00000000..b808086a --- /dev/null +++ b/src-esm/navigation/OcTree.js @@ -0,0 +1,77 @@ +import THREE from '../../shims/three/core.js'; + +import { OcTreeBase, OcTreeColorMode } from './OcTreeBase' + +/** + * @fileOverview + * @author Peter Sari - sari@photoneo.com + */ + +export class OcTree extends OcTreeBase { + + /** + * Specilaization of BaseOcTree + * + * @constructor + * @param options - object with following keys: + * * inherited from BaseOctree + * * occupancyThreshold (optional) - threshold value that separates occupied and free voxels from each other. (Default: 0) + * * colorMode (optional) - Coloring mode @see ROS3D.OcTreeColorMode. + * * palette (optional) - Palette used for false-coloring (default: predefined palette) + * * paletteSclae (optional) - Scale of palette to represent a wider range of values (default: 1.) + */ + + constructor(options) { + super(options); + + this._defaultOccupiedValue = 1.; + this._defaultFreeValue = -1.; + + this.occupancyThreshold = (typeof options.occupancyThreshold !== 'undefined') ? options.occupancyThreshold : 0.0000001; + + this.useFlatColoring = (typeof options.colorMode !== 'undefined') && options.colorMode === OcTreeColorMode.SOLID; + + this.palette = (typeof options.palette !== 'undefined') ? options.palette.map(color => new THREE.Color(color)) : + [ + { r: 0, g: 0, b: 128, }, // dark blue (low) + { r: 0, g: 255, b: 0, }, // green + { r: 255, g: 255, b: 0, }, // yellow (mid) + { r: 255, g: 128, b: 0, }, // orange + { r: 255, g: 0, b: 0, } // red (high) + ]; + + this.paletteScale = (typeof options.paletteScale !== 'undefined') ? options.paletteScale : 1.; + }; + + + _readNodeData(dataStream, node) { + node.value = dataStream.readFloat32(); + }; + + _obtainColor(node) { + if (this.useFlatColoring) { + return this.color; + } + + // Use a simple sigmoid curve to fit values from -inf..inf into 0..1 range + const value = 1. / (1. + Math.exp(-node.value * this.paletteScale)) * this.palette.length; // Normalize + + const intVal = Math.trunc(value); + const fracVal = value - intVal; + + if (intVal < 0) { return this.palette[0]; } + if (intVal >= this.palette.length - 1) { return this.palette[this.palette.length - 1]; } + + // Simple lerp + return { + r: fracVal * this.palette[intVal].r + (1. - fracVal) * this.palette[intVal + 1].r, + g: fracVal * this.palette[intVal].g + (1. - fracVal) * this.palette[intVal + 1].g, + b: fracVal * this.palette[intVal].b + (1. - fracVal) * this.palette[intVal + 1].b, + }; + + }; + + _checkOccupied(node) { + return node.value >= this.occupancyThreshold; + }; +} diff --git a/src-esm/navigation/OcTreeBase.js b/src-esm/navigation/OcTreeBase.js new file mode 100644 index 00000000..78a48985 --- /dev/null +++ b/src-esm/navigation/OcTreeBase.js @@ -0,0 +1,567 @@ +import THREE from '../../shims/three/core.js'; + +import { OcTreeBaseNode } from './OcTreeBaseNode' + +/** + * @fileOverview + * @author Peter Sari - sari@photoneo.com + */ + +/** + * Toggles voxel visibility + * + * * `occupied` - only voxels that are above or equal to the occupation threshold are shown + * * `free` - only voxels that are below the occupation threshold are shown + * * `all` - all allocated voxels are shown + */ +export var OcTreeVoxelRenderMode = { + OCCUPIED: 'occupied', + FREE: 'free', + ALL: 'all', +}; + +/** + * Coloring modes for each voxel + * + * * 'solid' - voxels will have a single solid color set by the tree globally + * * 'occupancy' - voxels are false colored by their occupancy value. Fall back for `solid` if not available. + * * 'color' - voxels will colorized by their + */ +export var OcTreeColorMode = { + SOLID: 'solid', + OCCUPANCY: 'occupancy', + COLOR: 'color' +}; + +// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + +/** + Quick and dirty helper class + to read ArrayBuffer in a streamed data-like fashion with mixed types in it +*/ +function InStream(data, isLittleEndian) { + this.buffer = data.buffer; + this.length = data.length; + this.isLittleEndian = (typeof isLittleEndian !== 'undefined') ? !!isLittleEndian : true; + this._dataView = new DataView(this.buffer); + this._cursor = 0; + + // Creates a set of wrapper functions for DataView + // also flattens all dependencies + [ + { kind: 'Int8', width: 1 }, + { kind: 'Uint8', width: 1 }, + { kind: 'Int16', width: 2 }, + { kind: 'Uint16', width: 2 }, + { kind: 'Int32', width: 4 }, + { kind: 'Uint32', width: 4 }, + { kind: 'BigInt64', width: 8 }, + { kind: 'BigUint64', width: 8 }, + { kind: 'Float32', width: 4 }, + { kind: 'Float64', width: 8 }, + ] + .forEach(wrap => { + const interfaceFunction = 'read' + wrap.kind; + const wrappedFunction = 'get' + wrap.kind; // Function name which going to be wrapped from DataView + + this[interfaceFunction] = () => { + if (this._cursor + wrap.width > this.length) { throw new Error('Cannot read data stream. Overflow. Len=' + this.length + ' crsr=' + this._cursor); } + const returningValue = this._dataView[wrappedFunction](this._cursor, this.isLittleEndian); + this._cursor += wrap.width; + return returningValue; + }; + }); + + Object.defineProperty(this, 'isEnd', { get: () => this.cursor >= this.data.length }); + return this; +}; + +// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- + +export class OcTreeBase { + + /** + * Represensta a BaseTree that can be build from ros message and create a THREE node from it. + * Due a tree can be represented different ways in a message, this class is also a base class to + * represent specialized versions fo the ree. + * + * @constructor + * @param options - object with following keys: + * + * * resolution - the size of leaf nodes in meter + * * color - color of the visualized map (if solid coloring option was set) + * * voxelRenderMode - toggle between rendering modes @see ROS3D.OcTreeVoxelRenderMode + */ + constructor(options) { + + this.resolution = (typeof options.resolution !== 'undefined') ? options.resolution : 1.; + this.color = new THREE.Color((typeof options.color !== 'undefined') ? options.color : 'green'); + this.opacity = (typeof options.opacity !== 'undefined') ? options.opacity : 1.; + + this.voxelRenderMode = (typeof options.voxelRenderMode !== 'undefined') ? options.voxelRenderMode : OcTreeVoxelRenderMode.OCCUPIED; + + this._rootNode = null; + this._treeDepth = 16; + this._treeMaxKeyVal = 32768; + + this._BINARY_UNALLOCATED = 0b00; + this._BINARY_LEAF_FREE = 0b01; + this._BINARY_LEAF_OCCUPIED = 0b10; + this._BINARY_HAS_CHILDREN = 0b11; + + this._BINARY_CHILD_BUILD_TABLE = {}; + + this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_FREE] = function (child) { + child.value = this._defaultFreeValue; + }; + + this._BINARY_CHILD_BUILD_TABLE[this._BINARY_LEAF_OCCUPIED] = function (child) { + child.value = this._defaultOccupiedValue; + }; + + this._BINARY_CHILD_BUILD_TABLE[this._BINARY_HAS_CHILDREN] = function (child) { + child.value = null; + }; + + /** + * Table which we are building the geometry data from. + */ + this._FACES = [ + { // 0. left (x=0) + normal: [-1, 0, 0,], + vertices: [ + [0, 1, 0], + [0, 0, 0], + [0, 1, 1], + [0, 0, 1], + ], + childIndex: [ + 0b001, + 0b011, + 0b101, + 0b111 + ] + }, + { // 1. right (x=1) + normal: [1, 0, 0,], + vertices: [ + [1, 1, 1], + [1, 0, 1], + [1, 1, 0], + [1, 0, 0], + ], + + childIndex: [ + 0b000, + 0b010, + 0b100, + 0b110 + ] + }, + { // 2. bottom (y=0) + normal: [0, -1, 0,], + vertices: [ + [1, 0, 1], + [0, 0, 1], + [1, 0, 0], + [0, 0, 0], + ], + childIndex: [ + 0b010, + 0b011, + 0b110, + 0b111 + ] + }, + { // 3. top (y=1) + normal: [0, 1, 0,], + vertices: [ + [0, 1, 1], + [1, 1, 1], + [0, 1, 0], + [1, 1, 0], + ], + childIndex: [ + 0b000, + 0b001, + 0b100, + 0b101 + ] + }, + { // 4. back (z=0) + normal: [0, 0, -1,], + vertices: [ + [1, 0, 0], + [0, 0, 0], + [1, 1, 0], + [0, 1, 0], + ], + childIndex: [ + 0b100, + 0b101, + 0b110, + 0b111 + ] + }, + { // 5.front (z=1) + normal: [0, 0, 1,], + vertices: [ + [0, 0, 1], + [1, 0, 1], + [0, 1, 1], + [1, 1, 1], + ], + childIndex: [ + 0b000, + 0b001, + 0b010, + 0b011 + ] + }, + ]; + + // Table of voxel size for each level of the tree + this.nodeSizeTable = new Array(this._treeDepth); + let _val = this.resolution; + for (let i = this._treeDepth - 1; i >= 0; --i) { + this.nodeSizeTable[i] = _val; + _val = 2. * _val; + } + + this._defaultOccupiedValue = true; + this._defaultFreeValue = false; + + this.object = null; + }; + + + /* + * Finds a key in a given depth. Search is performed on the lowest level by default. + * @return the node at given position, null if not found + */ + searchAtDepth(key, depth) { + depth = (typeof depth !== 'undefined') ? (depth > 0 ? depth : this._treeDepth) : this._treeDepth; + + const keyAtDepth = this._adjustKeyAtDepth(key, depth); + const diff = this._treeDepth - depth; + let currentNode = this._rootNode; + + // follow nodes down to requested level (for diff = 0 it's the last level) + // Return the closest node, or null if not any + + for (let i = (this._treeDepth - 1); i >= diff; --i) { + const pos = this._computeChildIdx(keyAtDepth, i); + if (currentNode.hasChildAt(pos)) { + currentNode = currentNode.getChildAt(pos); + } else { + // we expected a child but did not get it + // is the current node a leaf already? + if (!currentNode.hasChildren()) { return currentNode; } + // it is not, search failed + return null; + } + } + + return currentNode; + + }; + + /** + * + */ + _computeCoordFromKey(key) { + return key.map(keyVal => this.resolution * (keyVal - this._treeMaxKeyVal)); + }; + + _computeChildIdx(key, depth) { + let pos = 0; + if (key[0] & (1 << depth)) { pos += 1; } + if (key[1] & (1 << depth)) { pos += 2; } + if (key[2] & (1 << depth)) { pos += 4; } + + return pos; + }; + + _computeKeyFromChildIdx(index, offset, depth) { + const diff = this._treeDepth - depth - 1; + + return [ + offset[0] + (!!(index & 1) << diff), + offset[1] + (!!(index & 2) << diff), + offset[2] + (!!(index & 4) << diff), + ]; + + }; + + _adjustKeyAtDepth(key, depth) { + // generate appropriate key_at_depth for queried depth + let diff = this._treeDepth - depth; + if (diff === 0) { return key; } + + return key.map(keyVal => (((keyVal - this._treeMaxKeyVal) >> diff) << diff) + (1 << (diff - 1)) + this._treeMaxKeyVal); + }; + + _newNode() { return new OcTreeBaseNode(); }; + + /* + * Reads and builds a tree which was represented in a binary form from a message + * Binary form only contains the tree structure to be allocated, all the data of voxels are stripped, + * occupation is represented as a binary value. + * Each node is represented as a 2-bit value which makes up the 8 child nodes of the parent (16 bits in total) + * starting with the root node. + */ + + readBinary(data) { + if (this._rootNode !== null) { + delete this._rootNode; + } + this._rootNode = this._newNode(); + + let dataStream = new InStream(data, true); + + let stack = new Array(); + stack.push(this._rootNode); + + while (stack.length > 0) { + let node = stack.pop(); + + // 2 bits per children, 16 bit total + const childAllocationMap = dataStream.readUint16(); + + // Insert all children and leaves + let index = 8; + while (index !== 0) { + --index; + const allocation = (childAllocationMap & (0b11 << (2 * index))) >> (2 * index); + + if (allocation !== this._BINARY_UNALLOCATED) { + let child = this._newNode(); + + const fn = this._BINARY_CHILD_BUILD_TABLE[allocation].bind(this); + fn(child); + + node.createChildNodeAt(child, index); + if (allocation === this._BINARY_HAS_CHILDREN) { stack.push(child); } + } + } + } + + }; + + /** + * Reads a full tree (with node data) from a message. + * A pacjet starts with the node data, followed by the allocation map of their children. + * Each type of tree has different data structure @see ROS3DJS.OcTreeBase._readNodeData + */ + read(data) { + if (this._rootNode !== null) { + delete this._rootNode; + } + + this._rootNode = this._newNode(); + + let dataStream = new InStream(data, true); + + let stack = new Array(); + stack.push(this._rootNode); + + while (stack.length > 0) { + let node = stack.pop(); + + // Data comes first + this._readNodeData(dataStream, node); + + const childAllocationMap = dataStream.readUint8(); + + // Insert all children and leaves + let index = 8; + while (index !== 0) { + --index; + const hasChild = childAllocationMap & (1 << index); + if (hasChild) { + let child = this._newNode(); + child.value = null; + node.createChildNodeAt(child, index); + stack.push(child); + } + } + } + + }; + + /** + * Abstract function; Reads and sets data of a node + */ + _readNodeData(dataStream, node) { + // This needs to be implemented by specialized tree + console.error('Not implemented'); + }; + + /** + * Builds up THREE.js geometry from tree data. + */ + buildGeometry() { + console.assert(this._rootNode !== null, 'No tree data'); + const { vertices, normals, colors, indices } = this._buildFaces(); + + const geometry = new THREE.BufferGeometry(); + + const material = new THREE.MeshBasicMaterial({ + color: 'white', + flatShading: true, + vertexColors: THREE.VertexColors, + transparent: this.opacity < 1.0, + opacity: this.opacity + }); + + geometry.addAttribute('position', new THREE.BufferAttribute(new Float32Array(vertices), 3)); + geometry.addAttribute('normal', new THREE.BufferAttribute(new Float32Array(normals), 3)); + geometry.addAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3)); + + geometry.setIndex(indices); + + const mesh = new THREE.Mesh(geometry, material); + this.object = new THREE.Object3D(); + this.object.add(mesh); + }; + + _traverseLeaves(callback) { + let stack = new Array(); + stack.push({ node: this._rootNode, depth: 0, key: [0, 0, 0] }); + + while (stack.length > 0) { + let current = stack.pop(); + if (current.node.isLeafNode()) { + callback(current.node, current.key, current.depth - 1); + } else { + for (let index = 0; index < 8; ++index) { + if (current.node.hasChildAt(index)) { + const key = this._computeKeyFromChildIdx(index, current.key, current.depth); + stack.push({ + node: current.node.getChildAt(index), + depth: current.depth + 1, + key + }); + } + } + } + } + }; + + /** + * Abstract function; to implement different coloring schemes + */ + _obtainColor(node) { + return this.color; + }; + + _checkOccupied(node) { + return node.value !== false; + }; + + _buildFaces() { + let geometry = { + vertices: [], + indices: [], + normals: [], + colors: [], + + _insertFace: function (face, pos, size, color) { + const indexCount = this.vertices.length / 3; + + face.vertices.forEach(function(vertex) { + this.vertices.push( + pos[0] + vertex[0] * size, + pos[1] + vertex[1] * size, + pos[2] + vertex[2] * size + ); + }); + + const colorArr = [color.r, color.g, color.b]; + + this.colors.push(...colorArr, ...colorArr, ...colorArr, ...colorArr); + this.normals.push(...face.normal, ...face.normal, ...face.normal, ...face.normal); + + this.indices.push( + indexCount, indexCount + 1, indexCount + 2, + indexCount + 2, indexCount + 1, indexCount + 3 + ); + }, + + _checkNeighborsTouchingFace: function (face, neighborNode, voxelRenderMode) { + // Finds if there's not a node at a given position, aka a 'hole' + let stack = new Array(); + stack.push(neighborNode); + while (stack.length !== 0) { + const node = stack.pop(); + if (node.hasChildren()) { + face.childIndex.forEach(function(childIndex) { + if (node.hasChildAt(childIndex)) { + const child = node.getChildAt(childIndex); + + // filter occupancy + const isOccupied = this._checkOccupied(node); + const isNeedsToRender = (isOccupied && voxelRenderMode === ROS3D.OcTreeVoxelRenderMode.OCCUPIED) || (!isOccupied && voxelRenderMode === OcTreeVoxelRenderMode.FREE); + + if (isNeedsToRender) { stack.push(child); } + } + else { + return true; + } + }); + } + } + return false; + } + + }; + + this._traverseLeaves((node, key, depth) => { + const pos = this._computeCoordFromKey(key); + const size = this.nodeSizeTable[depth]; + const diff = this._treeDepth - depth; + + const isOccupied = this._checkOccupied(node); + + // By default it will show ALL + // Hide free voxels if set + if (!isOccupied && this.voxelRenderMode === OcTreeVoxelRenderMode.OCCUPIED) { return; } + + // Hide occuped voxels if set. + if (isOccupied && this.voxelRenderMode === OcTreeVoxelRenderMode.FREE) { return; } + + this._FACES.forEach(function(face) { + // Add geometry where there is no neighbor voxel + const neighborKey = [ + key[0] + face.normal[0] * diff * diff, + key[1] + face.normal[1] * diff * diff, + key[2] + face.normal[2] * diff * diff, + ]; + const neighborNode = this.searchAtDepth(neighborKey); + if (neighborNode === null) { + // 1. Simply add geometry where there is no neighbors + geometry._insertFace(face, pos, size, this._obtainColor(node)); + } else if (depth < this._treeDepth) { + // 2. Special case, when a node (voxel) is not on the lowest level + // of the tree, but also need to add a geometry, because might + // not be "fully covered" by neighboring voxels on the lowest level + + if (geometry._checkNeighborsTouchingFace(face, neighborNode, this.voxelRenderMode)) { + geometry._insertFace(face, pos, size, this._obtainColor(node)); + } + } + + }); + + }); + + // return geometry; + return { + vertices: geometry.vertices, + normals: geometry.normals, + colors: geometry.colors, + indices: geometry.indices + }; + + }; +} diff --git a/src-esm/navigation/OcTreeBaseNode.js b/src-esm/navigation/OcTreeBaseNode.js new file mode 100644 index 00000000..6ed25ad0 --- /dev/null +++ b/src-esm/navigation/OcTreeBaseNode.js @@ -0,0 +1,42 @@ +/** + * @fileOverview + * @author Peter Sari - sari@photoneo.com + */ + +export class OcTreeBaseNode { + + /** + * Base node type that represents one voxel as a node of the tree + */ + + constructor() { + this._children = [null, null, null, null, null, null, null, null]; + this.value = null; + }; + + createChildNodeAt(newNode, index) { + this._children[index % 8] = newNode; + }; + + hasChildAt(index) { + return this._children[index % 8] !== null; + }; + + getChildAt(index) { + return this._children[index % 8]; + }; + + isLeafNode() { + for (let i = 0; i < 8; ++i) { + if (this._children[i] !== null) { return false; } + } + return true; + }; + + hasChildren() { + for (let i = 0; i < 8; ++i) { + if (this._children[i] !== null) { return true; } + } + return false; + }; +} diff --git a/src-esm/navigation/OcTreeClient.js b/src-esm/navigation/OcTreeClient.js new file mode 100644 index 00000000..7e282bbf --- /dev/null +++ b/src-esm/navigation/OcTreeClient.js @@ -0,0 +1,185 @@ +import EventEmitter2 from 'eventemitter2'; +import THREE from '../../shims/three/core.js'; +import * as ROSLIB from 'roslib'; + +import { OcTreeBase } from './OcTreeBase' +import { OcTree } from './OcTree' +import { ColorOcTree } from './ColorOcTree' +import { SceneNode } from '../visualization/SceneNode' + +/** + * @fileOverview + * @author Peter Sari - sari@photoneo.com + */ + +export class OcTreeClient extends EventEmitter2 { + + /** + * An OcTree client that listens to a given OcTree topic. + * + * Emits the following events: + * + * 'change' - there was an update or change in the marker + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic (optional) - the map topic to listen to + * * continuous (optional) - if the map should be continuously loaded (e.g., for SLAM) + * * tfClient (optional) - the TF client handle to use for a scene node + * * compression (optional) - message compression (default: 'cbor') + * * rootObject (optional) - the root object to add this marker to + * * offsetPose (optional) - offset pose of the mao visualization, e.g. for z-offset (ROSLIB.Pose type) + * * colorMode (optional)) - colorization mode for each voxels @see RORS3D.OcTreeColorMode (default 'color') + * * color (optional) - color of the visualized map (if solid coloring option was set). Can be any value accepted by THREE.Color + * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) + * * palette (optional) - list of RGB colors to be used as palette (THREE.Color) + * * paletteScale (optional) - scale favtor of palette to cover wider range of values. (default: 1) + * * voxelRenderMode (optional)- toggle between rendering modes @see ROS3D.OcTreeVoxelRenderMode. (default `occupid`) + * + */ + + constructor(options) { + super(); + options = options || {}; + this.ros = options.ros; + this.topicName = options.topic || '/octomap'; + this.compression = options.compression || 'cbor'; + this.continuous = options.continuous; + this.tfClient = options.tfClient; + this.rootObject = options.rootObject || new THREE.Object3D(); + this.offsetPose = options.offsetPose || new ROSLIB.Pose(); + + // Options passed to converter + this.options = {}; + + // Append only when it was set, otherwise defaults are provided by the underlying layer + if (typeof options.color !== 'undefined') { this.options['color'] = options.color; } + if (typeof options.opacity !== 'undefined') { this.options['opacity'] = options.opacity; } + if (typeof options.colorMode !== 'undefined') { this.options['colorMode'] = options.colorMode; } + if (typeof options.palette !== 'undefined') { this.options['palette'] = options.palette; } + if (typeof options.paletteScale !== 'undefined') { this.options['paletteScale'] = options.palette; } + if (typeof options.voxelRenderMode !== 'undefined') { this.options['voxelRenderMode'] = options.voxelRenderMode; } + + // current grid that is displayed + this.currentMap = null; + + // subscribe to the topic + this.rosTopic = undefined; + this.subscribe(); + }; + + + unsubscribe() { + if (this.rosTopic) { + this.rosTopic.unsubscribe(this.processMessage); + } + }; + + subscribe() { + this.unsubscribe(); + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros: this.ros, + name: this.topicName, + messageType: 'octomap_msgs/Octomap', + queue_length: 1, + compression: this.compression + }); + this.rosTopic.subscribe(this.processMessage.bind(this)); + }; + + processMessage(message) { + // check for an old map + if (this.currentMap) { + if (this.currentMap.tfClient) { + this.currentMap.unsubscribeTf(); + } + } + + this._processMessagePrivate(message); + + if (!this.continuous) { + this.rosTopic.unsubscribe(this.processMessage); + } + + }; + + + _loadOcTree(message) { + + return new Promise( + function (resolve, reject) { + + // 1. Create the corresponding octree object from message + const options = Object.assign({ + resolution: message.resolution, + }, this.options); + + let newOcTree = null; + { + if (message.binary) { + newOcTree = new OcTreeBase( + options + ); + newOcTree.readBinary(message.data); + } else { + + const ctorTable = { + 'OcTree': OcTree, + 'ColorOcTree': ColorOcTree, + }; + + if (message.id in ctorTable) { + console.log(message.id, ctorTable); + + newOcTree = new ctorTable[message.id]( + options + ); + + newOcTree.read(message.data); + } + + } + } + + + { + newOcTree.buildGeometry(); + } + + resolve(newOcTree); + }.bind(this)); + + }; + + _processMessagePrivate(message) { + let promise = this._loadOcTree(message); + + promise.then( + // 3. Replace geometry + function (newOcTree) { + // check if we care about the scene + const oldNode = this.sceneNode; + if (this.tfClient) { + this.currentMap = newOcTree; + this.sceneNode = new SceneNode({ + frameID: message.header.frame_id, + tfClient: this.tfClient, + object: newOcTree.object, + pose: this.offsetPose + }); + } else { + this.sceneNode = newOcTree.object; + this.currentMap = newOcTree; + } + + this.rootObject.remove(oldNode); + this.rootObject.add(this.sceneNode); + + this.emit('change'); + }.bind(this) + ); + }; +} diff --git a/src-esm/navigation/OccupancyGrid.js b/src-esm/navigation/OccupancyGrid.js new file mode 100644 index 00000000..edf14a6f --- /dev/null +++ b/src-esm/navigation/OccupancyGrid.js @@ -0,0 +1,131 @@ +import THREE from '../../shims/three/core.js'; + +/** + * @fileOverview + * @author Russell Toris - rctoris@wpi.edu + */ + +export class OccupancyGrid extends THREE.Mesh { + + /** + * An OccupancyGrid can convert a ROS occupancy grid message into a THREE object. + * + * @constructor + * @param options - object with following keys: + * + * * message - the occupancy grid message + * * color (optional) - color of the visualized grid + * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) + */ + constructor(options) { + options = options || {}; + var message = options.message; + var opacity = options.opacity || 1.0; + var color = options.color || {r:255,g:255,b:255,a:255}; + + // create the geometry + var info = message.info; + var origin = info.origin; + var width = info.width; + var height = info.height; + var geom = new THREE.PlaneBufferGeometry(width, height); + + // create the color material + var imageData = new Uint8Array(width * height * 4); + var texture = new THREE.DataTexture(imageData, width, height, THREE.RGBAFormat); + texture.flipY = true; + texture.minFilter = THREE.NearestFilter; + texture.magFilter = THREE.NearestFilter; + texture.needsUpdate = true; + + var material = new THREE.MeshBasicMaterial({ + map : texture, + transparent : opacity < 1.0, + opacity : opacity + }); + material.side = THREE.DoubleSide; + + // create the mesh + super(geom, material); + // move the map so the corner is at X, Y and correct orientation (informations from message.info) + + // assign options to this for subclasses + Object.assign(this, options); + + this.quaternion.copy(new THREE.Quaternion( + origin.orientation.x, + origin.orientation.y, + origin.orientation.z, + origin.orientation.w + )); + this.position.x = (width * info.resolution) / 2 + origin.position.x; + this.position.y = (height * info.resolution) / 2 + origin.position.y; + this.position.z = origin.position.z; + this.scale.x = info.resolution; + this.scale.y = info.resolution; + + var data = message.data; + // update the texture (after the the super call and this are accessible) + this.color = color; + this.material = material; + this.texture = texture; + + for ( var row = 0; row < height; row++) { + for ( var col = 0; col < width; col++) { + + // determine the index into the map data + var invRow = (height - row - 1); + var mapI = col + (invRow * width); + // determine the value + var val = this.getValue(mapI, invRow, col, data); + + // determine the color + var color = this.getColor(mapI, invRow, col, val); + + // determine the index into the image data array + var i = (col + (row * width)) * 4; + + // copy the color + imageData.set(color, i); + } + } + + texture.needsUpdate = true; + + }; + + dispose() { + this.material.dispose(); + this.texture.dispose(); + }; + + /** + * Returns the value for a given grid cell + * @param {int} index the current index of the cell + * @param {int} row the row of the cell + * @param {int} col the column of the cell + * @param {object} data the data buffer + */ + getValue(index, row, col, data) { + return data[index]; + }; + + /** + * Returns a color value given parameters of the position in the grid; the default implementation + * scales the default color value by the grid value. Subclasses can extend this functionality + * (e.g. lookup a color in a color map). + * @param {int} index the current index of the cell + * @param {int} row the row of the cell + * @param {int} col the column of the cell + * @param {float} value the value of the cell + * @returns r,g,b,a array of values from 0 to 255 representing the color values for each channel + */ + getColor(index, row, col, value) { + return [ + (value * this.color.r) / 255, + (value * this.color.g) / 255, + (value * this.color.b) / 255, + 255 + ]; + }; +} diff --git a/src-esm/navigation/OccupancyGridClient.js b/src-esm/navigation/OccupancyGridClient.js new file mode 100644 index 00000000..4166749a --- /dev/null +++ b/src-esm/navigation/OccupancyGridClient.js @@ -0,0 +1,123 @@ +import EventEmitter2 from 'eventemitter2'; +import THREE from '../../shims/three/core.js'; +import * as ROSLIB from 'roslib'; + +import { OccupancyGrid } from './OccupancyGrid' +import { SceneNode } from '../visualization/SceneNode' + +/** + * @fileOverview + * @author Russell Toris - rctoris@wpi.edu + */ + +export class OccupancyGridClient extends EventEmitter2 { + + /** + * An occupancy grid client that listens to a given map topic. + * + * Emits the following events: + * + * * 'change' - there was an update or change in the marker + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic (optional) - the map topic to listen to + * * continuous (optional) - if the map should be continuously loaded (e.g., for SLAM) + * * tfClient (optional) - the TF client handle to use for a scene node + * * compression (optional) - message compression (default: 'cbor') + * * rootObject (optional) - the root object to add this marker to + * * offsetPose (optional) - offset pose of the grid visualization, e.g. for z-offset (ROSLIB.Pose type) + * * color (optional) - color of the visualized grid + * * opacity (optional) - opacity of the visualized grid (0.0 == fully transparent, 1.0 == opaque) + */ + constructor(options) { + super(); + options = options || {}; + this.ros = options.ros; + this.topicName = options.topic || '/map'; + this.compression = options.compression || 'cbor'; + this.continuous = options.continuous; + this.tfClient = options.tfClient; + this.rootObject = options.rootObject || new THREE.Object3D(); + this.offsetPose = options.offsetPose || new ROSLIB.Pose(); + this.color = options.color || {r:255,g:255,b:255}; + this.opacity = options.opacity || 1.0; + + // current grid that is displayed + this.currentGrid = null; + + // subscribe to the topic + this.rosTopic = undefined; + this.subscribe(); + }; + + unsubscribe(){ + if(this.rosTopic){ + this.rosTopic.unsubscribe(this.processMessage); + } + }; + + subscribe(){ + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros : this.ros, + name : this.topicName, + messageType : 'nav_msgs/OccupancyGrid', + queue_length : 1, + compression : this.compression + }); + this.sceneNode = null; + this.rosTopic.subscribe(this.processMessage.bind(this)); + }; + + processMessage(message){ + // check for an old map + if (this.currentGrid) { + // check if it there is a tf client + if (this.tfClient) { + // grid is of type ROS3D.SceneNode + this.sceneNode.unsubscribeTf(); + this.sceneNode.remove(this.currentGrid); + } else { + this.rootObject.remove(this.currentGrid); + } + this.currentGrid.dispose(); + } + + var newGrid = new OccupancyGrid({ + message : message, + color : this.color, + opacity : this.opacity + }); + + // check if we care about the scene + if (this.tfClient) { + this.currentGrid = newGrid; + if (this.sceneNode === null) { + this.sceneNode = new SceneNode({ + frameID : message.header.frame_id, + tfClient : this.tfClient, + object : newGrid, + pose : this.offsetPose + }); + this.rootObject.add(this.sceneNode); + } else { + this.sceneNode.add(this.currentGrid); + } + } else { + this.sceneNode = this.currentGrid = newGrid; + this.rootObject.add(this.currentGrid); + } + + this.emit('change'); + + // check if we should unsubscribe + if (!this.continuous) { + this.rosTopic.unsubscribe(this.processMessage); + } + }; +} diff --git a/src-esm/navigation/Odometry.js b/src-esm/navigation/Odometry.js new file mode 100644 index 00000000..189edab1 --- /dev/null +++ b/src-esm/navigation/Odometry.js @@ -0,0 +1,93 @@ +import THREE from '../../shims/three/core.js'; +import * as ROSLIB from 'roslib'; + +import { Arrow } from '../models/Arrow' +import { SceneNode } from '../visualization/SceneNode' + +/** + * @fileOverview + * @author David V. Lu!! - davidvlu@gmail.com + */ + +export class Odometry extends THREE.Object3D { + + /** + * An Odometry client + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add this marker to + * * keep (optional) - number of markers to keep around (default: 1) + * * color (optional) - color for line (default: 0xcc00ff) + * * length (optional) - the length of the arrow (default: 1.0) + * * headLength (optional) - the head length of the arrow (default: 0.2) + * * shaftDiameter (optional) - the shaft diameter of the arrow (default: 0.05) + * * headDiameter (optional) - the head diameter of the arrow (default: 0.1) + */ + constructor(options) { + super(); + this.options = options || {}; + this.ros = options.ros; + this.topicName = options.topic || '/particlecloud'; + this.tfClient = options.tfClient; + this.color = options.color || 0xcc00ff; + this.length = options.length || 1.0; + this.rootObject = options.rootObject || new THREE.Object3D(); + this.keep = options.keep || 1; + + this.sns = []; + + this.rosTopic = undefined; + this.subscribe(); + }; + + + unsubscribe(){ + if(this.rosTopic){ + this.rosTopic.unsubscribe(this.processMessage); + } + }; + + subscribe(){ + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros : this.ros, + name : this.topicName, + queue_length : 1, + messageType : 'nav_msgs/Odometry' + }); + this.rosTopic.subscribe(this.processMessage.bind(this)); + }; + + processMessage(message){ + if(this.sns.length >= this.keep) { + this.sns[0].unsubscribeTf(); + this.rootObject.remove(this.sns[0]); + this.sns.shift(); + } + + this.options.origin = new THREE.Vector3( message.pose.pose.position.x, message.pose.pose.position.y, + message.pose.pose.position.z); + + var rot = new THREE.Quaternion(message.pose.pose.orientation.x, message.pose.pose.orientation.y, + message.pose.pose.orientation.z, message.pose.pose.orientation.w); + this.options.direction = new THREE.Vector3(1,0,0); + this.options.direction.applyQuaternion(rot); + this.options.material = new THREE.MeshBasicMaterial({color: this.color}); + var arrow = new Arrow(this.options); + + this.sns.push(new SceneNode({ + frameID : message.header.frame_id, + tfClient : this.tfClient, + object : arrow + })); + + this.rootObject.add(this.sns[ this.sns.length - 1]); + }; +} diff --git a/src-esm/navigation/Path.js b/src-esm/navigation/Path.js new file mode 100644 index 00000000..f38339bd --- /dev/null +++ b/src-esm/navigation/Path.js @@ -0,0 +1,86 @@ +import THREE from '../../shims/three/core.js'; +import * as ROSLIB from 'roslib'; + +import { SceneNode } from '../visualization/SceneNode' + +/** + * @fileOverview + * @author David V. Lu!! - davidvlu@gmail.com + */ + +export class Path extends THREE.Object3D { + + /** + * A Path client that listens to a given topic and displays a line connecting the poses. + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add this marker to + * * color (optional) - color for line (default: 0xcc00ff) + */ + constructor(options) { + super(); + options = options || {}; + this.ros = options.ros; + this.topicName = options.topic || '/path'; + this.tfClient = options.tfClient; + this.color = options.color || 0xcc00ff; + this.rootObject = options.rootObject || new THREE.Object3D(); + + this.sn = null; + this.line = null; + + this.rosTopic = undefined; + this.subscribe(); + }; + + + unsubscribe(){ + if(this.rosTopic){ + this.rosTopic.unsubscribe(this.processMessage); + } + }; + + subscribe(){ + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros : this.ros, + name : this.topicName, + queue_length : 1, + messageType : 'nav_msgs/Path' + }); + this.rosTopic.subscribe(this.processMessage.bind(this)); + }; + + processMessage(message){ + if(this.sn!==null){ + this.sn.unsubscribeTf(); + this.rootObject.remove(this.sn); + } + + var lineGeometry = new THREE.Geometry(); + for(var i=0; i= message.range_min && range <= message.range_max){ + var angle = message.angle_min + i * message.angle_increment; + this.points.positions.array[j++] = range * Math.cos(angle); + this.points.positions.array[j++] = range * Math.sin(angle); + this.points.positions.array[j++] = 0.0; + } + } + this.points.update(j/3); + }; +} diff --git a/src-esm/sensors/NavSatFix.js b/src-esm/sensors/NavSatFix.js new file mode 100644 index 00000000..8e206ff0 --- /dev/null +++ b/src-esm/sensors/NavSatFix.js @@ -0,0 +1,101 @@ +import THREE from '../../shims/three/core.js'; +import * as ROSLIB from 'roslib'; + +/** + * @fileOverview + * @author Mathieu Bredif - mathieu.bredif@ign.fr + */ + +export class NavSatFix extends THREE.Object3D { + + /** + * A NavSatFix client that listens to a given topic and displays a line connecting the gps fixes. + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the NavSatFix topic to listen to + * * rootObject (optional) - the root object to add the trajectory line and the gps marker to + * * object3d (optional) - the object3d to be translated by the gps position + * * material (optional) - THREE.js material or options passed to a THREE.LineBasicMaterial, such as : + * * material.color (optional) - color for line + * * material.linewidth (optional) - line width + * * altitudeNaN (optional) - default altitude when the message altitude is NaN (default: 0) + * * keep (optional) - number of gps fix points to keep (default: 100) + * * convert (optional) - conversion function from lon/lat/alt to THREE.Vector3 (default: passthrough) + */ + + constructor(options) { + + super(); + options = options || {}; + this.ros = options.ros; + this.topicName = options.topic || '/gps/fix'; + this.rootObject = options.rootObject || new THREE.Object3D(); + this.object3d = options.object3d || new THREE.Object3D(); + var material = options.material || {}; + this.altitudeNaN = options.altitudeNaN || 0; + this.keep = options.keep || 100; + this.convert = options.convert || function(lon,lat,alt) { return new THREE.Vector3(lon,lat,alt); }; + this.count = 0; + this.next1 = 0; + this.next2 = this.keep; + + this.geom = new THREE.BufferGeometry(); + this.vertices = new THREE.BufferAttribute(new Float32Array( 6 * this.keep ), 3 ); + this.geom.addAttribute( 'position', this.vertices); + this.material = material.isMaterial ? material : new THREE.LineBasicMaterial( material ); + this.line = new THREE.Line( this.geom, this.material ); + this.rootObject.add(this.object3d); + this.rootObject.add(this.line); + + this.rosTopic = undefined; + this.subscribe(); + }; + + + unsubscribe(){ + if(this.rosTopic){ + this.rosTopic.unsubscribe(this.processMessage); + } + }; + + subscribe(){ + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros : this.ros, + name : this.topicName, + queue_length : 1, + messageType : 'sensor_msgs/NavSatFix' + }); + + this.rosTopic.subscribe(this.processMessage.bind(this)); + }; + + processMessage(message){ + var altitude = isNaN(message.altitude) ? this.altitudeNaN : message.altitude; + var p = this.convert(message.longitude, message.latitude, altitude); + + // move the object3d to the gps position + this.object3d.position.copy(p); + this.object3d.updateMatrixWorld(true); + + // copy the position twice in the circular buffer + // the second half replicates the first to allow a single drawRange + this.vertices.array[3*this.next1 ] = p.x; + this.vertices.array[3*this.next1+1] = p.y; + this.vertices.array[3*this.next1+2] = p.z; + this.vertices.array[3*this.next2 ] = p.x; + this.vertices.array[3*this.next2+1] = p.y; + this.vertices.array[3*this.next2+2] = p.z; + this.vertices.needsUpdate = true; + + this.next1 = (this.next1+1) % this.keep; + this.next2 = this.next1 + this.keep; + this.count = Math.min(this.count+1, this.keep); + this.geom.setDrawRange(this.next2-this.count, this.count ); + }; +} diff --git a/src-esm/sensors/PointCloud2.js b/src-esm/sensors/PointCloud2.js new file mode 100644 index 00000000..d5016d58 --- /dev/null +++ b/src-esm/sensors/PointCloud2.js @@ -0,0 +1,144 @@ +import THREE from '../../shims/three/core.js'; +import * as ROSLIB from 'roslib'; + +import { Points } from './Points' + +/** + * @fileOverview + * @author David V. Lu!! - davidvlu@gmail.com + * @author Mathieu Bredif - mathieu.bredif@ign.fr + */ + +/** + * Decodes the base64-encoded array 'inbytes' into the array 'outbytes' + * until 'inbytes' is exhausted or 'outbytes' is filled. + * if 'record_size' is specified, records of length 'record_size' bytes + * are copied every other 'pointRatio' records. + * returns the number of decoded records + */ +function decode64(inbytes, outbytes, record_size, pointRatio) { + var x,b=0,l=0,j=0,L=inbytes.length,A=outbytes.length; + record_size = record_size || A; // default copies everything (no skipping) + pointRatio = pointRatio || 1; // default copies everything (no skipping) + var bitskip = (pointRatio-1) * record_size * 8; + for(x=0;x=8){ + l-=8; + outbytes[j++]=(b>>>l)&0xff; + if((j % record_size) === 0) { // skip records + // no optimization: for(var i=0;i=8) {l-=8;i+=8;}} + // first optimization: for(;l0){b=decode64.e[inbytes.charAt(x)];} + } + } + } + return Math.floor(j/record_size); +} +// initialize decoder with static lookup table 'e' +decode64.S='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; +decode64.e={}; +for(var i=0;i<64;i++){decode64.e[decode64.S.charAt(i)]=i;} + + +export class PointCloud2 extends THREE.Object3D { + + /** + * A PointCloud2 client that listens to a given topic and displays the points. + * + * @constructor + * @param options - object with following keys: + * + * * ros - the ROSLIB.Ros connection handle + * * topic - the marker topic to listen to (default: '/points') + * * tfClient - the TF client handle to use + * * compression (optional) - message compression (default: 'cbor') + * * rootObject (optional) - the root object to add this marker to use for the points. + * * max_pts (optional) - number of points to draw (default: 10000) + * * pointRatio (optional) - point subsampling ratio (default: 1, no subsampling) + * * messageRatio (optional) - message subsampling ratio (default: 1, no subsampling) + * * material (optional) - a material object or an option to construct a PointsMaterial. + * * colorsrc (optional) - the field to be used for coloring (default: 'rgb') + * * colormap (optional) - function that turns the colorsrc field value to a color + */ + constructor(options) { + super(); + options = options || {}; + this.ros = options.ros; + this.topicName = options.topic || '/points'; + this.throttle_rate = options.throttle_rate || null; + this.compression = options.compression || 'cbor'; + this.max_pts = options.max_pts || 10000; + this.points = new Points(options); + this.rosTopic = undefined; + this.buffer = null; + this.subscribe(); + }; + + + unsubscribe(){ + if(this.rosTopic){ + this.rosTopic.unsubscribe(this.processMessage); + } + }; + + subscribe(){ + this.unsubscribe(); + + // subscribe to the topic + this.rosTopic = new ROSLIB.Topic({ + ros : this.ros, + name : this.topicName, + messageType : 'sensor_msgs/PointCloud2', + throttle_rate : this.throttle_rate, + queue_length : 1, + compression: this.compression + }); + this.rosTopic.subscribe(this.processMessage.bind(this)); + }; + + processMessage(msg){ + if(!this.points.setup(msg.header.frame_id, msg.point_step, msg.fields)) { + return; + } + + var n, pointRatio = this.points.pointRatio; + var bufSz = this.max_pts * msg.point_step; + + if (msg.data.buffer) { + this.buffer = msg.data.slice(0, Math.min(msg.data.byteLength, bufSz)); + n = Math.min(msg.height*msg.width / pointRatio, this.points.positions.array.length / 3); + } else { + if (!this.buffer || this.buffer.byteLength < bufSz) { + this.buffer = new Uint8Array(bufSz); + } + n = decode64(msg.data, this.buffer, msg.point_step, pointRatio); + pointRatio = 1; + } + + var dv = new DataView(this.buffer.buffer); + var littleEndian = !msg.is_bigendian; + var x = this.points.fields.x.offset; + var y = this.points.fields.y.offset; + var z = this.points.fields.z.offset; + var base, color; + for(var i = 0; i < n; i++){ + base = i * pointRatio * msg.point_step; + this.points.positions.array[3*i ] = dv.getFloat32(base+x, littleEndian); + this.points.positions.array[3*i + 1] = dv.getFloat32(base+y, littleEndian); + this.points.positions.array[3*i + 2] = dv.getFloat32(base+z, littleEndian); + + if(this.points.colors){ + color = this.points.colormap(this.points.getColor(dv,base,littleEndian)); + this.points.colors.array[3*i ] = color.r; + this.points.colors.array[3*i + 1] = color.g; + this.points.colors.array[3*i + 2] = color.b; + } + } + this.points.update(n); + }; +} diff --git a/src-esm/sensors/Points.js b/src-esm/sensors/Points.js new file mode 100644 index 00000000..df45f687 --- /dev/null +++ b/src-esm/sensors/Points.js @@ -0,0 +1,124 @@ +import THREE from '../../shims/three/core.js'; + +import { SceneNode } from '../visualization/SceneNode' + +/** + * @fileOverview + * @author David V. Lu!! - davidvlu@gmail.com + * @author Mathieu Bredif - mathieu.bredif@ign.fr + */ + +export class Points extends THREE.Object3D { + + /** + * A set of points. Used by PointCloud2 and LaserScan. + * + * @constructor + * @param options - object with following keys: + * + * * tfClient - the TF client handle to use + * * rootObject (optional) - the root object to add this marker to use for the points. + * * max_pts (optional) - number of points to draw (default: 10000) + * * pointRatio (optional) - point subsampling ratio (default: 1, no subsampling) + * * messageRatio (optional) - message subsampling ratio (default: 1, no subsampling) + * * material (optional) - a material object or an option to construct a PointsMaterial. + * * colorsrc (optional) - the field to be used for coloring (default: 'rgb') + * * colormap (optional) - function that turns the colorsrc field value to a color + */ + constructor(options) { + super(); + options = options || {}; + this.tfClient = options.tfClient; + this.rootObject = options.rootObject || new THREE.Object3D(); + this.max_pts = options.max_pts || 10000; + this.pointRatio = options.pointRatio || 1; + this.messageRatio = options.messageRatio || 1; + this.messageCount = 0; + this.material = options.material || {}; + this.colorsrc = options.colorsrc; + this.colormap = options.colormap; + + if(('color' in options) || ('size' in options) || ('texture' in options)) { + console.warn( + 'toplevel "color", "size" and "texture" options are deprecated.' + + 'They should beprovided within a "material" option, e.g. : '+ + ' { tfClient, material : { color: mycolor, size: mysize, map: mytexture }, ... }' + ); + } + + this.sn = null; + }; + + + setup(frame, point_step, fields) + { + if(this.sn===null){ + // turn fields to a map + fields = fields || []; + this.fields = {}; + for(var i=0; i 0) { + target = intersections[0].object; + event3D.intersection = this.lastIntersection = intersections[0]; + } else { + target = this.fallbackTarget; + } + + // if the mouse moves from one object to another (or from/to the 'null' object), notify both + if (target !== this.lastTarget && domEvent.type.match(/mouse/)) { + + // Event Status. TODO: Make it as enum + // 0: Accepted + // 1: Failed + // 2: Continued + var eventStatus = this.notify(target, 'mouseover', event3D); + if (eventStatus === 0) { + this.notify(this.lastTarget, 'mouseout', event3D); + } else if(eventStatus === 1) { + // if target was null or no target has caught our event, fall back + target = this.fallbackTarget; + if (target !== this.lastTarget) { + this.notify(target, 'mouseover', event3D); + this.notify(this.lastTarget, 'mouseout', event3D); + } + } + } + + // if the finger moves from one object to another (or from/to the 'null' object), notify both + if (target !== this.lastTarget && domEvent.type.match(/touch/)) { + var toucheventAccepted = this.notify(target, domEvent.type, event3D); + if (toucheventAccepted) { + this.notify(this.lastTarget, 'touchleave', event3D); + this.notify(this.lastTarget, 'touchend', event3D); + } else { + // if target was null or no target has caught our event, fall back + target = this.fallbackTarget; + if (target !== this.lastTarget) { + this.notify(this.lastTarget, 'touchmove', event3D); + this.notify(this.lastTarget, 'touchend', event3D); + } + } + } + + // pass through event + this.notify(target, domEvent.type, event3D); + if (domEvent.type === 'mousedown' || domEvent.type === 'touchstart' || domEvent.type === 'touchmove') { + this.dragging = true; + } + this.lastTarget = target; + }; + + /** + * Notify the listener of the type of event that occurred. + * + * @param target - the target of the event + * @param type - the type of event that occurred + * @param event3D - the 3D mouse even information + * @returns if an event was canceled + */ + notify(target, type, event3D) { + // ensure the type is set + // + event3D.type = type; + + // make the event cancelable + event3D.cancelBubble = false; + event3D.continueBubble = false; + event3D.stopPropagation = function() { + event3D.cancelBubble = true; + }; + + // it hit the selectable object but don't highlight + event3D.continuePropagation = function () { + event3D.continueBubble = true; + }; + + // walk up graph until event is canceled or root node has been reached + event3D.currentTarget = target; + + while (event3D.currentTarget) { + // try to fire event on object + if (event3D.currentTarget.dispatchEvent + && event3D.currentTarget.dispatchEvent instanceof Function) { + event3D.currentTarget.dispatchEvent(event3D); + if (event3D.cancelBubble) { + this.dispatchEvent(event3D); + return 0; // Event Accepted + } + else if(event3D.continueBubble) { + return 2; // Event Continued + } + } + // walk up + event3D.currentTarget = event3D.currentTarget.parent; + } + + return 1; // Event Failed + }; +} diff --git a/src-esm/visualization/interaction/OrbitControls.js b/src-esm/visualization/interaction/OrbitControls.js new file mode 100644 index 00000000..a3b69d74 --- /dev/null +++ b/src-esm/visualization/interaction/OrbitControls.js @@ -0,0 +1,522 @@ +import THREE from '../../../shims/three/core.js'; + +import { Axes } from '../../models/Axes' + +/** + * @fileOverview + * @author David Gossow - dgossow@willowgarage.com + * @author Xueqiao Xu - xueqiaoxu@gmail.com + * @author Mr.doob - http://mrdoob.com + * @author AlteredQualia - http://alteredqualia.com + */ + +export class OrbitControls extends THREE.EventDispatcher { + + /** + * Behaves like THREE.OrbitControls, but uses right-handed coordinates and z as up vector. + * + * @constructor + * @param scene - the global scene to use + * @param camera - the camera to use + * @param userZoomSpeed (optional) - the speed for zooming + * @param userRotateSpeed (optional) - the speed for rotating + * @param autoRotate (optional) - if the orbit should auto rotate + * @param autoRotateSpeed (optional) - the speed for auto rotating + * @param displayPanAndZoomFrame - whether to display a frame when panning/zooming + * (defaults to true) + * @param lineTypePanAndZoomFrame - line type for the frame that is displayed when + * panning/zooming. Only has effect when + * displayPanAndZoomFrame is set to true. + */ + constructor(options) { + super(); + var that = this; + options = options || {}; + var scene = options.scene; + this.camera = options.camera; + this.center = new THREE.Vector3(); + this.userZoom = true; + this.userZoomSpeed = options.userZoomSpeed || 1.0; + this.userRotate = true; + this.userRotateSpeed = options.userRotateSpeed || 1.0; + this.autoRotate = options.autoRotate; + this.autoRotateSpeed = options.autoRotateSpeed || 2.0; + this.displayPanAndZoomFrame = (options.displayPanAndZoomFrame === undefined) ? + true : + !!options.displayPanAndZoomFrame; + this.lineTypePanAndZoomFrame = options.dashedPanAndZoomFrame || 'full'; + // In ROS, z is pointing upwards + this.camera.up = new THREE.Vector3(0, 0, 1); + + // internals + var pixelsPerRound = 1800; + var touchMoveThreshold = 10; + var rotateStart = new THREE.Vector2(); + var rotateEnd = new THREE.Vector2(); + var rotateDelta = new THREE.Vector2(); + var zoomStart = new THREE.Vector2(); + var zoomEnd = new THREE.Vector2(); + var zoomDelta = new THREE.Vector2(); + var moveStartCenter = new THREE.Vector3(); + var moveStartNormal = new THREE.Vector3(); + var moveStartPosition = new THREE.Vector3(); + var moveStartIntersection = new THREE.Vector3(); + var touchStartPosition = new Array(2); + var touchMoveVector = new Array(2); + this.phiDelta = 0; + this.thetaDelta = 0; + this.scale = 1; + this.lastPosition = new THREE.Vector3(); + // internal states + var STATE = { + NONE : -1, + ROTATE : 0, + ZOOM : 1, + MOVE : 2 + }; + var state = STATE.NONE; + + this.axes = new Axes({ + shaftRadius : 0.025, + headRadius : 0.07, + headLength : 0.2, + lineType: this.lineTypePanAndZoomFrame + }); + if (this.displayPanAndZoomFrame) { + // initially not visible + scene.add(this.axes); + this.axes.traverse(function(obj) { + obj.visible = false; + }); + } + + /** + * Handle the mousedown 3D event. + * + * @param event3D - the 3D event to handle + */ + function onMouseDown(event3D) { + var event = event3D.domEvent; + event.preventDefault(); + + switch (event.button) { + case 0: + state = STATE.ROTATE; + rotateStart.set(event.clientX, event.clientY); + break; + case 1: + state = STATE.MOVE; + + moveStartNormal = new THREE.Vector3(0, 0, 1); + var rMat = new THREE.Matrix4().extractRotation(this.camera.matrix); + moveStartNormal.applyMatrix4(rMat); + + moveStartCenter = that.center.clone(); + moveStartPosition = that.camera.position.clone(); + moveStartIntersection = intersectViewPlane(event3D.mouseRay, + moveStartCenter, + moveStartNormal); + break; + case 2: + state = STATE.ZOOM; + zoomStart.set(event.clientX, event.clientY); + break; + } + + this.showAxes(); + } + + /** + * Handle the mousemove 3D event. + * + * @param event3D - the 3D event to handle + */ + function onMouseMove(event3D) { + var event = event3D.domEvent; + if (state === STATE.ROTATE) { + + rotateEnd.set(event.clientX, event.clientY); + rotateDelta.subVectors(rotateEnd, rotateStart); + + that.rotateLeft(2 * Math.PI * rotateDelta.x / pixelsPerRound * that.userRotateSpeed); + that.rotateUp(2 * Math.PI * rotateDelta.y / pixelsPerRound * that.userRotateSpeed); + + rotateStart.copy(rotateEnd); + this.showAxes(); + } else if (state === STATE.ZOOM) { + zoomEnd.set(event.clientX, event.clientY); + zoomDelta.subVectors(zoomEnd, zoomStart); + + if (zoomDelta.y > 0) { + that.zoomIn(); + } else { + that.zoomOut(); + } + + zoomStart.copy(zoomEnd); + this.showAxes(); + + } else if (state === STATE.MOVE) { + var intersection = intersectViewPlane(event3D.mouseRay, that.center, moveStartNormal); + + if (!intersection) { + return; + } + + var delta = new THREE.Vector3().subVectors(moveStartIntersection.clone(), intersection + .clone()); + + that.center.addVectors(moveStartCenter.clone(), delta.clone()); + that.camera.position.addVectors(moveStartPosition.clone(), delta.clone()); + that.update(); + that.camera.updateMatrixWorld(); + this.showAxes(); + } + } + + /** + * Used to track the movement during camera movement. + * + * @param mouseRay - the mouse ray to intersect with + * @param planeOrigin - the origin of the plane + * @param planeNormal - the normal of the plane + * @returns the intersection + */ + function intersectViewPlane(mouseRay, planeOrigin, planeNormal) { + + var vector = new THREE.Vector3(); + var intersection = new THREE.Vector3(); + + vector.subVectors(planeOrigin, mouseRay.origin); + var dot = mouseRay.direction.dot(planeNormal); + + // bail if ray and plane are parallel + if (Math.abs(dot) < mouseRay.precision) { + return null; + } + + // calc distance to plane + var scalar = planeNormal.dot(vector) / dot; + + intersection = mouseRay.direction.clone().multiplyScalar(scalar); + return intersection; + } + + /** + * Handle the mouseup 3D event. + * + * @param event3D - the 3D event to handle + */ + function onMouseUp(event3D) { + if (!that.userRotate) { + return; + } + + state = STATE.NONE; + } + + /** + * Handle the mousewheel 3D event. + * + * @param event3D - the 3D event to handle + */ + function onMouseWheel(event3D) { + if (!that.userZoom) { + return; + } + + var event = event3D.domEvent; + // wheelDelta --> Chrome, detail --> Firefox + var delta; + if (typeof (event.wheelDelta) !== 'undefined') { + delta = event.wheelDelta; + } else { + delta = -event.detail; + } + if (delta > 0) { + that.zoomIn(); + } else { + that.zoomOut(); + } + + this.showAxes(); + } + + /** + * Handle the touchdown 3D event. + * + * @param event3D - the 3D event to handle + */ + function onTouchDown(event3D) { + var event = event3D.domEvent; + switch (event.touches.length) { + case 1: + state = STATE.ROTATE; + rotateStart.set(event.touches[0].pageX - window.scrollX, + event.touches[0].pageY - window.scrollY); + break; + case 2: + state = STATE.NONE; + /* ready for move */ + moveStartNormal = new THREE.Vector3(0, 0, 1); + var rMat = new THREE.Matrix4().extractRotation(this.camera.matrix); + moveStartNormal.applyMatrix4(rMat); + moveStartCenter = that.center.clone(); + moveStartPosition = that.camera.position.clone(); + moveStartIntersection = intersectViewPlane(event3D.mouseRay, + moveStartCenter, + moveStartNormal); + touchStartPosition[0] = new THREE.Vector2(event.touches[0].pageX, + event.touches[0].pageY); + touchStartPosition[1] = new THREE.Vector2(event.touches[1].pageX, + event.touches[1].pageY); + touchMoveVector[0] = new THREE.Vector2(0, 0); + touchMoveVector[1] = new THREE.Vector2(0, 0); + break; + } + + this.showAxes(); + + event.preventDefault(); + } + + /** + * Handle the touchmove 3D event. + * + * @param event3D - the 3D event to handle + */ + function onTouchMove(event3D) { + var event = event3D.domEvent; + if (state === STATE.ROTATE) { + + rotateEnd.set(event.touches[0].pageX - window.scrollX, event.touches[0].pageY - window.scrollY); + rotateDelta.subVectors(rotateEnd, rotateStart); + + that.rotateLeft(2 * Math.PI * rotateDelta.x / pixelsPerRound * that.userRotateSpeed); + that.rotateUp(2 * Math.PI * rotateDelta.y / pixelsPerRound * that.userRotateSpeed); + + rotateStart.copy(rotateEnd); + this.showAxes(); + } else { + touchMoveVector[0].set(touchStartPosition[0].x - event.touches[0].pageX, + touchStartPosition[0].y - event.touches[0].pageY); + touchMoveVector[1].set(touchStartPosition[1].x - event.touches[1].pageX, + touchStartPosition[1].y - event.touches[1].pageY); + if (touchMoveVector[0].lengthSq() > touchMoveThreshold && + touchMoveVector[1].lengthSq() > touchMoveThreshold) { + touchStartPosition[0].set(event.touches[0].pageX, + event.touches[0].pageY); + touchStartPosition[1].set(event.touches[1].pageX, + event.touches[1].pageY); + if (touchMoveVector[0].dot(touchMoveVector[1]) > 0 && + state !== STATE.ZOOM) { + state = STATE.MOVE; + } else if (touchMoveVector[0].dot(touchMoveVector[1]) < 0 && + state !== STATE.MOVE) { + state = STATE.ZOOM; + } + if (state === STATE.ZOOM) { + var tmpVector = new THREE.Vector2(); + tmpVector.subVectors(touchStartPosition[0], + touchStartPosition[1]); + if (touchMoveVector[0].dot(tmpVector) < 0 && + touchMoveVector[1].dot(tmpVector) > 0) { + that.zoomOut(); + } else if (touchMoveVector[0].dot(tmpVector) > 0 && + touchMoveVector[1].dot(tmpVector) < 0) { + that.zoomIn(); + } + } + } + if (state === STATE.MOVE) { + var intersection = intersectViewPlane(event3D.mouseRay, + that.center, + moveStartNormal); + if (!intersection) { + return; + } + var delta = new THREE.Vector3().subVectors(moveStartIntersection.clone(), + intersection.clone()); + that.center.addVectors(moveStartCenter.clone(), delta.clone()); + that.camera.position.addVectors(moveStartPosition.clone(), delta.clone()); + that.update(); + that.camera.updateMatrixWorld(); + } + + this.showAxes(); + + event.preventDefault(); + } + } + + function onTouchEnd(event3D) { + var event = event3D.domEvent; + if (event.touches.length === 1 && + state !== STATE.ROTATE) { + state = STATE.ROTATE; + rotateStart.set(event.touches[0].pageX - window.scrollX, + event.touches[0].pageY - window.scrollY); + } + else { + state = STATE.NONE; + } + } + + // add event listeners + this.addEventListener('mousedown', onMouseDown); + this.addEventListener('mouseup', onMouseUp); + this.addEventListener('mousemove', onMouseMove); + this.addEventListener('touchstart', onTouchDown); + this.addEventListener('touchmove', onTouchMove); + this.addEventListener('touchend', onTouchEnd); + // Chrome/Firefox have different events here + this.addEventListener('mousewheel', onMouseWheel); + this.addEventListener('DOMMouseScroll', onMouseWheel); + }; + + /** + * Display the main axes for 1 second. + */ + showAxes() { + var that = this; + + this.axes.traverse(function(obj) { + obj.visible = true; + }); + if (this.hideTimeout) { + clearTimeout(this.hideTimeout); + } + this.hideTimeout = setTimeout(function() { + that.axes.traverse(function(obj) { + obj.visible = false; + }); + that.hideTimeout = false; + }, 1000); + }; + + /** + * Rotate the camera to the left by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + rotateLeft(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.thetaDelta -= angle; + }; + + /** + * Rotate the camera to the right by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + rotateRight(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.thetaDelta += angle; + }; + + /** + * Rotate the camera up by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + rotateUp(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.phiDelta -= angle; + }; + + /** + * Rotate the camera down by the given angle. + * + * @param angle (optional) - the angle to rotate by + */ + rotateDown(angle) { + if (angle === undefined) { + angle = 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + } + this.phiDelta += angle; + }; + + /** + * Zoom in by the given scale. + * + * @param zoomScale (optional) - the scale to zoom in by + */ + zoomIn(zoomScale) { + if (zoomScale === undefined) { + zoomScale = Math.pow(0.95, this.userZoomSpeed); + } + this.scale /= zoomScale; + }; + + /** + * Zoom out by the given scale. + * + * @param zoomScale (optional) - the scale to zoom in by + */ + zoomOut(zoomScale) { + if (zoomScale === undefined) { + zoomScale = Math.pow(0.95, this.userZoomSpeed); + } + this.scale *= zoomScale; + }; + + /** + * Update the camera to the current settings. + */ + update() { + // x->y, y->z, z->x + var position = this.camera.position; + var offset = position.clone().sub(this.center); + + // angle from z-axis around y-axis + var theta = Math.atan2(offset.y, offset.x); + + // angle from y-axis + var phi = Math.atan2(Math.sqrt(offset.y * offset.y + offset.x * offset.x), offset.z); + + if (this.autoRotate) { + this.rotateLeft(2 * Math.PI / 60 / 60 * this.autoRotateSpeed); + } + + theta += this.thetaDelta; + phi += this.phiDelta; + + // restrict phi to be between EPS and PI-EPS + var eps = 0.000001; + phi = Math.max(eps, Math.min(Math.PI - eps, phi)); + + var radius = offset.length(); + offset.set( + radius * Math.sin(phi) * Math.cos(theta), + radius * Math.sin(phi) * Math.sin(theta), + radius * Math.cos(phi) + ); + offset.multiplyScalar(this.scale); + + position.copy(this.center).add(offset); + + this.camera.lookAt(this.center); + + radius = offset.length(); + this.axes.position.copy(this.center); + this.axes.scale.set(radius * 0.05, radius * 0.05, radius * 0.05); + this.axes.updateMatrixWorld(true); + + this.thetaDelta = 0; + this.phiDelta = 0; + this.scale = 1; + + if (this.lastPosition.distanceTo(this.camera.position) > 0) { + this.dispatchEvent({ + type : 'change' + }); + this.lastPosition.copy(this.camera.position); + } + }; +} From 97d64361001e2afb9520bf6b98cee7dc38f06be5 Mon Sep 17 00:00:00 2001 From: atobaruela-ibrobotics Date: Wed, 12 Jul 2023 12:48:13 +0200 Subject: [PATCH 5/5] Mas adaptaciones para intentar usar interactive markers --- build/ros3d.js | 15 +++-- examples/interactivemarkers.html | 7 ++- examples/intermarker.py | 96 ++++++++++++++++++++++++++++++++ examples/pyesfera.py | 2 +- examples/urdf.html | 2 +- 5 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 examples/intermarker.py diff --git a/build/ros3d.js b/build/ros3d.js index 4e67fa81..17012fb7 100644 --- a/build/ros3d.js +++ b/build/ros3d.js @@ -55207,8 +55207,10 @@ var ROS3D = (function (exports, ROSLIB) { this.updateTopic = new ROSLIB__namespace.Topic({ ros : this.ros, - name : topic + '/tunneled/update', - messageType : 'visualization_msgs/InteractiveMarkerUpdate', + // name : topic + '/tunneled/update', + // messageType : 'visualization_msgs/InteractiveMarkerUpdate', + name : topic + '/update', + messageType : 'visualization_msgs/msg/InteractiveMarkerUpdate', // compression : 'png' compression : 'cbor' }); @@ -55217,7 +55219,8 @@ var ROS3D = (function (exports, ROSLIB) { this.feedbackTopic = new ROSLIB__namespace.Topic({ ros : this.ros, name : topic + '/feedback', - messageType : 'visualization_msgs/InteractiveMarkerFeedback', + // messageType : 'visualization_msgs/InteractiveMarkerFeedback', + messageType : 'visualization_msgs/msg/InteractiveMarkerFeedback', // compression : 'png' compression : 'cbor' }); @@ -55225,8 +55228,10 @@ var ROS3D = (function (exports, ROSLIB) { this.initService = new ROSLIB__namespace.Service({ ros : this.ros, - name : topic + '/tunneled/get_init', - serviceType : 'demo_interactive_markers/GetInit' + // name : topic + '/tunneled/get_init', + // serviceType : 'demo_interactive_markers/GetInit' + name : topic + '/simple_marker/get_interactive_markers', + serviceType : 'visualization_msgs/srv/GetInteractiveMarkers' }); var request = new ROSLIB__namespace.ServiceRequest({}); this.initService.callService(request, this.processInit.bind(this)); diff --git a/examples/interactivemarkers.html b/examples/interactivemarkers.html index d3aa7983..b7ca2b51 100644 --- a/examples/interactivemarkers.html +++ b/examples/interactivemarkers.html @@ -15,7 +15,8 @@ function init() { // Connect to ROS. var ros = new ROSLIB.Ros({ - url : 'ws://localhost:9090' + url : 'ws://localhost:9090', + groovyCompatibility: false, }); // Create the main viewer. @@ -33,14 +34,14 @@ angularThres : 0.01, transThres : 0.01, rate : 10.0, - fixedFrame : '/rotating_frame' + fixedFrame : 'base_link' }); // Setup the marker client. var imClient = new ROS3D.InteractiveMarkerClient({ ros : ros, tfClient : tfClient, - topic : '/basic_controls', + topic : '/simple_marker', camera : viewer.camera, rootObject : viewer.selectableObjects }); diff --git a/examples/intermarker.py b/examples/intermarker.py new file mode 100644 index 00000000..66866a9b --- /dev/null +++ b/examples/intermarker.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2011, Willow Garage, Inc. +# All rights reserved. +# +# Software License Agreement (BSD License 2.0) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Willow Garage, Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. + +import sys + +from interactive_markers import InteractiveMarkerServer +import rclpy +from visualization_msgs.msg import InteractiveMarker +from visualization_msgs.msg import InteractiveMarkerControl +from visualization_msgs.msg import Marker + + +def processFeedback(feedback): + p = feedback.pose.position + print(f'{feedback.marker_name} is now at {p.x}, {p.y}, {p.z}') + + +if __name__ == '__main__': + rclpy.init(args=sys.argv) + node = rclpy.create_node('simple_marker') + + # create an interactive marker server on the namespace simple_marker + server = InteractiveMarkerServer(node, 'simple_marker') + + # create an interactive marker for our server + int_marker = InteractiveMarker() + int_marker.header.frame_id = 'base_link' + int_marker.name = 'my_marker' + int_marker.description = 'Simple 1-DOF Control' + + # create a grey box marker + box_marker = Marker() + box_marker.type = Marker.CUBE + box_marker.scale.x = 0.45 + box_marker.scale.y = 0.45 + box_marker.scale.z = 0.45 + box_marker.color.r = 0.0 + box_marker.color.g = 0.5 + box_marker.color.b = 0.5 + box_marker.color.a = 1.0 + + # create a non-interactive control which contains the box + box_control = InteractiveMarkerControl() + box_control.always_visible = True + box_control.markers.append(box_marker) + + # add the control to the interactive marker + int_marker.controls.append(box_control) + + # create a control which will move the box + # this control does not contain any markers, + # which will cause RViz to insert two arrows + rotate_control = InteractiveMarkerControl() + rotate_control.name = 'move_x' + rotate_control.interaction_mode = InteractiveMarkerControl.MOVE_AXIS + + # add the control to the interactive marker + int_marker.controls.append(rotate_control) + + # add the interactive marker to our collection & + # tell the server to call processFeedback() when feedback arrives for it + server.insert(int_marker, feedback_callback=processFeedback) + + # 'commit' changes and send to all clients + server.applyChanges() + + rclpy.spin(node) + server.shutdown() diff --git a/examples/pyesfera.py b/examples/pyesfera.py index b73124ef..09cde5b3 100644 --- a/examples/pyesfera.py +++ b/examples/pyesfera.py @@ -7,7 +7,7 @@ class MarkerPublisherNode(Node): def __init__(self): super().__init__('marker_publisher') self.publisher_ = self.create_publisher(Marker, '/visualization_marker', 10) - self.timer_ = self.create_timer(1.0, self.publish_marker) + self.timer_ = self.create_timer(10.0, self.publish_marker) self.get_logger().info('Marker Publisher Node has been started.') def publish_marker(self): diff --git a/examples/urdf.html b/examples/urdf.html index 365eb933..f999c807 100644 --- a/examples/urdf.html +++ b/examples/urdf.html @@ -45,7 +45,7 @@ var urdfClient = new ROS3D.UrdfClient({ ros : ros, tfClient : tfClient, - path : 'https://raw.githubusercontent.com/PR2/pr2_common/melodic-devel/', + path : '/home/atobaruela/Documentos/GitHub/holorobot_react/src/status/urdf/share/modelo_robot/urdf', rootObject : viewer.scene, }); }