Browse Source

Merge remote branch 'alteredq/dev' into dev

Mr.doob 14 years ago
parent
commit
c5d812da29

File diff suppressed because it is too large
+ 107 - 106
build/Three.js


+ 1 - 1
build/custom/ThreeCanvas.js

@@ -44,7 +44,7 @@ THREE.Matrix4.makeInvert3x3=function(a){var b=a.m33,c=b.m,d=a.n33*a.n22-a.n32*a.
 THREE.Matrix4.makeFrustum=function(a,b,c,d,f,g){var e;e=new THREE.Matrix4;e.n11=2*f/(b-a);e.n12=0;e.n13=(b+a)/(b-a);e.n14=0;e.n21=0;e.n22=2*f/(d-c);e.n23=(d+c)/(d-c);e.n24=0;e.n31=0;e.n32=0;e.n33=-(g+f)/(g-f);e.n34=-2*g*f/(g-f);e.n41=0;e.n42=0;e.n43=-1;e.n44=0;return e};THREE.Matrix4.makePerspective=function(a,b,c,d){var f,a=c*Math.tan(a*Math.PI/360);f=-a;return THREE.Matrix4.makeFrustum(f*b,a*b,f,a,c,d)};
 THREE.Matrix4.makeOrtho=function(a,b,c,d,f,g){var e,h,i,l;e=new THREE.Matrix4;h=b-a;i=c-d;l=g-f;e.n11=2/h;e.n12=0;e.n13=0;e.n14=-((b+a)/h);e.n21=0;e.n22=2/i;e.n23=0;e.n24=-((c+d)/i);e.n31=0;e.n32=0;e.n33=-2/l;e.n34=-((g+f)/l);e.n41=0;e.n42=0;e.n43=0;e.n44=1;return e};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;
 THREE.Object3D=function(){this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=this.dynamic=!1;this.renderDepth=null;this.rotationAutoUpdate=!0;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate=!0;this.quaternion=new THREE.Quaternion;
-this.useQuaternion=!1;this.boundRadius=0;this.boundRadiusScale=1;this.visible=!0;this._vector=new THREE.Vector3;this.name=""};
+this.useQuaternion=!1;this.boundRadius=0;this.boundRadiusScale=1;this.visible=!0;this.receiveShadow=this.castShadow=!1;this._vector=new THREE.Vector3;this.name=""};
 THREE.Object3D.prototype={translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a,this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.setRotationFromMatrix(this.matrix)},addChild:function(a){if(this.children.indexOf(a)===
 -1){a.parent!==void 0&&a.parent.removeChild(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.addChildRecurse(a)}},removeChild:function(a){var b=this.children.indexOf(a);if(b!==-1)a.parent=void 0,this.children.splice(b,1)},getChildByName:function(a,b){var c,d,f;c=0;for(d=this.children.length;c<d;c++){f=this.children[c];if(f.name===a)return f;if(b&&(f=f.getChildByName(a,b),f!==void 0))return f}},updateMatrix:function(){this.matrix.setPosition(this.position);
 this.useQuaternion?this.matrix.setRotationFromQuaternion(this.quaternion):this.matrix.setRotationFromEuler(this.rotation,this.eulerOrder);if(this.scale.x!==1||this.scale.y!==1||this.scale.z!==1)this.matrix.scale(this.scale),this.boundRadiusScale=Math.max(this.scale.x,Math.max(this.scale.y,this.scale.z));this.matrixWorldNeedsUpdate=!0},update:function(a,b,c){this.matrixAutoUpdate&&this.updateMatrix();if(this.matrixWorldNeedsUpdate||b)a?this.matrixWorld.multiply(a,this.matrix):this.matrixWorld.copy(this.matrix),

+ 1 - 1
build/custom/ThreeDOM.js

@@ -44,7 +44,7 @@ THREE.Matrix4.makeInvert3x3=function(a){var b=a.m33,c=b.m,d=a.n33*a.n22-a.n32*a.
 THREE.Matrix4.makeFrustum=function(a,b,c,d,e,g){var f;f=new THREE.Matrix4;f.n11=2*e/(b-a);f.n12=0;f.n13=(b+a)/(b-a);f.n14=0;f.n21=0;f.n22=2*e/(d-c);f.n23=(d+c)/(d-c);f.n24=0;f.n31=0;f.n32=0;f.n33=-(g+e)/(g-e);f.n34=-2*g*e/(g-e);f.n41=0;f.n42=0;f.n43=-1;f.n44=0;return f};THREE.Matrix4.makePerspective=function(a,b,c,d){var e,a=c*Math.tan(a*Math.PI/360);e=-a;return THREE.Matrix4.makeFrustum(e*b,a*b,e,a,c,d)};
 THREE.Matrix4.makeOrtho=function(a,b,c,d,e,g){var f,h,j,i;f=new THREE.Matrix4;h=b-a;j=c-d;i=g-e;f.n11=2/h;f.n12=0;f.n13=0;f.n14=-((b+a)/h);f.n21=0;f.n22=2/j;f.n23=0;f.n24=-((c+d)/j);f.n31=0;f.n32=0;f.n33=-2/i;f.n34=-((g+e)/i);f.n41=0;f.n42=0;f.n43=0;f.n44=1;return f};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;
 THREE.Object3D=function(){this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=this.dynamic=!1;this.renderDepth=null;this.rotationAutoUpdate=!0;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate=!0;this.quaternion=new THREE.Quaternion;
-this.useQuaternion=!1;this.boundRadius=0;this.boundRadiusScale=1;this.visible=!0;this._vector=new THREE.Vector3;this.name=""};
+this.useQuaternion=!1;this.boundRadius=0;this.boundRadiusScale=1;this.visible=!0;this.receiveShadow=this.castShadow=!1;this._vector=new THREE.Vector3;this.name=""};
 THREE.Object3D.prototype={translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a,this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.setRotationFromMatrix(this.matrix)},addChild:function(a){if(this.children.indexOf(a)===
 -1){a.parent!==void 0&&a.parent.removeChild(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.addChildRecurse(a)}},removeChild:function(a){var b=this.children.indexOf(a);if(b!==-1)a.parent=void 0,this.children.splice(b,1)},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c<d;c++){e=this.children[c];if(e.name===a)return e;if(b&&(e=e.getChildByName(a,b),e!==void 0))return e}},updateMatrix:function(){this.matrix.setPosition(this.position);
 this.useQuaternion?this.matrix.setRotationFromQuaternion(this.quaternion):this.matrix.setRotationFromEuler(this.rotation,this.eulerOrder);if(this.scale.x!==1||this.scale.y!==1||this.scale.z!==1)this.matrix.scale(this.scale),this.boundRadiusScale=Math.max(this.scale.x,Math.max(this.scale.y,this.scale.z));this.matrixWorldNeedsUpdate=!0},update:function(a,b,c){this.matrixAutoUpdate&&this.updateMatrix();if(this.matrixWorldNeedsUpdate||b)a?this.matrixWorld.multiply(a,this.matrix):this.matrixWorld.copy(this.matrix),

+ 9 - 9
build/custom/ThreeExtras.js

@@ -40,10 +40,10 @@ void 0)this.constrainVertical=a.constrainVertical;if(a.verticalMin!==void 0)this
 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.mouseX=a.clientX-this.windowHalfX;this.mouseY=a.clientY-this.windowHalfY};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=!1;break;case 70:this.moveDown=!1}};this.update=
 function(){var a=(new Date).getTime();this.tdiff=(a-this.lastUpdate)/1E3;this.lastUpdate=a;if(!this.freeze){this.autoSpeedFactor=this.heightSpeed?this.tdiff*((this.position.y<this.heightMin?this.heightMin:this.position.y>this.heightMax?this.heightMax:this.position.y)-this.heightMin)*this.heightCoef:0;var c=this.tdiff*this.movementSpeed;(this.moveForward||this.autoForward&&!this.moveBackward)&&this.translateZ(-(c+this.autoSpeedFactor));this.moveBackward&&this.translateZ(c);this.moveLeft&&this.translateX(-c);
-this.moveRight&&this.translateX(c);this.moveUp&&this.translateY(c);this.moveDown&&this.translateY(-c);c=this.tdiff*this.lookSpeed;this.activeLook||(c=0);this.lon+=this.mouseX*c;this.lookVertical&&(this.lat-=this.mouseY*c);this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var a=this.target.position,f=this.position;a.x=f.x+100*Math.sin(this.phi)*Math.cos(this.theta);a.y=f.y+100*Math.cos(this.phi);a.z=f.z+100*Math.sin(this.phi)*Math.sin(this.theta)}this.lon+=
-this.mouseX*c;this.lookVertical&&(this.lat-=this.mouseY*c);this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi=(this.phi-0)*(this.verticalMax-this.verticalMin)/3.14+this.verticalMin;a=this.target.position;f=this.position;a.x=f.x+100*Math.sin(this.phi)*Math.cos(this.theta);a.y=f.y+100*Math.cos(this.phi);a.z=f.z+100*Math.sin(this.phi)*Math.sin(this.theta);this.supr.update.call(this)};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.FirstPersonCamera.prototype=new THREE.Camera;THREE.FirstPersonCamera.prototype.constructor=THREE.FirstPersonCamera;
-THREE.FirstPersonCamera.prototype.supr=THREE.Camera.prototype;THREE.FirstPersonCamera.prototype.translate=function(a,c){this.matrix.rotateAxis(c);if(this.noFly)c.y=0;this.position.addSelf(c.multiplyScalar(a));this.target.position.addSelf(c.multiplyScalar(a))};
+this.moveRight&&this.translateX(c);this.moveUp&&this.translateY(c);this.moveDown&&this.translateY(-c);c=this.tdiff*this.lookSpeed;this.activeLook||(c=0);this.lon+=this.mouseX*c;this.lookVertical&&(this.lat-=this.mouseY*c);this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;var a=this.target.position,f=this.position;a.x=f.x+100*Math.sin(this.phi)*Math.cos(this.theta);a.y=f.y+100*Math.cos(this.phi);a.z=f.z+100*Math.sin(this.phi)*Math.sin(this.theta)}a=
+1;this.constrainVertical&&(a=3.14/(this.verticalMax-this.verticalMin));this.lon+=this.mouseX*c;this.lookVertical&&(this.lat-=this.mouseY*c*a);this.lat=Math.max(-85,Math.min(85,this.lat));this.phi=(90-this.lat)*Math.PI/180;this.theta=this.lon*Math.PI/180;if(this.constrainVertical)this.phi=(this.phi-0)*(this.verticalMax-this.verticalMin)/3.14+this.verticalMin;a=this.target.position;f=this.position;a.x=f.x+100*Math.sin(this.phi)*Math.cos(this.theta);a.y=f.y+100*Math.cos(this.phi);a.z=f.z+100*Math.sin(this.phi)*
+Math.sin(this.theta);this.supr.update.call(this)};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.FirstPersonCamera.prototype=new THREE.Camera;THREE.FirstPersonCamera.prototype.constructor=THREE.FirstPersonCamera;THREE.FirstPersonCamera.prototype.supr=THREE.Camera.prototype;THREE.FirstPersonCamera.prototype.translate=function(a,c){this.matrix.rotateAxis(c);if(this.noFly)c.y=0;this.position.addSelf(c.multiplyScalar(a));this.target.position.addSelf(c.multiplyScalar(a))};
 THREE.PathCamera=function(a){function c(a,b,c,e){var g={name:c,fps:0.6,length:e,hierarchy:[]},h,f=b.getControlPointsArray(),j=b.getLength(),k=f.length,y=0;h=k-1;b={parent:-1,keys:[]};b.keys[0]={time:0,pos:f[0],rot:[0,0,0,1],scl:[1,1,1]};b.keys[h]={time:e,pos:f[h],rot:[0,0,0,1],scl:[1,1,1]};for(h=1;h<k-1;h++)y=e*j.chunks[h]/j.total,b.keys[h]={time:y,pos:f[h]};g.hierarchy[0]=b;THREE.AnimationHandler.add(g);return new THREE.Animation(a,c,THREE.AnimationHandler.CATMULLROM_FORWARD,!1)}function b(a,b){var c,
 e,g=new THREE.Geometry;for(c=0;c<a.points.length*b;c++)e=c/(a.points.length*b),e=a.getPoint(e),g.vertices[c]=new THREE.Vertex(new THREE.Vector3(e.x,e.y,e.z));return g}function g(a,c){var e=b(c,10),g=b(c,10),h=new THREE.LineBasicMaterial({color:16711680,linewidth:3});lineObj=new THREE.Line(e,h);particleObj=new THREE.ParticleSystem(g,new THREE.ParticleBasicMaterial({color:16755200,size:3}));lineObj.scale.set(1,1,1);a.addChild(lineObj);particleObj.scale.set(1,1,1);a.addChild(particleObj);g=new THREE.SphereGeometry(1,
 16,8);h=new THREE.MeshBasicMaterial({color:65280});for(i=0;i<c.points.length;i++)e=new THREE.Mesh(g,h),e.position.copy(c.points[i]),e.updateMatrix(),a.addChild(e)}THREE.Camera.call(this,a.fov,a.aspect,a.near,a.far,a.target);this.id="PathCamera"+THREE.PathCameraIdCounter++;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.0050;this.lookHorizontal=
@@ -142,11 +142,11 @@ THREE.FontUtils={faces:{},face:"helvetiker",weight:"normal",style:"normal",size:
 t,v,x;h=[];for(e=0;e<j.length;e++){k=j[e];f=k.shape;g=k.holes;for(l=0;l<g.length;l++){m=g[l];w=Number.POSITIVE_INFINITY;for(n=0;n<m.length;n++){v=m[n];for(b=0;b<f.length;b++)t=f[b],t=v.distanceTo(t),t<w&&(w=t,o=n,p=b)}b=p-1>=0?p-1:f.length-1;var n=o-1>=0?o-1:m.length-1,y=[];y.push(m[o]);y.push(f[p]);y.push(f[b]);w=this.Triangulate.area(y);var u=[];u.push(m[o]);u.push(m[n]);u.push(f[p]);v=this.Triangulate.area(u);t=p;x=o;p+=1;o+=-1;p<0&&(p+=f.length);p%=f.length;o<0&&(o+=m.length);o%=f.length;b=p-
 1>=0?p-1:f.length-1;n=o-1>=0?o-1:m.length-1;y=[];y.push(m[o]);y.push(f[p]);y.push(f[b]);y=this.Triangulate.area(y);u=[];u.push(m[o]);u.push(m[n]);u.push(f[p]);u=this.Triangulate.area(u);w+v>y+u&&(p=t,o=x,p<0&&(p+=f.length),p%=f.length,o<0&&(o+=m.length),o%=f.length,b=p-1>=0?p-1:f.length-1,n=o-1>=0?o-1:m.length-1);w=f.slice(0,p);v=f.slice(p);t=m.slice(o);x=m.slice(0,o);h.push(m[o]);h.push(f[p]);h.push(f[b]);h.push(m[o]);h.push(m[n]);h.push(f[p]);f=w.concat(t).concat(x).concat(v)}k.shape=f}o=[];p=[];
 for(e=l=0;e<j.length;e++){k=j[e];f=k.shape;o=o.concat(f);m=THREE.FontUtils.Triangulate(f,!0);for(g=0;g<m.length;g++)k=m[g],k[0]+=l,k[1]+=l,k[2]+=l;p=p.concat(m);l+=f.length}var z;for(g=0;g<h.length/3;g++){k=[];for(j=0;j<3;j++){e=!1;for(f=0;f<o.length&&!e;f++)z=g*3+j,o[f].equals(h[z])&&(k.push(f),e=!0);e||(o.push(h[z]),k.push(o.length-1),console.log("not found"))}p.push(k)}return{points:o,faces:p}},drawText:function(a){var c=[],b=[],g,f=this.getFace(),h=this.size/f.resolution,e=0;g=String(a).split("");
-for(var j=g.length,k=new THREE.Path,a=0;a<j;a++){var l=this.extractGlyphPoints(g[a],f,h,e,k);e+=l.offset;c.push(l.points);b=b.concat(l.points)}console.log(k);a=e/2;for(g=0;g<b.length;g++)b[g].x-=a;c=this.extractPoints(b,c);c.contour=b;f=[];h=[];g=[];for(var e=[],j=new THREE.Vector2,m,a=b.length;--a>=0;){if(m){if(m.equals(b[a])){m=null;k=this.Triangulate.area(g)>0;e.push(k);h.push(j.divideScalar(g.length));g=[];j=new THREE.Vector2;continue}}else m=b[a];j.addSelf(b[a]);g.push(b[a])}a=b.length;for(g=
-0;--a>=0;)k=b[a],j=h[g],k=k.clone().subSelf(j),l=this.bevelSize/k.length(),e[g]?l+=1:l=1-l,l=k.multiplyScalar(l).addSelf(j),f.unshift(l),m?m.equals(b[a])&&(m=null,g++):m=b[a];c.bevel=f;return c},b2p0:function(a,c){var b=1-a;return b*b*c},b2p1:function(a,c){return 2*(1-a)*a*c},b2p2:function(a,c){return a*a*c},b2:function(a,c,b,g){return this.b2p0(a,c)+this.b2p1(a,b)+this.b2p2(a,g)},b3p0:function(a,c){var b=1-a;return b*b*b*c},b3p1:function(a,c){var b=1-a;return 3*b*b*a*c},b3p2:function(a,c){return 3*
-(1-a)*a*a*c},b3p3:function(a,c){return a*a*a*c},b3:function(a,c,b,g,f){return this.b3p0(a,c)+this.b3p1(a,b)+this.b3p2(a,g)+this.b3p3(a,f)},extractGlyphPoints:function(a,c,b,g,f){var h=[],e,j,k,l,m,n,o,p,w,t,v=c.glyphs[a]||c.glyphs[ctxt.options.fallbackCharacter];if(v){if(v.o){c=v._cachedOutline||(v._cachedOutline=v.o.split(" "));k=c.length;for(a=0;a<k;)switch(j=c[a++],j){case "m":j=c[a++]*b+g;l=c[a++]*b;h.push(new THREE.Vector2(j,l));f.moveTo(j,l);break;case "l":j=c[a++]*b+g;l=c[a++]*b;h.push(new THREE.Vector2(j,
-l));f.lineTo(j,l);break;case "q":j=c[a++]*b+g;l=c[a++]*b;o=c[a++]*b+g;p=c[a++]*b;f.quadraticCurveTo(o,p,j,l);if(e=h[h.length-1]){m=e.x;n=e.y;e=1;for(divisions=this.divisions;e<=divisions;e++){var x=e/divisions,y=THREE.FontUtils.b2(x,m,o,j),x=THREE.FontUtils.b2(x,n,p,l);h.push(new THREE.Vector2(y,x))}}break;case "b":if(j=c[a++]*b+g,l=c[a++]*b,o=c[a++]*b+g,p=c[a++]*-b,w=c[a++]*b+g,t=c[a++]*-b,f.bezierCurveTo(j,l,o,p,w,t),e=h[h.length-1]){m=e.x;n=e.y;e=1;for(divisions=this.divisions;e<=divisions;e++)x=
-e/divisions,y=THREE.FontUtils.b3(x,m,o,w,j),x=THREE.FontUtils.b3(x,n,p,t,l),h.push(new THREE.Vector2(y,x))}}}return{offset:v.ha*b,points:h,path:f}}}};
+for(var j=g.length,k=new THREE.Path,a=0;a<j;a++){var l=this.extractGlyphPoints(g[a],f,h,e,k);e+=l.offset;c.push(l.points);b=b.concat(l.points)}a=e/2;for(g=0;g<b.length;g++)b[g].x-=a;c=this.extractPoints(b,c);c.contour=b;f=[];h=[];g=[];for(var e=[],j=new THREE.Vector2,m,a=b.length;--a>=0;){if(m){if(m.equals(b[a])){m=null;k=this.Triangulate.area(g)>0;e.push(k);h.push(j.divideScalar(g.length));g=[];j=new THREE.Vector2;continue}}else m=b[a];j.addSelf(b[a]);g.push(b[a])}a=b.length;for(g=0;--a>=0;)k=b[a],
+j=h[g],k=k.clone().subSelf(j),l=this.bevelSize/k.length(),e[g]?l+=1:l=1-l,l=k.multiplyScalar(l).addSelf(j),f.unshift(l),m?m.equals(b[a])&&(m=null,g++):m=b[a];c.bevel=f;return c},b2p0:function(a,c){var b=1-a;return b*b*c},b2p1:function(a,c){return 2*(1-a)*a*c},b2p2:function(a,c){return a*a*c},b2:function(a,c,b,g){return this.b2p0(a,c)+this.b2p1(a,b)+this.b2p2(a,g)},b3p0:function(a,c){var b=1-a;return b*b*b*c},b3p1:function(a,c){var b=1-a;return 3*b*b*a*c},b3p2:function(a,c){return 3*(1-a)*a*a*c},b3p3:function(a,
+c){return a*a*a*c},b3:function(a,c,b,g,f){return this.b3p0(a,c)+this.b3p1(a,b)+this.b3p2(a,g)+this.b3p3(a,f)},extractGlyphPoints:function(a,c,b,g,f){var h=[],e,j,k,l,m,n,o,p,w,t,v=c.glyphs[a]||c.glyphs[ctxt.options.fallbackCharacter];if(v){if(v.o){c=v._cachedOutline||(v._cachedOutline=v.o.split(" "));k=c.length;for(a=0;a<k;)switch(j=c[a++],j){case "m":j=c[a++]*b+g;l=c[a++]*b;h.push(new THREE.Vector2(j,l));f.moveTo(j,l);break;case "l":j=c[a++]*b+g;l=c[a++]*b;h.push(new THREE.Vector2(j,l));f.lineTo(j,
+l);break;case "q":j=c[a++]*b+g;l=c[a++]*b;o=c[a++]*b+g;p=c[a++]*b;f.quadraticCurveTo(o,p,j,l);if(e=h[h.length-1]){m=e.x;n=e.y;e=1;for(divisions=this.divisions;e<=divisions;e++){var x=e/divisions,y=THREE.FontUtils.b2(x,m,o,j),x=THREE.FontUtils.b2(x,n,p,l);h.push(new THREE.Vector2(y,x))}}break;case "b":if(j=c[a++]*b+g,l=c[a++]*b,o=c[a++]*b+g,p=c[a++]*-b,w=c[a++]*b+g,t=c[a++]*-b,f.bezierCurveTo(j,l,o,p,w,t),e=h[h.length-1]){m=e.x;n=e.y;e=1;for(divisions=this.divisions;e<=divisions;e++)x=e/divisions,
+y=THREE.FontUtils.b3(x,m,o,w,j),x=THREE.FontUtils.b3(x,n,p,t,l),h.push(new THREE.Vector2(y,x))}}}return{offset:v.ha*b,points:h,path:f}}}};
 (function(a){var c=function(a){for(var c=a.length,f=0,h=c-1,e=0;e<c;h=e++)f+=a[h].x*a[e].y-a[e].x*a[h].y;return f*0.5};a.Triangulate=function(a,g){var f=a.length;if(f<3)return null;var h=[],e=[],j=[],k,l,m;if(c(a)>0)for(l=0;l<f;l++)e[l]=l;else for(l=0;l<f;l++)e[l]=f-1-l;var n=2*f;for(l=f-1;f>2;){if(n--<=0){console.log("Warning, unable to triangulate polygon!");if(g)return j;return h}k=l;f<=k&&(k=0);l=k+1;f<=l&&(l=0);m=l+1;f<=m&&(m=0);var o;a:{o=a;var p=k,w=l,t=m,v=f,x=e,y=void 0,u=void 0,z=void 0,
 B=void 0,A=void 0,E=void 0,G=void 0,H=void 0,L=void 0,u=o[x[p]].x,z=o[x[p]].y,B=o[x[w]].x,A=o[x[w]].y,E=o[x[t]].x,G=o[x[t]].y;if(1.0E-10>(B-u)*(G-z)-(A-z)*(E-u))o=!1;else{for(y=0;y<v;y++)if(!(y==p||y==w||y==t)){var H=o[x[y]].x,L=o[x[y]].y,J=void 0,D=void 0,K=void 0,F=void 0,I=void 0,O=void 0,M=void 0,C=void 0,P=void 0,N=void 0,R=void 0,S=void 0,J=K=I=void 0,J=E-B,D=G-A,K=u-E,F=z-G,I=B-u,O=A-z,M=H-u,C=L-z,P=H-B,N=L-A,R=H-E,S=L-G,J=J*N-D*P,I=I*C-O*M,K=K*S-F*R;if(J>=0&&K>=0&&I>=0){o=!1;break a}}o=!0}}if(o){h.push([a[e[k]],
 a[e[l]],a[e[m]]]);j.push([e[k],e[l],e[m]]);k=l;for(m=l+1;m<f;k++,m++)e[k]=e[m];f--;n=2*f}}if(g)return j;return h};a.Triangulate.area=c;return a})(THREE.FontUtils);window._typeface_js={faces:THREE.FontUtils.faces,loadFace:THREE.FontUtils.loadFace};

