Pārlūkot izejas kodu

Added MorphBlendMesh, MD2CharacterComplex and corresponding example.

alteredq 13 gadi atpakaļ
vecāks
revīzija
eb37f601b5

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 97 - 97
build/Three.js


+ 1 - 1
build/custom/ThreeCanvas.js

@@ -79,7 +79,7 @@ f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c);this
 -Math.abs(this.y):Math.abs(this.y);this.z=0>a.n21-a.n12?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x*=-1;this.y*=-1;this.z*=-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);0===a?this.w=this.z=
 this.y=this.x=0:(a=1/a,this.x*=a,this.y*=a,this.z*=a,this.w*=a);return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y=c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplyVector3:function(a,b){b||(b=
 a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,l=this.w,i=l*c+g*e-h*d,j=l*d+h*c-f*e,n=l*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=i*l+c*-f+j*-h-n*-g;b.y=j*l+c*-g+n*-f-i*-h;b.z=n*l+c*-h+i*-g-j*-f;return b}};
-THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;0>e?(c.w=-b.w,c.x=-b.x,c.y=-b.y,c.z=-b.z,e=-e):c.copy(b);if(1<=Math.abs(e))return c.w=a.w,c.x=a.x,c.y=a.y,c.z=a.z,c;var f=Math.acos(e),e=Math.sqrt(1-e*e);if(0.001>Math.abs(e))return c.w=0.5*(a.w+b.w),c.x=0.5*(a.x+b.x),c.y=0.5*(a.y+b.y),c.z=0.5*(a.z+b.z),c;b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(a){this.position=a||new THREE.Vector3};
+THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;0>e?(c.w=-b.w,c.x=-b.x,c.y=-b.y,c.z=-b.z,e=-e):c.copy(b);if(1<=Math.abs(e))return c.w=a.w,c.x=a.x,c.y=a.y,c.z=a.z,c;var f=Math.acos(e),e=Math.sqrt(1-e*e);if(0.0010>Math.abs(e))return c.w=0.5*(a.w+b.w),c.x=0.5*(a.x+b.x),c.y=0.5*(a.y+b.y),c.z=0.5*(a.z+b.z),c;b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(a){this.position=a||new THREE.Vector3};
 THREE.Vertex.prototype={constructor:THREE.Vertex,clone:function(){return new THREE.Vertex(this.position.clone())}};THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3};
 THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;for(b=0,c=this.vertexNormals.length;b<c;b++)a.vertexNormals[b]=this.vertexNormals[b].clone();for(b=0,c=this.vertexColors.length;b<c;b++)a.vertexColors[b]=this.vertexColors[b].clone();for(b=0,c=this.vertexTangents.length;b<c;b++)a.vertexTangents[b]=this.vertexTangents[b].clone();
 return a}};THREE.Face4=function(a,b,c,d,e,f,g){this.a=a;this.b=b;this.c=c;this.d=d;this.normal=e instanceof THREE.Vector3?e:new THREE.Vector3;this.vertexNormals=e instanceof Array?e:[];this.color=f instanceof THREE.Color?f:new THREE.Color;this.vertexColors=f instanceof Array?f:[];this.vertexTangents=[];this.materialIndex=g;this.centroid=new THREE.Vector3};

+ 1 - 1
build/custom/ThreeDOM.js

@@ -78,7 +78,7 @@ f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c);this
 -Math.abs(this.y):Math.abs(this.y);this.z=0>a.n21-a.n12?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x*=-1;this.y*=-1;this.z*=-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);0===a?this.w=this.z=
 this.y=this.x=0:(a=1/a,this.x*=a,this.y*=a,this.z*=a,this.w*=a);return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y=c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplyVector3:function(a,b){b||(b=
 a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,k=this.w,i=k*c+g*e-h*d,j=k*d+h*c-f*e,l=k*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=i*k+c*-f+j*-h-l*-g;b.y=j*k+c*-g+l*-f-i*-h;b.z=l*k+c*-h+i*-g-j*-f;return b}};
-THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;0>e?(c.w=-b.w,c.x=-b.x,c.y=-b.y,c.z=-b.z,e=-e):c.copy(b);if(1<=Math.abs(e))return c.w=a.w,c.x=a.x,c.y=a.y,c.z=a.z,c;var f=Math.acos(e),e=Math.sqrt(1-e*e);if(0.001>Math.abs(e))return c.w=0.5*(a.w+b.w),c.x=0.5*(a.x+b.x),c.y=0.5*(a.y+b.y),c.z=0.5*(a.z+b.z),c;b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(a){this.position=a||new THREE.Vector3};
+THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;0>e?(c.w=-b.w,c.x=-b.x,c.y=-b.y,c.z=-b.z,e=-e):c.copy(b);if(1<=Math.abs(e))return c.w=a.w,c.x=a.x,c.y=a.y,c.z=a.z,c;var f=Math.acos(e),e=Math.sqrt(1-e*e);if(0.0010>Math.abs(e))return c.w=0.5*(a.w+b.w),c.x=0.5*(a.x+b.x),c.y=0.5*(a.y+b.y),c.z=0.5*(a.z+b.z),c;b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(a){this.position=a||new THREE.Vector3};
 THREE.Vertex.prototype={constructor:THREE.Vertex,clone:function(){return new THREE.Vertex(this.position.clone())}};THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3};
 THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;for(b=0,c=this.vertexNormals.length;b<c;b++)a.vertexNormals[b]=this.vertexNormals[b].clone();for(b=0,c=this.vertexColors.length;b<c;b++)a.vertexColors[b]=this.vertexColors[b].clone();for(b=0,c=this.vertexTangents.length;b<c;b++)a.vertexTangents[b]=this.vertexTangents[b].clone();
 return a}};THREE.Face4=function(a,b,c,d,e,f,g){this.a=a;this.b=b;this.c=c;this.d=d;this.normal=e instanceof THREE.Vector3?e:new THREE.Vector3;this.vertexNormals=e instanceof Array?e:[];this.color=f instanceof THREE.Color?f:new THREE.Color;this.vertexColors=f instanceof Array?f:[];this.vertexTangents=[];this.materialIndex=g;this.centroid=new THREE.Vector3};

+ 30 - 22
build/custom/ThreeExtras.js

@@ -102,7 +102,7 @@ c)THREE.Quaternion.slerp(f,g,a.quaternion,d);else if("scl"===c)c=a.scale,c.x=f[0
 THREE.Animation.prototype.interpolateCatmullRom=function(a,b){var c=[],d=[],f,g,e,h,i,k;f=(a.length-1)*b;g=Math.floor(f);f-=g;c[0]=0===g?g:g-1;c[1]=g;c[2]=g>a.length-2?g:g+1;c[3]=g>a.length-3?g:g+2;g=a[c[0]];h=a[c[1]];i=a[c[2]];k=a[c[3]];c=f*f;e=f*c;d[0]=this.interpolate(g[0],h[0],i[0],k[0],f,c,e);d[1]=this.interpolate(g[1],h[1],i[1],k[1],f,c,e);d[2]=this.interpolate(g[2],h[2],i[2],k[2],f,c,e);return d};
 THREE.Animation.prototype.interpolate=function(a,b,c,d,f,g,e){a=0.5*(c-a);d=0.5*(d-b);return(2*(b-c)+a+d)*e+(-3*(b-c)-2*a-d)*g+a*f+b};THREE.Animation.prototype.getNextKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?c<d.length-1?c:d.length-1:c%d.length;c<d.length;c++)if(void 0!==d[c][a])return d[c];return this.data.hierarchy[b].keys[0]};
 THREE.Animation.prototype.getPrevKeyWith=function(a,b,c){for(var d=this.data.hierarchy[b].keys,c=this.interpolationType===THREE.AnimationHandler.CATMULLROM||this.interpolationType===THREE.AnimationHandler.CATMULLROM_FORWARD?0<c?c:0:0<=c?c:c+d.length;0<=c;c--)if(void 0!==d[c][a])return d[c];return this.data.hierarchy[b].keys[d.length-1]};
-THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.001;this.isPlaying=!1;this.loop=this.isPaused=!0;this.JITCompile=void 0!==c?c:!0;a=0;for(b=this.hierarchy.length;a<b;a++){var c=this.data.hierarchy[a].sids,d=this.hierarchy[a];if(this.data.hierarchy[a].keys.length&&c){for(var f=0;f<c.length;f++){var g=c[f],e=this.getNextKeyWith(g,a,0);e&&e.apply(g)}d.matrixAutoUpdate=!1;this.data.hierarchy[a].node.updateMatrix();
+THREE.KeyFrameAnimation=function(a,b,c){this.root=a;this.data=THREE.AnimationHandler.get(b);this.hierarchy=THREE.AnimationHandler.parse(a);this.currentTime=0;this.timeScale=0.0010;this.isPlaying=!1;this.loop=this.isPaused=!0;this.JITCompile=void 0!==c?c:!0;a=0;for(b=this.hierarchy.length;a<b;a++){var c=this.data.hierarchy[a].sids,d=this.hierarchy[a];if(this.data.hierarchy[a].keys.length&&c){for(var f=0;f<c.length;f++){var g=c[f],e=this.getNextKeyWith(g,a,0);e&&e.apply(g)}d.matrixAutoUpdate=!1;this.data.hierarchy[a].node.updateMatrix();
 d.matrixWorldNeedsUpdate=!0}}};
 THREE.KeyFrameAnimation.prototype.play=function(a,b){if(!this.isPlaying){this.isPlaying=!0;this.loop=void 0!==a?a:!0;this.currentTime=void 0!==b?b:0;this.startTimeMs=b;this.startTime=1E7;this.endTime=-this.startTime;var c,d=this.hierarchy.length,f,g;for(c=0;c<d;c++){f=this.hierarchy[c];g=this.data.hierarchy[c];f.useQuaternion=!0;if(void 0===g.animationCache)g.animationCache={},g.animationCache.prevKey=null,g.animationCache.nextKey=null,g.animationCache.originalMatrix=f instanceof THREE.Bone?f.skinMatrix:
 f.matrix;f=this.data.hierarchy[c].keys;if(f.length)g.animationCache.prevKey=f[0],g.animationCache.nextKey=f[1],this.startTime=Math.min(f[0].time,this.startTime),this.endTime=Math.max(f[f.length-1].time,this.endTime)}this.update(0)}this.isPaused=!1;THREE.AnimationHandler.addToUpdate(this)};THREE.KeyFrameAnimation.prototype.pause=function(){this.isPaused?THREE.AnimationHandler.addToUpdate(this):THREE.AnimationHandler.removeFromUpdate(this);this.isPaused=!this.isPaused};
@@ -121,7 +121,7 @@ THREE.CombinedCamera.prototype.toOrthographic=function(){var a=this.cameraP.aspe
 THREE.CombinedCamera.prototype.setFov=function(a){this.fov=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};THREE.CombinedCamera.prototype.setLens=function(a,b){var c=2*Math.atan((void 0!==b?b:24)/(2*a))*(180/Math.PI);this.setFov(c);return c};THREE.CombinedCamera.prototype.setZoom=function(a){this.zoom=a;this.inPersepectiveMode?this.toPerspective():this.toOrthographic()};
 THREE.CombinedCamera.prototype.toFrontView=function(){this.rotation.x=0;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toBackView=function(){this.rotation.x=0;this.rotation.y=Math.PI;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toLeftView=function(){this.rotation.x=0;this.rotation.y=-Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=!1};
 THREE.CombinedCamera.prototype.toRightView=function(){this.rotation.x=0;this.rotation.y=Math.PI/2;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toTopView=function(){this.rotation.x=-Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=!1};THREE.CombinedCamera.prototype.toBottomView=function(){this.rotation.x=Math.PI/2;this.rotation.y=0;this.rotation.z=0;this.rotationAutoUpdate=!1};
-THREE.FirstPersonControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.target=new THREE.Vector3(0,0,0);this.domElement=void 0!==b?b:document;this.movementSpeed=1;this.lookSpeed=0.005;this.noFly=!1;this.lookVertical=!0;this.autoForward=!1;this.activeLook=!0;this.heightSpeed=!1;this.heightCoef=1;this.heightMin=0;this.constrainVertical=!1;this.verticalMin=0;this.verticalMax=Math.PI;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX=this.autoSpeedFactor=
+THREE.FirstPersonControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.target=new THREE.Vector3(0,0,0);this.domElement=void 0!==b?b:document;this.movementSpeed=1;this.lookSpeed=0.0050;this.noFly=!1;this.lookVertical=!0;this.autoForward=!1;this.activeLook=!0;this.heightSpeed=!1;this.heightCoef=1;this.heightMin=0;this.constrainVertical=!1;this.verticalMin=0;this.verticalMax=Math.PI;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX=this.autoSpeedFactor=
 0;this.mouseDragOn=this.freeze=this.moveRight=this.moveLeft=this.moveBackward=this.moveForward=!1;this.domElement===document?(this.viewHalfX=window.innerWidth/2,this.viewHalfY=window.innerHeight/2):(this.viewHalfX=this.domElement.offsetWidth/2,this.viewHalfY=this.domElement.offsetHeight/2,this.domElement.setAttribute("tabindex",-1));this.onMouseDown=function(a){this.domElement!==document&&this.domElement.focus();a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward=
 !0;break;case 2:this.moveBackward=!0}this.mouseDragOn=!0};this.onMouseUp=function(a){a.preventDefault();a.stopPropagation();if(this.activeLook)switch(a.button){case 0:this.moveForward=!1;break;case 2:this.moveBackward=!1}this.mouseDragOn=!1};this.onMouseMove=function(a){this.domElement===document?(this.mouseX=a.pageX-this.viewHalfX,this.mouseY=a.pageY-this.viewHalfY):(this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX,this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY)};this.onKeyDown=
 function(a){switch(a.keyCode){case 38:case 87:this.moveForward=!0;break;case 37:case 65:this.moveLeft=!0;break;case 40:case 83:this.moveBackward=!0;break;case 39:case 68:this.moveRight=!0;break;case 82:this.moveUp=!0;break;case 70:this.moveDown=!0;break;case 81:this.freeze=!this.freeze}};this.onKeyUp=function(a){switch(a.keyCode){case 38:case 87:this.moveForward=!1;break;case 37:case 65:this.moveLeft=!1;break;case 40:case 83:this.moveBackward=!1;break;case 39:case 68:this.moveRight=!1;break;case 82:this.moveUp=
@@ -131,14 +131,14 @@ this.moveUp&&this.object.translateY(b);this.moveDown&&this.object.translateY(-b)
 this.object.lookAt(b)}};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},!1);this.domElement.addEventListener("mousemove",c(this,this.onMouseMove),!1);this.domElement.addEventListener("mousedown",c(this,this.onMouseDown),!1);this.domElement.addEventListener("mouseup",c(this,this.onMouseUp),!1);this.domElement.addEventListener("keydown",c(this,this.onKeyDown),!1);this.domElement.addEventListener("keyup",c(this,this.onKeyUp),!1)};
 THREE.PathControls=function(a,b){function c(a){return 1>(a*=2)?0.5*a*a:-0.5*(--a*(a-2)-1)}function d(a,b){return function(){b.apply(a,arguments)}}function f(a,b,c,d){var e={name:c,fps:0.6,length:d,hierarchy:[]},f,g=b.getControlPointsArray(),h=b.getLength(),o=g.length,p=0;f=o-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:g[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[f]={time:d,pos:g[f],rot:[0,0,0,1],scl:[1,1,1]};for(f=1;f<o-1;f++)p=d*h.chunks[f]/h.total,b.keys[f]={time:p,pos:g[f]};e.hierarchy[0]=b;THREE.AnimationHandler.add(e);
 return new THREE.Animation(a,c,THREE.AnimationHandler.CATMULLROM_FORWARD,!1)}function g(a,b){var c,d,e=new THREE.Geometry;for(c=0;c<a.points.length*b;c++)d=c/(a.points.length*b),d=a.getPoint(d),e.vertices[c]=new THREE.Vertex(new THREE.Vector3(d.x,d.y,d.z));return e}this.object=a;this.domElement=void 0!==b?b:document;this.id="PathControls"+THREE.PathControlsIdCounter++;this.duration=1E4;this.waypoints=[];this.useConstantSpeed=!0;this.resamplingCoef=50;this.debugPath=new THREE.Object3D;this.debugDummy=
-new THREE.Object3D;this.animationParent=new THREE.Object3D;this.lookSpeed=0.005;this.lookHorizontal=this.lookVertical=!0;this.verticalAngleMap={srcRange:[0,2*Math.PI],dstRange:[0,2*Math.PI]};this.horizontalAngleMap={srcRange:[0,2*Math.PI],dstRange:[0,2*Math.PI]};this.target=new THREE.Object3D;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX=0;this.domElement===document?(this.viewHalfX=window.innerWidth/2,this.viewHalfY=window.innerHeight/2):(this.viewHalfX=this.domElement.offsetWidth/
+new THREE.Object3D;this.animationParent=new THREE.Object3D;this.lookSpeed=0.0050;this.lookHorizontal=this.lookVertical=!0;this.verticalAngleMap={srcRange:[0,2*Math.PI],dstRange:[0,2*Math.PI]};this.horizontalAngleMap={srcRange:[0,2*Math.PI],dstRange:[0,2*Math.PI]};this.target=new THREE.Object3D;this.theta=this.phi=this.lon=this.lat=this.mouseY=this.mouseX=0;this.domElement===document?(this.viewHalfX=window.innerWidth/2,this.viewHalfY=window.innerHeight/2):(this.viewHalfX=this.domElement.offsetWidth/
 2,this.viewHalfY=this.domElement.offsetHeight/2,this.domElement.setAttribute("tabindex",-1));var e=2*Math.PI,h=Math.PI/180;this.update=function(a){var b;this.lookHorizontal&&(this.lon+=this.mouseX*this.lookSpeed*a);this.lookVertical&&(this.lat-=this.mouseY*this.lookSpeed*a);this.lon=Math.max(0,Math.min(360,this.lon));this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*h;this.theta=this.lon*h;a=this.phi%e;this.phi=0<=a?a:a+e;b=this.verticalAngleMap.srcRange;a=this.verticalAngleMap.dstRange;
 b=THREE.Math.mapLinear(this.phi,b[0],b[1],a[0],a[1]);var d=a[1]-a[0];this.phi=c((b-a[0])/d)*d+a[0];b=this.horizontalAngleMap.srcRange;a=this.horizontalAngleMap.dstRange;b=THREE.Math.mapLinear(this.theta,b[0],b[1],a[0],a[1]);d=a[1]-a[0];this.theta=c((b-a[0])/d)*d+a[0];a=this.target.position;a.x=100*Math.sin(this.phi)*Math.cos(this.theta);a.y=100*Math.cos(this.phi);a.z=100*Math.sin(this.phi)*Math.sin(this.theta);this.object.lookAt(this.target.position)};this.onMouseMove=function(a){this.domElement===
 document?(this.mouseX=a.pageX-this.viewHalfX,this.mouseY=a.pageY-this.viewHalfY):(this.mouseX=a.pageX-this.domElement.offsetLeft-this.viewHalfX,this.mouseY=a.pageY-this.domElement.offsetTop-this.viewHalfY)};this.init=function(){this.spline=new THREE.Spline;this.spline.initFromArray(this.waypoints);this.useConstantSpeed&&this.spline.reparametrizeByArcLength(this.resamplingCoef);if(this.createDebugDummy){var a=new THREE.MeshLambertMaterial({color:30719}),b=new THREE.MeshLambertMaterial({color:65280}),
 c=new THREE.CubeGeometry(10,10,20),e=new THREE.CubeGeometry(2,2,10);this.animationParent=new THREE.Mesh(c,a);a=new THREE.Mesh(e,b);a.position.set(0,10,0);this.animation=f(this.animationParent,this.spline,this.id,this.duration);this.animationParent.add(this.object);this.animationParent.add(this.target);this.animationParent.add(a)}else this.animation=f(this.animationParent,this.spline,this.id,this.duration),this.animationParent.add(this.target),this.animationParent.add(this.object);if(this.createDebugPath){var a=
 this.debugPath,b=this.spline,e=g(b,10),c=g(b,10),h=new THREE.LineBasicMaterial({color:16711680,linewidth:3}),e=new THREE.Line(e,h),c=new THREE.ParticleSystem(c,new THREE.ParticleBasicMaterial({color:16755200,size:3}));e.scale.set(1,1,1);a.add(e);c.scale.set(1,1,1);a.add(c);for(var e=new THREE.SphereGeometry(1,16,8),h=new THREE.MeshBasicMaterial({color:65280}),n=0;n<b.points.length;n++)c=new THREE.Mesh(e,h),c.position.copy(b.points[n]),a.add(c)}this.domElement.addEventListener("mousemove",d(this,this.onMouseMove),
 !1)}};THREE.PathControlsIdCounter=0;
-THREE.FlyControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.domElement=void 0!==b?b:document;b&&this.domElement.setAttribute("tabindex",-1);this.movementSpeed=1;this.rollSpeed=0.005;this.autoForward=this.dragToLook=!1;this.object.useQuaternion=!0;this.tmpQuaternion=new THREE.Quaternion;this.mouseStatus=0;this.moveState={up:0,down:0,left:0,right:0,forward:0,back:0,pitchUp:0,pitchDown:0,yawLeft:0,yawRight:0,rollLeft:0,rollRight:0};this.moveVector=new THREE.Vector3(0,
+THREE.FlyControls=function(a,b){function c(a,b){return function(){b.apply(a,arguments)}}this.object=a;this.domElement=void 0!==b?b:document;b&&this.domElement.setAttribute("tabindex",-1);this.movementSpeed=1;this.rollSpeed=0.0050;this.autoForward=this.dragToLook=!1;this.object.useQuaternion=!0;this.tmpQuaternion=new THREE.Quaternion;this.mouseStatus=0;this.moveState={up:0,down:0,left:0,right:0,forward:0,back:0,pitchUp:0,pitchDown:0,yawLeft:0,yawRight:0,rollLeft:0,rollRight:0};this.moveVector=new THREE.Vector3(0,
 0,0);this.rotationVector=new THREE.Vector3(0,0,0);this.handleEvent=function(a){if("function"==typeof this[a.type])this[a.type](a)};this.keydown=function(a){if(!a.altKey){switch(a.keyCode){case 16:this.movementSpeedMultiplier=0.1;break;case 87:this.moveState.forward=1;break;case 83:this.moveState.back=1;break;case 65:this.moveState.left=1;break;case 68:this.moveState.right=1;break;case 82:this.moveState.up=1;break;case 70:this.moveState.down=1;break;case 38:this.moveState.pitchUp=1;break;case 40:this.moveState.pitchDown=
 1;break;case 37:this.moveState.yawLeft=1;break;case 39:this.moveState.yawRight=1;break;case 81:this.moveState.rollLeft=1;break;case 69:this.moveState.rollRight=1}this.updateMovementVector();this.updateRotationVector()}};this.keyup=function(a){switch(a.keyCode){case 16:this.movementSpeedMultiplier=1;break;case 87:this.moveState.forward=0;break;case 83:this.moveState.back=0;break;case 65:this.moveState.left=0;break;case 68:this.moveState.right=0;break;case 82:this.moveState.up=0;break;case 70:this.moveState.down=
 0;break;case 38:this.moveState.pitchUp=0;break;case 40:this.moveState.pitchDown=0;break;case 37:this.moveState.yawLeft=0;break;case 39:this.moveState.yawRight=0;break;case 81:this.moveState.rollLeft=0;break;case 69:this.moveState.rollRight=0}this.updateMovementVector();this.updateRotationVector()};this.mousedown=function(a){this.domElement!==document&&this.domElement.focus();a.preventDefault();a.stopPropagation();if(this.dragToLook)this.mouseStatus++;else switch(a.button){case 0:this.object.moveForward=
@@ -162,8 +162,8 @@ b.addSelf(c.object.up.clone().setLength(a.y));c.object.position.addSelf(b);c.tar
 c.noRotate||c.rotateCamera();c.noZoom||c.zoomCamera();c.noPan||c.panCamera();c.object.position.add(c.target,e);c.checkDistances();c.object.lookAt(c.target);0<d.distanceTo(c.object.position)&&(c.dispatchEvent(n),d.copy(c.object.position))};this.domElement.addEventListener("contextmenu",function(a){a.preventDefault()},!1);this.domElement.addEventListener("mousemove",function(a){c.enabled&&(f&&(h=i=c.getMouseProjectionOnBall(a.clientX,a.clientY),k=j=c.getMouseOnScreen(a.clientX,a.clientY),q=l=c.getMouseOnScreen(a.clientX,
 a.clientY),f=!1),-1!==g&&(0===g&&!c.noRotate?i=c.getMouseProjectionOnBall(a.clientX,a.clientY):1===g&&!c.noZoom?j=c.getMouseOnScreen(a.clientX,a.clientY):2===g&&!c.noPan&&(l=c.getMouseOnScreen(a.clientX,a.clientY))))},!1);this.domElement.addEventListener("mousedown",function(a){if(c.enabled&&(a.preventDefault(),a.stopPropagation(),-1===g))g=a.button,0===g&&!c.noRotate?h=i=c.getMouseProjectionOnBall(a.clientX,a.clientY):1===g&&!c.noZoom?k=j=c.getMouseOnScreen(a.clientX,a.clientY):this.noPan||(q=l=
 c.getMouseOnScreen(a.clientX,a.clientY))},!1);this.domElement.addEventListener("mouseup",function(a){c.enabled&&(a.preventDefault(),a.stopPropagation(),g=-1)},!1);window.addEventListener("keydown",function(a){c.enabled&&-1===g&&(a.keyCode===c.keys[0]&&!c.noRotate?g=0:a.keyCode===c.keys[1]&&!c.noZoom?g=1:a.keyCode===c.keys[2]&&!c.noPan&&(g=2),-1!==g&&(f=!0))},!1);window.addEventListener("keyup",function(){c.enabled&&-1!==g&&(g=-1)},!1)};
-THREE.CubeGeometry=function(a,b,c,d,f,g,e,h){function i(a,b,c,e,h,l,i,j){var m,n=d||1,q=f||1,r=h/2,p=l/2,o=k.vertices.length;if("x"===a&&"y"===b||"y"===a&&"x"===b)m="z";else if("x"===a&&"z"===b||"z"===a&&"x"===b)m="y",q=g||1;else if("z"===a&&"y"===b||"y"===a&&"z"===b)m="x",n=g||1;var s=n+1,t=q+1,B=h/n,M=l/q,L=new THREE.Vector3;L[m]=0<i?1:-1;for(h=0;h<t;h++)for(l=0;l<s;l++){var N=new THREE.Vector3;N[a]=(l*B-r)*c;N[b]=(h*M-p)*e;N[m]=i;k.vertices.push(new THREE.Vertex(N))}for(h=0;h<q;h++)for(l=0;l<n;l++)a=
-new THREE.Face4(l+s*h+o,l+s*(h+1)+o,l+1+s*(h+1)+o,l+1+s*h+o),a.normal.copy(L),a.vertexNormals.push(L.clone(),L.clone(),L.clone(),L.clone()),a.materialIndex=j,k.faces.push(a),k.faceVertexUvs[0].push([new THREE.UV(l/n,h/q),new THREE.UV(l/n,(h+1)/q),new THREE.UV((l+1)/n,(h+1)/q),new THREE.UV((l+1)/n,h/q)])}THREE.Geometry.call(this);var k=this,j=a/2,q=b/2,l=c/2,n,r,m,o,p,s;if(void 0!==e){if(e instanceof Array)this.materials=e;else{this.materials=[];for(n=0;6>n;n++)this.materials.push(e)}n=0;o=1;r=2;p=
+THREE.CubeGeometry=function(a,b,c,d,f,g,e,h){function i(a,b,c,e,h,i,l,j){var m,n=d||1,q=f||1,r=h/2,p=i/2,o=k.vertices.length;if("x"===a&&"y"===b||"y"===a&&"x"===b)m="z";else if("x"===a&&"z"===b||"z"===a&&"x"===b)m="y",q=g||1;else if("z"===a&&"y"===b||"y"===a&&"z"===b)m="x",n=g||1;var s=n+1,t=q+1,B=h/n,M=i/q,L=new THREE.Vector3;L[m]=0<l?1:-1;for(h=0;h<t;h++)for(i=0;i<s;i++){var N=new THREE.Vector3;N[a]=(i*B-r)*c;N[b]=(h*M-p)*e;N[m]=l;k.vertices.push(new THREE.Vertex(N))}for(h=0;h<q;h++)for(i=0;i<n;i++)a=
+new THREE.Face4(i+s*h+o,i+s*(h+1)+o,i+1+s*(h+1)+o,i+1+s*h+o),a.normal.copy(L),a.vertexNormals.push(L.clone(),L.clone(),L.clone(),L.clone()),a.materialIndex=j,k.faces.push(a),k.faceVertexUvs[0].push([new THREE.UV(i/n,h/q),new THREE.UV(i/n,(h+1)/q),new THREE.UV((i+1)/n,(h+1)/q),new THREE.UV((i+1)/n,h/q)])}THREE.Geometry.call(this);var k=this,j=a/2,q=b/2,l=c/2,n,r,m,o,p,s;if(void 0!==e){if(e instanceof Array)this.materials=e;else{this.materials=[];for(n=0;6>n;n++)this.materials.push(e)}n=0;o=1;r=2;p=
 3;m=4;s=5}else this.materials=[];this.sides={px:!0,nx:!0,py:!0,ny:!0,pz:!0,nz:!0};if(void 0!=h)for(var t in h)void 0!==this.sides[t]&&(this.sides[t]=h[t]);this.sides.px&&i("z","y",-1,-1,c,b,j,n);this.sides.nx&&i("z","y",1,-1,c,b,-j,o);this.sides.py&&i("x","z",1,1,a,c,q,r);this.sides.ny&&i("x","z",1,-1,a,c,-q,p);this.sides.pz&&i("x","y",1,-1,a,b,l,m);this.sides.nz&&i("x","y",-1,-1,a,b,-l,s);this.computeCentroids();this.mergeVertices()};THREE.CubeGeometry.prototype=new THREE.Geometry;
 THREE.CubeGeometry.prototype.constructor=THREE.CubeGeometry;
 THREE.CylinderGeometry=function(a,b,c,d,f,g){THREE.Geometry.call(this);var a=void 0!==a?a:20,b=void 0!==b?b:20,c=void 0!==c?c:100,e=c/2,d=d||8,f=f||1,h,i,k=[],j=[];for(i=0;i<=f;i++){var q=[],l=[],n=i/f,r=n*(b-a)+a;for(h=0;h<=d;h++){var m=h/d,o=r*Math.sin(2*m*Math.PI),p=-n*c+e,s=r*Math.cos(2*m*Math.PI);this.vertices.push(new THREE.Vertex(new THREE.Vector3(o,p,s)));q.push(this.vertices.length-1);l.push(new THREE.UV(m,n))}k.push(q);j.push(l)}for(i=0;i<f;i++)for(h=0;h<d;h++){var c=k[i][h],q=k[i+1][h],
@@ -171,16 +171,16 @@ l=k[i+1][h+1],n=k[i][h+1],r=this.vertices[c].position.clone().setY(0).normalize(
 0;h<d;h++)c=k[0][h],q=k[0][h+1],l=this.vertices.length-1,r=new THREE.Vector3(0,1,0),m=new THREE.Vector3(0,1,0),o=new THREE.Vector3(0,1,0),s=j[0][h].clone(),t=j[0][h+1].clone(),v=new THREE.UV(t.u,0),this.faces.push(new THREE.Face3(c,q,l,[r,m,o])),this.faceVertexUvs[0].push([s,t,v])}if(!g&&0<b){this.vertices.push(new THREE.Vertex(new THREE.Vector3(0,-e,0)));for(h=0;h<d;h++)c=k[i][h+1],q=k[i][h],l=this.vertices.length-1,r=new THREE.Vector3(0,-1,0),m=new THREE.Vector3(0,-1,0),o=new THREE.Vector3(0,-1,
 0),s=j[i][h+1].clone(),t=j[i][h].clone(),v=new THREE.UV(t.u,1),this.faces.push(new THREE.Face3(c,q,l,[r,m,o])),this.faceVertexUvs[0].push([s,t,v])}this.computeCentroids();this.computeFaceNormals()};THREE.CylinderGeometry.prototype=new THREE.Geometry;THREE.CylinderGeometry.prototype.constructor=THREE.CylinderGeometry;
 THREE.ExtrudeGeometry=function(a,b){if("undefined"!==typeof a){THREE.Geometry.call(this);var a=a instanceof Array?a:[a],c,d,f=a.length;this.shapebb=a[f-1].getBoundingBox();for(d=0;d<f;d++)c=a[d],this.addShape(c,b);this.computeCentroids();this.computeFaceNormals()}};THREE.ExtrudeGeometry.prototype=new THREE.Geometry;THREE.ExtrudeGeometry.prototype.constructor=THREE.ExtrudeGeometry;
-THREE.ExtrudeGeometry.prototype.addShape=function(a,b){function c(a,b,c){b||console.log("die");return b.clone().multiplyScalar(c).addSelf(a)}function d(a,b,c){var d=THREE.ExtrudeGeometry.__v1,e=THREE.ExtrudeGeometry.__v2,f=THREE.ExtrudeGeometry.__v3,g=THREE.ExtrudeGeometry.__v4,h=THREE.ExtrudeGeometry.__v5,l=THREE.ExtrudeGeometry.__v6;d.set(a.x-b.x,a.y-b.y);e.set(a.x-c.x,a.y-c.y);d=d.normalize();e=e.normalize();f.set(-d.y,d.x);g.set(e.y,-e.x);h.copy(a).addSelf(f);l.copy(a).addSelf(g);if(h.equals(l))return g.clone();
-h.copy(b).addSelf(f);l.copy(c).addSelf(g);f=d.dot(g);g=l.subSelf(h).dot(g);0===f&&(console.log("Either infinite or no solutions!"),0===g?console.log("Its finite solutions."):console.log("Too bad, no solutions."));g/=f;return 0>g?(b=Math.atan2(b.y-a.y,b.x-a.x),a=Math.atan2(c.y-a.y,c.x-a.x),b>a&&(a+=2*Math.PI),c=(b+a)/2,a=-Math.cos(c),c=-Math.sin(c),new THREE.Vector2(a,c)):d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function f(a){for(y=a.length;0<=--y;){K=y;B=y-1;0>B&&(B=a.length-1);for(var b=
-0,c=n+2*j,b=0;b<c;b++){var d=E*b,e=E*(b+1),f=O+K+d,g=O+B+d,h=O+B+e,l=O+K+e,f=f+A,g=g+A,h=h+A,l=l+A;x.faces.push(new THREE.Face4(f,g,h,l,null,null,v));var e=x.vertices[f].position.x,d=x.vertices[f].position.y,f=x.vertices[f].position.z,i=x.vertices[g].position.x,k=x.vertices[g].position.y,g=x.vertices[g].position.z,m=x.vertices[h].position.x,q=x.vertices[h].position.y,h=x.vertices[h].position.z,r=x.vertices[l].position.x,o=x.vertices[l].position.y,l=x.vertices[l].position.z;0.01>Math.abs(d-k)?x.faceVertexUvs[0].push([new THREE.UV(e,
-f),new THREE.UV(i,g),new THREE.UV(m,h),new THREE.UV(r,l)]):x.faceVertexUvs[0].push([new THREE.UV(d,f),new THREE.UV(k,g),new THREE.UV(q,h),new THREE.UV(o,l)])}}}function g(a,b,c){x.vertices.push(new THREE.Vertex(new THREE.Vector3(a,b,c)))}function e(a,b,c){a+=A;b+=A;c+=A;x.faces.push(new THREE.Face3(a,b,c,null,null,t));var d=x.vertices[b].position.x,b=x.vertices[b].position.y,e=x.vertices[c].position.x,c=x.vertices[c].position.y;x.faceVertexUvs[0].push([new THREE.UV(x.vertices[a].position.x,1-x.vertices[a].position.y),
+THREE.ExtrudeGeometry.prototype.addShape=function(a,b){function c(a,b,c){b||console.log("die");return b.clone().multiplyScalar(c).addSelf(a)}function d(a,b,c){var d=THREE.ExtrudeGeometry.__v1,e=THREE.ExtrudeGeometry.__v2,f=THREE.ExtrudeGeometry.__v3,g=THREE.ExtrudeGeometry.__v4,h=THREE.ExtrudeGeometry.__v5,i=THREE.ExtrudeGeometry.__v6;d.set(a.x-b.x,a.y-b.y);e.set(a.x-c.x,a.y-c.y);d=d.normalize();e=e.normalize();f.set(-d.y,d.x);g.set(e.y,-e.x);h.copy(a).addSelf(f);i.copy(a).addSelf(g);if(h.equals(i))return g.clone();
+h.copy(b).addSelf(f);i.copy(c).addSelf(g);f=d.dot(g);g=i.subSelf(h).dot(g);0===f&&(console.log("Either infinite or no solutions!"),0===g?console.log("Its finite solutions."):console.log("Too bad, no solutions."));g/=f;return 0>g?(b=Math.atan2(b.y-a.y,b.x-a.x),a=Math.atan2(c.y-a.y,c.x-a.x),b>a&&(a+=2*Math.PI),c=(b+a)/2,a=-Math.cos(c),c=-Math.sin(c),new THREE.Vector2(a,c)):d.multiplyScalar(g).addSelf(h).subSelf(a).clone()}function f(a){for(y=a.length;0<=--y;){K=y;B=y-1;0>B&&(B=a.length-1);for(var b=
+0,c=n+2*j,b=0;b<c;b++){var d=E*b,e=E*(b+1),f=O+K+d,g=O+B+d,h=O+B+e,i=O+K+e,f=f+A,g=g+A,h=h+A,i=i+A;x.faces.push(new THREE.Face4(f,g,h,i,null,null,v));var e=x.vertices[f].position.x,d=x.vertices[f].position.y,f=x.vertices[f].position.z,l=x.vertices[g].position.x,k=x.vertices[g].position.y,g=x.vertices[g].position.z,m=x.vertices[h].position.x,q=x.vertices[h].position.y,h=x.vertices[h].position.z,r=x.vertices[i].position.x,o=x.vertices[i].position.y,i=x.vertices[i].position.z;0.01>Math.abs(d-k)?x.faceVertexUvs[0].push([new THREE.UV(e,
+f),new THREE.UV(l,g),new THREE.UV(m,h),new THREE.UV(r,i)]):x.faceVertexUvs[0].push([new THREE.UV(d,f),new THREE.UV(k,g),new THREE.UV(q,h),new THREE.UV(o,i)])}}}function g(a,b,c){x.vertices.push(new THREE.Vertex(new THREE.Vector3(a,b,c)))}function e(a,b,c){a+=A;b+=A;c+=A;x.faces.push(new THREE.Face3(a,b,c,null,null,t));var d=x.vertices[b].position.x,b=x.vertices[b].position.y,e=x.vertices[c].position.x,c=x.vertices[c].position.y;x.faceVertexUvs[0].push([new THREE.UV(x.vertices[a].position.x,1-x.vertices[a].position.y),
 new THREE.UV(d,1-b),new THREE.UV(e,1-c)])}var h=void 0!==b.amount?b.amount:100,i=void 0!==b.bevelThickness?b.bevelThickness:6,k=void 0!==b.bevelSize?b.bevelSize:i-2,j=void 0!==b.bevelSegments?b.bevelSegments:3,q=void 0!==b.bevelEnabled?b.bevelEnabled:!0,l=void 0!==b.curveSegments?b.curveSegments:12,n=void 0!==b.steps?b.steps:1,r=b.bendPath,m=b.extrudePath,o,p=!1,s=void 0!==b.useSpacedPoints?b.useSpacedPoints:!1,t=b.material,v=b.extrudeMaterial;if(m)o=m.getPoints(l),n=o.length,p=!0,q=!1;q||(k=i=j=
 0);var u,w,z,x=this,A=this.vertices.length;r&&a.addWrapPath(r);l=s?a.extractAllSpacedPoints(l):a.extractAllPoints(l);r=l.shape;l=l.holes;if(m=!THREE.Shape.Utils.isClockWise(r)){r=r.reverse();for(w=0,z=l.length;w<z;w++)u=l[w],THREE.Shape.Utils.isClockWise(u)&&(l[w]=u.reverse());m=!1}m=THREE.Shape.Utils.triangulateShape(r,l);s=r;for(w=0,z=l.length;w<z;w++)u=l[w],r=r.concat(u);for(var D,G,J,F,E=r.length,C=m.length,H=[],y=0,I=s.length,K=I-1,B=y+1;y<I;y++,K++,B++)K===I&&(K=0),B===I&&(B=0),H[y]=d(s[y],
 s[K],s[B]);var M=[],L,N=H.concat();for(w=0,z=l.length;w<z;w++){u=l[w];L=[];for(y=0,I=u.length,K=I-1,B=y+1;y<I;y++,K++,B++)K===I&&(K=0),B===I&&(B=0),L[y]=d(u[y],u[K],u[B]);M.push(L);N=N.concat(L)}for(D=0;D<j;D++){G=D/j;J=i*(1-G);G=k*Math.sin(G*Math.PI/2);for(y=0,I=s.length;y<I;y++)F=c(s[y],H[y],G),g(F.x,F.y,-J);for(w=0,z=l.length;w<z;w++){u=l[w];L=M[w];for(y=0,I=u.length;y<I;y++)F=c(u[y],L[y],G),g(F.x,F.y,-J)}}G=k;for(y=0;y<E;y++)F=q?c(r[y],N[y],G):r[y],p?g(F.x,F.y+o[0].y,o[0].x):g(F.x,F.y,0);for(D=
 1;D<=n;D++)for(y=0;y<E;y++)F=q?c(r[y],N[y],G):r[y],p?g(F.x,F.y+o[D-1].y,o[D-1].x):g(F.x,F.y,h/n*D);for(D=j-1;0<=D;D--){G=D/j;J=i*(1-G);G=k*Math.sin(G*Math.PI/2);for(y=0,I=s.length;y<I;y++)F=c(s[y],H[y],G),g(F.x,F.y,h+J);for(w=0,z=l.length;w<z;w++){u=l[w];L=M[w];for(y=0,I=u.length;y<I;y++)F=c(u[y],L[y],G),p?g(F.x,F.y+o[n-1].y,o[n-1].x+J):g(F.x,F.y,h+J)}}if(q){i=0*E;for(y=0;y<C;y++)h=m[y],e(h[2]+i,h[1]+i,h[0]+i);i=E*(n+2*j);for(y=0;y<C;y++)h=m[y],e(h[0]+i,h[1]+i,h[2]+i)}else{for(y=0;y<C;y++)h=m[y],
 e(h[2],h[1],h[0]);for(y=0;y<C;y++)h=m[y],e(h[0]+E*n,h[1]+E*n,h[2]+E*n)}var O=0;f(s);O+=s.length;for(w=0,z=l.length;w<z;w++)u=l[w],f(u),O+=u.length};THREE.ExtrudeGeometry.__v1=new THREE.Vector2;THREE.ExtrudeGeometry.__v2=new THREE.Vector2;THREE.ExtrudeGeometry.__v3=new THREE.Vector2;THREE.ExtrudeGeometry.__v4=new THREE.Vector2;THREE.ExtrudeGeometry.__v5=new THREE.Vector2;THREE.ExtrudeGeometry.__v6=new THREE.Vector2;
-THREE.LatheGeometry=function(a,b,c){THREE.Geometry.call(this);this.steps=b||12;this.angle=c||2*Math.PI;for(var b=this.angle/this.steps,c=[],d=[],f=[],g=[],e=(new THREE.Matrix4).setRotationZ(b),h=0;h<a.length;h++)this.vertices.push(new THREE.Vertex(a[h])),c[h]=a[h].clone(),d[h]=this.vertices.length-1;for(var i=0;i<=this.angle+0.001;i+=b){for(h=0;h<c.length;h++)i<this.angle?(c[h]=e.multiplyVector3(c[h].clone()),this.vertices.push(new THREE.Vertex(c[h])),f[h]=this.vertices.length-1):f=g;0==i&&(g=d);
+THREE.LatheGeometry=function(a,b,c){THREE.Geometry.call(this);this.steps=b||12;this.angle=c||2*Math.PI;for(var b=this.angle/this.steps,c=[],d=[],f=[],g=[],e=(new THREE.Matrix4).setRotationZ(b),h=0;h<a.length;h++)this.vertices.push(new THREE.Vertex(a[h])),c[h]=a[h].clone(),d[h]=this.vertices.length-1;for(var i=0;i<=this.angle+0.0010;i+=b){for(h=0;h<c.length;h++)i<this.angle?(c[h]=e.multiplyVector3(c[h].clone()),this.vertices.push(new THREE.Vertex(c[h])),f[h]=this.vertices.length-1):f=g;0==i&&(g=d);
 for(h=0;h<d.length-1;h++)this.faces.push(new THREE.Face4(f[h],f[h+1],d[h+1],d[h])),this.faceVertexUvs[0].push([new THREE.UV(1-i/this.angle,h/a.length),new THREE.UV(1-i/this.angle,(h+1)/a.length),new THREE.UV(1-(i-b)/this.angle,(h+1)/a.length),new THREE.UV(1-(i-b)/this.angle,h/a.length)]);d=f;f=[]}this.computeCentroids();this.computeFaceNormals();this.computeVertexNormals()};THREE.LatheGeometry.prototype=new THREE.Geometry;THREE.LatheGeometry.prototype.constructor=THREE.LatheGeometry;
 THREE.PlaneGeometry=function(a,b,c,d){THREE.Geometry.call(this);for(var f=a/2,g=b/2,c=c||1,d=d||1,e=c+1,h=d+1,i=a/c,k=b/d,j=new THREE.Vector3(0,0,1),a=0;a<h;a++)for(b=0;b<e;b++)this.vertices.push(new THREE.Vertex(new THREE.Vector3(b*i-f,-(a*k-g),0)));for(a=0;a<d;a++)for(b=0;b<c;b++)f=new THREE.Face4(b+e*a,b+e*(a+1),b+1+e*(a+1),b+1+e*a),f.normal.copy(j),f.vertexNormals.push(j.clone(),j.clone(),j.clone(),j.clone()),this.faces.push(f),this.faceVertexUvs[0].push([new THREE.UV(b/c,a/d),new THREE.UV(b/
 c,(a+1)/d),new THREE.UV((b+1)/c,(a+1)/d),new THREE.UV((b+1)/c,a/d)]);this.computeCentroids()};THREE.PlaneGeometry.prototype=new THREE.Geometry;THREE.PlaneGeometry.prototype.constructor=THREE.PlaneGeometry;
@@ -237,11 +237,11 @@ THREE.BinaryLoader.prototype=new THREE.Loader;THREE.BinaryLoader.prototype.const
 THREE.BinaryLoader.prototype.loadAjaxJSON=function(a,b,c,d,f,g){var e=new XMLHttpRequest;e.onreadystatechange=function(){if(4==e.readyState)if(200==e.status||0==e.status){var h=JSON.parse(e.responseText);a.loadAjaxBuffers(h,c,f,d,g)}else console.error("THREE.BinaryLoader: Couldn't load ["+b+"] ["+e.status+"]")};e.open("GET",b,!0);e.overrideMimeType&&e.overrideMimeType("text/plain; charset=x-user-defined");e.setRequestHeader("Content-Type","text/plain");e.send(null)};
 THREE.BinaryLoader.prototype.loadAjaxBuffers=function(a,b,c,d,f){var g=new XMLHttpRequest,e=c+"/"+a.buffers,h=0;g.onreadystatechange=function(){4==g.readyState?200==g.status||0==g.status?THREE.BinaryLoader.prototype.createBinModel(g.response,b,d,a.materials):console.error("THREE.BinaryLoader: Couldn't load ["+e+"] ["+g.status+"]"):3==g.readyState?f&&(0==h&&(h=g.getResponseHeader("Content-Length")),f({total:h,loaded:g.responseText.length})):2==g.readyState&&(h=g.getResponseHeader("Content-Length"))};
 g.open("GET",e,!0);g.responseType="arraybuffer";g.send(null)};
-THREE.BinaryLoader.prototype.createBinModel=function(a,b,c,d){var f=function(b){var c,f,i,k,j,q,l,n,r,m,o,p,s,t,v;function u(a){return a%4?4-a%4:0}function w(a,b){return(new Uint8Array(a,b,1))[0]}function z(a,b){return(new Uint32Array(a,b,1))[0]}function x(b,c){var d,e,f,g,h,i,j,l,k=new Uint32Array(a,c,3*b);for(d=0;d<b;d++){e=k[3*d];f=k[3*d+1];g=k[3*d+2];h=y[2*e];e=y[2*e+1];i=y[2*f];j=y[2*f+1];f=y[2*g];l=y[2*g+1];g=E.faceVertexUvs[0];var m=[];m.push(new THREE.UV(h,e));m.push(new THREE.UV(i,j));m.push(new THREE.UV(f,
-l));g.push(m)}}function A(b,c){var d,e,f,g,h,i,j,l,k,m,n=new Uint32Array(a,c,4*b);for(d=0;d<b;d++){e=n[4*d];f=n[4*d+1];g=n[4*d+2];h=n[4*d+3];i=y[2*e];e=y[2*e+1];j=y[2*f];k=y[2*f+1];l=y[2*g];m=y[2*g+1];g=y[2*h];f=y[2*h+1];h=E.faceVertexUvs[0];var q=[];q.push(new THREE.UV(i,e));q.push(new THREE.UV(j,k));q.push(new THREE.UV(l,m));q.push(new THREE.UV(g,f));h.push(q)}}function D(b,c,d){for(var e,f,g,h,c=new Uint32Array(a,c,3*b),i=new Uint16Array(a,d,b),d=0;d<b;d++)e=c[3*d],f=c[3*d+1],g=c[3*d+2],h=i[d],
-E.faces.push(new THREE.Face3(e,f,g,null,null,h))}function G(b,c,d){for(var e,f,g,h,i,c=new Uint32Array(a,c,4*b),j=new Uint16Array(a,d,b),d=0;d<b;d++)e=c[4*d],f=c[4*d+1],g=c[4*d+2],h=c[4*d+3],i=j[d],E.faces.push(new THREE.Face4(e,f,g,h,null,null,i))}function J(b,c,d,e){for(var f,g,h,i,j,l,k,c=new Uint32Array(a,c,3*b),d=new Uint32Array(a,d,3*b),m=new Uint16Array(a,e,b),e=0;e<b;e++){f=c[3*e];g=c[3*e+1];h=c[3*e+2];j=d[3*e];l=d[3*e+1];k=d[3*e+2];i=m[e];var n=H[3*l],q=H[3*l+1];l=H[3*l+2];var o=H[3*k],p=
-H[3*k+1];k=H[3*k+2];E.faces.push(new THREE.Face3(f,g,h,[new THREE.Vector3(H[3*j],H[3*j+1],H[3*j+2]),new THREE.Vector3(n,q,l),new THREE.Vector3(o,p,k)],null,i))}}function F(b,c,d,e){for(var f,g,h,i,j,l,k,m,n,c=new Uint32Array(a,c,4*b),d=new Uint32Array(a,d,4*b),q=new Uint16Array(a,e,b),e=0;e<b;e++){f=c[4*e];g=c[4*e+1];h=c[4*e+2];i=c[4*e+3];l=d[4*e];k=d[4*e+1];m=d[4*e+2];n=d[4*e+3];j=q[e];var o=H[3*k],p=H[3*k+1];k=H[3*k+2];var r=H[3*m],s=H[3*m+1];m=H[3*m+2];var t=H[3*n],u=H[3*n+1];n=H[3*n+2];E.faces.push(new THREE.Face4(f,
-g,h,i,[new THREE.Vector3(H[3*l],H[3*l+1],H[3*l+2]),new THREE.Vector3(o,p,k),new THREE.Vector3(r,s,m),new THREE.Vector3(t,u,n)],null,j))}}var E=this,C=0,H=[],y=[],I,K,B;THREE.Geometry.call(this);THREE.Loader.prototype.initMaterials(E,d,b);(function(a,b,c){for(var a=new Uint8Array(a,b,c),d="",e=0;e<c;e++)d+=String.fromCharCode(a[b+e]);return d})(a,C,12);c=w(a,C+12);w(a,C+13);w(a,C+14);w(a,C+15);f=w(a,C+16);i=w(a,C+17);k=w(a,C+18);j=w(a,C+19);q=z(a,C+20);l=z(a,C+20+4);n=z(a,C+20+8);b=z(a,C+20+12);r=
+THREE.BinaryLoader.prototype.createBinModel=function(a,b,c,d){var f=function(b){var c,f,i,k,j,q,l,n,r,m,o,p,s,t,v;function u(a){return a%4?4-a%4:0}function w(a,b){return(new Uint8Array(a,b,1))[0]}function z(a,b){return(new Uint32Array(a,b,1))[0]}function x(b,c){var d,e,f,g,h,i,j,k,l=new Uint32Array(a,c,3*b);for(d=0;d<b;d++){e=l[3*d];f=l[3*d+1];g=l[3*d+2];h=y[2*e];e=y[2*e+1];i=y[2*f];j=y[2*f+1];f=y[2*g];k=y[2*g+1];g=E.faceVertexUvs[0];var m=[];m.push(new THREE.UV(h,e));m.push(new THREE.UV(i,j));m.push(new THREE.UV(f,
+k));g.push(m)}}function A(b,c){var d,e,f,g,h,i,j,k,l,m,n=new Uint32Array(a,c,4*b);for(d=0;d<b;d++){e=n[4*d];f=n[4*d+1];g=n[4*d+2];h=n[4*d+3];i=y[2*e];e=y[2*e+1];j=y[2*f];l=y[2*f+1];k=y[2*g];m=y[2*g+1];g=y[2*h];f=y[2*h+1];h=E.faceVertexUvs[0];var q=[];q.push(new THREE.UV(i,e));q.push(new THREE.UV(j,l));q.push(new THREE.UV(k,m));q.push(new THREE.UV(g,f));h.push(q)}}function D(b,c,d){for(var e,f,g,h,c=new Uint32Array(a,c,3*b),i=new Uint16Array(a,d,b),d=0;d<b;d++)e=c[3*d],f=c[3*d+1],g=c[3*d+2],h=i[d],
+E.faces.push(new THREE.Face3(e,f,g,null,null,h))}function G(b,c,d){for(var e,f,g,h,i,c=new Uint32Array(a,c,4*b),j=new Uint16Array(a,d,b),d=0;d<b;d++)e=c[4*d],f=c[4*d+1],g=c[4*d+2],h=c[4*d+3],i=j[d],E.faces.push(new THREE.Face4(e,f,g,h,null,null,i))}function J(b,c,d,e){for(var f,g,h,i,j,k,l,c=new Uint32Array(a,c,3*b),d=new Uint32Array(a,d,3*b),m=new Uint16Array(a,e,b),e=0;e<b;e++){f=c[3*e];g=c[3*e+1];h=c[3*e+2];j=d[3*e];k=d[3*e+1];l=d[3*e+2];i=m[e];var n=H[3*k],q=H[3*k+1];k=H[3*k+2];var o=H[3*l],p=
+H[3*l+1];l=H[3*l+2];E.faces.push(new THREE.Face3(f,g,h,[new THREE.Vector3(H[3*j],H[3*j+1],H[3*j+2]),new THREE.Vector3(n,q,k),new THREE.Vector3(o,p,l)],null,i))}}function F(b,c,d,e){for(var f,g,h,i,j,k,l,m,n,c=new Uint32Array(a,c,4*b),d=new Uint32Array(a,d,4*b),q=new Uint16Array(a,e,b),e=0;e<b;e++){f=c[4*e];g=c[4*e+1];h=c[4*e+2];i=c[4*e+3];k=d[4*e];l=d[4*e+1];m=d[4*e+2];n=d[4*e+3];j=q[e];var o=H[3*l],p=H[3*l+1];l=H[3*l+2];var r=H[3*m],s=H[3*m+1];m=H[3*m+2];var t=H[3*n],u=H[3*n+1];n=H[3*n+2];E.faces.push(new THREE.Face4(f,
+g,h,i,[new THREE.Vector3(H[3*k],H[3*k+1],H[3*k+2]),new THREE.Vector3(o,p,l),new THREE.Vector3(r,s,m),new THREE.Vector3(t,u,n)],null,j))}}var E=this,C=0,H=[],y=[],I,K,B;THREE.Geometry.call(this);THREE.Loader.prototype.initMaterials(E,d,b);(function(a,b,c){for(var a=new Uint8Array(a,b,c),d="",e=0;e<c;e++)d+=String.fromCharCode(a[b+e]);return d})(a,C,12);c=w(a,C+12);w(a,C+13);w(a,C+14);w(a,C+15);f=w(a,C+16);i=w(a,C+17);k=w(a,C+18);j=w(a,C+19);q=z(a,C+20);l=z(a,C+20+4);n=z(a,C+20+8);b=z(a,C+20+12);r=
 z(a,C+20+16);m=z(a,C+20+20);o=z(a,C+20+24);p=z(a,C+20+28);s=z(a,C+20+32);t=z(a,C+20+36);v=z(a,C+20+40);C+=c;c=3*f+j;B=4*f+j;I=b*c;K=r*(c+3*i);f=m*(c+3*k);j=o*(c+3*i+3*k);c=p*B;i=s*(B+4*i);k=t*(B+4*k);C+=function(b){var b=new Float32Array(a,b,3*q),c,d,e,f;for(c=0;c<q;c++)d=b[3*c],e=b[3*c+1],f=b[3*c+2],E.vertices.push(new THREE.Vertex(new THREE.Vector3(d,e,f)));return 3*q*Float32Array.BYTES_PER_ELEMENT}(C);C+=function(b){if(l){var b=new Int8Array(a,b,3*l),c,d,e,f;for(c=0;c<l;c++)d=b[3*c],e=b[3*c+1],
 f=b[3*c+2],H.push(d/127,e/127,f/127)}return 3*l*Int8Array.BYTES_PER_ELEMENT}(C);C+=u(3*l);C+=function(b){if(n){var b=new Float32Array(a,b,2*n),c,d,e;for(c=0;c<n;c++)d=b[2*c],e=b[2*c+1],y.push(d,e)}return 2*n*Float32Array.BYTES_PER_ELEMENT}(C);I=C+I+u(2*b);K=I+K+u(2*r);f=K+f+u(2*m);j=f+j+u(2*o);c=j+c+u(2*p);i=c+i+u(2*s);k=i+k+u(2*t);(function(a){if(m){var b=a+3*m*Uint32Array.BYTES_PER_ELEMENT;D(m,a,b+3*m*Uint32Array.BYTES_PER_ELEMENT);x(m,b)}})(K);(function(a){if(o){var b=a+3*o*Uint32Array.BYTES_PER_ELEMENT,
 c=b+3*o*Uint32Array.BYTES_PER_ELEMENT;J(o,a,b,c+3*o*Uint32Array.BYTES_PER_ELEMENT);x(o,c)}})(f);(function(a){if(t){var b=a+4*t*Uint32Array.BYTES_PER_ELEMENT;G(t,a,b+4*t*Uint32Array.BYTES_PER_ELEMENT);A(t,b)}})(i);(function(a){if(v){var b=a+4*v*Uint32Array.BYTES_PER_ELEMENT,c=b+4*v*Uint32Array.BYTES_PER_ELEMENT;F(v,a,b,c+4*v*Uint32Array.BYTES_PER_ELEMENT);A(v,c)}})(k);b&&D(b,C,C+3*b*Uint32Array.BYTES_PER_ELEMENT);(function(a){if(r){var b=a+3*r*Uint32Array.BYTES_PER_ELEMENT;J(r,a,b,b+3*r*Uint32Array.BYTES_PER_ELEMENT)}})(I);
@@ -255,8 +255,8 @@ scene:S}};d&&d(a);return a}function b(a,b,c){for(var a=Q.evaluate(a,Q,M,XPathRes
 for(c=0;c<e;c++){h=[];i=[];for(j=0;j<a.vertices.length;j++)i.push(new THREE.Vertex(new THREE.Vector3));d(b,h,c);j=h;k=f.skin;for(m=0;m<j.length;m++)if(l=j[m],n=-1,"JOINT"==l.type){for(var q=0;q<k.joints.length;q++)if(l.sid==k.joints[q]){n=q;break}if(0<=n){q=k.invBindMatrices[n];l.invBindMatrix=q;l.skinningMatrix=new THREE.Matrix4;l.skinningMatrix.multiply(l.world,q);l.weights=[];for(q=0;q<k.weights.length;q++)for(var o=0;o<k.weights[q].length;o++){var p=k.weights[q][o];p.joint==n&&l.weights.push(p)}}else throw"ColladaLoader: Could not find joint '"+
 l.sid+"'.";}for(j=0;j<h.length;j++)if("JOINT"==h[j].type)for(k=0;k<h[j].weights.length;k++)l=h[j].weights[k],m=l.index,l=l.weight,n=a.vertices[m],m=i[m],g.x=n.position.x,g.y=n.position.y,g.z=n.position.z,h[j].skinningMatrix.multiplyVector3(g),m.position.x+=g.x*l,m.position.y+=g.y*l,m.position.z+=g.z*l;a.morphTargets.push({name:"target_"+c,vertices:i})}}}function g(a){var b=new THREE.Object3D,c,d,e,h;for(e=0;e<a.controllers.length;e++){var i=T[a.controllers[e].url];switch(i.type){case "skin":if(U[i.skin.source]){var j=
 new m;j.url=i.skin.source;j.instance_material=a.controllers[e].instance_material;a.geometries.push(j);c=a.controllers[e]}else if(T[i.skin.source]&&(d=i=T[i.skin.source],i.morph&&U[i.morph.source]))j=new m,j.url=i.morph.source,j.instance_material=a.controllers[e].instance_material,a.geometries.push(j);break;case "morph":if(U[i.morph.source])j=new m,j.url=i.morph.source,j.instance_material=a.controllers[e].instance_material,a.geometries.push(j),d=a.controllers[e];console.log("ColladaLoader: Morph-controller partially supported.")}}for(e=
-0;e<a.geometries.length;e++){var i=a.geometries[e],j=i.instance_material,i=U[i.url],l={},k=[],q=0,o;if(i&&i.mesh&&i.mesh.primitives){if(0==b.name.length)b.name=i.id;if(j)for(h=0;h<j.length;h++){o=j[h];var p=fa[o.target],r=ga[p.instance_effect.url].shader;r.material.opacity=!r.material.opacity?1:r.material.opacity;l[o.symbol]=q;k.push(r.material);o=r.material;o.name=null==p.name||""===p.name?p.id:p.name;q++}j=o||new THREE.MeshLambertMaterial({color:14540253,shading:THREE.FlatShading});i=i.mesh.geometry3js;
-if(1<q){j=new THREE.MeshFaceMaterial;i.materials=k;for(h=0;h<i.faces.length;h++)k=i.faces[h],k.materialIndex=l[k.daeMaterial]}if(void 0!==c)f(i,c),j.morphTargets=!0,j=new THREE.SkinnedMesh(i,j),j.skeleton=c.skeleton,j.skinController=T[c.url],j.skinInstanceController=c,j.name="skin_"+ba.length,ba.push(j);else if(void 0!==d){h=i;l=d instanceof n?T[d.url]:d;if(!l||!l.morph)console.log("could not find morph controller!");else{l=l.morph;for(k=0;k<l.targets.length;k++)if(q=U[l.targets[k]],q.mesh&&q.mesh.primitives&&
+0;e<a.geometries.length;e++){var i=a.geometries[e],j=i.instance_material,i=U[i.url],k={},l=[],q=0,o;if(i&&i.mesh&&i.mesh.primitives){if(0==b.name.length)b.name=i.id;if(j)for(h=0;h<j.length;h++){o=j[h];var p=fa[o.target],r=ga[p.instance_effect.url].shader;r.material.opacity=!r.material.opacity?1:r.material.opacity;k[o.symbol]=q;l.push(r.material);o=r.material;o.name=null==p.name||""===p.name?p.id:p.name;q++}j=o||new THREE.MeshLambertMaterial({color:14540253,shading:THREE.FlatShading});i=i.mesh.geometry3js;
+if(1<q){j=new THREE.MeshFaceMaterial;i.materials=l;for(h=0;h<i.faces.length;h++)l=i.faces[h],l.materialIndex=k[l.daeMaterial]}if(void 0!==c)f(i,c),j.morphTargets=!0,j=new THREE.SkinnedMesh(i,j),j.skeleton=c.skeleton,j.skinController=T[c.url],j.skinInstanceController=c,j.name="skin_"+ba.length,ba.push(j);else if(void 0!==d){h=i;k=d instanceof n?T[d.url]:d;if(!k||!k.morph)console.log("could not find morph controller!");else{k=k.morph;for(l=0;l<k.targets.length;l++)if(q=U[k.targets[l]],q.mesh&&q.mesh.primitives&&
 q.mesh.primitives.length)q=q.mesh.primitives[0].geometry,q.vertices.length===h.vertices.length&&h.morphTargets.push({name:"target_1",vertices:q.vertices});h.morphTargets.push({name:"target_Z",vertices:h.vertices})}j.morphTargets=!0;j=new THREE.Mesh(i,j);j.name="morph_"+aa.length;aa.push(j)}else j=new THREE.Mesh(i,j);1<a.geometries.length?b.add(j):b=j}}for(e=0;e<a.cameras.length;e++)b=ha[a.cameras[e].url],b=new THREE.PerspectiveCamera(b.fov,b.aspect_ratio,b.znear,b.zfar);b.name=a.id||"";b.matrix=a.matrix;
 e=a.matrix.decompose();b.position=e[0];b.quaternion=e[1];b.useQuaternion=!0;b.scale=e[2];R.centerGeometry&&b.geometry&&(e=THREE.GeometryUtils.center(b.geometry),b.quaternion.multiplyVector3(e.multiplySelf(b.scale)),b.position.subSelf(e));for(e=0;e<a.nodes.length;e++)b.add(g(a.nodes[e],a));return b}function e(){this.init_from=this.id=""}function h(){this.type=this.name=this.id="";this.morph=this.skin=null}function i(){this.weights=this.targets=this.source=this.method=null}function k(){this.source=
 "";this.bindShapeMatrix=null;this.invBindMatrices=[];this.joints=[];this.weights=[]}function j(){this.name=this.id="";this.nodes=[];this.scene=new THREE.Object3D}function q(){this.sid=this.name=this.id="";this.nodes=[];this.controllers=[];this.transforms=[];this.geometries=[];this.channels=[];this.matrix=new THREE.Matrix4}function l(){this.type=this.sid="";this.data=[];this.obj=null}function n(){this.url="";this.skeleton=[];this.instance_material=[]}function r(){this.target=this.symbol=""}function m(){this.url=
@@ -270,8 +270,8 @@ R={centerGeometry:!1,convertUpAxis:!1,subdivideFaces:!0,upAxis:"Y"},$="Y",V=null
 this.type=c.nodeName;break;case "morph":this.morph=(new i).parse(c),this.type=c.nodeName}}return this};i.prototype.parse=function(a){var b={},c=[],d;this.method=a.getAttribute("method");this.source=a.getAttribute("source").replace(/^#/,"");for(d=0;d<a.childNodes.length;d++){var e=a.childNodes[d];if(1==e.nodeType)switch(e.nodeName){case "source":e=(new z).parse(e);b[e.id]=e;break;case "targets":c=this.parseInputs(e);break;default:console.log(e.nodeName)}}for(d=0;d<c.length;d++)switch(a=c[d],e=b[a.source],
 a.semantic){case "MORPH_TARGET":this.targets=e.read();break;case "MORPH_WEIGHT":this.weights=e.read()}return this};i.prototype.parseInputs=function(a){for(var b=[],c=0;c<a.childNodes.length;c++){var d=a.childNodes[c];if(1==d.nodeType)switch(d.nodeName){case "input":b.push((new w).parse(d))}}return b};k.prototype.parse=function(a){var b={},c,d;this.source=a.getAttribute("source").replace(/^#/,"");this.invBindMatrices=[];this.joints=[];this.weights=[];for(var e=0;e<a.childNodes.length;e++){var f=a.childNodes[e];
 if(1==f.nodeType)switch(f.nodeName){case "bind_shape_matrix":f=L(f.textContent);this.bindShapeMatrix=da(f);break;case "source":f=(new z).parse(f);b[f.id]=f;break;case "joints":c=f;break;case "vertex_weights":d=f;break;default:console.log(f.nodeName)}}this.parseJoints(c,b);this.parseWeights(d,b);return this};k.prototype.parseJoints=function(a,b){for(var c=0;c<a.childNodes.length;c++){var d=a.childNodes[c];if(1==d.nodeType)switch(d.nodeName){case "input":var d=(new w).parse(d),e=b[d.source];if("JOINT"==
-d.semantic)this.joints=e.read();else if("INV_BIND_MATRIX"==d.semantic)this.invBindMatrices=e.read()}}};k.prototype.parseWeights=function(a,b){for(var c,d,e=[],f=0;f<a.childNodes.length;f++){var g=a.childNodes[f];if(1==g.nodeType)switch(g.nodeName){case "input":e.push((new w).parse(g));break;case "v":c=N(g.textContent);break;case "vcount":d=N(g.textContent)}}for(f=g=0;f<d.length;f++){for(var h=d[f],i=[],j=0;j<h;j++){for(var l={},k=0;k<e.length;k++){var m=e[k],n=c[g+m.offset];switch(m.semantic){case "JOINT":l.joint=
-n;break;case "WEIGHT":l.weight=b[m.source].data[n]}}i.push(l);g+=e.length}for(j=0;j<i.length;j++)i[j].index=f;this.weights.push(i)}};j.prototype.getChildById=function(a,b){for(var c=0;c<this.nodes.length;c++){var d=this.nodes[c].getChildById(a,b);if(d)return d}return null};j.prototype.getChildBySid=function(a,b){for(var c=0;c<this.nodes.length;c++){var d=this.nodes[c].getChildBySid(a,b);if(d)return d}return null};j.prototype.parse=function(a){this.id=a.getAttribute("id");this.name=a.getAttribute("name");
+d.semantic)this.joints=e.read();else if("INV_BIND_MATRIX"==d.semantic)this.invBindMatrices=e.read()}}};k.prototype.parseWeights=function(a,b){for(var c,d,e=[],f=0;f<a.childNodes.length;f++){var g=a.childNodes[f];if(1==g.nodeType)switch(g.nodeName){case "input":e.push((new w).parse(g));break;case "v":c=N(g.textContent);break;case "vcount":d=N(g.textContent)}}for(f=g=0;f<d.length;f++){for(var h=d[f],i=[],j=0;j<h;j++){for(var k={},l=0;l<e.length;l++){var m=e[l],n=c[g+m.offset];switch(m.semantic){case "JOINT":k.joint=
+n;break;case "WEIGHT":k.weight=b[m.source].data[n]}}i.push(k);g+=e.length}for(j=0;j<i.length;j++)i[j].index=f;this.weights.push(i)}};j.prototype.getChildById=function(a,b){for(var c=0;c<this.nodes.length;c++){var d=this.nodes[c].getChildById(a,b);if(d)return d}return null};j.prototype.getChildBySid=function(a,b){for(var c=0;c<this.nodes.length;c++){var d=this.nodes[c].getChildBySid(a,b);if(d)return d}return null};j.prototype.parse=function(a){this.id=a.getAttribute("id");this.name=a.getAttribute("name");
 this.nodes=[];for(var b=0;b<a.childNodes.length;b++){var c=a.childNodes[b];if(1==c.nodeType)switch(c.nodeName){case "node":this.nodes.push((new q).parse(c))}}return this};q.prototype.getChannelForTransform=function(a){for(var b=0;b<this.channels.length;b++){var c=this.channels[b],d=c.target.split("/");d.shift();var e=d.shift(),f=0<=e.indexOf("."),g=0<=e.indexOf("("),h;if(f)d=e.split("."),e=d.shift(),d.shift();else if(g){h=e.split("(");e=h.shift();for(d=0;d<h.length;d++)h[d]=parseInt(h[d].replace(/\)/,
 ""))}if(e==a)return c.info={sid:e,dotSyntax:f,arrSyntax:g,arrIndices:h},c}return null};q.prototype.getChildById=function(a,b){if(this.id==a)return this;if(b)for(var c=0;c<this.nodes.length;c++){var d=this.nodes[c].getChildById(a,b);if(d)return d}return null};q.prototype.getChildBySid=function(a,b){if(this.sid==a)return this;if(b)for(var c=0;c<this.nodes.length;c++){var d=this.nodes[c].getChildBySid(a,b);if(d)return d}return null};q.prototype.getTransformBySid=function(a){for(var b=0;b<this.transforms.length;b++)if(this.transforms[b].sid==
 a)return this.transforms[b];return null};q.prototype.parse=function(a){var b;this.id=a.getAttribute("id");this.sid=a.getAttribute("sid");this.name=a.getAttribute("name");this.type=a.getAttribute("type");this.type="JOINT"==this.type?this.type:"NODE";this.nodes=[];this.transforms=[];this.geometries=[];this.cameras=[];this.controllers=[];this.matrix=new THREE.Matrix4;for(var c=0;c<a.childNodes.length;c++)if(b=a.childNodes[c],1==b.nodeType)switch(b.nodeName){case "node":this.nodes.push((new q).parse(b));
@@ -382,6 +382,14 @@ THREE.triTable=new Int32Array([-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0
 2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,3,8,9,1,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,9,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,3,8,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1]);THREE.LensFlare=function(a,b,c,d,f){THREE.Object3D.call(this);this.lensFlares=[];this.positionScreen=new THREE.Vector3;this.customUpdateCallback=void 0;void 0!==a&&this.add(a,b,c,d,f)};THREE.LensFlare.prototype=new THREE.Object3D;THREE.LensFlare.prototype.constructor=THREE.LensFlare;
 THREE.LensFlare.prototype.supr=THREE.Object3D.prototype;THREE.LensFlare.prototype.add=function(a,b,c,d,f,g){void 0===b&&(b=-1);void 0===c&&(c=0);void 0===g&&(g=1);void 0===f&&(f=new THREE.Color(16777215));if(void 0===d)d=THREE.NormalBlending;c=Math.min(c,Math.max(0,c));this.lensFlares.push({texture:a,size:b,distance:c,x:0,y:0,z:0,scale:1,rotation:1,opacity:g,color:f,blending:d})};
 THREE.LensFlare.prototype.updateLensFlares=function(){var a,b=this.lensFlares.length,c,d=2*-this.positionScreen.x,f=2*-this.positionScreen.y;for(a=0;a<b;a++)c=this.lensFlares[a],c.x=this.positionScreen.x+d*c.distance,c.y=this.positionScreen.y+f*c.distance,c.wantedRotation=0.25*c.x*Math.PI,c.rotation+=0.25*(c.wantedRotation-c.rotation)};
+THREE.MorphBlendMesh=function(a,b){THREE.Mesh.call(this,a,b);this.animationsMap={};this.animationsList=[];var c=this.geometry.morphTargets.length;this.createAnimation("__default",0,c-1,c/1);this.setAnimationWeight("__default",1)};THREE.MorphBlendMesh.prototype=new THREE.Mesh;THREE.MorphBlendMesh.prototype.constructor=THREE.MorphBlendMesh;
+THREE.MorphBlendMesh.prototype.createAnimation=function(a,b,c,d){b={startFrame:b,endFrame:c,length:c-b+1,fps:d,duration:(c-b)/d,lastFrame:0,currentFrame:0,active:!1,time:0,direction:1,weight:1,directionBackwards:!1,mirroredLoop:!1};this.animationsMap[a]=b;this.animationsList.push(b)};
+THREE.MorphBlendMesh.prototype.autoCreateAnimations=function(a){for(var b=/([a-z]+)(\d+)/,c,d={},f=this.geometry,g=0,e=f.morphTargets.length;g<e;g++){var h=f.morphTargets[g].name.match(b);if(h&&1<h.length){var i=h[1];d[i]||(d[i]={start:Infinity,end:-Infinity});h=d[i];if(g<h.start)h.start=g;if(g>h.end)h.end=g;c||(c=i)}}for(i in d)h=d[i],this.createAnimation(i,h.start,h.end,a);this.firstAnimation=c};
+THREE.MorphBlendMesh.prototype.setAnimationDirectionForward=function(a){if(a=this.animationsMap[a])a.direction=1,a.directionBackwards=!1};THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward=function(a){if(a=this.animationsMap[a])a.direction=-1,a.directionBackwards=!0};THREE.MorphBlendMesh.prototype.setAnimationFPS=function(a,b){var c=this.animationsMap[a];if(c)c.fps=b,c.duration=(c.end-c.start)/c.fps};
+THREE.MorphBlendMesh.prototype.setAnimationDuration=function(a,b){var c=this.animationsMap[a];if(c)c.duration=b,c.fps=(c.end-c.start)/c.duration};THREE.MorphBlendMesh.prototype.setAnimationWeight=function(a,b){var c=this.animationsMap[a];if(c)c.weight=b};THREE.MorphBlendMesh.prototype.setAnimationTime=function(a,b){var c=this.animationsMap[a];if(c)c.time=b};THREE.MorphBlendMesh.prototype.getAnimationTime=function(a){var b=0;if(a=this.animationsMap[a])b=a.time;return b};
+THREE.MorphBlendMesh.prototype.getAnimationDuration=function(a){var b=-1;if(a=this.animationsMap[a])b=a.duration;return b};THREE.MorphBlendMesh.prototype.playAnimation=function(a){var b=this.animationsMap[a];b?(b.time=0,b.active=!0):console.warn("animation["+a+"] undefined")};THREE.MorphBlendMesh.prototype.stopAnimation=function(a){if(a=this.animationsMap[a])a.active=!1};
+THREE.MorphBlendMesh.prototype.update=function(a){for(var b=0,c=this.animationsList.length;b<c;b++){var d=this.animationsList[b];if(d.active){var f=d.duration/d.length;d.time+=d.direction*a;if(d.mirroredLoop){if(d.time>d.duration||0>d.time){d.direction*=-1;if(d.time>d.duration)d.time=d.duration,d.directionBackwards=!0;if(0>d.time)d.time=0,d.directionBackwards=!1}}else d.time%=d.duration,0>d.time&&(d.time+=d.duration);var g=d.startFrame+THREE.Math.clamp(Math.floor(d.time/f),0,d.length-1),e=d.weight;
+if(g!==d.currentFrame)this.morphTargetInfluences[d.lastFrame]=0,this.morphTargetInfluences[d.currentFrame]=1*e,this.morphTargetInfluences[g]=0,d.lastFrame=d.currentFrame,d.currentFrame=g;f=d.time%f/f;d.directionBackwards&&(f=1-f);this.morphTargetInfluences[d.currentFrame]=f*e;this.morphTargetInfluences[d.lastFrame]=(1-f)*e}}};
 THREE.LensFlarePlugin=function(){function a(a){var c=b.createProgram(),d=b.createShader(b.FRAGMENT_SHADER),e=b.createShader(b.VERTEX_SHADER);b.shaderSource(d,a.fragmentShader);b.shaderSource(e,a.vertexShader);b.compileShader(d);b.compileShader(e);b.attachShader(c,d);b.attachShader(c,e);b.linkProgram(c);return c}var b,c,d,f,g,e,h,i,k,j,q,l,n;this.init=function(r){b=r.context;c=r;d=new Float32Array(16);f=new Uint16Array(6);r=0;d[r++]=-1;d[r++]=-1;d[r++]=0;d[r++]=0;d[r++]=1;d[r++]=-1;d[r++]=1;d[r++]=
 0;d[r++]=1;d[r++]=1;d[r++]=1;d[r++]=1;d[r++]=-1;d[r++]=1;d[r++]=0;d[r++]=1;r=0;f[r++]=0;f[r++]=1;f[r++]=2;f[r++]=0;f[r++]=2;f[r++]=3;g=b.createBuffer();e=b.createBuffer();b.bindBuffer(b.ARRAY_BUFFER,g);b.bufferData(b.ARRAY_BUFFER,d,b.STATIC_DRAW);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,e);b.bufferData(b.ELEMENT_ARRAY_BUFFER,f,b.STATIC_DRAW);h=b.createTexture();i=b.createTexture();b.bindTexture(b.TEXTURE_2D,h);b.texImage2D(b.TEXTURE_2D,0,b.RGB,16,16,0,b.RGB,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,
 b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);b.bindTexture(b.TEXTURE_2D,i);b.texImage2D(b.TEXTURE_2D,0,b.RGBA,16,16,0,b.RGBA,b.UNSIGNED_BYTE,null);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_S,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_WRAP_T,b.CLAMP_TO_EDGE);b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MAG_FILTER,b.NEAREST);
@@ -389,8 +397,8 @@ b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);0>=b.getParameter(b
 "color");l.scale=b.getUniformLocation(j,"scale");l.rotation=b.getUniformLocation(j,"rotation");l.screenPosition=b.getUniformLocation(j,"screenPosition");n=!1};this.render=function(a,d,f,p){var a=a.__webglFlares,s=a.length;if(s){var t=new THREE.Vector3,v=p/f,u=0.5*f,w=0.5*p,z=16/p,x=new THREE.Vector2(z*v,z),A=new THREE.Vector3(1,1,0),D=new THREE.Vector2(1,1),G=l,z=q;b.useProgram(j);n||(b.enableVertexAttribArray(q.vertex),b.enableVertexAttribArray(q.uv),n=!0);b.uniform1i(G.occlusionMap,0);b.uniform1i(G.map,
 1);b.bindBuffer(b.ARRAY_BUFFER,g);b.vertexAttribPointer(z.vertex,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(z.uv,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,e);b.disable(b.CULL_FACE);b.depthMask(!1);var J,F,E,C,H;for(J=0;J<s;J++)if(z=16/p,x.set(z*v,z),C=a[J],t.set(C.matrixWorld.n14,C.matrixWorld.n24,C.matrixWorld.n34),d.matrixWorldInverse.multiplyVector3(t),d.projectionMatrix.multiplyVector3(t),A.copy(t),D.x=A.x*u+u,D.y=A.y*w+w,k||0<D.x&&D.x<f&&0<D.y&&D.y<p){b.activeTexture(b.TEXTURE1);b.bindTexture(b.TEXTURE_2D,
 h);b.copyTexImage2D(b.TEXTURE_2D,0,b.RGB,D.x-8,D.y-8,16,16,0);b.uniform1i(G.renderType,0);b.uniform2f(G.scale,x.x,x.y);b.uniform3f(G.screenPosition,A.x,A.y,A.z);b.disable(b.BLEND);b.enable(b.DEPTH_TEST);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);b.activeTexture(b.TEXTURE0);b.bindTexture(b.TEXTURE_2D,i);b.copyTexImage2D(b.TEXTURE_2D,0,b.RGBA,D.x-8,D.y-8,16,16,0);b.uniform1i(G.renderType,1);b.disable(b.DEPTH_TEST);b.activeTexture(b.TEXTURE1);b.bindTexture(b.TEXTURE_2D,h);b.drawElements(b.TRIANGLES,
-6,b.UNSIGNED_SHORT,0);C.positionScreen.copy(A);C.customUpdateCallback?C.customUpdateCallback(C):C.updateLensFlares();b.uniform1i(G.renderType,2);b.enable(b.BLEND);for(F=0,E=C.lensFlares.length;F<E;F++)if(H=C.lensFlares[F],0.001<H.opacity&&0.001<H.scale)A.x=H.x,A.y=H.y,A.z=H.z,z=H.size*H.scale/p,x.x=z*v,x.y=z,b.uniform3f(G.screenPosition,A.x,A.y,A.z),b.uniform2f(G.scale,x.x,x.y),b.uniform1f(G.rotation,H.rotation),b.uniform1f(G.opacity,H.opacity),b.uniform3f(G.color,H.color.r,H.color.g,H.color.b),c.setBlending(H.blending),
-c.setTexture(H.texture,1),b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(!0)}}};
+6,b.UNSIGNED_SHORT,0);C.positionScreen.copy(A);C.customUpdateCallback?C.customUpdateCallback(C):C.updateLensFlares();b.uniform1i(G.renderType,2);b.enable(b.BLEND);for(F=0,E=C.lensFlares.length;F<E;F++)if(H=C.lensFlares[F],0.0010<H.opacity&&0.0010<H.scale)A.x=H.x,A.y=H.y,A.z=H.z,z=H.size*H.scale/p,x.x=z*v,x.y=z,b.uniform3f(G.screenPosition,A.x,A.y,A.z),b.uniform2f(G.scale,x.x,x.y),b.uniform1f(G.rotation,H.rotation),b.uniform1f(G.opacity,H.opacity),b.uniform3f(G.color,H.color.r,H.color.g,H.color.b),
+c.setBlending(H.blending),c.setTexture(H.texture,1),b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(!0)}}};
 THREE.ShadowMapPlugin=function(){var a,b,c,d,f=new THREE.Frustum,g=new THREE.Matrix4,e=new THREE.Vector3,h=new THREE.Vector3;this.init=function(e){a=e.context;b=e;var e=THREE.ShaderLib.depthRGBA,f=THREE.UniformsUtils.clone(e.uniforms);c=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f});d=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:f,morphTargets:!0});c._shadowPass=!0;d._shadowPass=!0};this.render=function(a,
 c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(i,k){var j,q,l,n,r,m,o,p,s,t=[];n=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);b.shadowMapCullFrontFaces&&a.cullFace(a.FRONT);b.setDepthTest(!0);for(j=0,q=i.__lights.length;j<q;j++)if(l=i.__lights[j],l.castShadow)if(l instanceof THREE.DirectionalLight&&l.shadowCascade)for(r=0;r<l.shadowCascadeCount;r++){var v;if(l.shadowCascadeArray[r])v=l.shadowCascadeArray[r];else{s=l;o=r;v=new THREE.DirectionalLight;v.isVirtual=
 !0;v.onlyShadow=!0;v.castShadow=!0;v.shadowCameraNear=s.shadowCameraNear;v.shadowCameraFar=s.shadowCameraFar;v.shadowCameraLeft=s.shadowCameraLeft;v.shadowCameraRight=s.shadowCameraRight;v.shadowCameraBottom=s.shadowCameraBottom;v.shadowCameraTop=s.shadowCameraTop;v.shadowCameraVisible=s.shadowCameraVisible;v.shadowDarkness=s.shadowDarkness;v.shadowBias=s.shadowCascadeBias[o];v.shadowMapWidth=s.shadowCascadeWidth[o];v.shadowMapHeight=s.shadowCascadeHeight[o];v.pointsWorld=[];v.pointsFrustum=[];p=

+ 1 - 1
build/custom/ThreeSVG.js

@@ -78,7 +78,7 @@ f-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c);this
 -Math.abs(this.y):Math.abs(this.y);this.z=0>a.n21-a.n12?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x*=-1;this.y*=-1;this.z*=-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);0===a?this.w=this.z=
 this.y=this.x=0:(a=1/a,this.x*=a,this.y*=a,this.z*=a,this.w*=a);return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,f=a.x,g=a.y,h=a.z,a=a.w;this.x=b*a+e*f+c*h-d*g;this.y=c*a+e*g+d*f-b*h;this.z=d*a+e*h+b*g-c*f;this.w=e*a-b*f-c*g-d*h;return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplyVector3:function(a,b){b||(b=
 a);var c=a.x,d=a.y,e=a.z,f=this.x,g=this.y,h=this.z,j=this.w,i=j*c+g*e-h*d,k=j*d+h*c-f*e,l=j*e+f*d-g*c,c=-f*c-g*d-h*e;b.x=i*j+c*-f+k*-h-l*-g;b.y=k*j+c*-g+l*-f-i*-h;b.z=l*j+c*-h+i*-g-k*-f;return b}};
-THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;0>e?(c.w=-b.w,c.x=-b.x,c.y=-b.y,c.z=-b.z,e=-e):c.copy(b);if(1<=Math.abs(e))return c.w=a.w,c.x=a.x,c.y=a.y,c.z=a.z,c;var f=Math.acos(e),e=Math.sqrt(1-e*e);if(0.001>Math.abs(e))return c.w=0.5*(a.w+b.w),c.x=0.5*(a.x+b.x),c.y=0.5*(a.y+b.y),c.z=0.5*(a.z+b.z),c;b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(a){this.position=a||new THREE.Vector3};
+THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;0>e?(c.w=-b.w,c.x=-b.x,c.y=-b.y,c.z=-b.z,e=-e):c.copy(b);if(1<=Math.abs(e))return c.w=a.w,c.x=a.x,c.y=a.y,c.z=a.z,c;var f=Math.acos(e),e=Math.sqrt(1-e*e);if(0.0010>Math.abs(e))return c.w=0.5*(a.w+b.w),c.x=0.5*(a.x+b.x),c.y=0.5*(a.y+b.y),c.z=0.5*(a.z+b.z),c;b=Math.sin((1-d)*f)/e;d=Math.sin(d*f)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(a){this.position=a||new THREE.Vector3};
 THREE.Vertex.prototype={constructor:THREE.Vertex,clone:function(){return new THREE.Vertex(this.position.clone())}};THREE.Face3=function(a,b,c,d,e,f){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=f;this.centroid=new THREE.Vector3};
 THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;for(b=0,c=this.vertexNormals.length;b<c;b++)a.vertexNormals[b]=this.vertexNormals[b].clone();for(b=0,c=this.vertexColors.length;b<c;b++)a.vertexColors[b]=this.vertexColors[b].clone();for(b=0,c=this.vertexTangents.length;b<c;b++)a.vertexTangents[b]=this.vertexTangents[b].clone();
 return a}};THREE.Face4=function(a,b,c,d,e,f,g){this.a=a;this.b=b;this.c=c;this.d=d;this.normal=e instanceof THREE.Vector3?e:new THREE.Vector3;this.vertexNormals=e instanceof Array?e:[];this.color=f instanceof THREE.Color?f:new THREE.Color;this.vertexColors=f instanceof Array?f:[];this.vertexTangents=[];this.materialIndex=g;this.centroid=new THREE.Vector3};

+ 2 - 2
build/custom/ThreeWebGL.js

@@ -79,7 +79,7 @@ g-d*b*c;return this},setFromAxisAngle:function(a,b){var c=b/2,d=Math.sin(c);this
 -Math.abs(this.y):Math.abs(this.y);this.z=0>a.n21-a.n12?-Math.abs(this.z):Math.abs(this.z);this.normalize();return this},calculateW:function(){this.w=-Math.sqrt(Math.abs(1-this.x*this.x-this.y*this.y-this.z*this.z));return this},inverse:function(){this.x*=-1;this.y*=-1;this.z*=-1;return this},length:function(){return Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w)},normalize:function(){var a=Math.sqrt(this.x*this.x+this.y*this.y+this.z*this.z+this.w*this.w);0===a?this.w=this.z=
 this.y=this.x=0:(a=1/a,this.x*=a,this.y*=a,this.z*=a,this.w*=a);return this},multiplySelf:function(a){var b=this.x,c=this.y,d=this.z,e=this.w,g=a.x,h=a.y,i=a.z,a=a.w;this.x=b*a+e*g+c*i-d*h;this.y=c*a+e*h+d*g-b*i;this.z=d*a+e*i+b*h-c*g;this.w=e*a-b*g-c*h-d*i;return this},multiply:function(a,b){this.x=a.x*b.w+a.y*b.z-a.z*b.y+a.w*b.x;this.y=-a.x*b.z+a.y*b.w+a.z*b.x+a.w*b.y;this.z=a.x*b.y-a.y*b.x+a.z*b.w+a.w*b.z;this.w=-a.x*b.x-a.y*b.y-a.z*b.z+a.w*b.w;return this},multiplyVector3:function(a,b){b||(b=
 a);var c=a.x,d=a.y,e=a.z,g=this.x,h=this.y,i=this.z,m=this.w,k=m*c+h*e-i*d,j=m*d+i*c-g*e,n=m*e+g*d-h*c,c=-g*c-h*d-i*e;b.x=k*m+c*-g+j*-i-n*-h;b.y=j*m+c*-h+n*-g-k*-i;b.z=n*m+c*-i+k*-h-j*-g;return b}};
-THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;0>e?(c.w=-b.w,c.x=-b.x,c.y=-b.y,c.z=-b.z,e=-e):c.copy(b);if(1<=Math.abs(e))return c.w=a.w,c.x=a.x,c.y=a.y,c.z=a.z,c;var g=Math.acos(e),e=Math.sqrt(1-e*e);if(0.001>Math.abs(e))return c.w=0.5*(a.w+b.w),c.x=0.5*(a.x+b.x),c.y=0.5*(a.y+b.y),c.z=0.5*(a.z+b.z),c;b=Math.sin((1-d)*g)/e;d=Math.sin(d*g)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(a){this.position=a||new THREE.Vector3};
+THREE.Quaternion.slerp=function(a,b,c,d){var e=a.w*b.w+a.x*b.x+a.y*b.y+a.z*b.z;0>e?(c.w=-b.w,c.x=-b.x,c.y=-b.y,c.z=-b.z,e=-e):c.copy(b);if(1<=Math.abs(e))return c.w=a.w,c.x=a.x,c.y=a.y,c.z=a.z,c;var g=Math.acos(e),e=Math.sqrt(1-e*e);if(0.0010>Math.abs(e))return c.w=0.5*(a.w+b.w),c.x=0.5*(a.x+b.x),c.y=0.5*(a.y+b.y),c.z=0.5*(a.z+b.z),c;b=Math.sin((1-d)*g)/e;d=Math.sin(d*g)/e;c.w=a.w*b+c.w*d;c.x=a.x*b+c.x*d;c.y=a.y*b+c.y*d;c.z=a.z*b+c.z*d;return c};THREE.Vertex=function(a){this.position=a||new THREE.Vector3};
 THREE.Vertex.prototype={constructor:THREE.Vertex,clone:function(){return new THREE.Vertex(this.position.clone())}};THREE.Face3=function(a,b,c,d,e,g){this.a=a;this.b=b;this.c=c;this.normal=d instanceof THREE.Vector3?d:new THREE.Vector3;this.vertexNormals=d instanceof Array?d:[];this.color=e instanceof THREE.Color?e:new THREE.Color;this.vertexColors=e instanceof Array?e:[];this.vertexTangents=[];this.materialIndex=g;this.centroid=new THREE.Vector3};
 THREE.Face3.prototype={constructor:THREE.Face3,clone:function(){var a=new THREE.Face3(this.a,this.b,this.c);a.normal.copy(this.normal);a.color.copy(this.color);a.centroid.copy(this.centroid);a.materialIndex=this.materialIndex;var b,c;for(b=0,c=this.vertexNormals.length;b<c;b++)a.vertexNormals[b]=this.vertexNormals[b].clone();for(b=0,c=this.vertexColors.length;b<c;b++)a.vertexColors[b]=this.vertexColors[b].clone();for(b=0,c=this.vertexTangents.length;b<c;b++)a.vertexTangents[b]=this.vertexTangents[b].clone();
 return a}};THREE.Face4=function(a,b,c,d,e,g,h){this.a=a;this.b=b;this.c=c;this.d=d;this.normal=e instanceof THREE.Vector3?e:new THREE.Vector3;this.vertexNormals=e instanceof Array?e:[];this.color=g instanceof THREE.Color?g:new THREE.Color;this.vertexColors=g instanceof Array?g:[];this.vertexTangents=[];this.materialIndex=h;this.centroid=new THREE.Vector3};
@@ -376,7 +376,7 @@ b.texParameteri(b.TEXTURE_2D,b.TEXTURE_MIN_FILTER,b.NEAREST);0>=b.getParameter(b
 "color");l.scale=b.getUniformLocation(j,"scale");l.rotation=b.getUniformLocation(j,"rotation");l.screenPosition=b.getUniformLocation(j,"screenPosition");q=!1};this.render=function(a,d,e,y){var a=a.__webglFlares,w=a.length;if(w){var N=new THREE.Vector3,A=y/e,u=0.5*e,H=0.5*y,I=16/y,D=new THREE.Vector2(I*A,I),L=new THREE.Vector3(1,1,0),K=new THREE.Vector2(1,1),M=l,I=n;b.useProgram(j);q||(b.enableVertexAttribArray(n.vertex),b.enableVertexAttribArray(n.uv),q=!0);b.uniform1i(M.occlusionMap,0);b.uniform1i(M.map,
 1);b.bindBuffer(b.ARRAY_BUFFER,g);b.vertexAttribPointer(I.vertex,2,b.FLOAT,!1,16,0);b.vertexAttribPointer(I.uv,2,b.FLOAT,!1,16,8);b.bindBuffer(b.ELEMENT_ARRAY_BUFFER,h);b.disable(b.CULL_FACE);b.depthMask(!1);var ja,oa,ka,X,$;for(ja=0;ja<w;ja++)if(I=16/y,D.set(I*A,I),X=a[ja],N.set(X.matrixWorld.n14,X.matrixWorld.n24,X.matrixWorld.n34),d.matrixWorldInverse.multiplyVector3(N),d.projectionMatrix.multiplyVector3(N),L.copy(N),K.x=L.x*u+u,K.y=L.y*H+H,k||0<K.x&&K.x<e&&0<K.y&&K.y<y){b.activeTexture(b.TEXTURE1);
 b.bindTexture(b.TEXTURE_2D,i);b.copyTexImage2D(b.TEXTURE_2D,0,b.RGB,K.x-8,K.y-8,16,16,0);b.uniform1i(M.renderType,0);b.uniform2f(M.scale,D.x,D.y);b.uniform3f(M.screenPosition,L.x,L.y,L.z);b.disable(b.BLEND);b.enable(b.DEPTH_TEST);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);b.activeTexture(b.TEXTURE0);b.bindTexture(b.TEXTURE_2D,m);b.copyTexImage2D(b.TEXTURE_2D,0,b.RGBA,K.x-8,K.y-8,16,16,0);b.uniform1i(M.renderType,1);b.disable(b.DEPTH_TEST);b.activeTexture(b.TEXTURE1);b.bindTexture(b.TEXTURE_2D,
-i);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);X.positionScreen.copy(L);X.customUpdateCallback?X.customUpdateCallback(X):X.updateLensFlares();b.uniform1i(M.renderType,2);b.enable(b.BLEND);for(oa=0,ka=X.lensFlares.length;oa<ka;oa++)if($=X.lensFlares[oa],0.001<$.opacity&&0.001<$.scale)L.x=$.x,L.y=$.y,L.z=$.z,I=$.size*$.scale/y,D.x=I*A,D.y=I,b.uniform3f(M.screenPosition,L.x,L.y,L.z),b.uniform2f(M.scale,D.x,D.y),b.uniform1f(M.rotation,$.rotation),b.uniform1f(M.opacity,$.opacity),b.uniform3f(M.color,
+i);b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0);X.positionScreen.copy(L);X.customUpdateCallback?X.customUpdateCallback(X):X.updateLensFlares();b.uniform1i(M.renderType,2);b.enable(b.BLEND);for(oa=0,ka=X.lensFlares.length;oa<ka;oa++)if($=X.lensFlares[oa],0.0010<$.opacity&&0.0010<$.scale)L.x=$.x,L.y=$.y,L.z=$.z,I=$.size*$.scale/y,D.x=I*A,D.y=I,b.uniform3f(M.screenPosition,L.x,L.y,L.z),b.uniform2f(M.scale,D.x,D.y),b.uniform1f(M.rotation,$.rotation),b.uniform1f(M.opacity,$.opacity),b.uniform3f(M.color,
 $.color.r,$.color.g,$.color.b),c.setBlending($.blending),c.setTexture($.texture,1),b.drawElements(b.TRIANGLES,6,b.UNSIGNED_SHORT,0)}b.enable(b.CULL_FACE);b.enable(b.DEPTH_TEST);b.depthMask(!0)}}};
 THREE.ShadowMapPlugin=function(){var a,b,c,d,e=new THREE.Frustum,g=new THREE.Matrix4,h=new THREE.Vector3,i=new THREE.Vector3;this.init=function(e){a=e.context;b=e;var e=THREE.ShaderLib.depthRGBA,g=THREE.UniformsUtils.clone(e.uniforms);c=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:g});d=new THREE.ShaderMaterial({fragmentShader:e.fragmentShader,vertexShader:e.vertexShader,uniforms:g,morphTargets:!0});c._shadowPass=!0;d._shadowPass=!0};this.render=function(a,
 c){b.shadowMapEnabled&&b.shadowMapAutoUpdate&&this.update(a,c)};this.update=function(m,k){var j,n,l,q,o,p,s,y,w,N=[];q=0;a.clearColor(1,1,1,1);a.disable(a.BLEND);b.shadowMapCullFrontFaces&&a.cullFace(a.FRONT);b.setDepthTest(!0);for(j=0,n=m.__lights.length;j<n;j++)if(l=m.__lights[j],l.castShadow)if(l instanceof THREE.DirectionalLight&&l.shadowCascade)for(o=0;o<l.shadowCascadeCount;o++){var A;if(l.shadowCascadeArray[o])A=l.shadowCascadeArray[o];else{w=l;s=o;A=new THREE.DirectionalLight;A.isVirtual=

+ 483 - 0
examples/js/MD2CharacterComplex.js

@@ -0,0 +1,483 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.MD2CharacterComplex = function () {
+
+	var scope = this;
+
+	this.scale = 1;
+
+	// animation parameters
+
+	this.animationFPS = 6;
+	this.transitionFrames = 15;
+
+	// movement model parameters
+
+	this.maxSpeed = 275;
+	this.maxReverseSpeed = -275;
+
+	this.frontAcceleration = 600;
+	this.backAcceleration = 600;
+
+	this.frontDecceleration = 600;
+
+	this.angularSpeed = 2.5;
+
+	// rig
+
+	this.root = new THREE.Object3D();
+
+	this.meshBody = null;
+	this.meshWeapon = null;
+
+	this.controls = null;
+
+	// skins
+
+	this.skinsBody = [];
+	this.skinsWeapon = [];
+
+	this.weapons = [];
+
+	this.currentSkin = undefined;
+
+	//
+
+	this.onLoadComplete = function () {};
+
+	// internals
+
+	this.loadCounter = 0;
+
+	// internal movement control variables
+
+	this.speed = 0;
+	this.bodyOrientation = 0;
+
+	// internal animation parameters
+
+	this.activeAnimation = null;
+	this.oldAnimation = null;
+
+	// API
+
+	this.loadParts = function ( config ) {
+
+		this.animations = config.animations;
+		this.walkSpeed = config.walkSpeed;
+		this.crouchSpeed = config.crouchSpeed;
+
+		this.loadCounter = config.weapons.length * 2 + config.skins.length + 1;
+
+		var weaponsTextures = []
+		for ( var i = 0; i < config.weapons.length; i ++ ) weaponsTextures[ i ] = config.weapons[ i ][ 1 ];
+
+		// SKINS
+
+		this.skinsBody = loadTextures( config.baseUrl + "skins/", config.skins );
+		this.skinsWeapon = loadTextures( config.baseUrl + "skins/", weaponsTextures );
+
+		// BODY
+
+		var loader = new THREE.JSONLoader();
+
+		loader.load( config.baseUrl + config.body, function( geo ) {
+
+			geo.computeBoundingBox();
+			scope.root.position.y = - scope.scale * geo.boundingBox.min.y;
+
+			var mesh = createPart( geo, scope.skinsBody[ 0 ] );
+			mesh.scale.set( scope.scale, scope.scale, scope.scale );
+
+			scope.root.add( mesh );
+
+			scope.meshBody = mesh;
+
+			checkLoadingComplete();
+
+		} );
+
+		// WEAPONS
+
+		var generateCallback = function ( index, name ) {
+
+			return function( geo ) {
+
+				var mesh = createPart( geo, scope.skinsWeapon[ index ] );
+				mesh.scale.set( scope.scale, scope.scale, scope.scale );
+				mesh.visible = false;
+
+				mesh.name = name;
+
+				scope.root.add( mesh );
+
+				scope.weapons[ index ] = mesh;
+				scope.meshWeapon = mesh;
+
+				checkLoadingComplete();
+
+			}
+
+		}
+
+		for ( var i = 0; i < config.weapons.length; i ++ ) {
+
+			loader.load( config.baseUrl + config.weapons[ i ][ 0 ], generateCallback( i, config.weapons[ i ][ 0 ] ) );
+
+		}
+
+	};
+
+	this.setPlaybackRate = function ( rate ) {
+
+		if ( this.meshBody ) this.meshBody.duration = this.meshBody.baseDuration / rate;
+		if ( this.meshWeapon ) this.meshWeapon.duration = this.meshWeapon.baseDuration / rate;
+
+	};
+
+	this.setWireframe = function ( wireframeEnabled ) {
+
+		if ( wireframeEnabled ) {
+
+			if ( this.meshBody ) this.meshBody.material = this.meshBody.materialWireframe;
+			if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialWireframe;
+
+		} else {
+
+			if ( this.meshBody ) this.meshBody.material = this.meshBody.materialTexture;
+			if ( this.meshWeapon ) this.meshWeapon.material = this.meshWeapon.materialTexture;
+
+		}
+
+	};
+
+	this.setSkin = function( index ) {
+
+		if ( this.meshBody && this.meshBody.material.wireframe === false ) {
+
+			this.meshBody.material.map = this.skinsBody[ index ];
+			this.currentSkin = index;
+
+		}
+
+	};
+
+	this.setWeapon = function ( index ) {
+
+		for ( var i = 0; i < this.weapons.length; i ++ ) this.weapons[ i ].visible = false;
+
+		var activeWeapon = this.weapons[ index ];
+
+		if ( activeWeapon ) {
+
+			activeWeapon.visible = true;
+			this.meshWeapon = activeWeapon;
+
+			activeWeapon.playAnimation( this.activeAnimation );
+			this.meshWeapon.setAnimationTime( this.activeAnimation, this.meshBody.getAnimationTime( this.activeAnimation ) );
+
+
+		}
+
+	};
+
+	this.setAnimation = function ( animationName ) {
+
+		if ( animationName === this.activeAnimation ) return;
+
+		if ( this.meshBody ) {
+
+			this.meshBody.setAnimationWeight( animationName, 0 );
+			this.meshBody.playAnimation( animationName );
+
+			this.oldAnimation = this.activeAnimation;
+			this.activeAnimation = animationName;
+
+			this.blendCounter = this.transitionFrames;
+
+		}
+
+		if ( this.meshWeapon ) {
+
+			this.meshWeapon.setAnimationWeight( animationName, 0 );
+			this.meshWeapon.playAnimation( animationName );
+
+		}
+
+
+	};
+
+	this.update = function ( delta ) {
+
+		if ( this.controls ) this.updateMovementModel( delta );
+
+		this.updateBehaviors( delta );
+		this.updateAnimations( delta );
+
+	};
+
+	this.updateAnimations = function ( delta ) {
+
+		var mix = 1;
+
+		if ( this.blendCounter > 0 ) {
+
+			mix = ( this.transitionFrames - this.blendCounter ) / this.transitionFrames;
+			this.blendCounter -= 1;
+
+		}
+
+		if ( this.meshBody ) {
+
+			this.meshBody.update( delta );
+
+			this.meshBody.setAnimationWeight( this.activeAnimation, mix );
+			this.meshBody.setAnimationWeight( this.oldAnimation,  1 - mix );
+
+		}
+
+		if ( this.meshWeapon ) {
+
+			this.meshWeapon.update( delta );
+
+			this.meshWeapon.setAnimationWeight( this.activeAnimation, mix );
+			this.meshWeapon.setAnimationWeight( this.oldAnimation,  1 - mix );
+
+		}
+
+	};
+
+	this.updateBehaviors = function ( delta ) {
+
+		var controls = this.controls;
+		var animations = this.animations;
+
+		var moveAnimation, idleAnimation;
+
+		// crouch vs stand
+
+		if ( controls.crouch ) {
+
+			moveAnimation = animations[ "crouchMove" ];
+			idleAnimation = animations[ "crouchIdle" ];
+
+		} else {
+
+			moveAnimation = animations[ "move" ];
+			idleAnimation = animations[ "idle" ];
+
+		}
+
+		// actions
+
+		if ( controls.jump ) {
+
+			moveAnimation = animations[ "jump" ];
+			idleAnimation = animations[ "jump" ];
+
+		}
+
+		if ( controls.attack ) {
+
+			if ( controls.crouch ) {
+
+				moveAnimation = animations[ "crouchAttack" ];
+				idleAnimation = animations[ "crouchAttack" ];
+
+			} else {
+
+				moveAnimation = animations[ "attack" ];
+				idleAnimation = animations[ "attack" ];
+
+			}
+
+		}
+
+		// set animations
+
+		if ( controls.moveForward || controls.moveBackward || controls.moveLeft || controls.moveRight ) {
+
+			if ( this.activeAnimation !== moveAnimation ) {
+
+				this.setAnimation( moveAnimation );
+
+			}
+
+		}
+
+
+		if ( Math.abs( this.speed ) < 0.2 * this.maxSpeed && !( controls.moveLeft || controls.moveRight ) ) {
+
+			if ( this.activeAnimation !== idleAnimation ) {
+
+				this.setAnimation( idleAnimation );
+
+			}
+
+		}
+
+		// set animation direction
+
+		if ( controls.moveForward ) {
+
+			if ( this.meshBody )   {
+
+				this.meshBody.setAnimationDirectionForward( this.activeAnimation );
+				this.meshBody.setAnimationDirectionForward( this.oldAnimation );
+
+			}
+
+			if ( this.meshWeapon ) {
+
+				this.meshWeapon.setAnimationDirectionForward( this.activeAnimation );
+				this.meshWeapon.setAnimationDirectionForward( this.oldAnimation );
+
+			}
+
+		}
+
+		if ( controls.moveBackward ) {
+
+			if ( this.meshBody ) {
+
+				this.meshBody.setAnimationDirectionBackward( this.activeAnimation );
+				this.meshBody.setAnimationDirectionBackward( this.oldAnimation );
+
+			}
+
+			if ( this.meshWeapon ) {
+
+				this.meshWeapon.setAnimationDirectionBackward( this.activeAnimation );
+				this.meshWeapon.setAnimationDirectionBackward( this.oldAnimation );
+
+			}
+
+		}
+
+	};
+
+	this.updateMovementModel = function ( delta ) {
+
+		var controls = this.controls;
+
+		// speed based on controls
+
+		if ( controls.crouch ) 	this.maxSpeed = this.crouchSpeed;
+		else  					this.maxSpeed = this.walkSpeed;
+
+		this.maxReverseSpeed = -this.maxSpeed;
+
+		if ( controls.moveForward )  this.speed = THREE.Math.clamp( this.speed + delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed );
+		if ( controls.moveBackward ) this.speed = THREE.Math.clamp( this.speed - delta * this.backAcceleration, this.maxReverseSpeed, this.maxSpeed );
+
+		// orientation based on controls
+		// (don't just stand while turning)
+
+		var dir = 1;
+
+		if ( controls.moveLeft ) {
+
+			this.bodyOrientation += delta * this.angularSpeed;
+			this.speed = THREE.Math.clamp( this.speed + dir * delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed );
+
+		}
+
+		if ( controls.moveRight ) {
+
+			this.bodyOrientation -= delta * this.angularSpeed;
+			this.speed = THREE.Math.clamp( this.speed + dir * delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed );
+
+		}
+
+		// speed decay
+
+		if ( ! ( controls.moveForward || controls.moveBackward ) ) {
+
+			if ( this.speed > 0 ) {
+
+				var k = exponentialEaseOut( this.speed / this.maxSpeed );
+				this.speed = THREE.Math.clamp( this.speed - k * delta * this.frontDecceleration, 0, this.maxSpeed );
+
+			} else {
+
+				var k = exponentialEaseOut( this.speed / this.maxReverseSpeed );
+				this.speed = THREE.Math.clamp( this.speed + k * delta * this.backAcceleration, this.maxReverseSpeed, 0 );
+
+			}
+
+		}
+
+		// displacement
+
+		var forwardDelta = this.speed * delta;
+
+		this.root.position.x += Math.sin( this.bodyOrientation ) * forwardDelta;
+		this.root.position.z += Math.cos( this.bodyOrientation ) * forwardDelta;
+
+		// steering
+
+		this.root.rotation.y = this.bodyOrientation;
+
+	};
+
+	// internal helpers
+
+	function loadTextures( baseUrl, textureUrls ) {
+
+		var mapping = new THREE.UVMapping();
+		var textures = [];
+
+		for ( var i = 0; i < textureUrls.length; i ++ ) {
+
+			textures[ i ] = THREE.ImageUtils.loadTexture( baseUrl + textureUrls[ i ], mapping, checkLoadingComplete );
+			textures[ i ].name = textureUrls[ i ];
+
+		}
+
+		return textures;
+
+	};
+
+	function createPart( geometry, skinMap ) {
+
+		geometry.computeMorphNormals();
+
+		var whiteMap = THREE.ImageUtils.generateDataTexture( 1, 1, new THREE.Color( 0xffffff ) );
+		var materialWireframe = new THREE.MeshPhongMaterial( { color: 0xffaa00, specular: 0x111111, shininess: 50, wireframe: true, shading: THREE.SmoothShading, map: whiteMap, morphTargets: true, morphNormals: true, perPixel: true, metal: true } );
+
+		var materialTexture = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shininess: 50, wireframe: false, shading: THREE.SmoothShading, map: skinMap, morphTargets: true, morphNormals: true, perPixel: true, metal: true } );
+		materialTexture.wrapAround = true;
+
+		//
+
+		var mesh = new THREE.MorphBlendMesh( geometry, materialTexture );
+		mesh.rotation.y = -Math.PI/2;
+
+		mesh.castShadow = true;
+		mesh.receiveShadow = true;
+
+		//
+
+		mesh.materialTexture = materialTexture;
+		mesh.materialWireframe = materialWireframe;
+
+		//
+
+		mesh.autoCreateAnimations( scope.animationFPS );
+
+		return mesh;
+
+	};
+
+	function checkLoadingComplete() {
+
+		scope.loadCounter -= 1;
+		if ( scope.loadCounter === 0 ) 	scope.onLoadComplete();
+
+	};
+
+	function exponentialEaseOut( k ) { return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1; }
+
+};

+ 132 - 0
examples/models/animated/ogro/Ogro.txt

@@ -0,0 +1,132 @@
+
+
+10/11/98
+================================================================
+Model Name              : Ogro
+installation directory  : quake2/baseq2/players/ogro
+
+Model Author		: Magarnigal
+			  email		:[email protected]
+			  homepage 	:http://magarn.3dpalette.com
+
+
+Skins Author            : Ogro_Fix 
+			  email		: [email protected]
+			  homepage	: http://www.fondation.com/pandemonium
+			
+
+Additional info		: Fix has included a cloth and ogrobase skin that people may use as a base for skinning ogro.  The
+			  mapping can be a bit confusing, 2d skinners beware.
+
+
+
+Additional skin by	: Deranged - (Sharokh)
+			  email		: [email protected]
+			  homepage 	: http://www.gibbed.com/thebin
+
+
+
+Ogrific law:
+
+An Ogro is similar to an ogre, but why the O?? In French ogre is pronounced ogrr, not oger, also 'gros' means to be fat/big...so ogre - gros makes Ogro!  After all, it's cuter than just ogre :).
+
+The Ogro is smaller than a normal ogre, but just as fat and only slightly less stupid. As opposed to common belief, he is not an evil creature, only killing as is absolutely necessary.  
+
+Imagine, if you will, an Ogro in the subway.  As he enters the carriage, people become plastered to the walls due to Ogro's size.  He's too big!  Ahh well, maybe Ogro should just sit on one of these tiny seats...a strange sound can be heard (sproottch).  Imagine now, the look of an astonished ogro...huh?!?  Standing up, he looks at the seat.  OMFO! (oh my fucking ogrod!)! Where a little old grandma had been sitting, now looks more like a pizza!  But, I swear, it was a grandma!
+
+This sort of occurrence is common to an Ogro...its in their nature.  when you want to talk to an ogro, stay at good distance (better if you call him from behind), as his movements are rather "uncontrolled", and you might cop a smash in the face!
+
+A special diet is required for Ogros.  When they're babies (ogrillons), their mum's (ogresses) give them copious amounts of chili con carne, canned beans and the like. The result of this carefully structured diet produces an Ogro capable of immense farting achievements.  
+
+The ogro is just full of bad smells. That's not to say he's not clean.  An ogro will wash himself often (doesn't fear water as opposed to trolls).  The problem lies in his intestinal flora (and fauna). all his orifices (ogrifices?) are used for ogrific spells. (green clouds, etc..). Nothing can be done against this kind of onslaught, except to run or stop breathing.
+
+It's a useful trait to have in the subway. people will often leave the carriage, trying to find the culprit. (Although all that is need it to look at the face of the ogro: he's 
+happy, he farted well, and it smells really bad).
+
+
+Ogro's existed long before humans. In fact, one school of thought holds to the theory that humans are a degenerated version of Ogro, more intelligent, but evil.
+
+
+Hidden Ogro's of today include:  Obelix, fat boy slim, any Sumo, Amish (braveheart movie), slamfist (small soldiers movie), bud spencer, etc...			  
+
+
+  
+
+
+Additional Credits to   : id software, Howzer, Rod, 
+
+
+
+================================================================
+* Play Information *
+
+New Sounds              : Yes,  original sounds from Eric vonRothkirch of 'The Coven', email him
+ 			  at [email protected]
+
+CTF Skins               : yes
+VWEP Support            : yes, standard Id weapons with modified, ogrific skins.  
+
+
+* Construction *
+Poly Counts
+Tris.md2		: 670
+weapon.md2		: 122
+
+Vert Counts
+tris.md2		: 358  - anyone actually need this number?
+weapon.md2		: 74
+
+Skin Wastage
+tris.md2		: 1%
+weapon.md2		: 2%
+
+Skin Count              : 14
+
+Base                    : none
+
+
+A background to some of the skins:
+
+Grok: the standard cyberpunk ogro
+
+freedom: this one is dedicated to braveheart.
+
+gib: this one didn't know how to use the ogrific mixer (used to make mammoth steaks), and jumped into it..the mixer did all the work.
+
+slaanesh: this one is an evil ogro, serving the god of lust.
+
+Khorne: this one is even more evil than slaanesh, serving the god of blood and violence.
+
+Nabogro: it's a dwarf (yeah, well, it was), he's a trollslayer. In french nabot means small/dwarfy, so, nabogro went logically.
+
+darkam: hoo, this one is a troll! (yes, he's green, and ogros hate green), but even if he's green it's the best friend of the original, the true ogro.
+
+Igdosh: played with a nuclear missile, thinking it was a cigar...
+
+Gorash: he's evil too, has been created by the doctor ogrenstein. but this is the prototype, the real ogrenstein is under construction for now.
+
+Arboshak: He felt in love with 3CPO and tried to cyborgize himself. but finally preferred R2D2, but too late
+
+
+
+Editors used:-
+
+Modelling/animation	: Lightwave 5.5 
+
+Converting/clean-up	: QME, Q2modeler
+
+Skinning/mapping	: NST, Paint shop Pro
+
+
+
+Build/Animation time    : longer than expected.  5-10 hours per skin.  
+
+
+* How to use this model *
+
+extract to quake2\baseq2\players\ogro  run quake2, send us money, frag other players.    
+
+
+* Copyright / Permissions *
+
+QUAKE(R) and QUAKE II(R) are registered trademarks of id Software, Inc.

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 15 - 0
examples/models/animated/ogro/ogro-light.js


BIN
examples/models/animated/ogro/skins/arboshak.png


BIN
examples/models/animated/ogro/skins/ctf_b.png


BIN
examples/models/animated/ogro/skins/ctf_r.png


BIN
examples/models/animated/ogro/skins/darkam.png


BIN
examples/models/animated/ogro/skins/freedom.png


BIN
examples/models/animated/ogro/skins/gib.png


BIN
examples/models/animated/ogro/skins/gordogh.png


BIN
examples/models/animated/ogro/skins/grok.jpg


BIN
examples/models/animated/ogro/skins/igdosh.png


BIN
examples/models/animated/ogro/skins/khorne.png


BIN
examples/models/animated/ogro/skins/nabogro.png


BIN
examples/models/animated/ogro/skins/ogrobase.png


BIN
examples/models/animated/ogro/skins/sharokh.png


BIN
examples/models/animated/ogro/skins/weapon.jpg


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 72 - 0
examples/models/animated/ogro/weapon-light.js


+ 1095 - 0
examples/webgl_morphtargets_md2_complex.html

@@ -0,0 +1,1095 @@
+<!doctype html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - morphtargets - MD2</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+		    body {
+			color: #fff;
+			font-family:Monospace;
+			font-size:13px;
+			text-align:center;
+			font-weight: bold;
+
+			background-color: #000;
+			margin: 0px;
+			overflow: hidden;
+		    }
+
+		    #info {
+			position: relative;
+			margin: 0 auto -2.1em;
+			top: 0px;
+
+			padding: 5px;
+			z-index:100;
+		    }
+
+		    a { color: skyblue; }
+		</style>
+	</head>
+
+	<body>
+		<div id="info">
+			<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - morphtargets -
+			MD2 character by <a href="http://planetquake.gamespy.com/View.php?view=Quake2.Detail&id=368">Brian Collins</a> -
+			converted by <a href="https://twitter.com/#!/oosmoxiecode">@oosmoxiecode</a>'s <a href="http://oos.moxiecode.com/blog/2012/01/md2-to-json-converter/">MD2 converter<a>
+		</div>
+
+		<script src="../src/Three.js"></script>
+		<script src="../src/core/Clock.js"></script>
+		<script src="../src/core/Color.js"></script>
+		<script src="../src/core/Vector2.js"></script>
+		<script src="../src/core/Vector3.js"></script>
+		<script src="../src/core/Vector4.js"></script>
+		<script src="../src/core/Frustum.js"></script>
+		<script src="../src/core/Ray.js"></script>
+		<script src="../src/core/Rectangle.js"></script>
+		<script src="../src/core/Math.js"></script>
+		<script src="../src/core/Matrix3.js"></script>
+		<script src="../src/core/Matrix4.js"></script>
+		<script src="../src/core/Object3D.js"></script>
+		<script src="../src/core/Projector.js"></script>
+		<script src="../src/core/Quaternion.js"></script>
+		<script src="../src/core/Vertex.js"></script>
+		<script src="../src/core/Face3.js"></script>
+		<script src="../src/core/Face4.js"></script>
+		<script src="../src/core/UV.js"></script>
+		<script src="../src/core/Geometry.js"></script>
+		<script src="../src/core/Spline.js"></script>
+		<script src="../src/core/Edge.js"></script>
+		<script src="../src/cameras/Camera.js"></script>
+		<script src="../src/cameras/OrthographicCamera.js"></script>
+		<script src="../src/cameras/PerspectiveCamera.js"></script>
+		<script src="../src/lights/Light.js"></script>
+		<script src="../src/lights/AmbientLight.js"></script>
+		<script src="../src/lights/DirectionalLight.js"></script>
+		<script src="../src/lights/PointLight.js"></script>
+		<script src="../src/lights/SpotLight.js"></script>
+		<script src="../src/materials/Material.js"></script>
+		<script src="../src/materials/LineBasicMaterial.js"></script>
+		<script src="../src/materials/MeshBasicMaterial.js"></script>
+		<script src="../src/materials/MeshLambertMaterial.js"></script>
+		<script src="../src/materials/MeshPhongMaterial.js"></script>
+		<script src="../src/materials/MeshDepthMaterial.js"></script>
+		<script src="../src/materials/MeshNormalMaterial.js"></script>
+		<script src="../src/materials/MeshFaceMaterial.js"></script>
+		<script src="../src/materials/MeshShaderMaterial.js"></script>
+		<script src="../src/materials/ParticleBasicMaterial.js"></script>
+		<script src="../src/materials/ParticleCanvasMaterial.js"></script>
+		<script src="../src/materials/ParticleDOMMaterial.js"></script>
+		<script src="../src/materials/ShaderMaterial.js"></script>
+		<script src="../src/textures/Texture.js"></script>
+		<script src="../src/textures/DataTexture.js"></script>
+		<script src="../src/objects/Particle.js"></script>
+		<script src="../src/objects/ParticleSystem.js"></script>
+		<script src="../src/objects/Line.js"></script>
+		<script src="../src/objects/Mesh.js"></script>
+		<script src="../src/objects/Bone.js"></script>
+		<script src="../src/objects/SkinnedMesh.js"></script>
+		<script src="../src/objects/MorphAnimMesh.js"></script>
+		<script src="../src/objects/Ribbon.js"></script>
+		<script src="../src/objects/LOD.js"></script>
+		<script src="../src/objects/Sprite.js"></script>
+		<script src="../src/scenes/Scene.js"></script>
+		<script src="../src/scenes/Fog.js"></script>
+		<script src="../src/scenes/FogExp2.js"></script>
+		<script src="../src/renderers/DOMRenderer.js"></script>
+		<script src="../src/renderers/CanvasRenderer.js"></script>
+		<script src="../src/renderers/SVGRenderer.js"></script>
+		<script src="../src/renderers/WebGLShaders.js"></script>
+		<script src="../src/renderers/WebGLRenderer.js"></script>
+		<script src="../src/renderers/WebGLRenderTarget.js"></script>
+		<script src="../src/renderers/WebGLRenderTargetCube.js"></script>
+		<script src="../src/renderers/renderables/RenderableVertex.js"></script>
+		<script src="../src/renderers/renderables/RenderableFace3.js"></script>
+		<script src="../src/renderers/renderables/RenderableFace4.js"></script>
+		<script src="../src/renderers/renderables/RenderableObject.js"></script>
+		<script src="../src/renderers/renderables/RenderableParticle.js"></script>
+		<script src="../src/renderers/renderables/RenderableLine.js"></script>
+		<script src="../src/extras/ColorUtils.js"></script>
+		<script src="../src/extras/GeometryUtils.js"></script>
+		<script src="../src/extras/ImageUtils.js"></script>
+		<script src="../src/extras/SceneUtils.js"></script>
+		<script src="../src/extras/ShaderUtils.js"></script>
+		<script src="../src/extras/core/BufferGeometry.js"></script>
+		<script src="../src/extras/core/Curve.js"></script>
+		<script src="../src/extras/core/CurvePath.js"></script>
+		<script src="../src/extras/core/EventTarget.js"></script>
+		<script src="../src/extras/core/Gyroscope.js"></script>
+		<script src="../src/extras/core/Path.js"></script>
+		<script src="../src/extras/core/Shape.js"></script>
+		<script src="../src/extras/core/TextPath.js"></script>
+		<script src="../src/extras/animation/AnimationHandler.js"></script>
+		<script src="../src/extras/animation/Animation.js"></script>
+		<script src="../src/extras/animation/KeyFrameAnimation.js"></script>
+		<script src="../src/extras/cameras/CubeCamera.js"></script>
+		<script src="../src/extras/cameras/CombinedCamera.js"></script>
+		<script src="../src/extras/controls/FirstPersonControls.js"></script>
+		<script src="../src/extras/controls/PathControls.js"></script>
+		<script src="../src/extras/controls/FlyControls.js"></script>
+		<script src="../src/extras/controls/RollControls.js"></script>
+		<script src="../src/extras/controls/TrackballControls.js"></script>
+		<script src="../src/extras/geometries/CubeGeometry.js"></script>
+		<script src="../src/extras/geometries/CylinderGeometry.js"></script>
+		<script src="../src/extras/geometries/ExtrudeGeometry.js"></script>
+		<script src="../src/extras/geometries/LatheGeometry.js"></script>
+		<script src="../src/extras/geometries/PlaneGeometry.js"></script>
+		<script src="../src/extras/geometries/SphereGeometry.js"></script>
+		<script src="../src/extras/geometries/TextGeometry.js"></script>
+		<script src="../src/extras/geometries/TorusGeometry.js"></script>
+		<script src="../src/extras/geometries/TorusKnotGeometry.js"></script>
+		<script src="../src/extras/geometries/PolyhedronGeometry.js"></script>
+		<script src="../src/extras/geometries/IcosahedronGeometry.js"></script>
+		<script src="../src/extras/geometries/OctahedronGeometry.js"></script>
+		<script src="../src/extras/geometries/TetrahedronGeometry.js"></script>
+		<script src="../src/extras/helpers/AxisHelper.js"></script>
+		<script src="../src/extras/helpers/CameraHelper.js"></script>
+		<script src="../src/extras/modifiers/SubdivisionModifier.js"></script>
+		<script src="../src/extras/loaders/Loader.js"></script>
+		<script src="../src/extras/loaders/BinaryLoader.js"></script>
+		<script src="../src/extras/loaders/ColladaLoader.js"></script>
+		<script src="../src/extras/loaders/JSONLoader.js"></script>
+		<script src="../src/extras/loaders/SceneLoader.js"></script>
+		<script src="../src/extras/loaders/UTF8Loader.js"></script>
+		<script src="../src/extras/objects/MarchingCubes.js"></script>
+		<script src="../src/extras/objects/LensFlare.js"></script>
+		<script src="../src/extras/renderers/plugins/LensFlarePlugin.js"></script>
+		<script src="../src/extras/renderers/plugins/ShadowMapPlugin.js"></script>
+		<script src="../src/extras/renderers/plugins/SpritePlugin.js"></script>
+		<script src="../src/extras/renderers/AnaglyphWebGLRenderer.js"></script>
+		<script src="../src/extras/renderers/CrosseyedWebGLRenderer.js"></script>
+		<script src="../src/extras/shaders/ShaderFlares.js"></script>
+		<script src="../src/extras/shaders/ShaderSprite.js"></script>
+
+		<script src="../src/objects/MorphBlendMesh.js"></script>
+		<script src='js/MD2CharacterComplex.js'></script>
+
+		<script src='js/ShaderExtras.js'></script>
+
+		<script src="js/postprocessing/EffectComposer.js"></script>
+		<script src="js/postprocessing/RenderPass.js"></script>
+		<script src="js/postprocessing/BloomPass.js"></script>
+		<script src="js/postprocessing/ShaderPass.js"></script>
+		<script src="js/postprocessing/MaskPass.js"></script>
+		<script src="js/postprocessing/SavePass.js"></script>
+
+		<script src='js/Detector.js'></script>
+		<script src='js/Stats.js'></script>
+		<script src='js/DAT.GUI.min.js'></script>
+
+		<script src="fonts/helvetiker_bold.typeface.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var MARGIN = 100;
+			var SCREEN_WIDTH = window.innerWidth;
+			var SCREEN_HEIGHT = window.innerHeight - 2 * MARGIN;
+
+			var SHADOW_MAP_WIDTH = 2048, SHADOW_MAP_HEIGHT = 2048;
+
+			var container, camera, scene, renderer;
+
+			var character;
+
+			var cameraControls;
+
+			var morphs = [];
+
+			var gui, playbackConfig = {
+
+				speed: 1.0,
+				wireframe: false
+
+			};
+
+			var controls = {
+
+				moveForward: false,
+				moveBackward: false,
+				moveLeft: false,
+				moveRight: false
+
+			};
+
+			var clock = new THREE.Clock();
+
+			init();
+			animate();
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				// SCENE
+
+				scene = new THREE.Scene();
+				scene.fog = new THREE.Fog( 0xffffff, 1000, 8000 );
+				scene.fog.color.setHSV( 0.6, 0.2, 0.99 );
+
+				// CAMERA
+
+				camera = new THREE.PerspectiveCamera( 40, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 8000 );
+				camera.position.set( 0, 150, 800 );
+				scene.add( camera );
+
+				// LIGHTS
+
+				scene.add( new THREE.AmbientLight( 0x222222 ) );
+
+				light1 = new THREE.DirectionalLight( 0xffffff, 1.2 );
+				light1.position.set( 200, 650, 500 );
+
+				light1.castShadow = true;
+				light1.shadowMapWidth = 1024;
+				light1.shadowMapHeight = 1024;
+				light1.shadowDarkness = 0.4;
+				//light1.shadowCameraVisible = true;
+
+				light1.shadowCascade = true;
+				light1.shadowCascadeCount = 3;
+				light1.shadowCascadeBias   = [ 0.001, 0, 0.0007 ];
+				light1.shadowCascadeNearZ = [ -1.000, 0.9975, 0.9995 ];
+				light1.shadowCascadeFarZ  = [  0.9975, 0.9995, 1.000 ];
+				light1.shadowCascadeWidth  = [ SHADOW_MAP_WIDTH, SHADOW_MAP_WIDTH, SHADOW_MAP_WIDTH ];
+				light1.shadowCascadeHeight = [ SHADOW_MAP_HEIGHT, SHADOW_MAP_HEIGHT, SHADOW_MAP_HEIGHT ];
+
+				scene.add( light1 );
+
+				//  GROUND
+
+				var gt = THREE.ImageUtils.loadTexture( "textures/terrain/grasslight-big.jpg" );
+				var gt = THREE.ImageUtils.loadTexture( "textures/patterns/bright_squares256.png" );
+				var gg = new THREE.PlaneGeometry( 32000, 32000 );
+				var gm = new THREE.MeshPhongMaterial( { color: 0xffffff, map: gt, perPixel: true } );
+
+				var ground = new THREE.Mesh( gg, gm );
+				ground.material.map.repeat.set( 32, 32);
+				ground.material.map.wrapS = ground.material.map.wrapT = THREE.RepeatWrapping;
+				ground.rotation.x = - Math.PI/2;
+				ground.receiveShadow = true;
+
+				scene.add( ground );
+
+				// OBJECTS
+
+				var objMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, maps: gt, perPixel: true } );
+				var geo = new THREE.CubeGeometry( 10, 10, 10, 1, 1, 1, objMaterial, { ny: false } );
+
+				var mergedGeo = new THREE.Geometry();
+
+
+				for ( var i = 0; i < 100; i ++ ) {
+
+					var s = THREE.Math.randFloat( 1, 30 );
+					var ss = THREE.Math.randFloat( 1, 75 );
+
+					var mesh = new THREE.Mesh( geo, objMaterial );
+					mesh.position.x = THREE.Math.randFloatSpread( 20000 );
+					mesh.position.z = THREE.Math.randFloatSpread( 20000 );
+					mesh.position.y = 0.5 * 10 * s;
+					mesh.scale.y = s;
+					mesh.scale.x = ss;
+					mesh.scale.z = ss;
+
+					mesh.matrixAutoUpdate = false;
+					mesh.updateMatrix();
+
+					THREE.GeometryUtils.merge( mergedGeo, mesh );
+
+				}
+
+				var mesh = new THREE.Mesh( mergedGeo, objMaterial );
+				mesh.castShadow = true;
+				mesh.receiveShadow = true;
+				scene.add( mesh );
+
+				// TEXT
+
+				var textGeo = new THREE.TextGeometry( "THREE.JS", {
+
+					size: 200,
+					height: 50,
+					curveSegments: 12,
+
+					font: "helvetiker",
+					weight: "bold",
+					style: "normal",
+
+					bevelThickness: 2,
+					bevelSize: 5,
+					bevelEnabled: true
+
+				});
+
+				textGeo.computeBoundingBox();
+				var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x );
+
+				var textMaterial = new THREE.MeshPhongMaterial( { color: 0x00aaff, specular: 0x00aaff, ambient: 0x00aaff, perPixel: true } );
+
+				var mesh = new THREE.Mesh( textGeo, textMaterial );
+				mesh.position.x = centerOffset;
+				mesh.position.y = 67;
+
+				mesh.castShadow = true;
+				mesh.receiveShadow = true;
+
+				scene.add( mesh );
+
+				// CUBES
+
+				var mesh = new THREE.Mesh( new THREE.CubeGeometry( 1500, 220, 150 ), objMaterial );
+
+				mesh.position.y = -50;
+				mesh.position.z = 20;
+
+				mesh.castShadow = true;
+				mesh.receiveShadow = true;
+
+				scene.add( mesh );
+
+				var mesh = new THREE.Mesh( new THREE.CubeGeometry( 1600, 170, 250 ), objMaterial );
+
+				mesh.position.y = -50;
+				mesh.position.z = 20;
+
+				mesh.castShadow = true;
+				mesh.receiveShadow = true;
+
+				scene.add( mesh );
+
+				// MORPHS
+
+				function addMorph( geometry, speed, duration, x, y, z, fudgeColor ) {
+
+					var s = 1;
+
+					var material = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0xffffff, shininess: 10, morphTargets: true, morphNormals: true, vertexColors: THREE.FaceColors, shading: THREE.FlatShading, perPixel: true } );
+
+					if ( 1 || fudgeColor ) {
+
+						THREE.ColorUtils.adjustHSV( material.color, 0, 0.5 - Math.random(), 0.5 - Math.random() );
+						material.ambient = material.color;
+
+					}
+
+					var meshAnim = new THREE.MorphAnimMesh( geometry, material );
+
+					meshAnim.speed = speed;
+					meshAnim.duration = duration;
+					meshAnim.time = 600 * Math.random();
+
+					meshAnim.position.set( x, y, z );
+					meshAnim.rotation.y = Math.PI/2;
+
+					meshAnim.scale.set( s, s, s );
+
+					meshAnim.castShadow = true;
+					meshAnim.receiveShadow = true;
+
+					scene.add( meshAnim );
+
+					morphs.push( meshAnim );
+
+				}
+
+				function morphColorsToFaceColors( geometry ) {
+
+					if ( geometry.morphColors && geometry.morphColors.length ) {
+
+						var colorMap = geometry.morphColors[ 0 ];
+
+						for ( var i = 0; i < colorMap.colors.length; i ++ ) {
+
+							geometry.faces[ i ].color = colorMap.colors[ i ];
+
+						}
+
+					}
+
+				}
+
+				var loader = new THREE.JSONLoader();
+
+				loader.load( "obj/morphs/shdw3walk.js", function( geometry ) {
+
+					geometry.computeMorphNormals();
+					morphColorsToFaceColors( geometry );
+
+					for ( var i = 0; i < 50; i ++ ) {
+
+						addMorph( geometry, 40, 2000, -3000 + Math.random() * 6000, 0 + 60, -3000 + Math.random() * 6000 );
+
+					}
+
+
+
+				} );
+
+
+				loader.load( "models/animated/horse.js", function( geometry ) {
+
+					geometry.computeMorphNormals();
+					morphColorsToFaceColors( geometry );
+
+					for ( var i = 0; i < 50; i ++ ) {
+
+						addMorph( geometry, 550, 1000, -5000 + Math.random() * 10000, 0, -5000 + Math.random() * 10000 );
+
+					}
+
+
+				} );
+
+				loader.load( "obj/morphs/flamingo.js", function( geometry ) {
+
+					geometry.computeMorphNormals();
+					morphColorsToFaceColors( geometry );
+
+					for ( var i = 0; i < 50; i ++ ) {
+
+						addMorph( geometry, 850, 750, -5000 + Math.random() * 10000, 0 + 500 + 500 * Math.random(), -5000 + Math.random() * 10000 );
+
+					}
+
+
+
+				} );
+
+				// RENDERER
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+				renderer.domElement.style.position = "relative";
+				renderer.domElement.style.top = MARGIN + 'px';
+				renderer.setClearColor( scene.fog.color, 1 );
+
+				container.appendChild( renderer.domElement );
+
+				// CONTROLS
+
+				cameraControls = new THREE.TrackballControls( camera, renderer.domElement );
+				cameraControls.target.set( 0, 0, 0 );
+
+				//
+
+				renderer.gammaInput = true;
+				renderer.gammaOutput = true;
+				//renderer.physicallyBasedShading = true;
+
+				renderer.shadowMapEnabled = true;
+				//renderer.shadowMapSoft = false;
+				//renderer.shadowMapCullFrontFaces = false;
+
+				renderer.shadowMapCascade = true;
+				//renderer.shadowMapDebug = true;
+
+				renderer.autoClear = false;
+
+				// STATS
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				stats.domElement.style.zIndex = 100;
+				container.appendChild( stats.domElement );
+
+				stats.domElement.children[ 0 ].children[ 0 ].style.color = "#aaa";
+				stats.domElement.children[ 0 ].style.background = "transparent";
+				stats.domElement.children[ 0 ].children[ 1 ].style.display = "none";
+
+				// EVENTS
+
+				window.addEventListener( 'resize', onWindowResize, false );
+				document.addEventListener( 'keydown', onKeyDown, false );
+				document.addEventListener( 'keyup', onKeyUp, false );
+
+				// GUI
+
+				gui = new DAT.GUI();
+
+				gui.add( playbackConfig, 'speed', 0, 2 ).onChange( function() {
+
+					character.setPlaybackRate( playbackConfig.speed );
+
+				} );
+
+				gui.add( playbackConfig, 'wireframe', false ).onChange( function() {
+
+					character.setWireframe( playbackConfig.wireframe );
+
+				} );
+
+				// CHARACTER
+
+				var configOgro = {
+
+					baseUrl: "models/animated/ogro/",
+
+					body: "ogro.js",
+					skins: [ "ogro.jpg", "igdosh.jpg" ],
+					weapons:  [ [ "weapon.js", "weapon.jpg" ]
+								],
+					animations: {
+						move: "run",
+						idle: "stand",
+						jump: "jump",
+						attack: "attack",
+						crouchMove: "cwalk",
+						crouchIdle: "cstand",
+						crouchAttach: "crattack"
+					},
+
+					walkSpeed: 350,
+					crouchSpeed: 175
+
+				};
+
+				var configSoldier = {
+
+					baseUrl: "models/animated/ss-soldier/",
+
+					body: "ss-soldier.js",
+					skins: [ "ss-soldier.jpg" ],
+					weapons:  [ [ "ss-weapon.js", "ss-weapon.jpg" ]
+								],
+					animations: {
+						move: "run",
+						idle: "stand",
+						jump: "jump",
+						attack: "attack",
+						crouchMove: "cwalk",
+						crouchIdle: "cstand",
+						crouchAttach: "crattack"
+					},
+
+					walkSpeed: 275,
+					crouchSpeed: 175
+
+				};
+
+				var configArchvile = {
+
+					baseUrl: "models/animated/archvile/",
+
+					body: "archvile.js",
+					skins: [ "archvile.jpg" ],
+					weapons:  [
+								],
+					animations: {
+						move: "run",
+						idle: "stand",
+						jump: "jump",
+						attack: "attack",
+						crouchMove: "cwalk",
+						crouchIdle: "cstand",
+						crouchAttach: "crattack"
+					},
+
+					walkSpeed: 275,
+					crouchSpeed: 175
+
+				};
+
+				var configRevenant = {
+
+					baseUrl: "models/animated/revenant/",
+
+					body: "revenant.js",
+					skins: [ "revenant.jpg", "revenant2.jpg", "revenant3.jpg", "revenant4.jpg", "revenantfire.jpg", "revenantfire2.jpg", "revenantfire3.jpg", "revenantfire4.jpg" ],
+					weapons:  [ [ "revenant_mf.js", "revenant_mf1.png" ],
+								//[ "revenant_mf.js", "revenant_mf2.png" ]
+								],
+					animations: {
+						move: "walk",
+						idle: "stand",
+						jump: "jump",
+						attack: "attack",
+						crouchMove: "cwalk",
+						crouchIdle: "cstand",
+						crouchAttach: "crattack"
+					},
+
+					walkSpeed: 275,
+					crouchSpeed: 175
+
+				};
+
+				var configKnight = {
+
+					baseUrl: "models/animated/knight/",
+
+					body: "knight.js",
+					skins: [ "skin.jpg" ],
+					weapons:  [
+								],
+					animations: {
+						move: "run",
+						idle: "stand",
+						jump: "jump",
+						attack: "attack",
+						crouchMove: "crwalk",
+						crouchIdle: "crstnd",
+						crouchAttach: "crattk"
+					},
+
+					walkSpeed: 275,
+					crouchSpeed: 175
+
+				};
+
+				var configGoblin = {
+
+					baseUrl: "models/animated/goblin/",
+
+					body: "goblin.js",
+					skins: [ "skin.jpg" ],
+					weapons:  [
+								],
+					animations: {
+						move: "run",
+						idle: "stand",
+						jump: "jump",
+						attack: "attack",
+						crouchMove: "crwalk",
+						crouchIdle: "crstnd",
+						crouchAttach: "crattk"
+					},
+
+					walkSpeed: 275,
+					crouchSpeed: 175
+
+				};
+
+				var configBauul = {
+
+					baseUrl: "models/animated/bauul/",
+
+					body: "bauul.js",
+					skins: [ "skin.jpg", "ctf_r.png", "ctf_b.png" ],
+					weapons:  [ [ "weapon.js", "weapon.png" ]
+								],
+					animations: {
+						move: "run",
+						idle: "stand",
+						jump: "jump",
+						attack: "attack",
+						crouchMove: "crwalk",
+						crouchIdle: "crstnd",
+						crouchAttach: "crattak"
+					},
+
+					walkSpeed: 275,
+					crouchSpeed: 175
+
+				};
+
+				var configRata = {
+
+					baseUrl: "models/animated/ratamahatta/",
+
+					body: "ratamahatta.js",
+					skins: [ "ratamahatta.png", "ctf_b.png", "ctf_r.png", "dead.png", "gearwhore.png" ],
+					weapons:  [  [ "weapon.js", "weapon.png" ],
+								 [ "w_bfg.js", "w_bfg.png" ],
+								 [ "w_blaster.js", "w_blaster.png" ],
+								 [ "w_chaingun.js", "w_chaingun.png" ],
+								 [ "w_glauncher.js", "w_glauncher.png" ],
+								 [ "w_hyperblaster.js", "w_hyperblaster.png" ],
+								 [ "w_machinegun.js", "w_machinegun.png" ],
+								 [ "w_railgun.js", "w_railgun.png" ],
+								 [ "w_rlauncher.js", "w_rlauncher.png" ],
+								 [ "w_shotgun.js", "w_shotgun.png" ],
+								 [ "w_sshotgun.js", "w_sshotgun.png" ]
+								],
+					animations: {
+						move: "run",
+						idle: "stand",
+						jump: "jump",
+						attack: "attack",
+						crouchMove: "crwalk",
+						crouchIdle: "crstand",
+						crouchAttach: "crattack"
+					},
+
+					walkSpeed: 400,
+					crouchSpeed: 175
+
+				};
+
+				character = new THREE.MD2CharacterComplex();
+				character.scale = 3.5;
+				character.controls = controls;
+				//character.animationFPS = 1;
+
+				character.onLoadComplete = function() {
+
+					setupSkinsGUI( character );
+					setupWeaponsGUI( character );
+					setupGUIAnimations( character );
+
+					//console.log( character );
+
+					scene.add( character.root );
+
+					var gyro = new THREE.Gyroscope();
+					gyro.add( camera );
+					character.root.add( gyro );
+
+				}
+
+				character.loadParts( configOgro );
+
+				//createOverlay();
+
+				// COMPOSER
+
+				renderer.autoClear = false;
+
+				renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
+				renderTarget = new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters );
+
+				effectFXAA = new THREE.ShaderPass( THREE.ShaderExtras[ "fxaa" ] );
+				var effectVignette = new THREE.ShaderPass( THREE.ShaderExtras[ "vignette" ] );
+
+				hblur = new THREE.ShaderPass( THREE.ShaderExtras[ "horizontalTiltShift" ] );
+				vblur = new THREE.ShaderPass( THREE.ShaderExtras[ "verticalTiltShift" ] );
+
+				var bluriness = 4;
+
+				hblur.uniforms[ 'h' ].value = bluriness / SCREEN_WIDTH;
+				vblur.uniforms[ 'v' ].value = bluriness / SCREEN_HEIGHT;
+
+				hblur.uniforms[ 'r' ].value = vblur.uniforms[ 'r' ].value = 0.5;
+
+				effectFXAA.uniforms[ 'resolution' ].value.set( 1 / SCREEN_WIDTH, 1 / SCREEN_HEIGHT );
+
+				composer = new THREE.EffectComposer( renderer, renderTarget );
+
+				var renderModel = new THREE.RenderPass( scene, camera );
+
+				effectVignette.renderToScreen = true;
+				vblur.renderToScreen = true;
+
+				composer = new THREE.EffectComposer( renderer, renderTarget );
+
+				composer.addPass( renderModel );
+
+				composer.addPass( effectFXAA );
+
+				composer.addPass( hblur );
+				composer.addPass( vblur );
+
+			}
+
+			// OVERLAY
+
+			function createOverlay() {
+
+				cameraOrtho = new THREE.OrthographicCamera( SCREEN_WIDTH / - 2, SCREEN_WIDTH / 2,  SCREEN_HEIGHT / 2, SCREEN_HEIGHT / - 2, -10, 1000 );
+				cameraOrtho.position.z = 10;
+
+				var shader = THREE.ShaderExtras[ "screen" ];
+				var uniforms = new THREE.UniformsUtils.clone( shader.uniforms );
+
+				hudMaterial = new THREE.ShaderMaterial( { vertexShader: shader.vertexShader, fragmentShader: shader.fragmentShader, uniforms: uniforms } );
+
+				var hudGeo = new THREE.PlaneGeometry( SCREEN_WIDTH, SCREEN_HEIGHT );
+				var hudMesh = new THREE.Mesh( hudGeo, hudMaterial );
+
+				sceneHUD = new THREE.Scene();
+				sceneHUD.add( hudMesh );
+
+				sceneHUD.add( cameraOrtho );
+
+				hudMaterial.uniforms.tDiffuse.texture = THREE.ImageUtils.loadTexture( "textures/vignette.png" );
+				hudMaterial.uniforms.opacity.value = 0.5;
+
+			}
+
+
+			// EVENT HANDLERS
+
+			function onWindowResize( event ) {
+
+				SCREEN_WIDTH = window.innerWidth;
+				SCREEN_HEIGHT = window.innerHeight - 2 * MARGIN;
+
+				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+
+				camera.aspect = SCREEN_WIDTH/ SCREEN_HEIGHT;
+				camera.updateProjectionMatrix();
+
+			}
+
+			function onKeyDown ( event ) {
+
+				switch( event.keyCode ) {
+
+					case 38: /*up*/
+					case 87: /*W*/ 	controls.moveForward = true; break;
+
+					case 40: /*down*/
+					case 83: /*S*/ 	 controls.moveBackward = true; break;
+
+					case 37: /*left*/
+					case 65: /*A*/   controls.moveLeft = true; break;
+
+					case 39: /*right*/
+					case 68: /*D*/    controls.moveRight = true; break;
+
+					case 67: /*C*/     controls.crouch = true; break;
+					case 32: /*space*/ controls.jump = true; break;
+					case 17: /*ctrl*/  controls.attack = true; break;
+
+					case 49: /*1*/	setWeapon( 0 ); break;
+					case 50: /*2*/	setWeapon( 1 ); break;
+					case 51: /*3*/	setWeapon( 2 ); break;
+					case 52: /*4*/	setWeapon( 3 ); break;
+					case 53: /*5*/	setWeapon( 4 ); break;
+					case 54: /*6*/	setWeapon( 5 ); break;
+					case 55: /*7*/	setWeapon( 6 ); break;
+					case 56: /*8*/	setWeapon( 7 ); break;
+					case 57: /*9*/	setWeapon( 8 ); break;
+					case 48: /*0*/	setWeapon( 10 ); break;
+
+				}
+
+			};
+
+			function onKeyUp ( event ) {
+
+				switch( event.keyCode ) {
+
+					case 38: /*up*/
+					case 87: /*W*/ controls.moveForward = false; break;
+
+					case 40: /*down*/
+					case 83: /*S*/ 	 controls.moveBackward = false; break;
+
+					case 37: /*left*/
+					case 65: /*A*/ 	 controls.moveLeft = false; break;
+
+					case 39: /*right*/
+					case 68: /*D*/ 	  controls.moveRight = false; break;
+
+					case 67: /*C*/     controls.crouch = false; break;
+					case 32: /*space*/ controls.jump = false; break;
+					case 17: /*ctrl*/  controls.attack = false; break;
+
+				}
+
+			};
+
+			//
+
+			function setWeapon( index ) {
+
+				character.setWeapon( index );
+
+			};
+
+			// GUI
+
+			function addGuiHeader( label, h, s, v ) {
+
+				// add dummy item
+
+				playbackConfig[ label ] = function() {};
+
+				// hack GUI item styling
+
+				var dummy = gui.add( playbackConfig, label, label );
+				setGuiHeaderStyle( dummy, h, s, v );
+
+			}
+
+			function setGuiHeaderStyle( g, h, s, v ) {
+
+				var color = "hsl(" + h + "," + s + "%, " + v + "%)";
+
+				g.domElement.style.borderLeft = "solid 5px " + color;
+				g.domElement.style.background = color;
+				g.domElement.style.fontWeight = "bold";
+
+			}
+
+			function setGuiElementStyle( a, h, s, v, display ) {
+
+				var i, s, color = "hsl(" + h + "," + s + "%, " + v + "%)";
+
+				for( i = 0; i < a.length; i ++ ) {
+
+					s = a[ i ].domElement.style;
+					s.borderLeft = "solid 5px " + color;
+					s.display = display ? display : "none";
+
+				}
+
+			}
+
+			function labelize( text ) {
+
+				var parts = text.split( "." );
+
+				if ( parts.length > 1 ) {
+
+					parts.length -= 1;
+					return parts.join( "." );
+
+				}
+
+				return text;
+
+			}
+
+			//
+
+			function setupWeaponsGUI( character ) {
+
+				addGuiHeader( "Weapons", 20, 90, 30 );
+
+				var generateCallback = function( index ) {
+
+					return function () { character.setWeapon( index ); };
+
+				}
+
+				var guiItems = [];
+
+				for ( var i = 0; i < character.weapons.length; i ++ ) {
+
+					var name = character.weapons[ i ].name;
+
+					playbackConfig[ name ] = generateCallback( i );
+					guiItems[ i ] = gui.add( playbackConfig, name ).name( labelize( name ) );
+
+				}
+
+				setGuiElementStyle( guiItems, 20, 90, 30, "block" );
+
+			}
+
+			//
+
+			function setupSkinsGUI( character ) {
+
+				addGuiHeader( "Skins", 0, 90, 30 );
+
+				var generateCallback = function( index ) {
+
+					return function () { character.setSkin( index ); };
+
+				}
+
+				var guiItems = [];
+
+				for ( var i = 0; i < character.skinsBody.length; i ++ ) {
+
+					var name = character.skinsBody[ i ].name;
+
+					playbackConfig[ name ] = generateCallback( i );
+					guiItems[ i ] = gui.add( playbackConfig, name ).name( labelize( name ) );
+
+				}
+
+				setGuiElementStyle( guiItems, 0, 90, 30, "block" );
+
+			}
+
+			//
+
+			function setupGUIAnimations( character ) {
+
+				addGuiHeader( "Animations", 100, 90, 30 );
+
+				var generateCallback = function( animationName ) {
+
+					return function () { character.setAnimation( animationName ); };
+
+				}
+
+				var i = 0, guiItems = [];
+				var animations = character.meshBody.geometry.animations;
+
+				for ( var a in animations ) {
+
+					playbackConfig[ a ] = generateCallback( a );
+					guiItems[ i ] = gui.add( playbackConfig, a, a );
+
+					i ++;
+
+				}
+
+				setGuiElementStyle( guiItems, 100, 90, 30, "block" );
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+				render();
+
+				stats.update();
+
+			}
+
+			function render() {
+
+				var delta = clock.getDelta();
+
+				for ( var i = 0; i < morphs.length; i ++ ) {
+
+					morph = morphs[ i ];
+
+					morph.updateAnimation( 1000 * delta );
+
+					morph.position.x += morph.speed * delta;
+
+					if ( morph.position.x  > 4000 )  {
+
+						morph.position.x = -4000 - Math.random() * 500;
+
+					}
+
+				}
+
+				cameraControls.update( delta );
+				character.update( delta );
+
+				//if (  character.meshBody )
+				//console.log( character.meshBody.length, character.meshBody.lastKeyframe,  character.meshBody.currentKeyframe, character.meshBody.morphTargetInfluences );
+
+				//renderer.clear();
+				//renderer.render( scene, camera );
+
+				//renderer.render( sceneHUD, cameraOrtho );
+
+				// render shadow map
+
+				renderer.autoUpdateObjects = false;
+
+				renderer.initWebGLObjects( scene );
+				renderer.updateShadowMap( scene, camera );
+
+				// render scene
+
+				renderer.autoUpdateObjects = true;
+
+				//renderer.render( scene, camera );
+				//renderer.clearTarget( null, 1, 1, 1 );
+				composer.render( 0.1 );
+
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 308 - 0
src/extras/objects/MorphBlendMesh.js

@@ -0,0 +1,308 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.MorphBlendMesh = function( geometry, material ) {
+
+	THREE.Mesh.call( this, geometry, material );
+
+	this.animationsMap = {};
+	this.animationsList = [];
+
+	// prepare default animation
+	// (all frames played together in 1 second)
+
+	var numFrames = this.geometry.morphTargets.length;
+
+	var name = "__default";
+
+	var startFrame = 0;
+	var endFrame = numFrames - 1;
+
+	var fps = numFrames / 1;
+
+	this.createAnimation( name, startFrame, endFrame, fps );
+	this.setAnimationWeight( name, 1 );
+
+};
+
+THREE.MorphBlendMesh.prototype = new THREE.Mesh();
+THREE.MorphBlendMesh.prototype.constructor = THREE.MorphBlendMesh;
+
+THREE.MorphBlendMesh.prototype.createAnimation = function ( name, start, end, fps ) {
+
+	var animation = {
+
+		startFrame: start,
+		endFrame: end,
+
+		length: end - start + 1,
+
+		fps: fps,
+		duration: ( end - start ) / fps,
+
+		lastFrame: 0,
+		currentFrame: 0,
+
+		active: false,
+
+		time: 0,
+		direction: 1,
+		weight: 1,
+
+		directionBackwards: false,
+		mirroredLoop: false
+
+	};
+
+	this.animationsMap[ name ] = animation;
+	this.animationsList.push( animation );
+
+};
+
+THREE.MorphBlendMesh.prototype.autoCreateAnimations = function ( fps ) {
+
+	var pattern = /([a-z]+)(\d+)/;
+
+	var firstAnimation, frameRanges = {};
+
+	var geometry = this.geometry;
+
+	for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
+
+		var morph = geometry.morphTargets[ i ];
+		var chunks = morph.name.match( pattern );
+
+		if ( chunks && chunks.length > 1 ) {
+
+			var name = chunks[ 1 ];
+			var num = chunks[ 2 ];
+
+			if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: -Infinity };
+
+			var range = frameRanges[ name ];
+
+			if ( i < range.start ) range.start = i;
+			if ( i > range.end ) range.end = i;
+
+			if ( ! firstAnimation ) firstAnimation = name;
+
+		}
+
+	}
+
+	for ( var name in frameRanges ) {
+
+		var range = frameRanges[ name ];
+		this.createAnimation( name, range.start, range.end, fps );
+
+	}
+
+	this.firstAnimation = firstAnimation;
+
+};
+
+THREE.MorphBlendMesh.prototype.setAnimationDirectionForward = function ( name ) {
+
+	var animation = this.animationsMap[ name ];
+
+	if ( animation ) {
+
+		animation.direction = 1;
+		animation.directionBackwards = false;
+
+	}
+
+};
+
+THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward = function ( name ) {
+
+	var animation = this.animationsMap[ name ];
+
+	if ( animation ) {
+
+		animation.direction = -1;
+		animation.directionBackwards = true;
+
+	}
+
+};
+
+THREE.MorphBlendMesh.prototype.setAnimationFPS = function ( name, fps ) {
+
+	var animation = this.animationsMap[ name ];
+
+	if ( animation ) {
+
+		animation.fps = fps;
+		animation.duration = ( animation.end - animation.start ) / animation.fps;
+
+	}
+
+};
+
+THREE.MorphBlendMesh.prototype.setAnimationDuration = function ( name, duration ) {
+
+	var animation = this.animationsMap[ name ];
+
+	if ( animation ) {
+
+		animation.duration = duration;
+		animation.fps = ( animation.end - animation.start ) / animation.duration;
+
+	}
+
+};
+
+THREE.MorphBlendMesh.prototype.setAnimationWeight = function ( name, weight ) {
+
+	var animation = this.animationsMap[ name ];
+
+	if ( animation ) {
+
+		animation.weight = weight;
+
+	}
+
+};
+
+THREE.MorphBlendMesh.prototype.setAnimationTime = function ( name, time ) {
+
+	var animation = this.animationsMap[ name ];
+
+	if ( animation ) {
+
+		animation.time = time;
+
+	}
+
+};
+
+THREE.MorphBlendMesh.prototype.getAnimationTime = function ( name ) {
+
+	var time = 0;
+
+	var animation = this.animationsMap[ name ];
+
+	if ( animation ) {
+
+		time = animation.time;
+
+	}
+
+	return time;
+
+};
+
+THREE.MorphBlendMesh.prototype.getAnimationDuration = function ( name ) {
+
+	var duration = -1;
+
+	var animation = this.animationsMap[ name ];
+
+	if ( animation ) {
+
+		duration = animation.duration;
+
+	}
+
+	return duration;
+
+};
+
+THREE.MorphBlendMesh.prototype.playAnimation = function ( name ) {
+
+	var animation = this.animationsMap[ name ];
+
+	if ( animation ) {
+
+		animation.time = 0;
+		animation.active = true;
+
+	} else {
+
+		console.warn( "animation[" + name + "] undefined" );
+
+	}
+
+};
+
+THREE.MorphBlendMesh.prototype.stopAnimation = function ( name ) {
+
+	var animation = this.animationsMap[ name ];
+
+	if ( animation ) {
+
+		animation.active = false;
+
+	}
+
+};
+
+THREE.MorphBlendMesh.prototype.update = function ( delta ) {
+
+	for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) {
+
+		var animation = this.animationsList[ i ];
+
+		if ( ! animation.active ) continue;
+
+		var frameTime = animation.duration / animation.length;
+
+		animation.time += animation.direction * delta;
+
+		if ( animation.mirroredLoop ) {
+
+			if ( animation.time > animation.duration || animation.time < 0 ) {
+
+				animation.direction *= -1;
+
+				if ( animation.time > animation.duration ) {
+
+					animation.time = animation.duration;
+					animation.directionBackwards = true;
+
+				}
+
+				if ( animation.time < 0 ) {
+
+					animation.time = 0;
+					animation.directionBackwards = false;
+
+				}
+
+			}
+
+		} else {
+
+			animation.time = animation.time % animation.duration;
+
+			if ( animation.time < 0 ) animation.time += animation.duration;
+
+		}
+
+		var keyframe = animation.startFrame + THREE.Math.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 );
+		var weight = animation.weight;
+
+		if ( keyframe !== animation.currentFrame ) {
+
+			this.morphTargetInfluences[ animation.lastFrame ] = 0;
+			this.morphTargetInfluences[ animation.currentFrame ] = 1 * weight;
+
+			this.morphTargetInfluences[ keyframe ] = 0;
+
+			animation.lastFrame = animation.currentFrame;
+			animation.currentFrame = keyframe;
+
+		}
+
+		var mix = ( animation.time % frameTime ) / frameTime;
+
+		if ( animation.directionBackwards ) mix = 1 - mix;
+
+		this.morphTargetInfluences[ animation.currentFrame ] = mix * weight;
+		this.morphTargetInfluences[ animation.lastFrame ] = ( 1 - mix ) * weight;
+
+	}
+
+};

+ 1 - 0
utils/build.py

@@ -131,6 +131,7 @@ EXTRAS_FILES = [
 'extras/loaders/UTF8Loader.js',
 'extras/objects/MarchingCubes.js',
 'extras/objects/LensFlare.js',
+'extras/objects/MorphBlendMesh.js',
 'extras/renderers/plugins/LensFlarePlugin.js',
 'extras/renderers/plugins/ShadowMapPlugin.js',
 'extras/renderers/plugins/SpritePlugin.js',

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels