فهرست منبع

Merge branch 'dev' into adsk-dev

Daniel Taub 11 سال پیش
والد
کامیت
6a2221e6a0

+ 6 - 10
build/three.js

@@ -15652,10 +15652,14 @@ THREE.LOD.prototype.clone = function ( object ) {
 
 THREE.Sprite = ( function () {
 
-	var vertices = new Float32Array( [ - 0.5, - 0.5, 0, 0.5, - 0.5, 0, 0.5, 0.5, 0 ] );
+	var indices = new Uint16Array( [ 0, 1, 2,  0, 2, 3 ] );
+	var vertices = new Float32Array( [ - 0.5, - 0.5, 0,   0.5, - 0.5, 0,   0.5, 0.5, 0,   - 0.5, 0.5, 0 ] );
+	var uvs = new Float32Array( [ 0, 0,   1, 0,   1, 1,   0, 1 ] );
 
 	var geometry = new THREE.BufferGeometry();
+	geometry.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
 	geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
+	geometry.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
 
 	return function ( material ) {
 
@@ -15699,14 +15703,6 @@ THREE.Sprite.prototype.raycast = ( function () {
 
 }() );
 
-THREE.Sprite.prototype.updateMatrix = function () {
-
-	this.matrix.compose( this.position, this.quaternion, this.scale );
-
-	this.matrixWorldNeedsUpdate = true;
-
-};
-
 THREE.Sprite.prototype.clone = function ( object ) {
 
 	if ( object === undefined ) object = new THREE.Sprite( this.material );
@@ -29849,7 +29845,7 @@ THREE.CircleGeometry.prototype = Object.create( THREE.Geometry.prototype );
 
 THREE.CubeGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {
 
-	console.warn( 'THEE.CubeGeometry has been renamed to THREE.BoxGeometry.' );
+	console.warn( 'THREE.CubeGeometry has been renamed to THREE.BoxGeometry.' );
 	return new THREE.BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments );
 
  };

+ 4 - 4
build/three.min.js

@@ -355,9 +355,9 @@ THREE.LOD.prototype.addLevel=function(a,b){void 0===b&&(b=0);b=Math.abs(b);for(v
 THREE.LOD.prototype.raycast=function(){var a=new THREE.Vector3;return function(b,c){a.setFromMatrixPosition(this.matrixWorld);var d=b.ray.origin.distanceTo(a);this.getObjectForDistance(d).raycast(b,c)}}();
 THREE.LOD.prototype.update=function(){var a=new THREE.Vector3,b=new THREE.Vector3;return function(c){if(1<this.objects.length){a.setFromMatrixPosition(c.matrixWorld);b.setFromMatrixPosition(this.matrixWorld);c=a.distanceTo(b);this.objects[0].object.visible=!0;for(var d=1,e=this.objects.length;d<e;d++)if(c>=this.objects[d].distance)this.objects[d-1].object.visible=!1,this.objects[d].object.visible=!0;else break;for(;d<e;d++)this.objects[d].object.visible=!1}}}();
 THREE.LOD.prototype.clone=function(a){void 0===a&&(a=new THREE.LOD);THREE.Object3D.prototype.clone.call(this,a);for(var b=0,c=this.objects.length;b<c;b++){var d=this.objects[b].object.clone();d.visible=0===b;a.addLevel(d,this.objects[b].distance)}return a};
-THREE.Sprite=function(){var a=new Float32Array([-0.5,-0.5,0,0.5,-0.5,0,0.5,0.5,0]),b=new THREE.BufferGeometry;b.addAttribute("position",new THREE.BufferAttribute(a,3));return function(a){THREE.Object3D.call(this);this.geometry=b;this.material=void 0!==a?a:new THREE.SpriteMaterial}}();THREE.Sprite.prototype=Object.create(THREE.Object3D.prototype);
-THREE.Sprite.prototype.raycast=function(){var a=new THREE.Vector3;return function(b,c){a.setFromMatrixPosition(this.matrixWorld);var d=b.ray.distanceToPoint(a);d>this.scale.x||c.push({distance:d,point:this.position,face:null,object:this})}}();THREE.Sprite.prototype.updateMatrix=function(){this.matrix.compose(this.position,this.quaternion,this.scale);this.matrixWorldNeedsUpdate=!0};
-THREE.Sprite.prototype.clone=function(a){void 0===a&&(a=new THREE.Sprite(this.material));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Particle=THREE.Sprite;THREE.Scene=function(){THREE.Object3D.call(this);this.overrideMaterial=this.fog=null;this.autoUpdate=!0;this.matrixAutoUpdate=!1};THREE.Scene.prototype=Object.create(THREE.Object3D.prototype);
+THREE.Sprite=function(){var a=new Uint16Array([0,1,2,0,2,3]),b=new Float32Array([-0.5,-0.5,0,0.5,-0.5,0,0.5,0.5,0,-0.5,0.5,0]),c=new Float32Array([0,0,1,0,1,1,0,1]),d=new THREE.BufferGeometry;d.addAttribute("index",new THREE.BufferAttribute(a,1));d.addAttribute("position",new THREE.BufferAttribute(b,3));d.addAttribute("uv",new THREE.BufferAttribute(c,2));return function(a){THREE.Object3D.call(this);this.geometry=d;this.material=void 0!==a?a:new THREE.SpriteMaterial}}();THREE.Sprite.prototype=Object.create(THREE.Object3D.prototype);
+THREE.Sprite.prototype.raycast=function(){var a=new THREE.Vector3;return function(b,c){a.setFromMatrixPosition(this.matrixWorld);var d=b.ray.distanceToPoint(a);d>this.scale.x||c.push({distance:d,point:this.position,face:null,object:this})}}();THREE.Sprite.prototype.clone=function(a){void 0===a&&(a=new THREE.Sprite(this.material));THREE.Object3D.prototype.clone.call(this,a);return a};THREE.Particle=THREE.Sprite;
+THREE.Scene=function(){THREE.Object3D.call(this);this.overrideMaterial=this.fog=null;this.autoUpdate=!0;this.matrixAutoUpdate=!1};THREE.Scene.prototype=Object.create(THREE.Object3D.prototype);
 THREE.Scene.prototype.clone=function(a){void 0===a&&(a=new THREE.Scene);THREE.Object3D.prototype.clone.call(this,a);null!==this.fog&&(a.fog=this.fog.clone());null!==this.overrideMaterial&&(a.overrideMaterial=this.overrideMaterial.clone());a.autoUpdate=this.autoUpdate;a.matrixAutoUpdate=this.matrixAutoUpdate;return a};THREE.Fog=function(a,b,c){this.name="";this.color=new THREE.Color(a);this.near=void 0!==b?b:1;this.far=void 0!==c?c:1E3};
 THREE.Fog.prototype.clone=function(){return new THREE.Fog(this.color.getHex(),this.near,this.far)};THREE.FogExp2=function(a,b){this.name="";this.color=new THREE.Color(a);this.density=void 0!==b?b:2.5E-4};THREE.FogExp2.prototype.clone=function(){return new THREE.FogExp2(this.color.getHex(),this.density)};
 THREE.CanvasRenderer=function(a){function b(a,b,c,d){m(b);n(c);p(d);r(a.getStyle());N.stroke();wa.expandByScalar(2*b)}function c(a){q(a.getStyle());N.fill()}function d(a){e(a.target)}function e(a){if(!(a instanceof THREE.CompressedTexture)){var b=a.wrapS===THREE.RepeatWrapping,c=a.wrapT===THREE.RepeatWrapping,d=a.image,e=document.createElement("canvas");e.width=d.width;e.height=d.height;var f=e.getContext("2d");f.setTransform(1,0,0,-1,0,d.height);f.drawImage(d,0,0);fb[a.id]=N.createPattern(e,!0===
@@ -683,7 +683,7 @@ THREE.BoxGeometry=function(a,b,c,d,e,f){function g(a,b,c,d,e,f,g,s){var v,x=h.wi
 0;e<u;e++)for(f=0;f<x;f++)y=f+C*e,a=f+C*(e+1),b=f+1+C*(e+1),c=f+1+C*e,d=new THREE.Vector2(f/x,1-e/u),g=new THREE.Vector2(f/x,1-(e+1)/u),v=new THREE.Vector2((f+1)/x,1-(e+1)/u),G=new THREE.Vector2((f+1)/x,1-e/u),y=new THREE.Face3(y+B,a+B,c+B),y.normal.copy(D),y.vertexNormals.push(D.clone(),D.clone(),D.clone()),y.materialIndex=s,h.faces.push(y),h.faceVertexUvs[0].push([d,g,G]),y=new THREE.Face3(a+B,b+B,c+B),y.normal.copy(D),y.vertexNormals.push(D.clone(),D.clone(),D.clone()),y.materialIndex=s,h.faces.push(y),
 h.faceVertexUvs[0].push([g.clone(),v,G.clone()])}THREE.Geometry.call(this);this.parameters={width:a,height:b,depth:c,widthSegments:d,heightSegments:e,depthSegments:f};this.widthSegments=d||1;this.heightSegments=e||1;this.depthSegments=f||1;var h=this;d=a/2;e=b/2;f=c/2;g("z","y",-1,-1,c,b,d,0);g("z","y",1,-1,c,b,-d,1);g("x","z",1,1,a,c,e,2);g("x","z",1,-1,a,c,-e,3);g("x","y",1,-1,a,b,f,4);g("x","y",-1,-1,a,b,-f,5);this.mergeVertices()};THREE.BoxGeometry.prototype=Object.create(THREE.Geometry.prototype);
 THREE.CircleGeometry=function(a,b,c,d){THREE.Geometry.call(this);this.parameters={radius:a,segments:b,thetaStart:c,thetaLength:d};a=a||50;b=void 0!==b?Math.max(3,b):8;c=void 0!==c?c:0;d=void 0!==d?d:2*Math.PI;var e,f=[];e=new THREE.Vector3;var g=new THREE.Vector2(0.5,0.5);this.vertices.push(e);f.push(g);for(e=0;e<=b;e++){var h=new THREE.Vector3,k=c+e/b*d;h.x=a*Math.cos(k);h.y=a*Math.sin(k);this.vertices.push(h);f.push(new THREE.Vector2((h.x/a+1)/2,(h.y/a+1)/2))}c=new THREE.Vector3(0,0,1);for(e=1;e<=
-b;e++)this.faces.push(new THREE.Face3(e,e+1,0,[c.clone(),c.clone(),c.clone()])),this.faceVertexUvs[0].push([f[e].clone(),f[e+1].clone(),g.clone()]);this.computeFaceNormals();this.boundingSphere=new THREE.Sphere(new THREE.Vector3,a)};THREE.CircleGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.CubeGeometry=function(a,b,c,d,e,f){console.warn("THEE.CubeGeometry has been renamed to THREE.BoxGeometry.");return new THREE.BoxGeometry(a,b,c,d,e,f)};
+b;e++)this.faces.push(new THREE.Face3(e,e+1,0,[c.clone(),c.clone(),c.clone()])),this.faceVertexUvs[0].push([f[e].clone(),f[e+1].clone(),g.clone()]);this.computeFaceNormals();this.boundingSphere=new THREE.Sphere(new THREE.Vector3,a)};THREE.CircleGeometry.prototype=Object.create(THREE.Geometry.prototype);THREE.CubeGeometry=function(a,b,c,d,e,f){console.warn("THREE.CubeGeometry has been renamed to THREE.BoxGeometry.");return new THREE.BoxGeometry(a,b,c,d,e,f)};
 THREE.CylinderGeometry=function(a,b,c,d,e,f){THREE.Geometry.call(this);this.parameters={radiusTop:a,radiusBottom:b,height:c,radialSegments:d,heightSegments:e,openEnded:f};a=void 0!==a?a:20;b=void 0!==b?b:20;c=void 0!==c?c:100;d=d||8;e=e||1;f=void 0!==f?f:!1;var g=c/2,h,k,m=[],n=[];for(k=0;k<=e;k++){var p=[],r=[],q=k/e,t=q*(b-a)+a;for(h=0;h<=d;h++){var s=h/d,v=new THREE.Vector3;v.x=t*Math.sin(s*Math.PI*2);v.y=-q*c+g;v.z=t*Math.cos(s*Math.PI*2);this.vertices.push(v);p.push(this.vertices.length-1);r.push(new THREE.Vector2(s,
 1-q))}m.push(p);n.push(r)}c=(b-a)/c;for(h=0;h<d;h++)for(0!==a?(p=this.vertices[m[0][h]].clone(),r=this.vertices[m[0][h+1]].clone()):(p=this.vertices[m[1][h]].clone(),r=this.vertices[m[1][h+1]].clone()),p.setY(Math.sqrt(p.x*p.x+p.z*p.z)*c).normalize(),r.setY(Math.sqrt(r.x*r.x+r.z*r.z)*c).normalize(),k=0;k<e;k++){var q=m[k][h],t=m[k+1][h],s=m[k+1][h+1],v=m[k][h+1],x=p.clone(),u=p.clone(),G=r.clone(),y=r.clone(),B=n[k][h].clone(),C=n[k+1][h].clone(),A=n[k+1][h+1].clone(),w=n[k][h+1].clone();this.faces.push(new THREE.Face3(q,
 t,v,[x,u,y]));this.faceVertexUvs[0].push([B,C,w]);this.faces.push(new THREE.Face3(t,s,v,[u.clone(),G,y.clone()]));this.faceVertexUvs[0].push([C.clone(),A,w.clone()])}if(!1===f&&0<a)for(this.vertices.push(new THREE.Vector3(0,g,0)),h=0;h<d;h++)q=m[0][h],t=m[0][h+1],s=this.vertices.length-1,x=new THREE.Vector3(0,1,0),u=new THREE.Vector3(0,1,0),G=new THREE.Vector3(0,1,0),B=n[0][h].clone(),C=n[0][h+1].clone(),A=new THREE.Vector2(C.x,0),this.faces.push(new THREE.Face3(q,t,s,[x,u,G])),this.faceVertexUvs[0].push([B,

+ 3 - 3
editor/js/Sidebar.Object3D.js

@@ -79,9 +79,9 @@ Sidebar.Object3D = function ( editor ) {
 
 	var objectScaleRow = new UI.Panel();
 	var objectScaleLock = new UI.Checkbox().setPosition( 'absolute' ).setLeft( '75px' );
-	var objectScaleX = new UI.Number( 1 ).setWidth( '50px' ).onChange( updateScaleX );
-	var objectScaleY = new UI.Number( 1 ).setWidth( '50px' ).onChange( updateScaleY );
-	var objectScaleZ = new UI.Number( 1 ).setWidth( '50px' ).onChange( updateScaleZ );
+	var objectScaleX = new UI.Number( 1 ).setRange( 0.01, Infinity ).setWidth( '50px' ).onChange( updateScaleX );
+	var objectScaleY = new UI.Number( 1 ).setRange( 0.01, Infinity ).setWidth( '50px' ).onChange( updateScaleY );
+	var objectScaleZ = new UI.Number( 1 ).setRange( 0.01, Infinity ).setWidth( '50px' ).onChange( updateScaleZ );
 
 	objectScaleRow.add( new UI.Text( 'Scale' ).setWidth( '90px' ) );
 	objectScaleRow.add( objectScaleLock );

+ 1 - 0
examples/index.html

@@ -298,6 +298,7 @@
 				"misc_controls_transform",
 				"misc_lights_test",
 				"misc_lookat",
+				"misc_fps",
 				"misc_sound",
 				"misc_ubiquity_test",
 				"misc_ubiquity_test2",

+ 1 - 1
examples/js/loaders/ColladaLoader.js

@@ -146,7 +146,7 @@ THREE.ColladaLoader = function () {
 		skins = [];
 
 		daeScene = parseScene();
-		scene = new THREE.Object3D();
+		scene = new THREE.Scene();
 
 		for ( var i = 0; i < daeScene.nodes.length; i ++ ) {
 

+ 400 - 227
examples/js/renderers/SoftwareRenderer.js

@@ -50,6 +50,10 @@ THREE.SoftwareRenderer = function ( parameters ) {
 	var vector1 = new THREE.Vector3();
 	var vector2 = new THREE.Vector3();
 	var vector3 = new THREE.Vector3();
+	
+	var texCoord1 = new THREE.Vector2();
+	var texCoord2 = new THREE.Vector2();
+	var texCoord3 = new THREE.Vector2();
 
 	this.domElement = canvas;
 
@@ -77,12 +81,12 @@ THREE.SoftwareRenderer = function ( parameters ) {
 
 		viewportXScale =  fixScale * canvasWidth  / 2;
 		viewportYScale = -fixScale * canvasHeight / 2;
-		viewportZScale =			 maxZVal	  / 2;
-
+		viewportZScale =             maxZVal      / 2;
+              
 		viewportXOffs  =  fixScale * canvasWidth  / 2 + 0.5;
 		viewportYOffs  =  fixScale * canvasHeight / 2 + 0.5;
-		viewportZOffs  =			 maxZVal	  / 2 + 0.5;
-
+		viewportZOffs  =             maxZVal      / 2 + 0.5;
+        
 		canvas.width = canvasWidth;
 		canvas.height = canvasHeight;
 
@@ -146,13 +150,27 @@ THREE.SoftwareRenderer = function ( parameters ) {
 			var shader = getMaterialShader( material );
 
 			if ( element instanceof THREE.RenderableFace ) {
-
-				drawTriangle(
-					element.v1.positionScreen,
-					element.v2.positionScreen,
-					element.v3.positionScreen,
-					shader, element, material
-				);
+				
+				if ( !element.uvs ) {
+					
+					drawTriangle(
+						element.v1.positionScreen,
+						element.v2.positionScreen,
+						element.v3.positionScreen,
+						null, null, null,
+						shader, element, material
+					);
+				} else {
+					
+					drawTriangle(
+						element.v1.positionScreen,
+						element.v2.positionScreen,
+						element.v3.positionScreen,
+						element.uvs[0], element.uvs[1], element.uvs[2],
+						shader, element, material
+					);					
+				}
+				
 
 			} else if ( element instanceof THREE.RenderableSprite ) {
 
@@ -170,11 +188,28 @@ THREE.SoftwareRenderer = function ( parameters ) {
 				vector3.copy( element );
 				vector3.x += scaleX;
 				vector3.y += scaleY;
+				
+				if ( material.map ) {
 
-				drawTriangle(
-					vector1, vector2, vector3,
-					shader, element, material
-				);
+					texCoord1.set( 0, 1 );
+					texCoord2.set( 0, 0 );
+					texCoord3.set( 1, 1 );
+				
+					drawTriangle(
+						vector1, vector2, vector3,
+						texCoord1, texCoord2, texCoord3,
+						shader, element, material
+					);
+
+				} else {
+					
+					drawTriangle(
+						vector1, vector2, vector3,
+						null, null, null,
+						shader, element, material
+					);
+
+				}			
 
 				vector1.copy( element );
 				vector1.x += scaleX;
@@ -187,11 +222,28 @@ THREE.SoftwareRenderer = function ( parameters ) {
 				vector3.copy( element );
 				vector3.x += scaleX;
 				vector3.y -= scaleY;
+				
+				if ( material.map ) {
 
-				drawTriangle(
-					vector1, vector2, vector3,
-					shader, element, material
-				);
+					texCoord1.set( 1, 1 );
+					texCoord2.set( 0, 0 );
+					texCoord3.set( 1, 0 );
+
+					drawTriangle(
+						vector1, vector2, vector3,
+						texCoord1, texCoord2, texCoord3,
+						shader, element, material
+					);
+
+				} else {
+					
+					drawTriangle(
+						vector1, vector2, vector3,
+						null, null, null,
+						shader, element, material
+					);
+
+				}				
 
 			}
 
@@ -234,17 +286,15 @@ THREE.SoftwareRenderer = function ( parameters ) {
 		var size = canvasWidth * canvasHeight * 4;
 
 		for ( var i = 0; i < size; i+=4 ) {
-
+			
 			data[ i ] = clearColor.r * 255 | 0;
 			data[ i+1 ] = clearColor.g * 255 | 0;
 			data[ i+2 ] = clearColor.b * 255 | 0;
-			data[ i+3 ] = 255;
-
+			data[ i+3 ] = 255; 
 		}
 
 		context.fillStyle = clearColor.getStyle();
 		context.fillRect( 0, 0, canvasWidth, canvasHeight );
-
 	}
 
 	function getPalette( material, bSimulateSpecular ) {
@@ -252,41 +302,46 @@ THREE.SoftwareRenderer = function ( parameters ) {
 		var diffuseG = material.ambient.g + material.color.g * 255;
 		var diffuseB = material.ambient.b + material.color.b * 255;
 		var palette = new Uint8Array(256*3);
-
+		
 		if ( bSimulateSpecular ) {
-
+			
 			var i = 0, j = 0;
-
 			while(i < 204) {
-
 				var r = i * diffuseR / 204;
 				var g = i * diffuseG / 204;
 				var b = i * diffuseB / 204;
+				if(r > 255)
+					r = 255;
+				if(g > 255)
+					g = 255;
+				if(b > 255)
+					b = 255;
 
-				palette[j++] = r > 255 ? 255 : r;
-				palette[j++] = g > 255 ? 255 : g;
-				palette[j++] = b > 255 ? 255 : b;
-
+				palette[j++] = r;
+				palette[j++] = g;
+				palette[j++] = b;
 				++i;
-
 			}
 
 			while(i < 256) { // plus specular highlight
-
 				var r = diffuseR + (i - 204) * (255 - diffuseR) / 82;
 				var g = diffuseG + (i - 204) * (255 - diffuseG) / 82;
 				var b = diffuseB + (i - 204) * (255 - diffuseB) / 82;
-
-				palette[j++] = r > 255 ? 255 : r;
-				palette[j++] = g > 255 ? 255 : g;
-				palette[j++] = b > 255 ? 255 : b;
-
+				if(r > 255)
+					r = 255;
+				if(g > 255)
+					g = 255;
+				if(b > 255)
+					b = 255;
+				
+				palette[j++] = r;
+				palette[j++] = g;
+				palette[j++] = b;
 				++i;
-
 			}
-
+			
 		} else {
-
+			
 			var i = 0, j = 0;
 			while(i < 256) {
 				var r = i * diffuseR / 255;
@@ -304,17 +359,18 @@ THREE.SoftwareRenderer = function ( parameters ) {
 				palette[j++] = b;
 				++i;
 			}
-
+			
 		}
-
+		
 		return palette;
 	}
+	
+	function basicMaterialShader( buffer, depthBuf, offset, depth, u, v, n, face, material ) {
+	
+		var colorOffset = offset * 4;
 
-	function basicMaterialShader( buffer, offset, u, v, n, face, material ) {
-
-		if ( material.map.needsUpdate ) {
+		if ( material.needsUpdate && !material.texture.data ) {
 			material.texture.CreateFromImage( material.map.image );
-			material.map.needsUpdate = false;
 		}
 
 		if ( !material.texture.data )
@@ -325,34 +381,35 @@ THREE.SoftwareRenderer = function ( parameters ) {
 		var tbound = tdim - 1;
 		var tdata = material.texture.data;
 		var tIndex = (((v * tdim) & tbound) * tdim + ((u * tdim) & tbound)) * 4;
-
+		
 		if ( !isTransparent ) {
-			buffer[ offset ] = tdata[tIndex];
-			buffer[ offset + 1 ] = tdata[tIndex+1];
-			buffer[ offset + 2 ] = tdata[tIndex+2];
-			buffer[ offset + 3 ] = material.opacity * 255;
-		} else {
+			buffer[ colorOffset ] = tdata[tIndex];
+			buffer[ colorOffset + 1 ] = tdata[tIndex+1];
+			buffer[ colorOffset + 2 ] = tdata[tIndex+2];
+			buffer[ colorOffset + 3 ] = material.opacity * 255;
+			depthBuf[ offset ] = depth;
+		}
+		else { 
 			var opaci = tdata[tIndex+3] * material.opacity;
-			var texel = tdata[tIndex] << 16 + tdata[tIndex+1] << 8 + tdata[tIndex+2];
+			var texel = (tdata[tIndex] << 16) + (tdata[tIndex+1] << 8) + tdata[tIndex+2];
 			if(opaci < 250) {
-				var backColor = buffer[ offset ] << 24 + buffer[ offset + 1 ] << 16 + buffer[ offset + 2 ] << 8;
-				texel = texel * opaci + backColor * (1-opaci);
-			}
-
-			buffer[ offset ] = (texel & 0xff0000) >> 16;
-			buffer[ offset + 1 ] = (texel & 0xff00) >> 8;
-			buffer[ offset + 2 ] = (texel & 0xff);
-			buffer[ offset + 3 ] = material.opacity * 255;
+				var backColor = (buffer[colorOffset] << 16) + (buffer[colorOffset + 1] << 8) + buffer[colorOffset + 2];
+				texel = texel * opaci + backColor * (1-opaci);						 
+			} 
+			
+			buffer[ colorOffset ] = (texel & 0xff0000) >> 16;
+			buffer[ colorOffset + 1 ] = (texel & 0xff00) >> 8;
+			buffer[ colorOffset + 2 ] = texel & 0xff;
+			buffer[ colorOffset + 3 ] = material.opacity * 255;
 		}
 	}
-
-	function lightingMaterialShader( buffer, offset, u, v, n, face, material ) {
-
-		if ( material.map.needsUpdate ) {
+	
+	function lightingMaterialShader( buffer, depthBuf, offset, depth, u, v, n, face, material ) {
+		
+		var colorOffset = offset * 4;
+		
+		if ( material.map.needsUpdate && !material.texture.data ) {
 			material.texture.CreateFromImage( material.map.image );
-			material.map.needsUpdate = false;
-
-			return;
 		}
 
 		if ( !material.texture.data )
@@ -364,49 +421,51 @@ THREE.SoftwareRenderer = function ( parameters ) {
 		var tbound = tdim - 1;
 		var tdata = material.texture.data;
 		var tIndex = (((v * tdim) & tbound) * tdim + ((u * tdim) & tbound)) * 4;
-
+		
 		if ( !isTransparent ) {
-			buffer[ offset ] = (material.palette[cIndex] * tdata[tIndex]) >> 8;
-			buffer[ offset + 1 ] = (material.palette[cIndex+1] * tdata[tIndex+1]) >> 8;
-			buffer[ offset + 2 ] = (material.palette[cIndex+2] * tdata[tIndex+2]) >> 8;
-			buffer[ offset + 3 ] = material.opacity * 255;
-		} else {
+			buffer[ colorOffset ] = (material.palette[cIndex] * tdata[tIndex]) >> 8;
+			buffer[ colorOffset + 1 ] = (material.palette[cIndex+1] * tdata[tIndex+1]) >> 8;
+			buffer[ colorOffset + 2 ] = (material.palette[cIndex+2] * tdata[tIndex+2]) >> 8;
+			buffer[ colorOffset + 3 ] = material.opacity * 255;			
+			depthBuf[ offset ] = depth;
+		} else { 
 			var opaci = tdata[tIndex+3] * material.opacity;
-			var foreColor = ((material.palette[cIndex] * tdata[tIndex]) << 16)
-						+ ((material.palette[cIndex+1] * tdata[tIndex+1]) << 8 )
-						+ (material.palette[cIndex+2] * tdata[tIndex+2]);
-
+			var foreColor = ((material.palette[cIndex] * tdata[tIndex]) << 16) 
+							+ ((material.palette[cIndex+1] * tdata[tIndex+1]) << 8 )
+							+ (material.palette[cIndex+2] * tdata[tIndex+2]);
+			
 			if(opaci < 250) {
-				var backColor = buffer[ offset ] << 24 + buffer[ offset + 1 ] << 16 + buffer[ offset + 2 ] << 8;
-				foreColor = foreColor * opaci + backColor * (1-opaci);
-			}
-			buffer[ offset ] = (foreColor & 0xff0000) >> 16;
-			buffer[ offset + 1 ] = (foreColor & 0xff00) >> 8;
-			buffer[ offset + 2 ] = (foreColor & 0xff);
-			buffer[ offset + 3 ] = material.opacity * 255;
+			var backColor = buffer[ colorOffset ] << 24 + buffer[ colorOffset + 1 ] << 16 + buffer[ colorOffset + 2 ] << 8;
+			foreColor = foreColor * opaci + backColor * (1-opaci);							
+			} 
+			
+			buffer[ colorOffset ] = (foreColor & 0xff0000) >> 16;
+			buffer[ colorOffset + 1 ] = (foreColor & 0xff00) >> 8;
+			buffer[ colorOffset + 2 ] = (foreColor & 0xff);
+			buffer[ colorOffset + 3 ] = material.opacity * 255;
 		}
-
+		
 	}
-
+	
 	function getMaterialShader( material ) {
 
 		var id = material.id;
 		var shader = shaders[ id ];
 
-		if ( shader === undefined ) {
-
+		if ( shaders[ id ] === undefined ) {
+			
 			if ( material instanceof THREE.MeshBasicMaterial ||
 				 material instanceof THREE.MeshLambertMaterial ||
 				 material instanceof THREE.MeshPhongMaterial ||
 				 material instanceof THREE.SpriteMaterial ) {
 
-				if ( material instanceof THREE.MeshLambertMaterial ) {
+				if ( material instanceof THREE.MeshLambertMaterial ) {			 
 					// Generate color palette
 					if ( !material.palette ) {
 						material.palette = getPalette( material, false );
 					}
-
-				} else if ( material instanceof THREE.MeshPhongMaterial ) {
+					
+				} else if ( material instanceof THREE.MeshPhongMaterial ) {			 
 					// Generate color palette
 					if ( !material.palette ) {
 						material.palette = getPalette( material, true );
@@ -414,57 +473,63 @@ THREE.SoftwareRenderer = function ( parameters ) {
 				}
 
 				var string;
-
+				
 				if ( material.map ) {
-
+					
 					var texture = new THREE.SoftwareRenderer.Texture();
-					material.texture = texture;
-
-					if ( material instanceof THREE.MeshBasicMaterial ) {
-
+					material.texture = texture;					
+					 
+					if ( material instanceof THREE.MeshBasicMaterial 
+						|| material instanceof THREE.SpriteMaterial ) { 
+						
 						shader = basicMaterialShader;
-
 					} else {
-
+						
 						shader = lightingMaterialShader;
-
 					}
-
+					
+					
 				} else {
-
+					
 					if ( material.vertexColors === THREE.FaceColors ) {
 
 						string = [
-							'buffer[ offset ] = face.color.r * 255;',
-							'buffer[ offset + 1 ] = face.color.g * 255;',
-							'buffer[ offset + 2 ] = face.color.b * 255;',
-							'buffer[ offset + 3 ] = material.opacity * 255;'
+							'var colorOffset = offset * 4;',
+							'buffer[ colorOffset ] = face.color.r * 255;',
+							'buffer[ colorOffset + 1 ] = face.color.g * 255;',
+							'buffer[ colorOffset + 2 ] = face.color.b * 255;',
+							'buffer[ colorOffset + 3 ] = material.opacity * 255;',
+							'depthBuf[ offset ] = depth;'
 						].join('\n');
 
 					} else {
 
 						string = [
-							'buffer[ offset ] = material.color.r * 255;',
-							'buffer[ offset + 1 ] = material.color.g * 255;',
-							'buffer[ offset + 2 ] = material.color.b * 255;',
-							'buffer[ offset + 3 ] = material.opacity * 255;'
+							'var colorOffset = offset * 4;',
+							'buffer[ colorOffset ] = material.color.r * 255;',
+							'buffer[ colorOffset + 1 ] = material.color.g * 255;',
+							'buffer[ colorOffset + 2 ] = material.color.b * 255;',
+							'buffer[ colorOffset + 3 ] = material.opacity * 255;',
+							'depthBuf[ offset ] = depth;'
 						].join('\n');
 
 					}
-
-					shader = new Function( 'buffer, offset, u, v, n, face, material', string );
-				}
+					
+					shader = new Function( 'buffer, depthBuf, offset, depth, u, v, n, face, material', string );
+				}			
 
 			} else {
 
 				var string = [
-					'buffer[ offset ] = u * 255;',
-					'buffer[ offset + 1 ] = v * 255;',
-					'buffer[ offset + 2 ] = 0;',
-					'buffer[ offset + 3 ] = 255;'
+					'var colorOffset = offset * 4;',
+					'buffer[ colorOffset ] = u * 255;',
+					'buffer[ colorOffset + 1 ] = v * 255;',
+					'buffer[ colorOffset + 2 ] = 0;',
+					'buffer[ colorOffset + 3 ] = 255;',
+					'depthBuf[ offset ] = depth;'
 				].join('\n');
 
-				shader = new Function( 'buffer, offset, u, v', string );
+				shader = new Function( 'buffer, depthBuf, offset, depth, u, v', string );
 
 			}
 
@@ -500,7 +565,7 @@ THREE.SoftwareRenderer = function ( parameters ) {
 
 	}
 
-	function drawTriangle( v1, v2, v3, shader, face, material ) {
+	function drawTriangle( v1, v2, v3, uv1, uv2, uv3, shader, face, material ) {
 
 		// TODO: Implement per-pixel z-clipping
 
@@ -524,21 +589,37 @@ THREE.SoftwareRenderer = function ( parameters ) {
 		var z1 = (v1.z * viewportZScale + viewportZOffs) | 0;
 		var z2 = (v2.z * viewportZScale + viewportZOffs) | 0;
 		var z3 = (v3.z * viewportZScale + viewportZOffs) | 0;
-
+		
 		// UV values
-
-		var tu1 = face.uvs[0].x;
-		var tv1 = 1-face.uvs[0].y;
-		var tu2 = face.uvs[1].x;
-		var tv2 = 1-face.uvs[1].y;
-		var tu3 = face.uvs[2].x;
-		var tv3 = 1-face.uvs[2].y;
-
+		var bHasUV = false;
+		var tu1, tv1, tu2, tv2, tu3, tv3;
+		
+		if ( uv1 && uv2 && uv3 ) {
+			bHasUV = true;
+			
+			tu1 = uv1.x; 
+			tv1 = 1-uv1.y; 
+			tu2 = uv2.x; 
+			tv2 = 1-uv2.y; 
+			tu3 = uv3.x; 
+			tv3 = 1-uv3.y; 
+		}			 
+		
 		// Normal values
-		var n1 = face.vertexNormalsModel[0], n2 = face.vertexNormalsModel[1], n3 = face.vertexNormalsModel[2];
-		var nz1 = n1.z * 255;
-		var nz2 = n2.z * 255;
-		var nz3 = n3.z * 255;
+		var bHasNormal = false;
+		var n1, n2, n3, nz1, nz2, nz3;
+		
+		if ( face.vertexNormalsModel ) {			
+			bHasNormal = true;
+			
+			n1 = face.vertexNormalsModel[0];
+			n2 = face.vertexNormalsModel[1];
+			n3 = face.vertexNormalsModel[2]; 
+			nz1 = n1.z * 255;
+			nz2 = n2.z * 255;
+			nz3 = n3.z * 255;
+		}
+		
 		// Deltas
 
 		var dx12 = x1 - x2, dy12 = y2 - y1;
@@ -603,43 +684,43 @@ THREE.SoftwareRenderer = function ( parameters ) {
 		var fixscale = (1 << subpixelBits);
 		dzdx = (dzdx * fixscale) | 0;
 		dzdy = (dzdy * fixscale) | 0;
-
-		// UV interpolation setup
-
-		var dtu12 = tu1 - tu2, dtu31 = tu3 - tu1;
-		var dtudx = (invDet * (dtu12*dy31 - dtu31*dy12)); // dtu per one subpixel step in x
-		var dtudy = (invDet * (dtu12*dx31 - dx12*dtu31)); // dtu per one subpixel step in y
-		var dtv12 = tv1 - tv2, dtv31 = tv3 - tv1;
-		var dtvdx = (invDet * (dtv12*dy31 - dtv31*dy12)); // dtv per one subpixel step in x
-		var dtvdy = (invDet * (dtv12*dx31 - dx12*dtv31)); // dtv per one subpixel step in y
-
-		// UV at top/left corner of rast area
-
-		var ctu = ( tu1 + (minXfixscale - x1) * dtudx + (minYfixscale - y1) * dtudy );
-		var ctv = ( tv1 + (minXfixscale - x1) * dtvdx + (minYfixscale - y1) * dtvdy );
-
-		// UV pixel steps
-
-		dtudx = dtudx * fixscale;
-		dtudy = dtudy * fixscale;
-		dtvdx = dtvdx * fixscale;
-		dtvdy = dtvdy * fixscale;
-
-		// Normal interpolation setup
-
-		var dnz12 = nz1 - nz2, dnz31 = nz3 - nz1;
-		var dnzdx = (invDet * (dnz12*dy31 - dnz31*dy12)); // dnz per one subpixel step in x
-		var dnzdy = (invDet * (dnz12*dx31 - dx12*dnz31)); // dnz per one subpixel step in y
-
-		 // Normal at top/left corner of rast area
-
-		var cnz = ( nz1 + (minXfixscale - x1) * dnzdx + (minYfixscale - y1) * dnzdy );
-
-		// Normal pixel steps
-
-		dnzdx = (dnzdx * fixscale);
-		dnzdy = (dnzdy * fixscale);
-
+		
+		var dtvdx, dtvdy, cbtu, cbtv;
+		if ( bHasUV ) {
+			// UV interpolation setup
+			var dtu12 = tu1 - tu2, dtu31 = tu3 - tu1;
+			var dtudx = (invDet * (dtu12*dy31 - dtu31*dy12)); // dtu per one subpixel step in x
+			var dtudy = (invDet * (dtu12*dx31 - dx12*dtu31)); // dtu per one subpixel step in y
+			var dtv12 = tv1 - tv2, dtv31 = tv3 - tv1;
+			dtvdx = (invDet * (dtv12*dy31 - dtv31*dy12)); // dtv per one subpixel step in x
+			dtvdy = (invDet * (dtv12*dx31 - dx12*dtv31)); // dtv per one subpixel step in y	 
+			
+			// UV at top/left corner of rast area
+			cbtu = ( tu1 + (minXfixscale - x1) * dtudx + (minYfixscale - y1) * dtudy );
+			cbtv = ( tv1 + (minXfixscale - x1) * dtvdx + (minYfixscale - y1) * dtvdy );
+			
+			// UV pixel steps			
+			dtudx = dtudx * fixscale;
+			dtudy = dtudy * fixscale;		
+			dtvdx = dtvdx * fixscale;
+			dtvdy = dtvdy * fixscale;
+		}				
+
+		var dnxdx, dnzdy, cbnz;
+		if ( bHasNormal ) {
+			 // Normal interpolation setup		
+			var dnz12 = nz1 - nz2, dnz31 = nz3 - nz1;
+			var dnzdx = (invDet * (dnz12*dy31 - dnz31*dy12)); // dnz per one subpixel step in x
+			var dnzdy = (invDet * (dnz12*dx31 - dx12*dnz31)); // dnz per one subpixel step in y
+			
+			// Normal at top/left corner of rast area		 
+			cbnz = ( nz1 + (minXfixscale - x1) * dnzdx + (minYfixscale - y1) * dnzdy );
+
+			// Normal pixel steps
+			dnzdx = (dnzdx * fixscale);
+			dnzdy = (dnzdy * fixscale);
+		}
+		
 		// Set up min/max corners
 		var qm1 = q - 1; // for convenience
 		var nmin1 = 0, nmax1 = 0;
@@ -663,17 +744,23 @@ THREE.SoftwareRenderer = function ( parameters ) {
 		var cb2 = c2;
 		var cb3 = c3;
 		var cbz = cz;
-		var cbtu = ctu;
-		var cbtv = ctv;
-		var cbnz = cnz;
 		var qstep = -q;
 		var e1x = qstep * dy12;
 		var e2x = qstep * dy23;
 		var e3x = qstep * dy31;
 		var ezx = qstep * dzdx;
-		var etux = qstep * dtudx;
-		var etvx = qstep * dtvdx;
-		var enzx = qstep * dnzdx;
+		
+		var etux, etvx; 
+		if ( bHasUV ) {
+			etux = qstep * dtudx;
+			etvx = qstep * dtvdx;
+		}
+
+		var enzx; 
+		if ( bHasNormal ) {
+			enzx = qstep * dnzdx;
+		}
+				
 		var x0 = minx;
 
 		for ( var y0 = miny; y0 < maxy; y0 += q ) {
@@ -686,9 +773,16 @@ THREE.SoftwareRenderer = function ( parameters ) {
 				cb2 += e2x;
 				cb3 += e3x;
 				cbz += ezx;
-				cbtu += etux;
-				cbtv += etvx;
-				cbnz += enzx;
+				
+				if ( bHasUV ) {
+					cbtu += etux;
+					cbtv += etvx;
+				}
+				
+				if ( bHasNormal ) {
+					cbnz += enzx;
+				}				
+				
 			}
 
 			// Okay, we're now in a block we know is outside. Reverse direction and go into main loop.
@@ -697,9 +791,15 @@ THREE.SoftwareRenderer = function ( parameters ) {
 			e2x = -e2x;
 			e3x = -e3x;
 			ezx = -ezx;
-			etux = -etux;
-			etvx = -etvx;
-			enzx = -enzx;
+			
+			if ( bHasUV ) {				
+				etux = -etux;
+				etvx = -etvx;
+			}
+			 
+			if ( bHasNormal ) {
+				enzx = -enzx;
+			}			
 
 			while ( 1 ) {
 
@@ -709,9 +809,15 @@ THREE.SoftwareRenderer = function ( parameters ) {
 				cb2 += e2x;
 				cb3 += e3x;
 				cbz += ezx;
-				cbtu += etux;
-				cbtv += etvx;
-				cbnz += enzx;
+				
+				if ( bHasUV ) {
+					cbtu += etux;
+					cbtv += etvx;
+				}
+				 
+				if ( bHasNormal ) {
+					cbnz += enzx;
+				}				
 
 				// We're done with this block line when at least one edge completely out
 				// If an edge function is too small and decreasing in the current traversal
@@ -737,7 +843,7 @@ THREE.SoftwareRenderer = function ( parameters ) {
 
 				// Offset at top-left corner
 				var offset = x0 + y0 * canvasWidth;
-
+				
 				// Accept whole block when fully covered
 				if ( cb1 >= nmin1 && cb2 >= nmin2 && cb3 >= nmin3 ) {
 
@@ -747,34 +853,58 @@ THREE.SoftwareRenderer = function ( parameters ) {
 					var cy1 = cb1;
 					var cy2 = cb2;
 					var cyz = cbz;
-					var cytu = cbtu;
-					var cytv = cbtv;
-					var cynz = cbnz;
+					
+					var cytu, cytv;					
+					if ( bHasUV ) {
+						cytu = cbtu;
+						cytv = cbtv;
+					}
+					
+					var cynz;
+					if ( bHasNormal ) {
+						cynz = cbnz;
+					}
+					
 
 					for ( var iy = 0; iy < q; iy ++ ) {
 
 						var cx1 = cy1;
 						var cx2 = cy2;
 						var cxz = cyz;
-						var cxtu = cytu;
-						var cxtv = cytv;
-						var cxnz = cynz;
+						
+						var cxtu;
+						var cxtv;						
+						if ( bHasUV ) {
+							cxtu = cytu;
+							cxtv = cytv;
+						}
+						
+						var cxnz; 
+						if ( bHasNormal ) {
+							cxnz = cynz; 
+						}												 
 
 						for ( var ix = 0; ix < q; ix ++ ) {
 
 							var z = cxz;
-
-							if ( z < zbuffer[ offset ] ) {
-								zbuffer[ offset ] = z;
-								shader( data, offset * 4, cxtu, cxtv, cxnz, face, material );
+							 
+							if ( z < zbuffer[ offset ] ) {		 
+								shader( data, zbuffer, offset, z, cxtu, cxtv, cxnz, face, material );								
 							}
 
 							cx1 += dy12;
 							cx2 += dy23;
 							cxz += dzdx;
-							cxtu += dtudx;
-							cxtv += dtvdx;
-							cxnz += dnzdx;
+							
+							if ( bHasUV ) {
+								cxtu += dtudx;
+								cxtv += dtvdx;
+							}
+							
+							if ( bHasNormal ) {
+								cxnz += dnzdx;
+							}							
+							
 							offset++;
 
 						}
@@ -782,9 +912,16 @@ THREE.SoftwareRenderer = function ( parameters ) {
 						cy1 += dx12;
 						cy2 += dx23;
 						cyz += dzdy;
-						cytu += dtudy;
-						cytv += dtvdy;
-						cynz += dnzdy;
+						
+						if ( bHasUV ) {
+							cytu += dtudy;
+							cytv += dtvdy;
+						}
+						
+						if ( bHasNormal ) {
+							cynz += dnzdy;
+						}						
+						
 						offset += linestep;
 
 					}
@@ -795,9 +932,17 @@ THREE.SoftwareRenderer = function ( parameters ) {
 					var cy2 = cb2;
 					var cy3 = cb3;
 					var cyz = cbz;
-					var cytu = cbtu;
-					var cytv = cbtv;
-					var cynz = cbnz;
+					
+					var cytu, cytv;
+					if ( bHasUV ) {
+						cytu = cbtu;
+						cytv = cbtv;
+					}
+					
+					var cynz;
+					if ( bHasNormal ) {
+						cynz = cbnz;
+					}					
 
 					for ( var iy = 0; iy < q; iy ++ ) {
 
@@ -805,19 +950,27 @@ THREE.SoftwareRenderer = function ( parameters ) {
 						var cx2 = cy2;
 						var cx3 = cy3;
 						var cxz = cyz;
-						var cxtu = cytu;
-						var cxtv = cytv;
-						var cxnz = cynz;
+						
+						var cxtu;
+						var cxtv;							
+						if ( bHasUV ) {
+							cxtu = cytu;
+							cxtv = cytv;
+						}
+						
+						var cxnz;						
+						if ( bHasNormal ) {
+							cxnz = cynz;	 
+						}						 
 
 						for ( var ix = 0; ix < q; ix ++ ) {
 
 							if ( ( cx1 | cx2 | cx3 ) >= 0 ) {
 
-								var z = cxz;
+								var z = cxz;								
 
-								if ( z < zbuffer[ offset ] ) {
-									zbuffer[ offset ] = z;
-									shader( data, offset * 4, cxtu, cxtv, cxnz, face, material );
+								if ( z < zbuffer[ offset ] ) {						 
+									shader( data, zbuffer, offset, z, cxtu, cxtv, cxnz, face, material );
 								}
 
 							}
@@ -826,9 +979,16 @@ THREE.SoftwareRenderer = function ( parameters ) {
 							cx2 += dy23;
 							cx3 += dy31;
 							cxz += dzdx;
-							cxtu += dtudx;
-							cxtv += dtvdx;
-							cxnz += dnzdx;
+							
+							if ( bHasUV ) {
+								cxtu += dtudx;
+								cxtv += dtvdx;
+							}
+							
+							if ( bHasNormal ) {
+								cxnz += dnzdx;
+							}
+							
 							offset++;
 
 						}
@@ -837,9 +997,16 @@ THREE.SoftwareRenderer = function ( parameters ) {
 						cy2 += dx23;
 						cy3 += dx31;
 						cyz += dzdy;
-						cytu += dtudy;
-						cytv += dtvdy;
-						cynz += dnzdy;
+						
+						if ( bHasUV ) {
+							cytu += dtudy;
+							cytv += dtvdy;
+						}
+						
+						if ( bHasNormal ) {
+							cynz += dnzdy;
+						}						
+						
 						offset += linestep;
 
 					}
@@ -853,9 +1020,16 @@ THREE.SoftwareRenderer = function ( parameters ) {
 			cb2 += q*dx23;
 			cb3 += q*dx31;
 			cbz += q*dzdy;
-			cbtu += q*dtudy;
-			cbtv += q*dtvdy;
-			cbnz += q*dnzdy;
+			
+			if ( bHasUV ) {
+				cbtu += q*dtudy;
+				cbtv += q*dtvdy;
+			}
+			
+			if ( bHasNormal ) {
+				cbnz += q*dnzdy;
+			}			
+			
 		}
 
 	}
@@ -913,14 +1087,13 @@ THREE.SoftwareRenderer = function ( parameters ) {
 };
 
 THREE.SoftwareRenderer.Texture = function() {
-
 	var canvas = null;
-
+	
 	this.CreateFromImage = function( image ) {
-
-		if(image.width <=0 || image.height <=0)
+		
+		if( !image || image.width <=0 || image.height <=0 )
 			return;
-
+	
 		var isCanvasClean = false;
 		var canvas = THREE.SoftwareRenderer.Texture.canvas;
 		if ( !canvas ) {

+ 322 - 0
examples/misc_fps.html

@@ -0,0 +1,322 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js - platformer demo</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 {
+				background-color: rgb(200,200,200);
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px; width: 100%;
+				color: #ffffff;
+				padding: 5px;
+				font-family:Monospace;
+				font-size:13px;
+				font-weight: bold;
+				text-align:center;
+			}
+
+			a {
+				color: #ffffff;
+			}
+		</style>
+	</head>
+	<body>
+
+		<div id="container"></div>
+		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - platformer demo. cubemap by <a href="http://www.zfight.com/" target="_blank">Jochum Skoglund</a>.<br />Use arrow keys to look around and WASD to move.</div>
+
+		<script src="../build/three.min.js"></script>
+
+		<script>
+
+			// player motion parameters
+
+			var motion = {
+				airborne : false,
+				position : new THREE.Vector3(), velocity : new THREE.Vector3(),
+				rotation : new THREE.Vector2(), spinning : new THREE.Vector2()
+			};
+
+			motion.position.y = -150;
+
+
+			// game systems code
+
+			var resetPlayer = function() {
+				if( motion.position.y < -123 ) {
+					motion.position.set( -2, 7.7, 25 );
+					motion.velocity.multiplyScalar( 0 );
+				}
+			};
+
+			var keyboardControls = (function() {
+
+				var keys = { SP : 32, W : 87, A : 65, S : 83, D : 68, UP : 38, LT : 37, DN : 40, RT : 39 };
+
+				var keysPressed = {};
+
+				(function( watchedKeyCodes ) {
+					var handler = function( down ) {
+						return function( e ) {
+							var index = watchedKeyCodes.indexOf( e.keyCode );
+							if( index >= 0 ) {
+								keysPressed[watchedKeyCodes[index]] = down; e.preventDefault();
+							}
+						};
+					}
+					window.addEventListener( "keydown", handler( true ), false );
+					window.addEventListener( "keyup", handler( false ), false );
+				})([
+					keys.SP, keys.W, keys.A, keys.S, keys.D, keys.UP, keys.LT, keys.DN, keys.RT
+				]);
+
+				var forward = new THREE.Vector3();
+				var sideways = new THREE.Vector3();
+
+				return function() {
+					if( !motion.airborne ) {
+
+						// look around
+						var sx = keysPressed[keys.UP] ? 0.03 : ( keysPressed[keys.DN] ? -0.03 : 0 );
+						var sy = keysPressed[keys.LT] ? 0.03 : ( keysPressed[keys.RT] ? -0.03 : 0 );
+
+						if( Math.abs( sx ) >= Math.abs( motion.spinning.x ) ) motion.spinning.x = sx;
+						if( Math.abs( sy ) >= Math.abs( motion.spinning.y ) ) motion.spinning.y = sy;
+
+						// move around
+						forward.set( Math.sin( motion.rotation.y ), 0, Math.cos( motion.rotation.y ) );
+						sideways.set( forward.z, 0, -forward.x );
+
+						forward.multiplyScalar( keysPressed[keys.W] ? -0.1 : (keysPressed[keys.S] ? 0.1 : 0));
+						sideways.multiplyScalar( keysPressed[keys.A] ? -0.1 : (keysPressed[keys.D] ? 0.1 : 0));
+
+						var combined = forward.add( sideways );
+						if( Math.abs( combined.x ) >= Math.abs( motion.velocity.x ) ) motion.velocity.x = combined.x;
+						if( Math.abs( combined.y ) >= Math.abs( motion.velocity.y ) ) motion.velocity.y = combined.y;
+						if( Math.abs( combined.z ) >= Math.abs( motion.velocity.z ) ) motion.velocity.z = combined.z;
+					}
+				};
+			})();
+
+			var jumpPads = (function() {
+				var pads = [ new THREE.Vector3( -17.5, 8, -10 ), new THREE.Vector3( 17.5, 8, -10 ), new THREE.Vector3( 0, 8, 21 ) ];
+				var temp = new THREE.Vector3();
+
+				return function() {
+					if( !motion.airborne ) {
+						for( var j = 0, n = pads.length; j < n; j++ ) {
+							if ( pads[j].distanceToSquared( motion.position ) < 2.3 ) {
+
+								// calculate velocity towards another side of platform from jump pad position
+								temp.copy( pads[j] ); temp.y = 0; temp.setLength( -0.8 ); temp.y = 0.7;
+
+								motion.airborne = true; motion.velocity.copy( temp ); break;
+							}
+						}
+					}
+				};
+			})();
+
+			var applyPhysics = (function() {
+				var timeStep = 5;
+				var timeLeft = timeStep + 1;
+
+				var birdsEye = 100;
+				var kneeDeep = 0.4;
+
+				var raycaster = new THREE.Raycaster();
+				raycaster.ray.direction.set( 0, -1, 0 );
+
+				var angles = new THREE.Vector2();
+				var displacement = new THREE.Vector3();
+
+				return function( dt ) {
+					var platform = scene.getObjectByName( "platform", true );
+					if( platform ) {
+
+						timeLeft += dt;
+
+						// run several fixed-step iterations to approximate varying-step
+
+						dt = 5;
+						while( timeLeft >= dt ) {
+
+							var time = 0.3, damping = 0.93, gravity = 0.01, tau = 2 * Math.PI;
+
+							raycaster.ray.origin.copy( motion.position );
+							raycaster.ray.origin.y += birdsEye;
+
+							var hits = raycaster.intersectObject( platform );
+
+							motion.airborne = true;
+
+							// are we above, or at most knee deep in, the platform?
+
+							if( ( hits.length > 0 ) && ( hits[0].face.normal.y > 0 ) ) {
+								var actualHeight = hits[0].distance - birdsEye;
+
+								// collision: stick to the surface if landing on it
+								
+								if( ( motion.velocity.y <= 0 ) && ( Math.abs( actualHeight ) < kneeDeep ) ) {
+									motion.position.y -= actualHeight;
+									motion.velocity.y = 0;
+									motion.airborne = false;
+								}
+							}
+
+							if( motion.airborne ) motion.velocity.y -= gravity;
+
+							angles.copy( motion.spinning ).multiplyScalar( time );
+							if( !motion.airborne ) motion.spinning.multiplyScalar( damping );
+
+							displacement.copy( motion.velocity ).multiplyScalar( time );
+							if( !motion.airborne ) motion.velocity.multiplyScalar( damping );
+
+							motion.rotation.add( angles );
+							motion.position.add( displacement );
+
+							// limit the tilt at ±0.4 radians
+
+							motion.rotation.x = Math.max( -0.4, Math.min ( +0.4, motion.rotation.x ) );
+							
+							// wrap horizontal rotation to 0...2π
+							
+							motion.rotation.y += tau; motion.rotation.y %= tau;
+
+							timeLeft -= dt;
+						}
+					}
+				};
+			})();
+
+			var updateCamera = (function() {
+				var euler = new THREE.Euler( 0, 0, 0, 'YXZ' );
+
+				return function() {
+					euler.x = motion.rotation.x;
+					euler.y = motion.rotation.y;
+					camera.quaternion.setFromEuler( euler );
+
+					camera.position.copy( motion.position );
+
+					camera.position.y += 3.0;
+				};
+			})();
+
+
+			// init 3D stuff
+
+			function makeSkybox( urls, size ) {
+				var skyboxCubemap = THREE.ImageUtils.loadTextureCube( urls );
+				skyboxCubemap.format = THREE.RGBFormat;
+
+				var skyboxShader = THREE.ShaderLib['cube'];
+				skyboxShader.uniforms['tCube'].value = skyboxCubemap;
+
+				return new THREE.Mesh(
+					new THREE.BoxGeometry( size, size, size ),
+					new THREE.ShaderMaterial({
+						fragmentShader : skyboxShader.fragmentShader, vertexShader : skyboxShader.vertexShader,
+						uniforms : skyboxShader.uniforms, depthWrite : false, side : THREE.BackSide
+					})
+				);
+			};
+
+			function makePlatform( jsonUrl, textureUrl, textureQuality ) {
+				var placeholder = new THREE.Object3D();
+
+				var texture = THREE.ImageUtils.loadTexture( textureUrl );
+				texture.anisotropy = textureQuality;
+
+				var loader = new THREE.JSONLoader();
+				loader.load( jsonUrl, function( geometry ) {
+
+					geometry.computeFaceNormals();
+
+					var platform = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial({ map : texture }) );
+
+					platform.name = "platform";
+
+					placeholder.add( platform );
+				});
+
+				return placeholder;
+			};
+
+			var renderer = new THREE.WebGLRenderer({ antialias : true });
+
+			var camera = new THREE.PerspectiveCamera( 60, 1, 0.1, 9000 );
+
+			var scene = new THREE.Scene();
+			
+			scene.add( camera );
+
+			scene.add( makeSkybox( [
+				'textures/cube/skybox/px.jpg', // right
+				'textures/cube/skybox/nx.jpg', // left
+				'textures/cube/skybox/py.jpg', // top
+				'textures/cube/skybox/ny.jpg', // bottom
+				'textures/cube/skybox/pz.jpg', // back
+				'textures/cube/skybox/nz.jpg'  // front
+			], 8000 ));
+
+			scene.add( makePlatform(
+				'models/platform/platform.json',
+				'models/platform/platform.jpg',
+				renderer.getMaxAnisotropy()
+			));
+
+
+			// start the game
+
+			var start = function( gameLoop, gameViewportSize ) {
+				var resize = function() {
+					var viewport = gameViewportSize();
+					renderer.setSize( viewport.width, viewport.height );
+					camera.aspect = viewport.width / viewport.height;
+					camera.updateProjectionMatrix();
+				};
+
+				window.addEventListener( 'resize', resize, false );
+				resize();
+
+				var lastTimeStamp;
+				var render = function( timeStamp ) {
+					var timeElapsed = lastTimeStamp ? timeStamp - lastTimeStamp : 0; lastTimeStamp = timeStamp;
+
+					// call our game loop with the time elapsed since last rendering, in ms
+					gameLoop( timeElapsed );
+					
+					renderer.render( scene, camera );
+					requestAnimationFrame( render );
+				};
+
+				requestAnimationFrame( render );
+			};
+
+
+			var gameLoop = function( dt ) {
+				resetPlayer();
+				keyboardControls();
+				jumpPads();
+				applyPhysics( dt );
+				updateCamera();
+			};
+
+			var gameViewportSize = function() { return {
+				width: window.innerWidth, height: window.innerHeight
+			}};
+
+			document.getElementById( 'container' ).appendChild( renderer.domElement );
+
+			start( gameLoop, gameViewportSize );
+		</script>
+	</body>
+</html>

+ 1 - 1
examples/misc_ubiquity_test.html

@@ -143,7 +143,7 @@
 				// SPRITES
 
 				var texture = THREE.ImageUtils.loadTexture( 'textures/sprite.png' );
-				var material = new THREE.SpriteMaterial( { map: texture } );
+				var material = new THREE.SpriteMaterial( { map: texture, transparent: true } );
 
 				for ( var i = 0; i < 50; i ++ ) {
 

BIN
examples/models/platform/platform.jpg


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 5 - 0
examples/models/platform/platform.json


+ 2 - 7
examples/webgl_loader_vrml.html

@@ -34,7 +34,7 @@
 
 		<script src="../build/three.min.js"></script>
 
-		<script src="js/controls/TrackballControls.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
 
 		<script src="js/loaders/VRMLLoader.js"></script>
 
@@ -59,20 +59,15 @@
 				camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.01, 1e10 );
 				camera.position.z = 6;
 
-				controls = new THREE.TrackballControls( camera );
+				controls = new THREE.OrbitControls( camera );
 
 				controls.rotateSpeed = 5.0;
 				controls.zoomSpeed = 5;
-				controls.panSpeed = 2;
 
 				controls.noZoom = false;
 				controls.noPan = false;
 
-				controls.staticMoving = true;
-				controls.dynamicDampingFactor = 0.3;
-
 				scene = new THREE.Scene();
-
 				scene.add( camera );
 
 				// light

+ 2 - 2
examples/webgl_marchingcubes.html

@@ -60,7 +60,7 @@
 
 	<script src="../build/three.min.js"></script>
 
-	<script src="js/controls/TrackballControls.js"></script>
+	<script src="js/controls/OrbitControls.js"></script>
 
 	<script src="js/shaders/CopyShader.js"></script>
 	<script src="js/shaders/FXAAShader.js"></script>
@@ -174,7 +174,7 @@
 
 			// CONTROLS
 
-			controls = new THREE.TrackballControls( camera, renderer.domElement );
+			controls = new THREE.OrbitControls( camera, renderer.domElement );
 
 			// STATS
 

+ 15 - 25
examples/webgl_materials_lightmap.html

@@ -26,7 +26,7 @@
 	<body>
 		<script src="../build/three.min.js"></script>
 
-		<script src="js/controls/TrackballControls.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
 
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
@@ -96,8 +96,7 @@
 
 				// CONTROLS
 
-				controls = new THREE.TrackballControls( camera );
-				controls.target.z = 150;
+				controls = new THREE.OrbitControls( camera );
 
 				// LIGHTS
 
@@ -127,7 +126,12 @@
 				scene.fog.color.copy( uniforms.bottomColor.value );
 
 				var skyGeo = new THREE.SphereGeometry( 4000, 32, 15 );
-				var skyMat = new THREE.ShaderMaterial( { vertexShader: vertexShader, fragmentShader: fragmentShader, uniforms: uniforms, side: THREE.BackSide } );
+				var skyMat = new THREE.ShaderMaterial( {
+					uniforms: uniforms,
+					vertexShader: vertexShader,
+					fragmentShader: fragmentShader,
+					side: THREE.BackSide
+				} );
 
 				var sky = new THREE.Mesh( skyGeo, skyMat );
 				scene.add( sky );
@@ -151,9 +155,13 @@
 				// MODEL
 
 				var loader = new THREE.JSONLoader();
-				var callback = function ( geometry, materials ) { createScene( geometry, materials, 0, 0, 0, 0, 100 ) };
+				loader.load( "obj/lightmap/lightmap.js", function ( geometry, materials ) {
 
-				loader.load( "obj/lightmap/lightmap.js", callback );
+					var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
+					mesh.scale.multiplyScalar( 100 );
+					scene.add( mesh );
+
+				} );
 
 				//
 
@@ -170,32 +178,14 @@
 
 			}
 
-			function createScene( geometry, materials, x, y, z, b, s ) {
-
-				var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );
-				mesh.position.set( x, y, z );
-				mesh.scale.set( s, s, s );
-				scene.add( mesh );
-
-			}
-
 			//
 
 			function animate() {
 
 				requestAnimationFrame( animate );
 
-				render();
-				stats.update();
-
-			}
-
-			function render() {
-
-				var delta = clock.getDelta();
-				controls.update( delta );
-
 				renderer.render( scene, camera );
+				stats.update();
 
 			}
 

+ 2 - 2
examples/webgl_morphtargets_md2.html

@@ -46,7 +46,7 @@
 
 		<script src="../build/three.min.js"></script>
 
-		<script src="js/controls/TrackballControls.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
 
 		<script src='js/MD2Character.js'></script>
 
@@ -159,7 +159,7 @@
 
 				// CONTROLS
 
-				controls = new THREE.TrackballControls( camera, renderer.domElement );
+				controls = new THREE.OrbitControls( camera, renderer.domElement );
 				controls.target.set( 0, 50, 0 );
 
 				// GUI

+ 2 - 2
examples/webgl_morphtargets_md2_control.html

@@ -46,7 +46,7 @@
 
 		<script src="../build/three.min.js"></script>
 
-		<script src="js/controls/TrackballControls.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
 
 		<script src='js/MD2CharacterComplex.js'></script>
 
@@ -166,7 +166,7 @@
 
 				// CONTROLS
 
-				cameraControls = new THREE.TrackballControls( camera, renderer.domElement );
+				cameraControls = new THREE.OrbitControls( camera, renderer.domElement );
 				cameraControls.target.set( 0, 50, 0 );
 
 				// CHARACTER

+ 2 - 5
examples/webgl_terrain_dynamic.html

@@ -56,7 +56,7 @@
 
 		<script src="../build/three.min.js"></script>
 
-		<script src="js/controls/TrackballControls.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
 
 		<script src="js/shaders/BleachBypassShader.js"></script>
 		<script src="js/shaders/ConvolutionShader.js"></script>
@@ -279,7 +279,7 @@
 				camera = new THREE.PerspectiveCamera( 40, SCREEN_WIDTH / SCREEN_HEIGHT, 2, 4000 );
 				camera.position.set( -1200, 800, 1200 );
 
-				controls = new THREE.TrackballControls( camera );
+				controls = new THREE.OrbitControls( camera );
 				controls.target.set( 0, 0, 0 );
 
 				controls.rotateSpeed = 1.0;
@@ -289,9 +289,6 @@
 				controls.noZoom = false;
 				controls.noPan = false;
 
-				controls.staticMoving = false;
-				controls.dynamicDampingFactor = 0.15;
-
 				controls.keys = [ 65, 83, 68 ];
 
 				// SCENE (FINAL)

+ 5 - 9
src/objects/Sprite.js

@@ -5,10 +5,14 @@
 
 THREE.Sprite = ( function () {
 
-	var vertices = new Float32Array( [ - 0.5, - 0.5, 0, 0.5, - 0.5, 0, 0.5, 0.5, 0 ] );
+	var indices = new Uint16Array( [ 0, 1, 2,  0, 2, 3 ] );
+	var vertices = new Float32Array( [ - 0.5, - 0.5, 0,   0.5, - 0.5, 0,   0.5, 0.5, 0,   - 0.5, 0.5, 0 ] );
+	var uvs = new Float32Array( [ 0, 0,   1, 0,   1, 1,   0, 1 ] );
 
 	var geometry = new THREE.BufferGeometry();
+	geometry.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
 	geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
+	geometry.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
 
 	return function ( material ) {
 
@@ -52,14 +56,6 @@ THREE.Sprite.prototype.raycast = ( function () {
 
 }() );
 
-THREE.Sprite.prototype.updateMatrix = function () {
-
-	this.matrix.compose( this.position, this.quaternion, this.scale );
-
-	this.matrixWorldNeedsUpdate = true;
-
-};
-
 THREE.Sprite.prototype.clone = function ( object ) {
 
 	if ( object === undefined ) object = new THREE.Sprite( this.material );

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است