+ 1 - 1
build/custom/ThreeSVG.js

@@ -44,7 +44,7 @@ THREE.Matrix4.makeInvert3x3=function(a){var b=a.m33,c=b.m,d=a.n33*a.n22-a.n32*a.
 THREE.Matrix4.makeFrustum=function(a,b,c,d,e,g){var f;f=new THREE.Matrix4;f.n11=2*e/(b-a);f.n12=0;f.n13=(b+a)/(b-a);f.n14=0;f.n21=0;f.n22=2*e/(d-c);f.n23=(d+c)/(d-c);f.n24=0;f.n31=0;f.n32=0;f.n33=-(g+e)/(g-e);f.n34=-2*g*e/(g-e);f.n41=0;f.n42=0;f.n43=-1;f.n44=0;return f};THREE.Matrix4.makePerspective=function(a,b,c,d){var e,a=c*Math.tan(a*Math.PI/360);e=-a;return THREE.Matrix4.makeFrustum(e*b,a*b,e,a,c,d)};
 THREE.Matrix4.makeOrtho=function(a,b,c,d,e,g){var f,h,k,l;f=new THREE.Matrix4;h=b-a;k=c-d;l=g-e;f.n11=2/h;f.n12=0;f.n13=0;f.n14=-((b+a)/h);f.n21=0;f.n22=2/k;f.n23=0;f.n24=-((c+d)/k);f.n31=0;f.n32=0;f.n33=-2/l;f.n34=-((g+e)/l);f.n41=0;f.n42=0;f.n43=0;f.n44=1;return f};THREE.Matrix4.__v1=new THREE.Vector3;THREE.Matrix4.__v2=new THREE.Vector3;THREE.Matrix4.__v3=new THREE.Vector3;
 THREE.Object3D=function(){this.parent=void 0;this.children=[];this.up=new THREE.Vector3(0,1,0);this.position=new THREE.Vector3;this.rotation=new THREE.Vector3;this.eulerOrder="XYZ";this.scale=new THREE.Vector3(1,1,1);this.flipSided=this.doubleSided=this.dynamic=!1;this.renderDepth=null;this.rotationAutoUpdate=!0;this.matrix=new THREE.Matrix4;this.matrixWorld=new THREE.Matrix4;this.matrixRotationWorld=new THREE.Matrix4;this.matrixWorldNeedsUpdate=this.matrixAutoUpdate=!0;this.quaternion=new THREE.Quaternion;
-this.useQuaternion=!1;this.boundRadius=0;this.boundRadiusScale=1;this.visible=!0;this._vector=new THREE.Vector3;this.name=""};
+this.useQuaternion=!1;this.boundRadius=0;this.boundRadiusScale=1;this.visible=!0;this.receiveShadow=this.castShadow=!1;this._vector=new THREE.Vector3;this.name=""};
 THREE.Object3D.prototype={translate:function(a,b){this.matrix.rotateAxis(b);this.position.addSelf(b.multiplyScalar(a))},translateX:function(a){this.translate(a,this._vector.set(1,0,0))},translateY:function(a){this.translate(a,this._vector.set(0,1,0))},translateZ:function(a){this.translate(a,this._vector.set(0,0,1))},lookAt:function(a){this.matrix.lookAt(a,this.position,this.up);this.rotationAutoUpdate&&this.rotation.setRotationFromMatrix(this.matrix)},addChild:function(a){if(this.children.indexOf(a)===
 -1){a.parent!==void 0&&a.parent.removeChild(a);a.parent=this;this.children.push(a);for(var b=this;b.parent!==void 0;)b=b.parent;b!==void 0&&b instanceof THREE.Scene&&b.addChildRecurse(a)}},removeChild:function(a){var b=this.children.indexOf(a);if(b!==-1)a.parent=void 0,this.children.splice(b,1)},getChildByName:function(a,b){var c,d,e;c=0;for(d=this.children.length;c<d;c++){e=this.children[c];if(e.name===a)return e;if(b&&(e=e.getChildByName(a,b),e!==void 0))return e}},updateMatrix:function(){this.matrix.setPosition(this.position);
 this.useQuaternion?this.matrix.setRotationFromQuaternion(this.quaternion):this.matrix.setRotationFromEuler(this.rotation,this.eulerOrder);if(this.scale.x!==1||this.scale.y!==1||this.scale.z!==1)this.matrix.scale(this.scale),this.boundRadiusScale=Math.max(this.scale.x,Math.max(this.scale.y,this.scale.z));this.matrixWorldNeedsUpdate=!0},update:function(a,b,c){this.matrixAutoUpdate&&this.updateMatrix();if(this.matrixWorldNeedsUpdate||b)a?this.matrixWorld.multiply(a,this.matrix):this.matrixWorld.copy(this.matrix),

File diff suppressed because it is too large
+ 75 - 75
build/custom/ThreeWebGL.js


+ 416 - 0
examples/webgl_shadowmap.html

@@ -0,0 +1,416 @@
+<!DOCTYPE HTML>
+<html lang="en">
+	<head>
+		<title>three.js webgl - shadow map</title>
+		<meta charset="utf-8">
+		<style type="text/css">
+			body {
+				font-family: Monospace;
+				background-color: #000;
+				color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#info {
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				z-index: 100;
+				display:block;
+			}
+			#info a { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
+		</style>
+	</head>
+
+	<body>
+
+		<div id="info">
+		<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - shadowmap - models by <a href="http://mirada.com/">mirada</a> from <a href="http://ro.me">rome</a></br>
+		move camera with WASD / RF + mouse
+		</div>
+
+		<script type="text/javascript" src="../build/Three.js"></script>
+
+		<script type="text/javascript" src="js/Detector.js"></script>
+		<script type="text/javascript" src="js/RequestAnimationFrame.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
+
+		<script type="text/javascript" src="fonts/helvetiker_bold.typeface.js"></script>
+
+		<script type="text/javascript">
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var SHADOW_MAP_WIDTH = 1024, SHADOW_MAP_HEIGHT = 1024;
+
+			var MARGIN = 100;
+
+			var SCREEN_WIDTH = window.innerWidth;
+			var SCREEN_HEIGHT = window.innerHeight - 2 * MARGIN;
+			var FLOOR = -250;
+
+			var camera, scene, renderer;
+			var container, stats;
+
+			var NEAR = 5, FAR = 3000;
+
+			var sceneHUD, cameraOrtho, hudMaterial;
+
+			var initPos = new THREE.Vector3( 700, 50, 1900 );
+			var initLight = new THREE.Vector3( 0, 1500, 1000 );
+			var deltaCam = new THREE.Vector3();
+
+			var morphs = [];
+
+			var light;
+
+			init();
+			animate();
+
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				// SCENE CAMERA
+
+				camera = new THREE.FirstPersonCamera( { fov: 23, aspect: SCREEN_WIDTH / SCREEN_HEIGHT, near: NEAR, far: FAR,
+														lookSpeed: 0.0125, movementSpeed: 500, noFly: false, lookVertical: true,
+														constrainVertical: true, verticalMin: 1.5, verticalMax: 2.0
+														} );
+
+				camera.position.set( 700, 50, 1900 );
+				camera.lon = -110;
+
+				// SHADOW TEXTURE
+
+				var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
+				shadowTexture = new THREE.WebGLRenderTarget( SHADOW_MAP_WIDTH, SHADOW_MAP_HEIGHT, pars );
+
+				// SCENE
+
+				scene = new THREE.Scene();
+				scene.fog = new THREE.Fog( 0xffaa55, 1000, FAR );
+				THREE.ColorUtils.adjustHSV( scene.fog.color, 0.02, -0.15, -0.65 );
+
+				// LIGHTS
+
+				var ambient = new THREE.AmbientLight( 0x444444 );
+				scene.addLight( ambient );
+
+				light = new THREE.SpotLight( 0xffffff );
+				light.position.set( 0, 1500, 1000 );
+				light.target.position.set( 0, 0, 0 );
+				light.castShadow = true;
+				scene.addLight( light );
+
+				createHUD();
+				createScene();
+
+				// RENDERER
+
+				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: false } );
+				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+				renderer.domElement.style.position = "relative";
+				renderer.domElement.style.top = MARGIN + 'px';
+				container.appendChild( renderer.domElement );
+
+				renderer.setClearColor( scene.fog.color, 1 );
+				renderer.autoClear = false;
+
+				renderer.shadowCameraNear = 3;
+				renderer.shadowCameraFar = camera.far;
+				renderer.shadowCameraFov = 50;
+
+				renderer.shadowMapBias = 0.0039;
+				renderer.shadowMapDarkness = 0.5;
+				renderer.shadowMapWidth = SHADOW_MAP_WIDTH;
+				renderer.shadowMapHeight = SHADOW_MAP_HEIGHT;
+
+				renderer.shadowMapEnabled = true;
+				renderer.shadowMapSoft = true;
+
+				// STATS
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				stats.domElement.style.zIndex = 100;
+				//container.appendChild( stats.domElement );
+
+			}
+
+			function createHUD() {
+
+				cameraOrtho = new THREE.Camera( 45, SHADOW_MAP_WIDTH / SHADOW_MAP_HEIGHT, NEAR, FAR );
+				cameraOrtho.projectionMatrix = THREE.Matrix4.makeOrtho( SCREEN_WIDTH / - 2, SCREEN_WIDTH / 2,  SCREEN_HEIGHT / 2, SCREEN_HEIGHT / - 2, -10, 1000 );
+				cameraOrtho.position.z = 10;
+
+				var shader = THREE.ShaderUtils.lib[ "screen" ];
+				var uniforms = new THREE.UniformsUtils.clone( shader.uniforms );
+
+				hudMaterial = new THREE.MeshShaderMaterial( { vertexShader: shader.vertexShader, fragmentShader: shader.fragmentShader, uniforms: uniforms } );
+
+				var hudGeo = new THREE.PlaneGeometry( SHADOW_MAP_WIDTH / 2, SHADOW_MAP_HEIGHT / 2 );
+				var hudMesh = new THREE.Mesh( hudGeo, hudMaterial );
+				hudMesh.position.x = ( SCREEN_WIDTH - SHADOW_MAP_WIDTH / 2 ) * -0.5;
+				hudMesh.position.y = ( SCREEN_HEIGHT - SHADOW_MAP_HEIGHT / 2 ) * -0.5;
+
+				sceneHUD = new THREE.Scene();
+				sceneHUD.addObject( hudMesh );
+
+			}
+
+			function createScene( ) {
+
+				// GROUND
+
+				var geometry = new THREE.PlaneGeometry( 100, 100 );
+				var planeMaterial = new THREE.MeshLambertMaterial( { color: 0xffdd99 } );
+				THREE.ColorUtils.adjustHSV( planeMaterial.color, 0, 0, 0.9 );
+
+				var ground = new THREE.Mesh( geometry, planeMaterial );
+
+				ground.position.set( 0, FLOOR, 0 );
+				ground.rotation.x = -1.57;
+				ground.scale.set( 100, 100, 100 );
+
+				ground.castShadow = false;
+				ground.receiveShadow = true;
+
+				scene.addObject( ground );
+
+				// TEXT
+
+				var textGeo = new THREE.TextGeometry( "THREE.JS", {
+
+					size: 200,
+					height: 50,
+					curveSegments: 7,
+
+					font: "helvetiker",
+					weight: "bold",
+					style: "normal",
+
+					bevelThickness: 1,
+					bevelSize: 5,
+					bevelEnabled: true
+
+				});
+
+				var textMaterial = new THREE.MeshPhongMaterial( { color: 0xff0000, specular: 0xffffff, ambient: 0xaa0000 } );
+
+				var mesh = new THREE.Mesh( textGeo, textMaterial );
+				mesh.position.y = FLOOR + 67;
+
+				mesh.castShadow = true;
+				mesh.receiveShadow = true;
+
+				scene.addObject( mesh );
+
+				// CUBES
+
+				var mesh = new THREE.Mesh( new THREE.CubeGeometry( 1500, 220, 150 ), planeMaterial );
+
+				mesh.position.y = FLOOR - 50;
+				mesh.position.z = 20;
+
+				mesh.castShadow = true;
+				mesh.receiveShadow = true;
+
+				scene.addObject( mesh );
+
+				var mesh = new THREE.Mesh( new THREE.CubeGeometry( 1600, 170, 250 ), planeMaterial );
+
+				mesh.position.y = FLOOR - 50;
+				mesh.position.z = 20;
+
+				mesh.castShadow = true;
+				mesh.receiveShadow = true;
+
+				scene.addObject( mesh );
+
+				// MORPHS
+
+				function addMorph( geometry, speed, duration, x, y, z, fudgeColor ) {
+
+					var material = new THREE.MeshLambertMaterial( { color: 0xffaa55, morphTargets: true, vertexColors: THREE.FaceColors } );
+
+					if ( fudgeColor ) THREE.ColorUtils.adjustHSV( material.color, 0, 0.5 - Math.random(), 0.5 - Math.random() );
+
+					var meshAnim = new THREE.Mesh( geometry, material );
+
+					meshAnim.position.set( x, y, z );
+					meshAnim.rotation.y = 1.57;
+
+					meshAnim.castShadow = true;
+					meshAnim.receiveShadow = false;
+
+					scene.addObject( meshAnim );
+
+					morphs.push( { mesh: meshAnim, lastKeyframe: 0, currentKeyframe: 0,
+								   offset: Math.random() * 6, speed: speed, duration: duration,
+								   oldTime: new Date().getTime() } );
+
+				}
+
+				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( { model: "models/animated/horse.js", callback: function( geometry ) {
+
+					morphColorsToFaceColors( geometry );
+
+					addMorph( geometry, 0.55, 1000, 100 - Math.random() * 1000, FLOOR, 300, true );
+					addMorph( geometry, 0.55, 1000, 100 - Math.random() * 1000, FLOOR, 450, true );
+					addMorph( geometry, 0.55, 1000, 100 - Math.random() * 1000, FLOOR, 600, true );
+
+					addMorph( geometry, 0.55, 1000, 100 - Math.random() * 1000, FLOOR, -300, true );
+					addMorph( geometry, 0.55, 1000, 100 - Math.random() * 1000, FLOOR, -450, true );
+					addMorph( geometry, 0.55, 1000, 100 - Math.random() * 1000, FLOOR, -600, true );
+
+				} } );
+
+				/*
+				loader.load( { model: "obj/morphs/fox.js", callback: function( geometry ) {
+
+					morphColorsToFaceColors( geometry );
+					addMorph( geometry, 0.2, 1000, 100 - Math.random() * 500, FLOOR - 5, 600 );
+
+				} } );
+
+				loader.load( { model: "obj/morphs/shdw3walk.js", callback: function( geometry ) {
+
+					morphColorsToFaceColors( geometry );
+					addMorph( geometry, 0.04, 2000, -500, FLOOR + 60, 245 );
+
+				} } );
+
+				loader.load( { model: "obj/morphs/flamingo.js", callback: function( geometry ) {
+
+					morphColorsToFaceColors( geometry );
+					addMorph( geometry, 0.5, 1000, 500 - Math.random() * 500, FLOOR + 350, 40 );
+
+				} } );
+
+				loader.load( { model: "obj/morphs/stork.js", callback: function( geometry ) {
+
+					morphColorsToFaceColors( geometry );
+					addMorph( geometry, 0.35, 1000, 500 - Math.random() * 500, FLOOR + 350, 340 );
+
+				} } );
+
+				loader.load( { model: "obj/morphs/mountainlion.js", callback: function( geometry ) {
+
+					morphColorsToFaceColors( geometry );
+					addMorph( geometry, 0.4, 1000, 500 - Math.random() * 500, FLOOR - 5, 700 );
+
+				} } );
+
+				loader.load( { model: "obj/morphs/bearBrown.js", callback: function( geometry ) {
+
+					morphColorsToFaceColors( geometry );
+					addMorph( geometry, 0.3, 2500, -500, FLOOR - 5, -750 );
+
+				} } );
+
+				loader.load( { model: "obj/morphs/parrot.js", callback: function( geometry ) {
+
+					morphColorsToFaceColors( geometry );
+					addMorph( geometry, 0.45, 500, 500 - Math.random() * 500, FLOOR + 300, 700 );
+
+				} } );
+
+				*/
+
+			}
+
+
+			var t = 0, newTime, delta;
+
+
+			function updateMorph( morph ) {
+
+				// Alternate morph targets
+
+				var interpolation = morph.duration / ( morph.mesh.geometry.morphTargets.length - 1 );
+
+				var time = ( new Date().getTime()  + morph.offset * 100 ) % morph.duration;
+				var keyframe = Math.floor( time / interpolation ) + 1;
+
+				var mesh = morph.mesh;
+
+				if ( keyframe != morph.currentKeyframe ) {
+
+					mesh.morphTargetInfluences[ morph.lastKeyframe ] = 0;
+					mesh.morphTargetInfluences[ morph.currentKeyframe ] = 1;
+					mesh.morphTargetInfluences[ keyframe ] = 0;
+
+					morph.lastKeyframe = morph.currentKeyframe;
+					morph.currentKeyframe = keyframe;
+
+				}
+
+				mesh.morphTargetInfluences[ keyframe ] = ( time % interpolation ) / interpolation;
+				mesh.morphTargetInfluences[ morph.lastKeyframe ] = 1 - mesh.morphTargetInfluences[ keyframe ];
+
+				var newTime = new Date().getTime();
+				delta = newTime - morph.oldTime;
+				morph.oldTime = newTime;
+
+				mesh.position.x += morph.speed * delta;
+
+				if ( mesh.position.x  > 2000 )  {
+
+					mesh.position.x = -1000 - Math.random() * 500;
+
+				}
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				for ( var i = 0; i < morphs.length; i++ ) updateMorph( morphs[ i ] );
+
+				renderer.clear();
+				renderer.render( scene, camera );
+
+				// Render debug HUD with shadow map
+
+				//hudMaterial.uniforms.tDiffuse.texture = renderer.shadowMap[ 0 ];
+				//renderer.render( sceneHUD, cameraOrtho );
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 4 - 1
src/core/Object3D.js

@@ -17,7 +17,7 @@ THREE.Object3D = function() {
 	this.scale = new THREE.Vector3( 1, 1, 1 );
 
 	this.dynamic = false; // when true it retains arrays so they can be updated with __dirty*
-	
+
 	this.doubleSided = false;
 	this.flipSided = false;
 
@@ -40,6 +40,9 @@ THREE.Object3D = function() {
 
 	this.visible = true;
 
+	this.castShadow = false;
+	this.receiveShadow = false;
+
 	this._vector = new THREE.Vector3();
 
 	this.name = "";

+ 10 - 1
src/extras/cameras/FirstPersonCamera.js

@@ -253,11 +253,20 @@ THREE.FirstPersonCamera = function ( parameters ) {
 
 		}
 
+		var verticalLookRatio = 1;
+
+		if ( this.constrainVertical ) {
+
+			verticalLookRatio = 3.14 / ( this.verticalMax - this.verticalMin );
+
+		}
+
 		this.lon += this.mouseX * actualLookSpeed;
-		if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed;
+		if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
 
 		this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
 		this.phi = ( 90 - this.lat ) * Math.PI / 180;
+
 		this.theta = this.lon * Math.PI / 180;
 
 		if ( this.constrainVertical ) {

+ 1 - 1
src/extras/geometries/TextGeometry.js

@@ -678,7 +678,7 @@ THREE.FontUtils = {
 		}
 
 		//path.debug(document.getElementById("boo"));
-		console.log(path);
+		//console.log(path);
 
 
 		// get the width

+ 20 - 0
src/lights/SpotLight.js

@@ -0,0 +1,20 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.SpotLight = function ( hex, intensity, distance, castShadow ) {
+
+	THREE.Light.call( this, hex );
+
+	this.position = new THREE.Vector3( 0, 1, 0 );
+	this.target = new THREE.Object3D();
+
+	this.intensity = intensity || 1;
+	this.distance = distance || 0;
+
+	this.castShadow = castShadow !== undefined ? castShadow : false;
+
+};
+
+THREE.SpotLight.prototype = new THREE.Light();
+THREE.SpotLight.prototype.constructor = THREE.SpotLight;

+ 379 - 29
src/renderers/WebGLRenderer.js

@@ -92,6 +92,40 @@ THREE.WebGLRenderer = function ( parameters ) {
 	this.autoClear = true;
 	this.sortObjects = true;
 
+	// shadow map
+
+	this.shadowMapBias = 0.0039;
+	this.shadowMapDarkness = 0.5;
+	this.shadowMapWidth = 512;
+	this.shadowMapHeight = 512;
+
+	this.shadowCameraNear = 1;
+	this.shadowCameraFar = 5000;
+	this.shadowCameraFov = 50;
+
+	this.shadowMap = [];
+	this.shadowMapEnabled = false;
+	this.shadowMapSoft = true;
+
+	var _cameraLight,
+		_shadowMatrix = [];
+
+	var depthShader = THREE.ShaderLib[ "depthRGBA" ];
+	var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
+
+	var _depthMaterial = new THREE.MeshShaderMaterial( { fragmentShader: depthShader.fragmentShader,
+														 vertexShader: depthShader.vertexShader,
+														 uniforms: depthUniforms } );
+
+	var _depthMaterialMorph = new THREE.MeshShaderMaterial( { fragmentShader: depthShader.fragmentShader,
+															  vertexShader: depthShader.vertexShader,
+															  uniforms: depthUniforms,
+															  morphTargets: true
+															} );
+
+	_depthMaterial._shadowPass = true;
+	_depthMaterialMorph._shadowPass = true;
+
 	// Init GL
 
 	try {
@@ -401,18 +435,19 @@ THREE.WebGLRenderer = function ( parameters ) {
 	this.setStencilShadowDarkness = function( value ) {
 
 		_stencilShadow.darkness = value;
+
 	};
 
 	this.getContext = function() {
 
 		return _gl;
 
-	}
-
+	};
 
 	function setupLights ( program, lights ) {
 
-		var l, ll, light, r = 0, g = 0, b = 0,
+		var l, ll, light, n,
+		r = 0, g = 0, b = 0,
 		color, position, intensity, distance,
 
 		zlights = _lights,
@@ -449,25 +484,41 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				doffset = dlength * 3;
 
-				dcolors[ doffset ] = color.r * intensity;
+				dcolors[ doffset ]     = color.r * intensity;
 				dcolors[ doffset + 1 ] = color.g * intensity;
 				dcolors[ doffset + 2 ] = color.b * intensity;
 
-				dpositions[ doffset ] = position.x;
+				dpositions[ doffset ]     = position.x;
 				dpositions[ doffset + 1 ] = position.y;
 				dpositions[ doffset + 2 ] = position.z;
 
 				dlength += 1;
 
+			} else if ( light instanceof THREE.SpotLight ) { // hack, not a proper spotlight
+
+				doffset = dlength * 3;
+
+				dcolors[ doffset ]     = color.r * intensity;
+				dcolors[ doffset + 1 ] = color.g * intensity;
+				dcolors[ doffset + 2 ] = color.b * intensity;
+
+				n = 1 / position.length();
+
+				dpositions[ doffset ]     = position.x * n;
+				dpositions[ doffset + 1 ] = position.y * n;
+				dpositions[ doffset + 2 ] = position.z * n;
+
+				dlength += 1;
+
 			} else if( light instanceof THREE.PointLight ) {
 
 				poffset = plength * 3;
 
-				pcolors[ poffset ] = color.r * intensity;
+				pcolors[ poffset ]     = color.r * intensity;
 				pcolors[ poffset + 1 ] = color.g * intensity;
 				pcolors[ poffset + 2 ] = color.b * intensity;
 
-				ppositions[ poffset ] = position.x;
+				ppositions[ poffset ]     = position.x;
 				ppositions[ poffset + 1 ] = position.y;
 				ppositions[ poffset + 2 ] = position.z;
 
@@ -923,6 +974,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		obj_skinVerticesB = geometry.skinVerticesB,
 		obj_skinIndices = geometry.skinIndices,
 		obj_skinWeights = geometry.skinWeights,
+
 		obj_edgeFaces = object instanceof THREE.ShadowVolume ? geometry.edgeFaces : undefined,
 
 		morphTargets = geometry.morphTargets;
@@ -1944,6 +1996,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 				_gl.bufferData( _gl.ARRAY_BUFFER, morphTargetsArrays[ vk ], hint );
 
 			}
+
 		}
 
 		if ( dirtyColors && offset_color > 0 ) {
@@ -2511,9 +2564,28 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
+	function refreshUniformsShadow( uniforms, material ) {
+
+		if ( uniforms.shadowMatrix ) {
+
+			for ( var i = 0; i < _shadowMatrix.length; i ++ ) {
+
+				uniforms.shadowMatrix.value[ i ] = _shadowMatrix[ i ];
+				uniforms.shadowMap.texture[ i ] = _this.shadowMap[ i ];
+
+
+			}
+
+			uniforms.shadowDarkness.value = _this.shadowMapDarkness;
+			uniforms.shadowBias.value = _this.shadowMapBias;
+
+		}
+
+	};
+
 	this.initMaterial = function ( material, lights, fog, object ) {
 
-		var u, a, identifiers, i, parameters, maxLightCount, maxBones, shaderID;
+		var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
 
 		if ( material instanceof THREE.MeshDepthMaterial ) {
 
@@ -2560,9 +2632,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		maxLightCount = allocateLights( lights, 4 );
 
+		maxShadows = allocateShadows( lights );
+
 		maxBones = allocateBones( object );
 
 		parameters = {
+
 			map: !!material.map, envMap: !!material.envMap, lightMap: !!material.lightMap,
 			vertexColors: material.vertexColors,
 			fog: fog, sizeAttenuation: material.sizeAttenuation,
@@ -2570,7 +2645,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 			morphTargets: material.morphTargets,
 			maxMorphTargets: this.maxMorphTargets,
 			maxDirLights: maxLightCount.directional, maxPointLights: maxLightCount.point,
-			maxBones: maxBones
+			maxBones: maxBones,
+			shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
+			shadowMapSoft: this.shadowMapSoft,
+			shadowMapWidth: this.shadowMapWidth,
+			shadowMapHeight: this.shadowMapHeight,
+			maxShadows: maxShadows
+
 		};
 
 		material.program = buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, parameters );
@@ -2607,7 +2688,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			material.numSupportedMorphTargets = 0;
 
-
 			if ( attributes.morphTarget0 >= 0 ) {
 
 				_gl.enableVertexAttribArray( attributes.morphTarget0 );
@@ -2664,14 +2744,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			}
 
-			object.__webglMorphTargetInfluences = new Float32Array( this.maxMorphTargets );
-
-			for ( var i = 0, il = this.maxMorphTargets; i < il; i ++ ) {
-
-				object.__webglMorphTargetInfluences[ i ] = 0;
-
-			}
-
 		}
 
 	};
@@ -2684,6 +2756,22 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
+		if ( material.morphTargets ) {
+
+			if ( ! object.__webglMorphTargetInfluences ) {
+
+				object.__webglMorphTargetInfluences = new Float32Array( _this.maxMorphTargets );
+
+				for ( var i = 0, il = this.maxMorphTargets; i < il; i ++ ) {
+
+					object.__webglMorphTargetInfluences[ i ] = 0;
+
+				}
+
+			}
+
+		}
+
 		var program = material.program,
 			p_uniforms = program.uniforms,
 			m_uniforms = material.uniforms;
@@ -2752,6 +2840,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 		} else if ( material instanceof THREE.MeshNormalMaterial ) {
 
 			m_uniforms.opacity.value = material.opacity;
+
+		}
+
+		if ( object.receiveShadow && ! material._shadowPass ) {
+
+			refreshUniformsShadow( m_uniforms, material );
+
 		}
 
 		// load common uniforms
@@ -2776,7 +2871,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( material instanceof THREE.MeshShaderMaterial ||
 			 material.envMap ||
-			 material.skinning ) {
+			 material.skinning ||
+			 object.receiveShadow ) {
 
 			if ( p_uniforms.objectMatrix !== null ) {
 
@@ -3098,6 +3194,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 						candidateInfluence = influences[ candidate ];
 
 					}
+
 				}
 
 				_gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ candidate ] );
@@ -3108,7 +3205,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 				used[ candidate ] = 1;
 				candidateInfluence = -1;
 				m ++;
+
 			}
+
 		}
 
 		// load updated influences uniform
@@ -3377,13 +3476,184 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
-
 	function painterSort( a, b ) {
 
 		return b.z - a.z;
 
 	};
 
+	function renderShadowMap( scene, camera ) {
+
+		var i, il, light,
+			j = 0,
+			shadowMap, shadowMatrix,
+			oil,
+			material,
+			o, ol, webglObject, object,
+			lights = scene.lights,
+			fog = null;
+
+		if ( ! _cameraLight ) {
+
+			_cameraLight = new THREE.Camera( _this.shadowCameraFov, camera.aspect, _this.shadowCameraNear, _this.shadowCameraFar );
+
+		}
+
+		for ( i = 0, il = lights.length; i < il; i ++ ) {
+
+			light = lights[ i ];
+
+			if ( light instanceof THREE.SpotLight && light.castShadow ) {
+
+				if ( ! _this.shadowMap[ j ] ) {
+
+					var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
+					_this.shadowMap[ j ] = new THREE.WebGLRenderTarget( _this.shadowMapWidth, _this.shadowMapHeight, pars );
+
+				}
+
+				if ( ! _shadowMatrix[ j ] ) {
+
+					_shadowMatrix[ j ] = new THREE.Matrix4();
+
+				}
+
+				shadowMap = _this.shadowMap[ j ];
+				shadowMatrix = _shadowMatrix[ j ];
+
+				_cameraLight.position.copy( light.position );
+				_cameraLight.target.position.copy( light.target.position );
+
+				_cameraLight.update( undefined, true );
+
+				scene.update( undefined, false, _cameraLight );
+
+				// compute shadow matrix
+
+				shadowMatrix.set( 0.5, 0.0, 0.0, 0.5,
+								  0.0, 0.5, 0.0, 0.5,
+								  0.0, 0.0, 0.5, 0.5,
+								  0.0, 0.0, 0.0, 1.0 );
+
+				shadowMatrix.multiplySelf( _cameraLight.projectionMatrix );
+				shadowMatrix.multiplySelf( _cameraLight.matrixWorldInverse );
+
+				// render shadow map
+
+				_cameraLight.matrixWorldInverse.flattenToArray( _viewMatrixArray );
+				_cameraLight.projectionMatrix.flattenToArray( _projectionMatrixArray );
+
+				_projScreenMatrix.multiply( _cameraLight.projectionMatrix, _cameraLight.matrixWorldInverse );
+				computeFrustum( _projScreenMatrix );
+
+				_this.initWebGLObjects( scene );
+
+				setRenderTarget( shadowMap );
+
+				// using arbitrary clear color in depth pass
+				// creates variance in shadows
+
+				_gl.clearColor( 1, 1, 1, 1 );
+				//_gl.clearColor( 0, 0, 0, 1 );
+
+				_this.clear();
+
+				_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
+
+
+				// set matrices & frustum culling
+
+				ol = scene.__webglObjects.length;
+				oil = scene.__webglObjectsImmediate.length;
+
+				for ( o = 0; o < ol; o ++ ) {
+
+					webglObject = scene.__webglObjects[ o ];
+					object = webglObject.object;
+
+					if ( object.visible && object.castShadow ) {
+
+						if ( ! ( object instanceof THREE.Mesh ) || isInFrustum( object ) ) {
+
+							object.matrixWorld.flattenToArray( object._objectMatrixArray );
+
+							setupMatrices( object, _cameraLight, false );
+
+							webglObject.render = true;
+
+						} else {
+
+							webglObject.render = false;
+
+						}
+
+					} else {
+
+						webglObject.render = false;
+
+					}
+
+				}
+
+				setDepthTest( true );
+				setBlending( THREE.NormalBlending ); // maybe blending should be just disabled?
+
+				//_gl.cullFace( _gl.FRONT );
+
+				for ( o = 0; o < ol; o ++ ) {
+
+					webglObject = scene.__webglObjects[ o ];
+
+					if ( webglObject.render ) {
+
+						object = webglObject.object;
+						buffer = webglObject.buffer;
+
+						setObjectFaces( object );
+
+						material = object.geometry.morphTargets.length ? _depthMaterialMorph : _depthMaterial;
+
+						renderBuffer( _cameraLight, lights, fog, material, buffer, object );
+
+					}
+
+				}
+
+
+				for ( o = 0; o < oil; o++ ) {
+
+					webglObject = scene.__webglObjectsImmediate[ o ];
+					object = webglObject.object;
+
+					if ( object.visible && object.castShadow ) {
+
+						if( object.matrixAutoUpdate ) {
+
+							object.matrixWorld.flattenToArray( object._objectMatrixArray );
+
+						}
+
+						setupMatrices( object, _cameraLight, false );
+
+						setObjectFaces( object );
+
+						program = setProgram( _cameraLight, lights, fog, _depthMaterial, object );
+						object.render( function( object ) { renderBufferImmediate( object, program, _depthMaterial.shading ); } );
+
+					}
+
+				}
+
+				//_gl.cullFace( _gl.BACK );
+
+				j ++;
+
+			}
+
+		}
+
+	};
+
 	this.render = function( scene, camera, renderTarget, forceClear ) {
 
 		var i, program, opaque, transparent, material,
@@ -3391,6 +3661,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 			lights = scene.lights,
 			fog = scene.fog;
 
+		if ( this.shadowMapEnabled ) renderShadowMap( scene, camera );
+
 		_this.data.vertices = 0;
 		_this.data.faces = 0;
 		_this.data.drawCalls = 0;
@@ -3430,7 +3702,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					object.matrixWorld.flattenToArray( object._objectMatrixArray );
 
-					setupMatrices( object, camera );
+					setupMatrices( object, camera, true );
 
 					unrollBufferMaterials( webglObject );
 
@@ -3488,7 +3760,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				}
 
-				setupMatrices( object, camera );
+				setupMatrices( object, camera, true );
 
 				unrollImmediateBufferMaterials( webglObject );
 
@@ -4183,10 +4455,15 @@ THREE.WebGLRenderer = function ( parameters ) {
 	};
 
 
-	function setupMatrices( object, camera ) {
+	function setupMatrices( object, camera, computeNormalMatrix ) {
 
 		object._modelViewMatrix.multiplyToArray( camera.matrixWorldInverse, object.matrixWorld, object._modelViewMatrixArray );
-		THREE.Matrix4.makeInvert3x3( object._modelViewMatrix ).transposeIntoArray( object._normalMatrixArray );
+
+		if ( computeNormalMatrix ) {
+
+			THREE.Matrix4.makeInvert3x3( object._modelViewMatrix ).transposeIntoArray( object._normalMatrixArray );
+
+		}
 
 	};
 
@@ -4787,6 +5064,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
 			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
 
+			"#define MAX_SHADOWS " + parameters.maxShadows,
+
 			"#define MAX_BONES " + parameters.maxBones,
 
 			parameters.map ? "#define USE_MAP" : "",
@@ -4796,6 +5075,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 			parameters.skinning ? "#define USE_SKINNING" : "",
 			parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
 
+			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
+			parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
+
 			parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
 
 			"uniform mat4 objectMatrix;",
@@ -4853,6 +5135,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
 			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
 
+			"#define MAX_SHADOWS " + parameters.maxShadows,
+
 			parameters.fog ? "#define USE_FOG" : "",
 			parameters.fog instanceof THREE.FogExp2 ? "#define FOG_EXP2" : "",
 
@@ -4861,6 +5145,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
 			parameters.vertexColors ? "#define USE_COLOR" : "",
 
+			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
+			parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
+			parameters.shadowMapSoft ? "#define SHADOWMAP_WIDTH " + parameters.shadowMapWidth.toFixed( 1 ) : "",
+			parameters.shadowMapSoft ? "#define SHADOWMAP_HEIGHT " + parameters.shadowMapHeight.toFixed( 1 ) : "",
+
 			"uniform mat4 viewMatrix;",
 			"uniform vec3 cameraPosition;",
 			""
@@ -4949,14 +5238,14 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	function loadUniformsGeneric( program, uniforms ) {
 
-		var u, uniform, value, type, location, texture;
+		var u, uniform, value, type, location, texture, i, il;
 
 		for( u in uniforms ) {
 
-			location = program.uniforms[u];
+			location = program.uniforms[ u ];
 			if ( !location ) continue;
 
-			uniform = uniforms[u];
+			uniform = uniforms[ u ];
 
 			type = uniform.type;
 			value = uniform.value;
@@ -5000,6 +5289,22 @@ THREE.WebGLRenderer = function ( parameters ) {
 				value.flattenToArray( uniform._array );
 				_gl.uniformMatrix4fv( location, false, uniform._array );
 
+			} else if( type == "m4v" ) {
+
+				if ( ! uniform._array ) {
+
+					uniform._array = new Float32Array( 16 * value.length );
+
+				}
+
+				for ( i = 0, il = value.length; i < il; i ++ ) {
+
+					value[ i ].flattenToArrayOffset( uniform._array, i * 16 );
+
+				}
+
+				_gl.uniformMatrix4fv( location, false, uniform._array );
+
 			} else if( type == "c" ) {
 
 				_gl.uniform3f( location, value.r, value.g, value.b );
@@ -5022,6 +5327,32 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				}
 
+			} else if( type == "tv" ) {
+
+				if ( ! uniform._array ) {
+
+					uniform._array = [];
+
+					for( i = 0, il = uniform.texture.length; i < il; i ++ ) {
+
+						uniform._array[ i ] = value + i;
+
+					}
+
+				}
+
+				_gl.uniform1iv( location, uniform._array );
+
+				for( i = 0, il = uniform.texture.length; i < il; i ++ ) {
+
+					texture = uniform.texture[ i ];
+
+					if ( !texture ) continue;
+
+					setTexture( texture, uniform._array[ i ] );
+
+				}
+
 			}
 
 		}
@@ -5608,8 +5939,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			light = lights[ l ];
 
-			if ( light instanceof THREE.DirectionalLight ) dirLights++;
-			if ( light instanceof THREE.PointLight ) pointLights++;
+			if ( light instanceof THREE.SpotLight ) dirLights ++; // hack, not a proper spotlight
+			if ( light instanceof THREE.DirectionalLight ) dirLights ++;
+			if ( light instanceof THREE.PointLight ) pointLights ++;
 
 		}
 
@@ -5629,6 +5961,24 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
+	function allocateShadows( lights ) {
+
+		var l, ll, light,
+			maxShadows = 0;
+
+		for ( l = 0, ll = lights.length; l < ll; l++ ) {
+
+			light = lights[ l ];
+
+			if ( light instanceof THREE.SpotLight && light.castShadow ) maxShadows ++;
+
+		}
+
+		return maxShadows;
+
+	};
+
+
 	/* DEBUG
 	function getGLParams() {
 

+ 240 - 12
src/renderers/WebGLShaders.js

@@ -6,7 +6,6 @@
 
 THREE.ShaderChunk = {
 
-
 	// FOG
 
 	fog_pars_fragment: [
@@ -16,10 +15,14 @@ THREE.ShaderChunk = {
 		"uniform vec3 fogColor;",
 
 		"#ifdef FOG_EXP2",
+
 			"uniform float fogDensity;",
+
 		"#else",
+
 			"uniform float fogNear;",
 			"uniform float fogFar;",
+
 		"#endif",
 
 	"#endif"
@@ -33,11 +36,15 @@ THREE.ShaderChunk = {
 		"float depth = gl_FragCoord.z / gl_FragCoord.w;",
 
 		"#ifdef FOG_EXP2",
+
 			"const float LOG2 = 1.442695;",
 			"float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );",
 			"fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );",
+
 		"#else",
+
 			"float fogFactor = smoothstep( fogNear, fogFar, depth );",
+
 		"#endif",
 
 		"gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );",
@@ -53,6 +60,7 @@ THREE.ShaderChunk = {
 	"#ifdef USE_ENVMAP",
 
 		"varying vec3 vReflect;",
+
 		"uniform float reflectivity;",
 		"uniform samplerCube envMap;",
 		"uniform int combine;",
@@ -69,7 +77,6 @@ THREE.ShaderChunk = {
 
 		"if ( combine == 1 ) {",
 
-			//"gl_FragColor = mix( gl_FragColor, cubeColor, reflectivity );",
 			"gl_FragColor = vec4( mix( gl_FragColor.xyz, cubeColor.xyz, reflectivity ), opacity );",
 
 		"} else {",
@@ -87,6 +94,7 @@ THREE.ShaderChunk = {
 	"#ifdef USE_ENVMAP",
 
 		"varying vec3 vReflect;",
+
 		"uniform float refractionRatio;",
 		"uniform bool useRefract;",
 
@@ -99,7 +107,7 @@ THREE.ShaderChunk = {
 	"#ifdef USE_ENVMAP",
 
 		"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
-		"vec3 nWorld = mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal;",
+		"vec3 nWorld = mat3( objectMatrix[ 0 ].xyz, objectMatrix[ 1 ].xyz, objectMatrix[ 2 ].xyz ) * normal;",
 
 		"if ( useRefract ) {",
 
@@ -244,7 +252,9 @@ THREE.ShaderChunk = {
 		"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
 
 		"#ifdef PHONG",
+
 			"varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
+
 		"#endif",
 
 	"#endif"
@@ -265,7 +275,7 @@ THREE.ShaderChunk = {
 
 		"#if MAX_DIR_LIGHTS > 0",
 
-		"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
+		"for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
 
 			"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
 			"float directionalLightWeighting = max( dot( transformedNormal, normalize( lDirection.xyz ) ), 0.0 );",
@@ -277,7 +287,7 @@ THREE.ShaderChunk = {
 
 		"#if MAX_POINT_LIGHTS > 0",
 
-			"for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
+			"for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 
 				"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
 
@@ -359,7 +369,7 @@ THREE.ShaderChunk = {
 		"vec4 dirDiffuse  = vec4( 0.0 );",
 		"vec4 dirSpecular = vec4( 0.0 );" ,
 
-		"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
+		"for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
 
 			"vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
 
@@ -384,11 +394,15 @@ THREE.ShaderChunk = {
 	"vec4 totalLight = vec4( ambient, opacity );",
 
 	"#if MAX_DIR_LIGHTS > 0",
+
 		"totalLight += dirDiffuse + dirSpecular;",
+
 	"#endif",
 
 	"#if MAX_POINT_LIGHTS > 0",
+
 		"totalLight += pointDiffuse + pointSpecular;",
+
 	"#endif",
 
 	"gl_FragColor = gl_FragColor * totalLight;"
@@ -439,7 +453,7 @@ THREE.ShaderChunk = {
 
 	].join("\n"),
 
-	// skinning
+	// SKINNING
 
 	skinning_pars_vertex: [
 
@@ -467,7 +481,7 @@ THREE.ShaderChunk = {
 
 	].join("\n"),
 
-	// morphing
+	// MORPHING
 
 	morphtarget_pars_vertex: [
 
@@ -510,7 +524,139 @@ THREE.ShaderChunk = {
 	"#endif",
 	"#endif"
 
-	].join("\n")
+	].join("\n"),
+
+	// SHADOW MAP
+
+	// based on SpiderGL shadow map and Fabien Sanglard's GLSL shadow mapping examples
+	//  http://spidergl.org/example.php?id=6
+	// 	http://fabiensanglard.net/shadowmapping
+
+	shadowmap_pars_fragment: [
+
+	"#ifdef USE_SHADOWMAP",
+
+		"uniform sampler2D shadowMap[ MAX_SHADOWS ];",
+
+		"uniform float shadowDarkness;",
+		"uniform float shadowBias;",
+
+		"varying vec4 vShadowCoord[ MAX_SHADOWS ];",
+
+		"float unpackDepth( const in vec4 rgba_depth ) {",
+
+			"const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );",
+			"float depth = dot( rgba_depth, bit_shift );",
+			"return depth;",
+
+		"}",
+
+	"#endif"
+
+	].join("\n"),
+
+	shadowmap_fragment: [
+
+	"#ifdef USE_SHADOWMAP",
+
+		"#ifdef SHADOWMAP_SOFT",
+
+			"const float xPixelOffset = 1.0 / SHADOWMAP_WIDTH;",
+			"const float yPixelOffset = 1.0 / SHADOWMAP_HEIGHT;",
+
+		"#endif",
+
+		"vec4 shadowColor = vec4( 1.0 );",
+
+		"for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
+
+			"vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;",
+
+			"if ( shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0 ) {",
+
+				"#ifdef SHADOWMAP_SOFT",
+
+					// Percentage-close filtering
+					// (9 pixel kernel)
+					// http://fabiensanglard.net/shadowmappingPCF/
+
+					"float shadow = 0.0;",
+
+					"for ( float y = -1.25; y <= 1.25; y += 1.25 )",
+						"for ( float x = -1.25; x <= 1.25; x += 1.25 ) {",
+
+							"vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );",
+
+							// doesn't seem to produce any noticeable visual difference compared to simple "texture2D" lookup
+							//"vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );",
+
+							"float fDepth = unpackDepth( rgbaDepth );",
+
+							"if ( fDepth < ( shadowCoord.z + shadowBias ) )",
+								"shadow += 1.0;",
+
+					"}",
+
+					"shadow /= 9.0;",
+
+					"shadowColor = shadowColor * vec4( vec3( ( 1.0 - shadowDarkness * shadow ) ), 1.0 );",
+
+				"#else",
+
+					"vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );",
+					"float fDepth = unpackDepth( rgbaDepth );",
+
+					"if ( fDepth < ( shadowCoord.z + shadowBias ) )",
+
+						// spot with multiple shadows is darker
+
+						"shadowColor = shadowColor * vec4( vec3( shadowDarkness ), 1.0 );",
+
+						// spot with multiple shadows has the same color as single shadow spot
+
+						//"shadowColor = min( shadowColor, vec4( vec3( shadowDarkness ), 1.0 ) );",
+
+				"#endif",
+
+			"}",
+
+
+			// uncomment to see light frustum boundaries
+			//"if ( !( shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0 ) )",
+			//	"gl_FragColor =  gl_FragColor * vec4( 1.0, 0.0, 0.0, 1.0 );",
+
+		"}",
+
+		"gl_FragColor = gl_FragColor * shadowColor;",
+
+	"#endif"
+
+	].join("\n"),
+
+	shadowmap_pars_vertex: [
+
+	"#ifdef USE_SHADOWMAP",
+
+		"varying vec4 vShadowCoord[ MAX_SHADOWS ];",
+		"uniform mat4 shadowMatrix[ MAX_SHADOWS ];",
+
+	"#endif"
+
+	].join("\n"),
+
+	shadowmap_vertex: [
+
+	"#ifdef USE_SHADOWMAP",
+
+		"for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
+
+			"vShadowCoord[ i ] = shadowMatrix[ i ] * objectMatrix * vec4( position, 1.0 );",
+
+		"}",
+
+	"#endif"
+
+	].join("\n"),
 
 };
 
@@ -633,6 +779,16 @@ THREE.UniformsLib = {
 		"fogFar" : { type: "f", value: 2000 },
 		"fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) }
 
+	},
+
+	shadowmap: {
+
+		"shadowMap": { type: "tv", value: 3, texture: [] },
+		"shadowMatrix" : { type: "m4v", value: [] },
+
+		"shadowBias" : { type: "f", value: 0.0039 },
+		"shadowDarkness": { type: "f", value: 0.2 }
+
 	}
 
 };
@@ -934,7 +1090,7 @@ THREE.ShaderLib = {
 			"void main() {",
 
 				"vec4 pos      = objectMatrix * vec4( position, 1.0 );",
-				"vec3 norm     = mat3( objectMatrix[0].xyz, objectMatrix[1].xyz, objectMatrix[2].xyz ) * normal;",
+				"vec3 norm     = mat3( objectMatrix[ 0 ].xyz, objectMatrix[ 1 ].xyz, objectMatrix[ 2 ].xyz ) * normal;",
 				"vec4 extruded = vec4( directionalLightDirection * 5000.0 * step( 0.0, dot( directionalLightDirection, norm ) ), 0.0 );",
 
 				"gl_Position   = projectionMatrix * viewMatrix * ( pos + extruded );",
@@ -1030,7 +1186,8 @@ THREE.ShaderLib = {
 		uniforms: THREE.UniformsUtils.merge( [
 
 			THREE.UniformsLib[ "common" ],
-			THREE.UniformsLib[ "fog" ]
+			THREE.UniformsLib[ "fog" ],
+			THREE.UniformsLib[ "shadowmap" ]
 
 		] ),
 
@@ -1044,6 +1201,7 @@ THREE.ShaderLib = {
 			THREE.ShaderChunk[ "lightmap_pars_fragment" ],
 			THREE.ShaderChunk[ "envmap_pars_fragment" ],
 			THREE.ShaderChunk[ "fog_pars_fragment" ],
+			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
 
 			"void main() {",
 
@@ -1053,6 +1211,7 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "lightmap_fragment" ],
 				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "envmap_fragment" ],
+				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 			"}"
@@ -1067,6 +1226,7 @@ THREE.ShaderLib = {
 			THREE.ShaderChunk[ "color_pars_vertex" ],
 			THREE.ShaderChunk[ "skinning_pars_vertex" ],
 			THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
+			THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
 
 			"void main() {",
 
@@ -1079,6 +1239,7 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "skinning_vertex" ],
 				THREE.ShaderChunk[ "morphtarget_vertex" ],
 				THREE.ShaderChunk[ "default_vertex" ],
+				THREE.ShaderChunk[ "shadowmap_vertex" ],
 
 			"}"
 
@@ -1092,7 +1253,8 @@ THREE.ShaderLib = {
 
 			THREE.UniformsLib[ "common" ],
 			THREE.UniformsLib[ "fog" ],
-			THREE.UniformsLib[ "lights" ]
+			THREE.UniformsLib[ "lights" ],
+			THREE.UniformsLib[ "shadowmap" ]
 
 		] ),
 
@@ -1108,6 +1270,7 @@ THREE.ShaderLib = {
 			THREE.ShaderChunk[ "lightmap_pars_fragment" ],
 			THREE.ShaderChunk[ "envmap_pars_fragment" ],
 			THREE.ShaderChunk[ "fog_pars_fragment" ],
+			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
 
 			"void main() {",
 
@@ -1118,6 +1281,7 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "lightmap_fragment" ],
 				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "envmap_fragment" ],
+				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 			"}"
@@ -1135,6 +1299,7 @@ THREE.ShaderLib = {
 			THREE.ShaderChunk[ "color_pars_vertex" ],
 			THREE.ShaderChunk[ "skinning_pars_vertex" ],
 			THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
+			THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
 
 			"void main() {",
 
@@ -1151,6 +1316,8 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "skinning_vertex" ],
 				THREE.ShaderChunk[ "morphtarget_vertex" ],
 				THREE.ShaderChunk[ "default_vertex" ],
+				THREE.ShaderChunk[ "shadowmap_vertex" ],
+
 
 			"}"
 
@@ -1165,6 +1332,7 @@ THREE.ShaderLib = {
 			THREE.UniformsLib[ "common" ],
 			THREE.UniformsLib[ "fog" ],
 			THREE.UniformsLib[ "lights" ],
+			THREE.UniformsLib[ "shadowmap" ],
 
 			{
 				"ambient"  : { type: "c", value: new THREE.Color( 0x050505 ) },
@@ -1191,6 +1359,7 @@ THREE.ShaderLib = {
 			THREE.ShaderChunk[ "envmap_pars_fragment" ],
 			THREE.ShaderChunk[ "fog_pars_fragment" ],
 			THREE.ShaderChunk[ "lights_pars_fragment" ],
+			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
 
 			"void main() {",
 
@@ -1201,6 +1370,7 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "lightmap_fragment" ],
 				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "envmap_fragment" ],
+				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 			"}"
@@ -1222,6 +1392,7 @@ THREE.ShaderLib = {
 			THREE.ShaderChunk[ "color_pars_vertex" ],
 			THREE.ShaderChunk[ "skinning_pars_vertex" ],
 			THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
+			THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
 
 			"void main() {",
 
@@ -1233,7 +1404,9 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "color_vertex" ],
 
 				"#ifndef USE_ENVMAP",
+
 					"vec4 mPosition = objectMatrix * vec4( position, 1.0 );",
+
 				"#endif",
 
 				"vViewPosition = cameraPosition - mPosition.xyz;",
@@ -1245,6 +1418,7 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "skinning_vertex" ],
 				THREE.ShaderChunk[ "morphtarget_vertex" ],
 				THREE.ShaderChunk[ "default_vertex" ],
+				THREE.ShaderChunk[ "shadowmap_vertex" ],
 
 			"}"
 
@@ -1302,6 +1476,60 @@ THREE.ShaderLib = {
 
 		].join("\n")
 
+	},
+
+	// Depth encoding into RGBA texture
+	// 	based on SpiderGL shadow map example
+	// 		http://spidergl.org/example.php?id=6
+	// 	originally from
+	//		http://www.gamedev.net/topic/442138-packing-a-float-into-a-a8r8g8b8-texture-shader/page__whichpage__1%25EF%25BF%25BD
+	// 	see also here:
+	//		http://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/
+
+	'depthRGBA': {
+
+		uniforms: {},
+
+		fragmentShader: [
+
+			"vec4 pack_depth( const in float depth ) {",
+
+				"const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );",
+				"const vec4 bit_mask  = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );",
+				"vec4 res = fract( depth * bit_shift );",
+				"res -= res.xxyz * bit_mask;",
+				"return res;",
+
+			"}",
+
+			"void main() {",
+
+				"gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );",
+
+				//"gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z / gl_FragCoord.w );",
+				//"float z = ( ( gl_FragCoord.z / gl_FragCoord.w ) - 3.0 ) / ( 4000.0 - 3.0 );",
+				//"gl_FragData[ 0 ] = pack_depth( z );",
+				//"gl_FragData[ 0 ] = vec4( z, z, z, 1.0 );",
+
+			"}"
+
+		].join("\n"),
+
+		vertexShader: [
+
+			THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
+
+			"void main() {",
+
+				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+
+				THREE.ShaderChunk[ "morphtarget_vertex" ],
+				THREE.ShaderChunk[ "default_vertex" ],
+
+			"}"
+
+		].join("\n")
+
 	}
 
 };

+ 2 - 0
utils/build.py

@@ -35,6 +35,7 @@ COMMON_FILES = [
 'lights/AmbientLight.js',
 'lights/DirectionalLight.js',
 'lights/PointLight.js',
+'lights/SpotLight.js',
 'lights/LensFlare.js',
 'materials/Material.js',
 'materials/Mappings.js',
@@ -263,6 +264,7 @@ WEBGL_FILES = [
 'lights/AmbientLight.js',
 'lights/DirectionalLight.js',
 'lights/PointLight.js',
+'lights/SpotLight.js',
 'lights/LensFlare.js',
 'materials/Material.js',
 'materials/Mappings.js',

Some files were not shown because too many files changed in this diff