浏览代码

Merge remote branch 'upstream/master'

Conflicts:
	src/renderers/Renderer.js
	src/renderers/WebGLRenderer.js
Julian Walker 15 年之前
父节点
当前提交
69287b8d10
共有 61 个文件被更改,包括 1830 次插入498 次删除
  1. 11 0
      AUTHORS
  2. 1 1
      LICENSE
  3. 15 5
      README.md
  4. 19 15
      TODO
  5. 0 1
      build/Three.js
  6. 0 1
      build/ThreeDebug.js
  7. 39 18
      examples/camera_free.html
  8. 1 0
      examples/geometry/Qrcode.js
  9. 47 0
      examples/geometry/primitives/ClickCube.js
  10. 1 0
      examples/geometry/primitives/Cube.js
  11. 1 0
      examples/geometry/primitives/Cylinder.js
  12. 1 0
      examples/geometry/primitives/Plane.js
  13. 3 0
      examples/geometry/primitives/Sphere.js
  14. 1 1
      examples/geometry_birds.html
  15. 26 26
      examples/geometry_cube.html
  16. 1 1
      examples/geometry_earth.html
  17. 1 1
      examples/geometry_terrain.html
  18. 187 0
      examples/hci_clickcube.html
  19. 1 0
      examples/js/Stats.js
  20. 1 1
      examples/materials_video.html
  21. 1 1
      examples/particles_floor.html
  22. 20 20
      examples/particles_random.html
  23. 32 32
      examples/particles_waves.html
  24. 21 13
      examples/test.html
  25. 2 0
      src/cameras/Camera.js
  26. 50 9
      src/core/Color.js
  27. 10 2
      src/core/Face3.js
  28. 9 8
      src/core/Face4.js
  29. 40 10
      src/core/Geometry.js
  30. 19 8
      src/core/Matrix4.js
  31. 13 1
      src/core/Vector2.js
  32. 18 0
      src/core/Vector3.js
  33. 8 0
      src/core/Vector4.js
  34. 5 1
      src/core/Vertex.js
  35. 202 0
      src/hci/ClickResolver.js
  36. 10 0
      src/hci/SelectableFace3.js
  37. 11 0
      src/hci/SelectableFace4.js
  38. 4 4
      src/lights/AmbientLight.js
  39. 7 8
      src/lights/DirectionalLight.js
  40. 3 3
      src/lights/Light.js
  41. 11 0
      src/lights/PointLight.js
  42. 14 6
      src/objects/Object3D.js
  43. 279 26
      src/renderers/CanvasRenderer.js
  44. 6 7
      src/renderers/DOMRenderer.js
  45. 230 0
      src/renderers/Projector.js
  46. 0 225
      src/renderers/Renderer.js
  47. 150 13
      src/renderers/SVGRenderer.js
  48. 5 3
      src/renderers/WebGLRenderer.js
  49. 3 0
      src/renderers/renderables/RenderableFace3.js
  50. 3 0
      src/renderers/renderables/RenderableFace4.js
  51. 6 5
      utils/Builder.py
  52. 6 5
      utils/BuilderCanvas.py
  53. 1 1
      utils/BuilderDOM.py
  54. 6 5
      utils/BuilderDebug.py
  55. 6 6
      utils/BuilderSVG.py
  56. 5 4
      utils/BuilderWebGL.py
  57. 1 1
      utils/REVISION
  58. 80 0
      utils/exporters/blender/2.54/scripts/op/io_mesh_threejs/__init__.py
  59. 176 0
      utils/exporters/blender/2.54/scripts/op/io_mesh_threejs/export_threejs.py
  60. 0 0
      utils/exporters/blender/export_threejs_2.53b.py
  61. 0 0
      utils/exporters/blender/export_threejs_2.5a2.py

+ 11 - 0
AUTHORS

@@ -0,0 +1,11 @@
+Authors ordered by first contribution.
+
+http://github.com/mrdoob
+http://github.com/supereggbert
+http://github.com/sole
+http://kile.stravaganza.org
+http://github.com/kikko
+http://github.com/philogb
+http://github.com/julianwa
+http://github.com/mindlapse
+http://github.com/alteredq

+ 1 - 1
LICENSE

@@ -1,6 +1,6 @@
 The MIT License
 The MIT License
 
 
-Copyright (c) 2010 Mr.doob
+Copyright (c) 2010 Mr.doob, http://mrdoob.com
 
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 of this software and associated documentation files (the "Software"), to deal

+ 15 - 5
README.md

@@ -101,13 +101,14 @@ For creating a customised version of the library, including the source files in
 	<script type="text/javascript" src="js/three/core/UV.js"></script>
 	<script type="text/javascript" src="js/three/core/UV.js"></script>
 	<script type="text/javascript" src="js/three/core/Geometry.js"></script>
 	<script type="text/javascript" src="js/three/core/Geometry.js"></script>
 	<script type="text/javascript" src="js/three/cameras/Camera.js"></script>
 	<script type="text/javascript" src="js/three/cameras/Camera.js"></script>
-	<script type="text/javascript" src="js/three/objects/Object3D.js"></script>
-	<script type="text/javascript" src="js/three/objects/Line.js"></script>
-	<script type="text/javascript" src="js/three/objects/Mesh.js"></script>
-	<script type="text/javascript" src="js/three/objects/Particle.js"></script>
 	<script type="text/javascript" src="js/three/lights/Light.js"></script>
 	<script type="text/javascript" src="js/three/lights/Light.js"></script>
 	<script type="text/javascript" src="js/three/lights/AmbientLight.js"></script>
 	<script type="text/javascript" src="js/three/lights/AmbientLight.js"></script>
 	<script type="text/javascript" src="js/three/lights/DirectionalLight.js"></script>
 	<script type="text/javascript" src="js/three/lights/DirectionalLight.js"></script>
+	<script type="text/javascript" src="js/three/lights/PointLight.js"></script>
+	<script type="text/javascript" src="js/three/objects/Object3D.js"></script>
+	<script type="text/javascript" src="js/three/objects/Particle.js"></script>
+	<script type="text/javascript" src="js/three/objects/Line.js"></script>
+	<script type="text/javascript" src="js/three/objects/Mesh.js"></script>
 	<script type="text/javascript" src="js/three/materials/LineColorMaterial.js"></script>
 	<script type="text/javascript" src="js/three/materials/LineColorMaterial.js"></script>
 	<script type="text/javascript" src="js/three/materials/MeshBitmapUVMappingMaterial.js"></script>
 	<script type="text/javascript" src="js/three/materials/MeshBitmapUVMappingMaterial.js"></script>
 	<script type="text/javascript" src="js/three/materials/MeshColorFillMaterial.js"></script>
 	<script type="text/javascript" src="js/three/materials/MeshColorFillMaterial.js"></script>
@@ -117,7 +118,7 @@ For creating a customised version of the library, including the source files in
 	<script type="text/javascript" src="js/three/materials/ParticleBitmapMaterial.js"></script>
 	<script type="text/javascript" src="js/three/materials/ParticleBitmapMaterial.js"></script>
 	<script type="text/javascript" src="js/three/materials/ParticleCircleMaterial.js"></script>
 	<script type="text/javascript" src="js/three/materials/ParticleCircleMaterial.js"></script>
 	<script type="text/javascript" src="js/three/scenes/Scene.js"></script>
 	<script type="text/javascript" src="js/three/scenes/Scene.js"></script>
-	<script type="text/javascript" src="js/three/renderers/Renderer.js"></script>
+	<script type="text/javascript" src="js/three/renderers/Projector.js"></script>
 	<script type="text/javascript" src="js/three/renderers/CanvasRenderer.js"></script>
 	<script type="text/javascript" src="js/three/renderers/CanvasRenderer.js"></script>
 	<script type="text/javascript" src="js/three/renderers/SVGRenderer.js"></script>
 	<script type="text/javascript" src="js/three/renderers/SVGRenderer.js"></script>
 	<script type="text/javascript" src="js/three/renderers/WebGLRenderer.js"></script>
 	<script type="text/javascript" src="js/three/renderers/WebGLRenderer.js"></script>
@@ -136,6 +137,15 @@ Thanks to the power of the internets (and github <3) these people have kindly he
 
 
 ### Change Log ###
 ### Change Log ###
 
 
+2010 10 06 - **r18** (44.420 kb)
+
+* Added `PointLight`
+* `CanvasRenderer` and `SVGRenderer` basic lighting support (ColorStroke/ColorFill only)
+* `Renderer` > `Projector`. `CanvasRenderer`, `SVGRenderer` and `DOMRenderer` do not extend anymore
+* Interactivity base code (hdi folder). To be refactored... ([mindlapse](http://github.com/mindlapse))
+* Added `computeCentroids` method to `Geometry`
+
+
 2010 09 17 - **r17** (39.487 kb)
 2010 09 17 - **r17** (39.487 kb)
 
 
 * Added `Light`, `AmbientLight` and `DirectionalLight` ([philogb](http://github.com/philogb))
 * Added `Light`, `AmbientLight` and `DirectionalLight` ([philogb](http://github.com/philogb))

+ 19 - 15
TODO

@@ -1,16 +1,20 @@
-- Core
-	- Simple hierarchy system (look at D1plo1d and tamask branches)
-	- Interaction, 2D to 3D projection.
-- Examples
-	- DOMRenderer example
-- Materials
-	- MeshBitmapSphereMappingMaterial. http://en.wikipedia.org/wiki/Sphere_mapping
-	- MeshBitmapCubeMappingMaterial. http://en.wikipedia.org/wiki/Cube_mapping
-	- MeshShaderMaterial for WebGLRenderer
-	- Add MeshBitmapUVMappingMaterial to WebGLRenderer
-- Renderers
-	- Add Lights to Renderer (CanvasRenderer and SVGRenderer)
-	- FrustrumClipping near to Renderer (CanvasRenderer and SVGRenderer)
-- Utils
-	- Blender 2.5b4 plugin system has change considerably :/
+Core
+* Simple hierarchy system (look at D1plo1d and tamask branches)
+* Interaction, 2D to 3D projection. (look at mindlapse branch)
 
 
+Examples
+* DOMRenderer example
+
+Materials
+* MeshFaceMaterial? (Renderer would use face materials instead, MeshFaceColorFillFaceMaterial/MeshFaceColorStrokeMaterial wouldn't be needed?)
+* MeshBitmapSphereMappingMaterial. http://en.wikipedia.org/wiki/Sphere_mapping
+* MeshBitmapCubeMappingMaterial. http://en.wikipedia.org/wiki/Cube_mapping
+* MeshBitmapMaterial? (Merge all MeshBitmap*Materials and have a mode parameter like... MeshBitmapMaterial.UV_MAPPING)
+* MeshShaderMaterial for WebGLRenderer
+* Add MeshBitmapUVMappingMaterial to WebGLRenderer
+
+Renderers
+* Add PointLight to WebGLRenderer
+* WebGLRenderer support MeshBitmapUVMappingMaterial (look at alteredq branch)
+* Double check DirectionalLight WebGLRenderer code (doesn't seem correct)
+* FrustrumClipping near to Renderer (CanvasRenderer and SVGRenderer)

文件差异内容过多而无法显示
+ 0 - 1
build/Three.js


文件差异内容过多而无法显示
+ 0 - 1
build/ThreeDebug.js


+ 39 - 18
examples/camera_free.html

@@ -30,6 +30,10 @@
 		<script type="text/javascript" src="../src/core/UV.js"></script>
 		<script type="text/javascript" src="../src/core/UV.js"></script>
 		<script type="text/javascript" src="../src/core/Geometry.js"></script>
 		<script type="text/javascript" src="../src/core/Geometry.js"></script>
 		<script type="text/javascript" src="../src/cameras/Camera.js"></script>
 		<script type="text/javascript" src="../src/cameras/Camera.js"></script>
+		<script type="text/javascript" src="../src/lights/Light.js"></script>
+		<script type="text/javascript" src="../src/lights/AmbientLight.js"></script>
+		<script type="text/javascript" src="../src/lights/DirectionalLight.js"></script>
+		<script type="text/javascript" src="../src/lights/PointLight.js"></script>
 		<script type="text/javascript" src="../src/objects/Object3D.js"></script>
 		<script type="text/javascript" src="../src/objects/Object3D.js"></script>
 		<script type="text/javascript" src="../src/objects/Mesh.js"></script>
 		<script type="text/javascript" src="../src/objects/Mesh.js"></script>
 		<script type="text/javascript" src="../src/objects/Particle.js"></script>
 		<script type="text/javascript" src="../src/objects/Particle.js"></script>
@@ -43,7 +47,7 @@
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
-		<script type="text/javascript" src="../src/renderers/Renderer.js"></script>
+		<script type="text/javascript" src="../src/renderers/Projector.js"></script>
 		<script type="text/javascript" src="../src/renderers/CanvasRenderer.js"></script>
 		<script type="text/javascript" src="../src/renderers/CanvasRenderer.js"></script>
 		<script type="text/javascript" src="../src/renderers/SVGRenderer.js"></script>
 		<script type="text/javascript" src="../src/renderers/SVGRenderer.js"></script>
 		<script type="text/javascript" src="../src/renderers/WebGLRenderer.js"></script>
 		<script type="text/javascript" src="../src/renderers/WebGLRenderer.js"></script>
@@ -54,10 +58,10 @@
 
 
 		<script type="text/javascript" src="cameras/FreeCamera.js"></script>
 		<script type="text/javascript" src="cameras/FreeCamera.js"></script>
 
 
-		<script type="text/javascript" src="geometry/primitives/Cube.js"></script>
+		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
 		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
 		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
 
 
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/Stats.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
 
 
 		<script type="text/javascript">
 		<script type="text/javascript">
 
 
@@ -99,6 +103,7 @@
 			var debugContext;
 			var debugContext;
 
 
 			init();
 			init();
+			loop();
 			setInterval(loop, 1000/60);
 			setInterval(loop, 1000/60);
 
 
 			function init() {
 			function init() {
@@ -113,18 +118,21 @@
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 
 
-				// Cube
+				// Plane
 
 
-				geometry = new Cube(200, 200, 200);
+				plane = new THREE.Mesh( new Plane( 1000, 1000, 10, 10 ), new THREE.MeshColorStrokeMaterial( 0x000000, 0.5, 1 ) );
+				plane.rotation.x = - 90 * ( Math.PI / 180 );
+				plane.doubleSided = true;
+				scene.add( plane );
 
 
-				for (var i = 0; i < geometry.faces.length; i++) {
+				// Spheres
 
 
-					geometry.faces[i].color.setRGBA( Math.random() * 0.5, Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 1 );
-				}
+				geometry = new Sphere( 100, 16, 8 );
 
 
 				for (var i = 0; i < 10; i ++ ) {
 				for (var i = 0; i < 10; i ++ ) {
 
 
-					cube = new THREE.Mesh(geometry, new THREE.MeshFaceColorFillMaterial() );
+					cube = new THREE.Mesh(geometry, new THREE.MeshColorFillMaterial( 0xffffff ) );
+					cube.overdraw = true;
 
 
 					cube.position.x = Math.random() * 1000 - 500;
 					cube.position.x = Math.random() * 1000 - 500;
 					cube.position.y = Math.random() * 1000 - 500;
 					cube.position.y = Math.random() * 1000 - 500;
@@ -140,16 +148,26 @@
 
 
 				}
 				}
 
 
-				// Plane
+				// Lights
+
+				var ambientLight = new THREE.AmbientLight( Math.random() * 0x202020 );
+				scene.addLight( ambientLight );
+
+				var directionalLight = new THREE.DirectionalLight( Math.random() * 0xffffff );
+				directionalLight.position.x = Math.random() - 0.5;
+				directionalLight.position.y = Math.random() - 0.5;
+				directionalLight.position.z = Math.random() - 0.5;
+				directionalLight.position.normalize();
+				scene.addLight( directionalLight );
+
+				var pointLight = new THREE.PointLight( 0xff0000, 1 );
+				scene.addLight( pointLight );
 
 
-				plane = new THREE.Mesh( new Plane( 1000, 1000, 10, 10 ), new THREE.MeshColorStrokeMaterial( 0x000000, 0.5, 1 ) );
-				plane.rotation.x = -90 * (Math.PI / 180);
-				scene.add(plane);
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
+				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 
-				container.appendChild(renderer.domElement);
+				container.appendChild( renderer.domElement );
 
 
 				var debugCanvas = document.createElement( 'canvas' );
 				var debugCanvas = document.createElement( 'canvas' );
 				debugCanvas.width = 512;
 				debugCanvas.width = 512;
@@ -169,8 +187,8 @@
 				stats.domElement.style.top = '0px';
 				stats.domElement.style.top = '0px';
 				container.appendChild(stats.domElement);
 				container.appendChild(stats.domElement);
 
 
-				document.addEventListener('keydown', onDocumentKeyDown, false);
-				document.addEventListener('keyup', onDocumentKeyUp, false);
+				document.addEventListener( 'keydown', onDocumentKeyDown, false );
+				document.addEventListener( 'keyup', onDocumentKeyUp, false );
 			}
 			}
 
 
 			function onDocumentKeyDown( event ) {
 			function onDocumentKeyDown( event ) {
@@ -251,9 +269,12 @@
 				debugContext.rect( camera.target.position.x * 0.1 - 5, camera.target.position.z * 0.1 - 5, 10, 10 );
 				debugContext.rect( camera.target.position.x * 0.1 - 5, camera.target.position.z * 0.1 - 5, 10, 10 );
 				debugContext.rect( - 50, - 50, 100, 100 );
 				debugContext.rect( - 50, - 50, 100, 100 );
 
 
-				for ( var i = 0; i < scene.objects.length; i++ ) {
+				for ( var i = 1; i < scene.objects.length; i++ ) {
 
 
 					var object = scene.objects[i];
 					var object = scene.objects[i];
+					object.rotation.x += 0.01;
+					object.rotation.y += 0.005;
+					object.position.y = Math.sin( object.rotation.x ) * 200;
 
 
 					debugContext.rect( object.position.x * 0.1 - 5, object.position.z * 0.1 - 5, 10, 10 );
 					debugContext.rect( object.position.x * 0.1 - 5, object.position.z * 0.1 - 5, 10, 10 );
 
 

+ 1 - 0
examples/geometry/Qrcode.js

@@ -1431,6 +1431,7 @@ var Qrcode = function () {
 	f4(20,21,363,362,0xffc0c0c0);
 	f4(20,21,363,362,0xffc0c0c0);
 	f4(19,20,362,361,0xffc0c0c0);
 	f4(19,20,362,361,0xffc0c0c0);
 
 
+	this.computeCentroids();
 	this.computeNormals();
 	this.computeNormals();
 
 
 	function v( x, y, z ) {
 	function v( x, y, z ) {

+ 47 - 0
examples/geometry/primitives/ClickCube.js

@@ -0,0 +1,47 @@
+/**
+ * @author mr.doob / http://mrdoob.com/
+ */
+
+var ClickCube = function (width, height, depth, onSelect) {
+
+	THREE.Geometry.call(this);
+
+	var scope = this,
+	width_half = width / 2,
+	height_half = height / 2,
+	depth_half = depth / 2;
+
+	v(  width_half,  height_half, -depth_half );
+	v(  width_half, -height_half, -depth_half );
+	v( -width_half, -height_half, -depth_half );
+	v( -width_half,  height_half, -depth_half );
+	v(  width_half,  height_half,  depth_half );
+	v(  width_half, -height_half,  depth_half );
+	v( -width_half, -height_half,  depth_half );
+	v( -width_half,  height_half,  depth_half );
+
+	f4( 0, 1, 2, 3 );
+	
+	f4( 4, 7, 6, 5 );
+	f4( 0, 4, 5, 1 );
+	f4( 2, 6, 7, 3 );
+	f4( 1, 5, 6, 2 );
+	f4( 4, 0, 3, 7 );
+
+	function v(x, y, z) {
+
+		scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
+	}
+
+	function f4(a, b, c, d) {
+		var f = new THREE.SelectableFace4( a, b, c, d, onSelect );
+		scope.faces.push(f);
+	}
+
+	this.computeCentroids();
+	this.computeNormals();
+
+};
+
+ClickCube.prototype = new THREE.Geometry();
+ClickCube.prototype.constructor = ClickCube;

+ 1 - 0
examples/geometry/primitives/Cube.js

@@ -37,6 +37,7 @@ var Cube = function (width, height, depth) {
 		scope.faces.push( new THREE.Face4( a, b, c, d ) );
 		scope.faces.push( new THREE.Face4( a, b, c, d ) );
 	}
 	}
 
 
+	this.computeCentroids();
 	this.computeNormals();
 	this.computeNormals();
 
 
 }
 }

+ 1 - 0
examples/geometry/primitives/Cylinder.js

@@ -65,6 +65,7 @@ var Cylinder = function (numSegs, topRad, botRad, height, topOffset, botOffset)
 		}
 		}
 	}
 	}
 
 
+	this.computeCentroids();
 	this.computeNormals();
 	this.computeNormals();
 
 
 	function v(x, y, z) {
 	function v(x, y, z) {

+ 1 - 0
examples/geometry/primitives/Plane.js

@@ -52,6 +52,7 @@ var Plane = function ( width, height, segments_width, segments_height ) {
 
 
 	}
 	}
 
 
+	this.computeCentroids();
 	this.computeNormals();
 	this.computeNormals();
 
 
 }
 }

+ 3 - 0
examples/geometry/primitives/Sphere.js

@@ -86,6 +86,9 @@ var Sphere = function ( radius, segments_width, segments_height ) {
 			}
 			}
 		}
 		}
 	}
 	}
+
+	this.computeCentroids();
+	this.computeNormals();
 }
 }
 
 
 Sphere.prototype = new THREE.Geometry();
 Sphere.prototype = new THREE.Geometry();

+ 1 - 1
examples/geometry_birds.html

@@ -26,7 +26,7 @@
 		<div id="container"></div>
 		<div id="container"></div>
 		<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - birds demo</div>
 		<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - birds demo</div>
 
 
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/Stats.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
 
 
 		<script type="text/javascript" src="../build/Three.js"></script>
 		<script type="text/javascript" src="../build/Three.js"></script>
 		<script type="text/javascript" src="geometry/Bird.js"></script>
 		<script type="text/javascript" src="geometry/Bird.js"></script>

+ 26 - 26
examples/geometry_cube.html

@@ -20,7 +20,7 @@
 		<script type="text/javascript" src="geometry/primitives/Cube.js"></script>
 		<script type="text/javascript" src="geometry/primitives/Cube.js"></script>
 		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
 		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
 
 
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/Stats.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
 
 
 		<script type="text/javascript">
 		<script type="text/javascript">
 
 
@@ -79,27 +79,27 @@
 
 
 				cube = new THREE.Mesh(geometry, new THREE.MeshFaceColorFillMaterial() );
 				cube = new THREE.Mesh(geometry, new THREE.MeshFaceColorFillMaterial() );
 				cube.position.y = 150;
 				cube.position.y = 150;
-				scene.addObject(cube);
+				scene.addObject( cube );
 
 
 				// Plane
 				// Plane
 
 
-				plane = new THREE.Mesh( new Plane( 200, 200, 4, 4 ), new THREE.MeshColorFillMaterial( 0xe0e0e0 ) );
+				plane = new THREE.Mesh( new Plane( 200, 200 ), new THREE.MeshColorFillMaterial( 0xe0e0e0 ) );
 				plane.rotation.x = -90 * ( Math.PI / 180 );
 				plane.rotation.x = -90 * ( Math.PI / 180 );
-				scene.addObject(plane);
+				scene.addObject( plane );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
+				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 
-				container.appendChild(renderer.domElement);
+				container.appendChild( renderer.domElement );
 
 
 				stats = new Stats();
 				stats = new Stats();
 				stats.domElement.style.position = 'absolute';
 				stats.domElement.style.position = 'absolute';
 				stats.domElement.style.top = '0px';
 				stats.domElement.style.top = '0px';
-				container.appendChild(stats.domElement);
+				container.appendChild( stats.domElement );
 
 
-				document.addEventListener('mousedown', onDocumentMouseDown, false);
-				document.addEventListener('touchstart', onDocumentTouchStart, false);
-				document.addEventListener('touchmove', onDocumentTouchMove, false);
+				document.addEventListener( 'mousedown', onDocumentMouseDown, false );
+				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
 			}
 			}
 
 
 			//
 			//
@@ -108,9 +108,9 @@
 
 
 				event.preventDefault();
 				event.preventDefault();
 
 
-				document.addEventListener('mousemove', onDocumentMouseMove, false);
-				document.addEventListener('mouseup', onDocumentMouseUp, false);
-				document.addEventListener('mouseout', onDocumentMouseOut, false);
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.addEventListener( 'mouseup', onDocumentMouseUp, false );
+				document.addEventListener( 'mouseout', onDocumentMouseOut, false );
 
 
 				mouseXOnMouseDown = event.clientX - windowHalfX;
 				mouseXOnMouseDown = event.clientX - windowHalfX;
 				targetRotationOnMouseDown = targetRotation;
 				targetRotationOnMouseDown = targetRotation;
@@ -120,30 +120,30 @@
 
 
 				mouseX = event.clientX - windowHalfX;
 				mouseX = event.clientX - windowHalfX;
 
 
-				targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
+				targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
 			}
 			}
 
 
 			function onDocumentMouseUp( event ) {
 			function onDocumentMouseUp( event ) {
 
 
-				document.removeEventListener('mousemove', onDocumentMouseMove, false);
-				document.removeEventListener('mouseup', onDocumentMouseUp, false);
-				document.removeEventListener('mouseout', onDocumentMouseOut, false);
+				document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+				document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
 			}
 			}
 
 
 			function onDocumentMouseOut( event ) {
 			function onDocumentMouseOut( event ) {
 
 
-				document.removeEventListener('mousemove', onDocumentMouseMove, false);
-				document.removeEventListener('mouseup', onDocumentMouseUp, false);
-				document.removeEventListener('mouseout', onDocumentMouseOut, false);
+				document.removeEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+				document.removeEventListener( 'mouseout', onDocumentMouseOut, false );
 			}
 			}
 
 
 			function onDocumentTouchStart( event ) {
 			function onDocumentTouchStart( event ) {
 
 
-				if(event.touches.length == 1) {
+				if ( event.touches.length == 1 ) {
 
 
 					event.preventDefault();
 					event.preventDefault();
 
 
-					mouseXOnMouseDown = event.touches[0].pageX - windowHalfX;
+					mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
 					targetRotationOnMouseDown = targetRotation;
 					targetRotationOnMouseDown = targetRotation;
 
 
 				}
 				}
@@ -151,12 +151,12 @@
 
 
 			function onDocumentTouchMove( event ) {
 			function onDocumentTouchMove( event ) {
 
 
-				if(event.touches.length == 1) {
+				if ( event.touches.length == 1 ) {
 
 
 					event.preventDefault();
 					event.preventDefault();
 
 
-					mouseX = event.touches[0].pageX - windowHalfX;
-					targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05;
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
 
 
 				}
 				}
 			}
 			}
@@ -165,7 +165,7 @@
 
 
 			function loop() {
 			function loop() {
 
 
-				plane.rotation.z = cube.rotation.y += (targetRotation - cube.rotation.y) * 0.05;
+				plane.rotation.z = cube.rotation.y += ( targetRotation - cube.rotation.y ) * 0.05;
 
 
 				renderer.render(scene, camera);
 				renderer.render(scene, camera);
 				stats.update();
 				stats.update();

+ 1 - 1
examples/geometry_earth.html

@@ -33,7 +33,7 @@
 		<div id="container"></div> 
 		<div id="container"></div> 
 		<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - earth demo</div>
 		<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - earth demo</div>
 
 
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/Stats.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
 
 
 		<script type="text/javascript" src="../build/Three.js"></script>
 		<script type="text/javascript" src="../build/Three.js"></script>
 
 

+ 1 - 1
examples/geometry_terrain.html

@@ -33,7 +33,7 @@
 		<div id="container"><br /><br /><br /><br /><br />Generating...</div> 
 		<div id="container"><br /><br /><br /><br /><br />Generating...</div> 
 		<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - terrain demo. <a href="geometry_terrain.html">generate another</a></div> 
 		<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - terrain demo. <a href="geometry_terrain.html">generate another</a></div> 
 
 
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/Stats.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
 
 
 		<script type="text/javascript" src="../build/Three.js"></script>
 		<script type="text/javascript" src="../build/Three.js"></script>
 
 

+ 187 - 0
examples/hci_clickcube.html

@@ -0,0 +1,187 @@
+<!DOCTYPE HTML>
+<html lang="en">
+	<head>
+		<title>three.js - geometry - cube</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
+		<style type="text/css">
+			body {
+				font-family: Monospace;
+				background-color: #f0f0f0;
+				margin: 0px;
+				overflow: hidden;
+			}
+		</style>
+	</head>
+	<body>
+
+
+		<script type="text/javascript" src="../src/Three.js"></script>
+		<script type="text/javascript" src="../src/core/Color.js"></script>
+		<script type="text/javascript" src="../src/core/Vector2.js"></script>
+		<script type="text/javascript" src="../src/core/Vector3.js"></script>
+		<script type="text/javascript" src="../src/core/Vector4.js"></script>
+		<script type="text/javascript" src="../src/core/Rectangle.js"></script>
+		<script type="text/javascript" src="../src/core/Matrix4.js"></script>
+		<script type="text/javascript" src="../src/core/Vertex.js"></script>
+		<script type="text/javascript" src="../src/core/Face3.js"></script>
+		<script type="text/javascript" src="../src/core/Face4.js"></script>
+		<script type="text/javascript" src="../src/core/UV.js"></script>
+		<script type="text/javascript" src="../src/core/Geometry.js"></script>
+		<script type="text/javascript" src="../src/cameras/Camera.js"></script>
+		<script type="text/javascript" src="../src/objects/Object3D.js"></script>
+		<script type="text/javascript" src="../src/objects/Line.js"></script>
+		<script type="text/javascript" src="../src/objects/Mesh.js"></script>
+		<script type="text/javascript" src="../src/objects/Particle.js"></script>
+		<script type="text/javascript" src="../src/lights/Light.js"></script>
+		<script type="text/javascript" src="../src/lights/AmbientLight.js"></script>
+		<script type="text/javascript" src="../src/lights/DirectionalLight.js"></script>
+		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshBitmapUVMappingMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshColorStrokeMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshFaceColorFillMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshFaceColorStrokeMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
+		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
+		<script type="text/javascript" src="../src/renderers/Projector.js"></script>
+		<script type="text/javascript" src="../src/renderers/CanvasRenderer.js"></script>
+		<script type="text/javascript" src="../src/renderers/SVGRenderer.js"></script>
+		<script type="text/javascript" src="../src/renderers/WebGLRenderer.js"></script>
+		<script type="text/javascript" src="../src/renderers/renderables/RenderableFace3.js"></script>
+		<script type="text/javascript" src="../src/renderers/renderables/RenderableFace4.js"></script>
+		<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
+		<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
+		<script type="text/javascript" src="../src/hci/ClickResolver.js"></script>
+		<script type="text/javascript" src="../src/hci/SelectableFace3.js"></script>
+		<script type="text/javascript" src="../src/hci/SelectableFace4.js"></script>
+		<script type="text/javascript" src="geometry/primitives/ClickCube.js"></script>
+		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
+
+		<script type="text/javascript" src="js/Stats.js"></script>
+
+		<script type="text/javascript">
+
+			var SCREEN_WIDTH = window.innerWidth;
+			var SCREEN_HEIGHT = window.innerHeight;
+
+			var container;
+			var stats;
+
+			var camera;
+			var scene;
+			var renderer;
+
+			var cube, plane;
+
+			var targetRotation = 0;
+			var targetRotationOnMouseDown = 0;
+
+			var mouseX = 0;
+			var mouseXOnMouseDown = 0;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+			var clickResolver;
+
+			init();
+			setInterval(loop, 1000/60);
+
+			function init() {
+
+				container = document.createElement('div');
+				document.body.appendChild(container);
+
+				var info = document.createElement('div');
+				info.id = 'msg';
+				info.style.position = 'absolute';
+				info.style.top = '10px';
+				info.style.width = '100%';
+				info.style.textAlign = 'center';
+				info.innerHTML = 'No click detected';
+				container.appendChild(info);
+
+				camera = new THREE.Camera( 70, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
+				camera.position.y = 300;
+				camera.position.z = 500;
+				camera.target.position.y = 150;
+
+				scene = new THREE.Scene();
+				clickResolver = new THREE.ClickResolver( camera, scene );
+
+				// Click Cube
+				var opacity = 0.8;
+
+				geometry = new ClickCube( 200, 200, 200, 
+					function ( s, c, o, f, p ) {
+						f.color.setRGBA( Math.random() * 0.5, Math.random() * 0.5, Math.random() * 0.5, opacity );
+						document.getElementById( "msg" ).innerHTML = "Click detected at " + p; 
+					});
+
+				for (var i = 0; i < geometry.faces.length; i++) {
+					geometry.faces[i].color.setRGBA( Math.random() * 0.5, Math.random() * 0.5, Math.random() * 0.5, opacity );
+				}
+
+				cube = new THREE.Mesh( geometry, new THREE.MeshFaceColorFillMaterial() );
+				cube.position.y = 150;
+				scene.addObject(cube);
+
+				geometry2 = new ClickCube( 100, 100, 100, 
+						function ( s, c, o, f, p ) {
+							f.color.setRGBA( Math.random() * 0.5, Math.random() * 0.5, Math.random() * 0.5, opacity );
+							document.getElementById( "msg" ).innerHTML = "Click detected at " + p; 
+						});
+
+				for (var i = 0; i < geometry2.faces.length; i++) {
+					geometry2.faces[i].color.setRGBA( Math.random() * 0.5, Math.random() * 0.5, Math.random() * 0.5, opacity );
+				}
+				
+				cube2 = new THREE.Mesh( geometry2, new THREE.MeshFaceColorFillMaterial() );
+				cube2.position.y = 150;
+				cube2.position.z = 200;
+				scene.addObject(cube2);
+				
+				// Plane
+				renderer = new THREE.CanvasRenderer();
+				renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
+
+				container.appendChild(renderer.domElement);
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild(stats.domElement);
+
+				document.addEventListener('mousedown', onDocumentMouseDown, false);
+			}
+
+			function onDocumentMouseDown( event ) {
+
+				event.preventDefault();
+
+				document.getElementById("msg").innerHTML = ""; 
+				
+				clickResolver.findIntersectInScene(
+						event.clientX/window.innerWidth,
+						event.clientY/window.innerHeight);
+					
+			}
+
+			var radius = 600;
+			var theta = 0;
+			
+			function loop() {
+
+				theta += 1;
+				camera.position.x = radius * Math.sin( theta * Math.PI / 360 );
+				camera.position.z = radius * Math.cos( theta * Math.PI / 360 );
+
+				renderer.render(scene, camera);
+				stats.update();
+			}
+
+		</script>
+
+	</body>
+</html>

文件差异内容过多而无法显示
+ 1 - 0
examples/js/Stats.js


+ 1 - 1
examples/materials_video.html

@@ -15,7 +15,7 @@
 	</head>
 	</head>
 	<body>
 	<body>
 
 
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/Stats.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
 		<script type="text/javascript" src="../build/Three.js"></script>
 		<script type="text/javascript" src="../build/Three.js"></script>
 
 
 		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
 		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>

+ 1 - 1
examples/particles_floor.html

@@ -19,7 +19,7 @@
 	<body>
 	<body>
 
 
 		<script type="text/javascript" src="../build/Three.js"></script>
 		<script type="text/javascript" src="../build/Three.js"></script>
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/Stats.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
 
 
 		<script type="text/javascript">
 		<script type="text/javascript">
 
 

+ 20 - 20
examples/particles_random.html

@@ -20,7 +20,7 @@
 
 
 		<script type="text/javascript" src="../build/Three.js"></script>
 		<script type="text/javascript" src="../build/Three.js"></script>
 
 
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/Stats.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
 
 
 		<script type="text/javascript">
 		<script type="text/javascript">
 
 
@@ -44,7 +44,7 @@
 
 
 
 
 			init();
 			init();
-			setInterval(loop, 1000 / 60);
+			setInterval( loop, 1000 / 60 );
 
 
 			function init() {
 			function init() {
 
 
@@ -66,48 +66,48 @@
 					particle.position.y = Math.random() * 2000 - 1000;
 					particle.position.y = Math.random() * 2000 - 1000;
 					particle.position.z = Math.random() * 2000 - 1000;
 					particle.position.z = Math.random() * 2000 - 1000;
 					particle.scale.x = particle.scale.y = Math.random() * 10 + 5;
 					particle.scale.x = particle.scale.y = Math.random() * 10 + 5;
-					scene.add(particle);
+					scene.add( particle );
 				}
 				}
 
 
-				container.appendChild(renderer.domElement);
+				container.appendChild( renderer.domElement );
 
 
 				stats = new Stats();
 				stats = new Stats();
 				stats.domElement.style.position = 'absolute';
 				stats.domElement.style.position = 'absolute';
 				stats.domElement.style.top = '0px';
 				stats.domElement.style.top = '0px';
-				container.appendChild(stats.domElement);
+				container.appendChild( stats.domElement );
 
 
-				document.addEventListener('mousemove', onDocumentMouseMove, false);
-				document.addEventListener('touchstart', onDocumentTouchStart, false);
-				document.addEventListener('touchmove', onDocumentTouchMove, false);
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
 			}
 			}
 
 
 			//
 			//
 
 
-			function onDocumentMouseMove(event) {
+			function onDocumentMouseMove( event ) {
 
 
 				mouseX = event.clientX - windowHalfX;
 				mouseX = event.clientX - windowHalfX;
 				mouseY = event.clientY - windowHalfY;
 				mouseY = event.clientY - windowHalfY;
 			}
 			}
 
 
-			function onDocumentTouchStart(event) {
+			function onDocumentTouchStart( event ) {
 
 
-				if(event.touches.length == 1) {
+				if ( event.touches.length == 1 ) {
 
 
 					event.preventDefault();
 					event.preventDefault();
 
 
-					mouseX = event.touches[0].pageX - windowHalfX;
-					mouseY = event.touches[0].pageY - windowHalfY;
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
 				}
 				}
 			}
 			}
 
 
-			function onDocumentTouchMove(event) {
+			function onDocumentTouchMove( event ) {
 
 
-				if(event.touches.length == 1) {
+				if ( event.touches.length == 1 ) {
 
 
 					event.preventDefault();
 					event.preventDefault();
 
 
-					mouseX = event.touches[0].pageX - windowHalfX;
-					mouseY = event.touches[0].pageY - windowHalfY;
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
 				}
 				}
 			}
 			}
 
 
@@ -115,10 +115,10 @@
 
 
 			function loop() {
 			function loop() {
 
 
-				camera.position.x += (mouseX - camera.position.x) * .05;
-				camera.position.y += (-mouseY - camera.position.y) * .05;
+				camera.position.x += ( mouseX - camera.position.x ) * 0.05;
+				camera.position.y += ( - mouseY - camera.position.y ) * 0.05;
 
 
-				renderer.render(scene, camera);
+				renderer.render( scene, camera );
 
 
 				stats.update();
 				stats.update();
 			}
 			}

+ 32 - 32
examples/particles_waves.html

@@ -18,7 +18,7 @@
 	</head>
 	</head>
 	<body>
 	<body>
 		<script type="text/javascript" src="../build/Three.js"></script>
 		<script type="text/javascript" src="../build/Three.js"></script>
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/Stats.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
 
 
 		<script type="text/javascript">
 		<script type="text/javascript">
 
 
@@ -50,8 +50,8 @@
 
 
 			function init() {
 			function init() {
 
 
-				container = document.createElement('div');
-				document.body.appendChild(container);
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
 
 
 				camera = new THREE.Camera( 75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
 				camera = new THREE.Camera( 75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
 				camera.position.z = 1000;
 				camera.position.z = 1000;
@@ -59,67 +59,67 @@
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
+				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 
 				particles = new Array();
 				particles = new Array();
 
 
 				var i = 0;
 				var i = 0;
-				var material = new THREE.ParticleCircleMaterial(0xffffff, 1);
+				var material = new THREE.ParticleCircleMaterial( 0xffffff, 1 );
 
 
-				for (var ix = 0; ix < AMOUNTX; ix++) {
+				for ( var ix = 0; ix < AMOUNTX; ix ++ ) {
 
 
-					for(var iy = 0; iy < AMOUNTY; iy++) {
+					for ( var iy = 0; iy < AMOUNTY; iy ++ ) {
 
 
-						particle = particles[i++] = new THREE.Particle( material );
-						particle.position.x = ix * SEPARATION - ((AMOUNTX * SEPARATION) / 2);
-						particle.position.z = iy * SEPARATION - ((AMOUNTY * SEPARATION) / 2);
+						particle = particles[ i ++ ] = new THREE.Particle( material );
+						particle.position.x = ix * SEPARATION - ( ( AMOUNTX * SEPARATION ) / 2 );
+						particle.position.z = iy * SEPARATION - ( ( AMOUNTY * SEPARATION ) / 2 );
 						scene.add( particle );
 						scene.add( particle );
 					}
 					}
 				}
 				}
 
 
 				count = 0;
 				count = 0;
 
 
-				container.appendChild(renderer.domElement);
+				container.appendChild( renderer.domElement );
 
 
 				stats = new Stats();
 				stats = new Stats();
 				stats.domElement.style.position = 'absolute';
 				stats.domElement.style.position = 'absolute';
 				stats.domElement.style.top = '0px';
 				stats.domElement.style.top = '0px';
-				container.appendChild(stats.domElement);
+				container.appendChild( stats.domElement );
 
 
-				document.addEventListener('mousemove', onDocumentMouseMove, false);
-				document.addEventListener('touchstart', onDocumentTouchStart, false);
-				document.addEventListener('touchmove', onDocumentTouchMove, false);
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
+				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
 			}
 			}
 
 
 			//
 			//
 
 
-			function onDocumentMouseMove(event) {
+			function onDocumentMouseMove( event ) {
 
 
 				mouseX = event.clientX - windowHalfX;
 				mouseX = event.clientX - windowHalfX;
 				mouseY = event.clientY - windowHalfY;
 				mouseY = event.clientY - windowHalfY;
 
 
 			}
 			}
 
 
-			function onDocumentTouchStart(event) {
+			function onDocumentTouchStart( event ) {
 
 
-				if(event.touches.length == 1) {
+				if ( event.touches.length == 1 ) {
 
 
 					event.preventDefault();
 					event.preventDefault();
 
 
-					mouseX = event.touches[0].pageX - windowHalfX;
-					mouseY = event.touches[0].pageY - windowHalfY;
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
 
 
 				}
 				}
 			}
 			}
 
 
-			function onDocumentTouchMove(event) {
+			function onDocumentTouchMove( event ) {
 
 
-				if(event.touches.length == 1) {
+				if ( event.touches.length == 1 ) {
 
 
 					event.preventDefault();
 					event.preventDefault();
 
 
-					mouseX = event.touches[0].pageX - windowHalfX;
-					mouseY = event.touches[0].pageY - windowHalfY;
+					mouseX = event.touches[ 0 ].pageX - windowHalfX;
+					mouseY = event.touches[ 0 ].pageY - windowHalfY;
 
 
 				}
 				}
 			}
 			}
@@ -128,23 +128,23 @@
 
 
 			function loop() {
 			function loop() {
 
 
-				camera.position.x += (mouseX - camera.position.x) * .05;
-				camera.position.y += (-mouseY - camera.position.y) * .05;
+				camera.position.x += ( mouseX - camera.position.x ) * .05;
+				camera.position.y += ( - mouseY - camera.position.y ) * .05;
 
 
 				var i = 0;
 				var i = 0;
 
 
-				for (var ix = 0; ix < AMOUNTX; ix++) {
+				for ( var ix = 0; ix < AMOUNTX; ix ++ ) {
 
 
-					for(var iy = 0; iy < AMOUNTY; iy++) {
+					for ( var iy = 0; iy < AMOUNTY; iy ++ ) {
 
 
-						particle = particles[i++];
-						particle.position.y = (Math.sin((ix + count) * .3) * 50) + (Math.sin((iy + count) * .5) * 50);
-						particle.scale.x = particle.scale.y = (Math.sin((ix + count) * .3) + 1) * 2 + (Math.sin((iy + count) * .5) + 1) * 2;
+						particle = particles[ i++ ];
+						particle.position.y = ( Math.sin( ( ix + count ) * 0.3 ) * 50 ) + ( Math.sin( ( iy + count ) * 0.5 ) * 50 );
+						particle.scale.x = particle.scale.y = ( Math.sin( ( ix + count ) * 0.3 ) + 1 ) * 2 + ( Math.sin( ( iy + count ) * 0.5 ) + 1 ) * 2;
 
 
 					}
 					}
 				}
 				}
 
 
-				renderer.render(scene, camera);
+				renderer.render( scene, camera );
 
 
 				stats.update();
 				stats.update();
 
 

+ 21 - 13
examples/test.html

@@ -28,13 +28,14 @@
 		<script type="text/javascript" src="../src/core/UV.js"></script>
 		<script type="text/javascript" src="../src/core/UV.js"></script>
 		<script type="text/javascript" src="../src/core/Geometry.js"></script>
 		<script type="text/javascript" src="../src/core/Geometry.js"></script>
 		<script type="text/javascript" src="../src/cameras/Camera.js"></script>
 		<script type="text/javascript" src="../src/cameras/Camera.js"></script>
+		<script type="text/javascript" src="../src/lights/Light.js"></script>
+		<script type="text/javascript" src="../src/lights/AmbientLight.js"></script>
+		<script type="text/javascript" src="../src/lights/DirectionalLight.js"></script>
+		<script type="text/javascript" src="../src/lights/PointLight.js"></script>
 		<script type="text/javascript" src="../src/objects/Object3D.js"></script>
 		<script type="text/javascript" src="../src/objects/Object3D.js"></script>
 		<script type="text/javascript" src="../src/objects/Mesh.js"></script>
 		<script type="text/javascript" src="../src/objects/Mesh.js"></script>
 		<script type="text/javascript" src="../src/objects/Particle.js"></script>
 		<script type="text/javascript" src="../src/objects/Particle.js"></script>
 		<script type="text/javascript" src="../src/objects/Line.js"></script>
 		<script type="text/javascript" src="../src/objects/Line.js"></script>
-    <script type="text/javascript" src="../src/lights/Light.js"></script>
-    <script type="text/javascript" src="../src/lights/AmbientLight.js"></script>
-    <script type="text/javascript" src="../src/lights/DirectionalLight.js"></script>
 		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshBitmapUVMappingMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshBitmapUVMappingMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
@@ -44,7 +45,7 @@
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
-		<script type="text/javascript" src="../src/renderers/Renderer.js"></script>
+		<script type="text/javascript" src="../src/renderers/Projector.js"></script>
 		<script type="text/javascript" src="../src/renderers/CanvasRenderer.js"></script>
 		<script type="text/javascript" src="../src/renderers/CanvasRenderer.js"></script>
 		<script type="text/javascript" src="../src/renderers/SVGRenderer.js"></script>
 		<script type="text/javascript" src="../src/renderers/SVGRenderer.js"></script>
 		<script type="text/javascript" src="../src/renderers/WebGLRenderer.js"></script>
 		<script type="text/javascript" src="../src/renderers/WebGLRenderer.js"></script>
@@ -58,7 +59,7 @@
 		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
 		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
 		<script type="text/javascript" src="geometry/primitives/Cylinder.js"></script>
 		<script type="text/javascript" src="geometry/primitives/Cylinder.js"></script>
 
 
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/Stats.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
 
 
 		<script type="text/javascript">
 		<script type="text/javascript">
 
 
@@ -73,7 +74,7 @@
 			var scene;
 			var scene;
 			var canvasRenderer, svgRenderer, webglRenderer;
 			var canvasRenderer, svgRenderer, webglRenderer;
 
 
-			var mesh;
+			var mesh, qrcode;
 
 
 			var mouseX = 0;
 			var mouseX = 0;
 			var mouseY = 0;
 			var mouseY = 0;
@@ -103,7 +104,7 @@
 
 
 				// QRCODE
 				// QRCODE
 
 
-				mesh = new THREE.Mesh(new Qrcode(), new THREE.MeshFaceColorFillMaterial());
+				qrcode = mesh = new THREE.Mesh(new Qrcode(), new THREE.MeshFaceColorFillMaterial());
 				mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
 				mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
 				mesh.updateMatrix();
 				mesh.updateMatrix();
 				scene.add(mesh);
 				scene.add(mesh);
@@ -167,6 +168,8 @@
 					geometry.faces.push( face );
 					geometry.faces.push( face );
 				}
 				}
 
 
+				geometry.computeNormals();
+
 				mesh = new THREE.Mesh( geometry, new THREE.MeshFaceColorFillMaterial() );
 				mesh = new THREE.Mesh( geometry, new THREE.MeshFaceColorFillMaterial() );
 				mesh.doubleSided = true;
 				mesh.doubleSided = true;
 				mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
 				mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
@@ -186,12 +189,12 @@
 				}
 				}
 
 
 				// LIGHTS
 				// LIGHTS
-				
-				var ambient = new THREE.AmbientLight( new THREE.Color( Math.random() * 0xffffff ) );
-        scene.addLight(ambient);
-				var directional = new THREE.DirectionalLight( new THREE.Color( Math.random() * 0xffffff ), 
-						new THREE.Vector3( 600, 0, 0 ) );
-        scene.addLight(directional);
+
+				var ambient = new THREE.AmbientLight( 0x80ffff );
+				scene.addLight( ambient );
+
+				var directional = new THREE.DirectionalLight( 0xffff00 );
+				scene.addLight( directional );
 
 
 				canvasRenderer = new THREE.CanvasRenderer();
 				canvasRenderer = new THREE.CanvasRenderer();
 				canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
@@ -229,6 +232,11 @@
 				mesh.rotation.y += 0.01;
 				mesh.rotation.y += 0.01;
 				mesh.updateMatrix();
 				mesh.updateMatrix();
 
 
+				/*
+				qrcode.rotation.x += 0.01;
+				qrcode.rotation.z += 0.02;
+				*/
+
 				canvasRenderer.render( scene, camera );
 				canvasRenderer.render( scene, camera );
 				svgRenderer.render( scene, camera );
 				svgRenderer.render( scene, camera );
 				webglRenderer.render( scene, camera );
 				webglRenderer.render( scene, camera );

+ 2 - 0
src/cameras/Camera.js

@@ -4,6 +4,8 @@
 
 
 THREE.Camera = function ( fov, aspect, near, far ) {
 THREE.Camera = function ( fov, aspect, near, far ) {
 
 
+	this.fov = fov;
+	this.aspect = aspect;
 	this.position = new THREE.Vector3( 0, 0, 0 );
 	this.position = new THREE.Vector3( 0, 0, 0 );
 	this.target = { position: new THREE.Vector3( 0, 0, 0 ) };
 	this.target = { position: new THREE.Vector3( 0, 0, 0 ) };
 
 

+ 50 - 9
src/core/Color.js

@@ -4,29 +4,70 @@
 
 
 THREE.Color = function ( hex ) {
 THREE.Color = function ( hex ) {
 
 
+	/*
+	this.r; this.g; this.b; this.a;
+	this.hex;
+	this.__styleString;
+	*/
+
+	this.autoUpdate = true;
 	this.setHex( hex );
 	this.setHex( hex );
 
 
 }
 }
 
 
 THREE.Color.prototype = {
 THREE.Color.prototype = {
 
 
+	setRGBA: function ( r, g, b, a ) {
+
+		this.r = r;
+		this.g = g;
+		this.b = b;
+		this.a = a;
+
+		if ( this.autoUpdate ) {
+
+			this.updateHex();
+			this.updateStyleString();
+
+		}
+
+	},
+
 	setHex: function ( hex ) {
 	setHex: function ( hex ) {
 
 
 		this.hex = hex;
 		this.hex = hex;
-		this.updateRGBA();
-		this.updateStyleString();
+
+		if ( this.autoUpdate ) {
+
+			this.updateRGBA();
+			this.updateStyleString();
+
+		}
 
 
 	},
 	},
 
 
-	setRGBA: function ( r, g, b, a ) {
+	copyRGB: function ( color ) {
 
 
-		this.r = r;
-		this.g = g;
-		this.b = b;
-		this.a = a;
+		this.r = color.r;
+		this.g = color.g;
+		this.b = color.b;
+
+	},
+
+	copyRGBA: function ( color ) {
+
+		this.r = color.r;
+		this.g = color.g;
+		this.b = color.b;
+		this.a = color.a;
+
+	},
+
+	multiplySelfRGB: function ( color ) {
 
 
-		this.updateHex();
-		this.updateStyleString();
+		this.r *= color.r;
+		this.g *= color.g;
+		this.b *= color.b;
 
 
 	},
 	},
 
 

+ 10 - 2
src/core/Face3.js

@@ -8,15 +8,23 @@ THREE.Face3 = function ( a, b, c, normal, color ) {
 	this.b = b;
 	this.b = b;
 	this.c = c;
 	this.c = c;
 
 
+	this.centroid = new THREE.Vector3();
 	this.normal = normal || new THREE.Vector3();
 	this.normal = normal || new THREE.Vector3();
-	this.screen = new THREE.Vector3();
 
 
-	this.color = color || new THREE.Color( 0x000000 );
+	this.color = color || new THREE.Color( 0xff000000 );
 
 
 };
 };
 
 
 THREE.Face3.prototype = {
 THREE.Face3.prototype = {
 
 
+	// TODO: Dupe? (Geometry/computeCentroid)
+
+	getCenter : function(){
+
+		return this.a.clone().addSelf( this.b ).addSelf( this.c ).divideScalar( 3 );
+
+	},
+
 	toString: function () {
 	toString: function () {
 
 
 		return 'THREE.Face3 ( ' + this.a + ', ' + this.b + ', ' + this.c + ' )';
 		return 'THREE.Face3 ( ' + this.a + ', ' + this.b + ', ' + this.c + ' )';

+ 9 - 8
src/core/Face4.js

@@ -9,26 +9,27 @@ THREE.Face4 = function ( a, b, c, d, normal, color ) {
 	this.c = c;
 	this.c = c;
 	this.d = d;
 	this.d = d;
 
 
+	this.centroid = new THREE.Vector3();
 	this.normal = normal || new THREE.Vector3();
 	this.normal = normal || new THREE.Vector3();
-	this.screen = new THREE.Vector3();
 
 
-	this.color = color || new THREE.Color( 0x000000 );
+	this.color = color || new THREE.Color( 0xff000000 );
 
 
 };
 };
 
 
 THREE.Face4.prototype = {
 THREE.Face4.prototype = {
 
 
-	toString: function () {
+	// TODO: Dupe? (Geometry/computeCentroid)
 
 
-		return 'THREE.Face4 ( ' + this.a + ', ' + this.b + ', ' + this.c + ' ' + this.d + ' )';
+	getCenter : function(){
+
+		return this.a.clone().addSelf( this.b ).addSelf( this.c ).addSelf( this.d ).divideScalar( 4 );
 
 
 	},
 	},
-	
-	getCenter : function(){
 
 
-	  return this.a.clone().addSelf(this.b).addSelf(this.c).addSelf(this.d).divideScalar(4);
+	toString: function () {
+
+		return 'THREE.Face4 ( ' + this.a + ', ' + this.b + ', ' + this.c + ' ' + this.d + ' )';
 
 
 	}
 	}
 
 
-  
 }
 }

+ 40 - 10
src/core/Geometry.js

@@ -13,24 +13,54 @@ THREE.Geometry = function () {
 
 
 THREE.Geometry.prototype = {
 THREE.Geometry.prototype = {
 
 
+	computeCentroids: function () {
+
+		var f, fl, face;
+
+		for ( f = 0, fl = this.faces.length; f < fl; f++ ) {
+
+			face = this.faces[ f ];
+			face.centroid.set( 0, 0, 0 );
+
+			if ( face instanceof THREE.Face3 ) {
+
+				face.centroid.addSelf( this.vertices[ face.a ].position );
+				face.centroid.addSelf( this.vertices[ face.b ].position );
+				face.centroid.addSelf( this.vertices[ face.c ].position );
+				face.centroid.divideScalar( 3 );
+
+			} else if ( face instanceof THREE.Face4 ) {
+
+				face.centroid.addSelf( this.vertices[ face.a ].position );
+				face.centroid.addSelf( this.vertices[ face.b ].position );
+				face.centroid.addSelf( this.vertices[ face.c ].position );
+				face.centroid.addSelf( this.vertices[ face.d ].position );
+				face.centroid.divideScalar( 4 );
+
+			}
+
+		}
+
+	},
+
 	computeNormals: function () {
 	computeNormals: function () {
 
 
-		var v, f, vA, vB, vC, cb, ab;
+		var v, vl, vertex, f, fl, face, vA, vB, vC, cb = new THREE.Vector3(), ab = new THREE.Vector3();
 
 
-		for ( v = 0; v < this.vertices.length; v++ ) {
+		for ( v = 0, vl = this.vertices.length; v < vl; v++ ) {
 
 
-			this.vertices[ v ].normal.set( 0, 0, 0 );
+			vertex = this.vertices[ v ];
+			vertex.normal.set( 0, 0, 0 );
 
 
 		}
 		}
 
 
-		for ( f = 0; f < this.faces.length; f++ ) {
+		for ( f = 0, fl = this.faces.length; f < fl; f++ ) {
 
 
-			vA = this.vertices[ this.faces[ f ].a ];
-			vB = this.vertices[ this.faces[ f ].b ];
-			vC = this.vertices[ this.faces[ f ].c ];
+			face = this.faces[ f ];
 
 
-			cb = new THREE.Vector3();
-			ab = new THREE.Vector3();
+			vA = this.vertices[ face.a ];
+			vB = this.vertices[ face.b ];
+			vC = this.vertices[ face.c ];
 
 
 			cb.sub( vC.position, vB.position );
 			cb.sub( vC.position, vB.position );
 			ab.sub( vA.position, vB.position );
 			ab.sub( vA.position, vB.position );
@@ -42,7 +72,7 @@ THREE.Geometry.prototype = {
 
 
 			}
 			}
 
 
-			this.faces[ f ].normal = cb;
+			face.normal.copy( cb );
 
 
 		}
 		}
 
 

+ 19 - 8
src/core/Matrix4.js

@@ -30,6 +30,15 @@ THREE.Matrix4.prototype = {
 
 
 	},
 	},
 
 
+	copy: function ( m ) {
+
+		this.n11 = m.n11; this.n12 = m.n12; this.n13 = m.n13; this.n14 = m.n14;
+		this.n21 = m.n21; this.n22 = m.n22; this.n23 = m.n23; this.n24 = m.n24;
+		this.n31 = m.n31; this.n32 = m.n32; this.n33 = m.n33; this.n34 = m.n34;
+		this.n41 = m.n41; this.n42 = m.n42; this.n43 = m.n43; this.n44 = m.n44;
+
+	},
+
 	lookAt: function ( eye, center, up ) {
 	lookAt: function ( eye, center, up ) {
 
 
 		var x = this._x, y = this._y, z = this._z;
 		var x = this._x, y = this._y, z = this._z;
@@ -71,6 +80,8 @@ THREE.Matrix4.prototype = {
 
 
 		}
 		}
 
 
+		return v;
+
 	},
 	},
 
 
 	crossVector: function ( a ) {
 	crossVector: function ( a ) {
@@ -220,19 +231,19 @@ THREE.Matrix4.prototype = {
 
 
 	flatten: function() {
 	flatten: function() {
 
 
-	  return [this.n11, this.n21, this.n31, this.n41,
-	      this.n12, this.n22, this.n32, this.n42,
-	      this.n13, this.n23, this.n33, this.n43,
-	      this.n14, this.n24, this.n34, this.n44];
+		return [this.n11, this.n21, this.n31, this.n41,
+			this.n12, this.n22, this.n32, this.n42,
+			this.n13, this.n23, this.n33, this.n43,
+			this.n14, this.n24, this.n34, this.n44];
 
 
 	},
 	},
 
 
 	toString: function() {
 	toString: function() {
 
 
-		return "| " + this.n11 + " " + this.n12 + " " + this.n13 + " " + this.n14 + " |\n" +
-		"| " + this.n21 + " " + this.n22 + " " + this.n23 + " " + this.n24 + " |\n" +
-		"| " + this.n31 + " " + this.n32 + " " + this.n33 + " " + this.n34 + " |\n" +
-		"| " + this.n41 + " " + this.n42 + " " + this.n43 + " " + this.n44 + " |";
+		return  "| " + this.n11 + " " + this.n12 + " " + this.n13 + " " + this.n14 + " |\n" +
+			"| " + this.n21 + " " + this.n22 + " " + this.n23 + " " + this.n24 + " |\n" +
+			"| " + this.n31 + " " + this.n32 + " " + this.n33 + " " + this.n34 + " |\n" +
+			"| " + this.n41 + " " + this.n42 + " " + this.n43 + " " + this.n44 + " |";
 
 
 	}
 	}
 
 

+ 13 - 1
src/core/Vector2.js

@@ -17,6 +17,8 @@ THREE.Vector2.prototype = {
 		this.x = x;
 		this.x = x;
 		this.y = y;
 		this.y = y;
 
 
+		return this;
+
 	},
 	},
 
 
 	copy: function ( v ) {
 	copy: function ( v ) {
@@ -24,13 +26,15 @@ THREE.Vector2.prototype = {
 		this.x = v.x;
 		this.x = v.x;
 		this.y = v.y;
 		this.y = v.y;
 
 
+		return this;
+
 	},
 	},
 
 
 	addSelf: function ( v ) {
 	addSelf: function ( v ) {
 
 
 		this.x += v.x;
 		this.x += v.x;
 		this.y += v.y;
 		this.y += v.y;
-		
+
 		return this;
 		return this;
 
 
 	},
 	},
@@ -40,6 +44,8 @@ THREE.Vector2.prototype = {
 		this.x = v1.x + v2.x;
 		this.x = v1.x + v2.x;
 		this.y = v1.y + v2.y;
 		this.y = v1.y + v2.y;
 
 
+		return this;
+
 	},
 	},
 
 
 	subSelf: function ( v ) {
 	subSelf: function ( v ) {
@@ -56,6 +62,8 @@ THREE.Vector2.prototype = {
 		this.x = v1.x - v2.x;
 		this.x = v1.x - v2.x;
 		this.y = v1.y - v2.y;
 		this.y = v1.y - v2.y;
 
 
+		return this;
+
 	},
 	},
 
 
 	multiplyScalar: function ( s ) {
 	multiplyScalar: function ( s ) {
@@ -71,6 +79,8 @@ THREE.Vector2.prototype = {
 
 
 		this.multiplyScalar( 1 / this.length() );
 		this.multiplyScalar( 1 / this.length() );
 
 
+		return this;
+
 	},
 	},
 
 
 	length: function () {
 	length: function () {
@@ -90,6 +100,8 @@ THREE.Vector2.prototype = {
 		this.x = - this.x;
 		this.x = - this.x;
 		this.y = - this.y;
 		this.y = - this.y;
 
 
+		return this;
+
 	},
 	},
 
 
 	clone: function () {
 	clone: function () {

+ 18 - 0
src/core/Vector3.js

@@ -20,6 +20,8 @@ THREE.Vector3.prototype = {
 		this.y = y;
 		this.y = y;
 		this.z = z;
 		this.z = z;
 
 
+		return this;
+
 	},
 	},
 
 
 	copy: function ( v ) {
 	copy: function ( v ) {
@@ -28,6 +30,8 @@ THREE.Vector3.prototype = {
 		this.y = v.y;
 		this.y = v.y;
 		this.z = v.z;
 		this.z = v.z;
 
 
+		return this;
+
 	},
 	},
 
 
 	add: function( v1, v2 ) {
 	add: function( v1, v2 ) {
@@ -36,6 +40,8 @@ THREE.Vector3.prototype = {
 		this.y = v1.y + v2.y;
 		this.y = v1.y + v2.y;
 		this.z = v1.z + v2.z;
 		this.z = v1.z + v2.z;
 
 
+		return this;
+
 	},
 	},
 
 
 	addSelf: function ( v ) {
 	addSelf: function ( v ) {
@@ -64,6 +70,8 @@ THREE.Vector3.prototype = {
 		this.y = v1.y - v2.y;
 		this.y = v1.y - v2.y;
 		this.z = v1.z - v2.z;
 		this.z = v1.z - v2.z;
 
 
+		return this;
+
 	},
 	},
 
 
 	subSelf: function ( v ) {
 	subSelf: function ( v ) {
@@ -82,6 +90,8 @@ THREE.Vector3.prototype = {
 		this.y = v1.z * v2.x - v1.x * v2.z;
 		this.y = v1.z * v2.x - v1.x * v2.z;
 		this.z = v1.x * v2.y - v1.y * v2.x;
 		this.z = v1.x * v2.y - v1.y * v2.x;
 
 
+		return this;
+
 	},
 	},
 
 
 	crossSelf: function ( v ) {
 	crossSelf: function ( v ) {
@@ -179,6 +189,14 @@ THREE.Vector3.prototype = {
 
 
 		}
 		}
 
 
+		return this;
+
+	},
+
+	setLength: function( len ) {
+
+		return this.normalize().multiplyScalar( len );
+
 	},
 	},
 
 
 	isZero: function () {
 	isZero: function () {

+ 8 - 0
src/core/Vector4.js

@@ -20,6 +20,8 @@ THREE.Vector4.prototype = {
 		this.y = y;
 		this.y = y;
 		this.z = z;
 		this.z = z;
 		this.w = w;
 		this.w = w;
+		
+		return this;
 
 
 	},
 	},
 
 
@@ -30,6 +32,8 @@ THREE.Vector4.prototype = {
 		this.z = v.z;
 		this.z = v.z;
 		this.w = v.w;
 		this.w = v.w;
 
 
+		return this;
+
 	},
 	},
 
 
 	add: function ( v1, v2 ) {
 	add: function ( v1, v2 ) {
@@ -39,6 +43,8 @@ THREE.Vector4.prototype = {
 		this.z = v1.z + v2.z;
 		this.z = v1.z + v2.z;
 		this.w = v1.w + v2.w;
 		this.w = v1.w + v2.w;
 
 
+		return this;
+
 	},
 	},
 
 
 	addSelf: function ( v ) {
 	addSelf: function ( v ) {
@@ -59,6 +65,8 @@ THREE.Vector4.prototype = {
 		this.z = v1.z - v2.z;
 		this.z = v1.z - v2.z;
 		this.w = v1.w - v2.w;
 		this.w = v1.w - v2.w;
 
 
+		return this;
+
 	},
 	},
 
 
 	subSelf: function ( v ) {
 	subSelf: function ( v ) {

+ 5 - 1
src/core/Vertex.js

@@ -5,8 +5,12 @@
 THREE.Vertex = function ( position, normal ) {
 THREE.Vertex = function ( position, normal ) {
 
 
 	this.position = position || new THREE.Vector3();
 	this.position = position || new THREE.Vector3();
+	this.positionWorld = new THREE.Vector3();
+	this.positionScreen = new THREE.Vector3();
+
 	this.normal = normal || new THREE.Vector3();
 	this.normal = normal || new THREE.Vector3();
-	this.screen = new THREE.Vector3();
+	this.normalWorld = new THREE.Vector3();
+	this.normalScreen = new THREE.Vector3();
 
 
 	this.__visible = true;
 	this.__visible = true;
 
 

+ 202 - 0
src/hci/ClickResolver.js

@@ -0,0 +1,202 @@
+
+THREE.ClickResolver = function( camera, scene ) {
+
+	this.camera = camera;
+	this.scene  = scene;
+	this._debug = false;
+	
+};
+
+THREE.ClickResolver.prototype = {
+	
+	findIntersectInScene : function ( xPercent, yPercent ) {
+	
+		var objects = this.scene.objects;
+		var intersects = [];
+		
+		var mouseRayStart = this.translateScreenCoordsToZIndex( xPercent, yPercent, 300 );
+		var mouseRayEnd =   this.translateScreenCoordsToZIndex( xPercent, yPercent, 800 );
+		
+		var mouseRayDir = new THREE.Vector3().sub( mouseRayEnd, mouseRayStart );
+		
+		var closestIntersect = null;
+		
+		for ( var i = 0; i < objects.length; i++ ) {
+			
+			var o = objects[i];
+			var intersect = this.getIntersectingFaces( this.scene, camera, o, mouseRayStart, mouseRayDir );
+			
+			if ( intersect.face != null &&
+					(closestIntersect == null ||
+					 closestIntersect.distance > intersect.distance)
+					 ) {
+				
+				closestIntersect = intersect;
+			}
+		}
+		
+		if ( closestIntersect != null && closestIntersect.face.onSelect ) {
+			
+			closestIntersect.face.onSelect( scene, camera, o, closestIntersect.face, closestIntersect.point );
+		}
+	},
+		
+	
+	translateScreenCoordsToZIndex : function ( xPercent, yPercent, targetZIndex ) {
+
+		var maxVisibleXatZIndex, maxVisibleYatZIndex;
+		var rayToZIndex   = new THREE.Vector3();
+		var left          = new THREE.Vector3();
+		var up            = new THREE.Vector3();
+		var coordAtZIndex = new THREE.Vector3();
+
+		rayToZIndex.sub( this.camera.target.position, this.camera.position ).setLength( targetZIndex );
+		
+		maxVisibleYatZIndex = rayToZIndex.length() * Math.tan( this.camera.fov * Math.PI / 360 );
+		maxVisibleXatZIndex = maxVisibleYatZIndex  * this.camera.aspect;
+		
+		left.cross( this.camera.up, rayToZIndex );
+		up  .cross( rayToZIndex, left );
+		
+		return coordAtZIndex.add( this.camera.position, rayToZIndex ).
+			addSelf( left.setLength( maxVisibleXatZIndex * ( 1 - 2 * xPercent ))).
+			addSelf( up  .setLength( maxVisibleYatZIndex * ( 1 - 2 * yPercent )));
+	},
+	
+	
+	logPoint: function( scene, v, hex ) {
+		
+		if ( this._debug ) {
+			
+			var vg = new THREE.Geometry();
+			
+			vg.vertices[ 0 ] = new THREE.Vertex( v );
+			vg.vertices[ 1 ] = new THREE.Vertex( v );
+			
+			scene.addObject( new THREE.Line( vg, new THREE.LineColorMaterial( hex, 1, 10 )));
+		}
+	},
+	
+	
+	logLine: function( scene, s, e, hex ) {
+
+		if ( this._debug ) {
+
+			this.logPoint( scene, s.clone(), 0x000000 );
+			
+			var lg = new THREE.Geometry();
+			
+			lg.vertices[0] = new THREE.Vertex( s.clone() );
+			lg.vertices[1] = new THREE.Vertex( e.clone() );
+			
+			scene.addObject(new THREE.Line( lg, new THREE.LineColorMaterial( hex, 1, 4 ) ));
+		}
+
+	},
+	
+	
+	getIntersectingFaces: function( scene, camera, object3d, linePoint, lineDir ) {
+		
+		var intersect = {
+			face     : null,
+			point    : null,
+			distance : Number.MAX_VALUE
+		};
+		
+		var geo    = object3d.geometry;
+		var matrix = object3d.matrix;
+		
+		for ( f = 0; f < geo.faces.length; f++ ) {
+			
+			var face = geo.faces[ f ];
+			
+			if ( !face.selectable ) continue;
+			
+			var a = matrix.transform( geo.vertices[ face.a ].position.clone() );
+			var b = matrix.transform( geo.vertices[ face.b ].position.clone() );
+			var c = matrix.transform( geo.vertices[ face.c ].position.clone() );
+			var d = null;
+			
+			if ( face.d ) {
+				
+				d = matrix.transform( geo.vertices[ face.d ].position.clone() );
+			}
+			
+			var lineStart = linePoint.clone();
+			var lineDirection = lineDir.clone();
+			var dot = face.normal.dot( lineDirection );
+			
+			if ( this._debug ) {
+
+				this.logLine( scene, a, new THREE.Vector3().add( a, new THREE.Vector3().addSelf( face.normal ).multiplyScalar( 100 )), 0x0000FF );
+				this.logLine( scene, lineStart, lineStart.clone().addSelf(lineDirection), 0x55FF88 );
+				this.logPoint( scene, a, 0xFF0000 ); // r
+				this.logPoint( scene, b, 0x00FF00 ); // g
+				this.logPoint( scene, c, 0x0000FF ); // b
+				this.logPoint( scene, d, 0xFFFF00 ); // y
+			}
+				
+			if ( Math.abs(dot) > .0001 ) {
+				
+				var s = face.normal.dot( new THREE.Vector3().sub( a, lineStart ) ) / dot;
+				var planeIntersect = lineStart.addSelf( lineDirection.multiplyScalar( s ) );
+				
+				if ( this._debug ) this.logPoint( scene, planeIntersect, 0xFFCCAA );
+				
+				if ( d == null ) {
+					
+					var ab = isInsideBoundary( planeIntersect, a, b, c );
+					var bc = isInsideBoundary( planeIntersect, b, c, a );
+					var ca = isInsideBoundary( planeIntersect, c, a, b );
+					
+					if ( ab && bc && ca ) {
+						
+						if ( this._debug ) this.logPoint( scene, planeIntersect, 0xFF0000 );
+						logIntersect( planeIntersect, face );
+						
+					}
+				} else {
+					
+					var ab = isInsideBoundary( planeIntersect, a, b, c );
+					var bc = isInsideBoundary( planeIntersect, b, c, d );
+					var cd = isInsideBoundary( planeIntersect, c, d, a );
+					var da = isInsideBoundary( planeIntersect, d, a, b );
+					
+					if ( ab && bc && cd && da ) {
+						
+						if ( this._debug ) this.logPoint( scene, planeIntersect, 0xFF0000 );
+						logIntersect( planeIntersect, face );
+						
+					}
+				}
+			}
+		}
+		
+		function logIntersect( planeIntersect, face ) {
+			
+			var distance = camera.position.distanceTo( planeIntersect );
+			
+			if ( distance < intersect.distance ) {
+				
+				intersect.distance = distance;
+				intersect.face = face;
+				intersect.point = planeIntersect;
+			}
+		}
+		
+		function isInsideBoundary( pointOnPlaneToCheck, pointInside, boundaryPointA, boundaryPointB ) {
+		
+			var toB = boundaryPointB.clone().subSelf( boundaryPointA );
+			var toI = pointInside.clone().subSelf( boundaryPointA );
+			var pointMid = toB.setLength( toI.dot( toB ) ).addSelf( boundaryPointA );
+			var pointMirror = pointMid.subSelf( pointInside ).multiplyScalar( 2 ).addSelf( pointInside );
+			
+			return pointOnPlaneToCheck.distanceToSquared( pointInside ) <
+				   pointOnPlaneToCheck.distanceToSquared( pointMirror );
+		};
+		
+		return intersect;
+	}
+
+
+};

+ 10 - 0
src/hci/SelectableFace3.js

@@ -0,0 +1,10 @@
+THREE.SelectableFace3 =  function ( a, b, c, normal, color, onSelect) {
+	
+	THREE.Face3.call( this, a, b, c, normal, color );
+	
+	this.selectable = true;
+	this.onSelect = onSelect;
+};
+
+THREE.SelectableFace3.prototype = new THREE.Face3();
+THREE.SelectableFace3.prototype.constructor = THREE.SelectableFace3;

+ 11 - 0
src/hci/SelectableFace4.js

@@ -0,0 +1,11 @@
+var SelectableFace4 = function ( a, b, c, d, onSelect, normal, color) {
+	
+	THREE.Face4.call( this, a, b, c, d, normal, color );
+	
+	this.selectable = true;
+	this.onSelect = onSelect;
+};
+
+SelectableFace4.prototype = new THREE.Face4();
+SelectableFace4.prototype.constructor = SelectableFace4;  
+THREE.SelectableFace4 = SelectableFace4;

+ 4 - 4
src/lights/AmbientLight.js

@@ -1,8 +1,8 @@
-THREE.AmbientLight = function(color) {
-  
-  THREE.Light.call(this, color);
+THREE.AmbientLight = function ( hex ) {
+
+	THREE.Light.call( this, hex );
 
 
 };
 };
 
 
 THREE.AmbientLight.prototype = new THREE.Light();
 THREE.AmbientLight.prototype = new THREE.Light();
-THREE.AmbientLight.prototype.constructor = THREE.AmbientLight; 
+THREE.AmbientLight.prototype.constructor = THREE.AmbientLight; 

+ 7 - 8
src/lights/DirectionalLight.js

@@ -1,12 +1,11 @@
-THREE.DirectionalLight = function(color, direction) {
-  
-  THREE.Light.call(this, color);
-  
-  this.direction = direction || new Vector3(1, 1, 1);
-  
-  this.direction.normalize();
+THREE.DirectionalLight = function ( hex, intensity ) {
+
+	THREE.Light.call( this, hex );
+
+	this.position = new THREE.Vector3( 0, 1, 0 );
+	this.intensity = intensity || 1;
 
 
 };
 };
 
 
 THREE.DirectionalLight.prototype = new THREE.Light();
 THREE.DirectionalLight.prototype = new THREE.Light();
-THREE.DirectionalLight.prototype.constructor = THREE.DirectionalLight; 
+THREE.DirectionalLight.prototype.constructor = THREE.DirectionalLight; 

+ 3 - 3
src/lights/Light.js

@@ -1,5 +1,5 @@
-THREE.Light = function(color) {
+THREE.Light = function ( hex ) {
 
 
-  this.color = color;
+	this.color = new THREE.Color( 0xff << 24 | hex );
 
 
-};
+};

+ 11 - 0
src/lights/PointLight.js

@@ -0,0 +1,11 @@
+THREE.PointLight = function ( hex, intensity ) {
+
+	THREE.Light.call( this, hex );
+
+	this.position = new THREE.Vector3( 0, 0, 0 );
+	this.intensity = intensity || 1;
+
+};
+
+THREE.DirectionalLight.prototype = new THREE.Light();
+THREE.DirectionalLight.prototype.constructor = THREE.PointLight; 

+ 14 - 6
src/objects/Object3D.js

@@ -9,19 +9,27 @@ THREE.Object3D = function ( material ) {
 	this.scale = new THREE.Vector3( 1, 1, 1 );
 	this.scale = new THREE.Vector3( 1, 1, 1 );
 
 
 	this.matrix = new THREE.Matrix4();
 	this.matrix = new THREE.Matrix4();
+	this.matrixTranslation = new THREE.Matrix4();
+	this.matrixRotation = new THREE.Matrix4();
+	this.matrixScale = new THREE.Matrix4();
+
 	this.screen = new THREE.Vector3();
 	this.screen = new THREE.Vector3();
 
 
 	this.autoUpdateMatrix = true;
 	this.autoUpdateMatrix = true;
 
 
 	this.updateMatrix = function () {
 	this.updateMatrix = function () {
 
 
-		this.matrix.identity();
+		this.matrixPosition = THREE.Matrix4.translationMatrix( this.position.x, this.position.y, this.position.z );
+
+		this.matrixRotation = THREE.Matrix4.rotationXMatrix( this.rotation.x );
+		this.matrixRotation.multiplySelf( THREE.Matrix4.rotationYMatrix( this.rotation.y ) );
+		this.matrixRotation.multiplySelf( THREE.Matrix4.rotationZMatrix( this.rotation.z ) );
+
+		this.matrixScale = THREE.Matrix4.scaleMatrix( this.scale.x, this.scale.y, this.scale.z );
 
 
-		this.matrix.multiplySelf( THREE.Matrix4.translationMatrix( this.position.x, this.position.y, this.position.z ) );
-		this.matrix.multiplySelf( THREE.Matrix4.rotationXMatrix( this.rotation.x ) );
-		this.matrix.multiplySelf( THREE.Matrix4.rotationYMatrix( this.rotation.y ) );
-		this.matrix.multiplySelf( THREE.Matrix4.rotationZMatrix( this.rotation.z ) );
-		this.matrix.multiplySelf( THREE.Matrix4.scaleMatrix( this.scale.x, this.scale.y, this.scale.z ) );
+		this.matrix.copy( this.matrixPosition );
+		this.matrix.multiplySelf( this.matrixRotation );
+		this.matrix.multiplySelf( this.matrixScale );
 
 
 	};
 	};
 
 

+ 279 - 26
src/renderers/CanvasRenderer.js

@@ -4,17 +4,24 @@
 
 
 THREE.CanvasRenderer = function () {
 THREE.CanvasRenderer = function () {
 
 
-	THREE.Renderer.call( this );
+	var _renderList = null,
+	_projector = new THREE.Projector(),
 
 
-	var _canvas = document.createElement( 'canvas' ),
+	_canvas = document.createElement( 'canvas' ),
 	_context = _canvas.getContext( '2d' ),
 	_context = _canvas.getContext( '2d' ),
 	_width, _height, _widthHalf, _heightHalf,
 	_width, _height, _widthHalf, _heightHalf,
 	_clipRect = new THREE.Rectangle(),
 	_clipRect = new THREE.Rectangle(),
 	_clearRect = new THREE.Rectangle(),
 	_clearRect = new THREE.Rectangle(),
 	_bboxRect = new THREE.Rectangle(),
 	_bboxRect = new THREE.Rectangle(),
-	_vector2 = new THREE.Vector2(),
 
 
-	v5 = new THREE.Vector2(), v6 = new THREE.Vector2(),
+	_enableLighting = false,
+	_color = new THREE.Color( 0xffffffff ),
+	_light = new THREE.Color( 0xffffffff ),
+	_ambientLight = new THREE.Color( 0xffffffff ),
+
+	_vector2 = new THREE.Vector2(), // Needed for expand
+	_vector3 = new THREE.Vector3(), // Needed for PointLight
+	v5 = new THREE.Vector2(), v6 = new THREE.Vector2(), // Needed for latter splitting tris to quads
 	uv1 = new THREE.UV(), uv2 = new THREE.UV(), uv3 = new THREE.UV(), uv4 = new THREE.UV();
 	uv1 = new THREE.UV(), uv2 = new THREE.UV(), uv3 = new THREE.UV(), uv4 = new THREE.UV();
 
 
 	this.domElement = _canvas;
 	this.domElement = _canvas;
@@ -39,14 +46,14 @@ THREE.CanvasRenderer = function () {
 			_clearRect.inflate( 1 );
 			_clearRect.inflate( 1 );
 			_clearRect.minSelf( _clipRect );
 			_clearRect.minSelf( _clipRect );
 
 
-			/*
 			_context.setTransform( 1, 0, 0, - 1, _widthHalf, _heightHalf );
 			_context.setTransform( 1, 0, 0, - 1, _widthHalf, _heightHalf );
 			_context.clearRect( _clearRect.getX(), _clearRect.getY(), _clearRect.getWidth(), _clearRect.getHeight() );
 			_context.clearRect( _clearRect.getX(), _clearRect.getY(), _clearRect.getWidth(), _clearRect.getHeight() );
-			*/
 
 
+			/*
 			// Opera workaround
 			// Opera workaround
 			_context.setTransform( 1, 0, 0, 1, _widthHalf, _heightHalf );
 			_context.setTransform( 1, 0, 0, 1, _widthHalf, _heightHalf );
 			_context.clearRect( _clearRect.getX(), - ( _clearRect.getHeight() + _clearRect.getY() ), _clearRect.getWidth(), _clearRect.getHeight() );
 			_context.clearRect( _clearRect.getX(), - ( _clearRect.getHeight() + _clearRect.getY() ), _clearRect.getWidth(), _clearRect.getHeight() );
+			*/
 
 
 			_clearRect.empty();
 			_clearRect.empty();
 
 
@@ -55,19 +62,19 @@ THREE.CanvasRenderer = function () {
 
 
 	this.render = function ( scene, camera ) {
 	this.render = function ( scene, camera ) {
 
 
-		var e, el, m, ml, element, material, pi2 = Math.PI * 2,
+		var e, el, element, m, ml, material, pi2 = Math.PI * 2,
 		v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y, v5x, v5y, v6x, v6y,
 		v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y, v5x, v5y, v6x, v6y,
 		width, height, scaleX, scaleY, offsetX, offsetY,
 		width, height, scaleX, scaleY, offsetX, offsetY,
 		bitmap, bitmapWidth, bitmapHeight;
 		bitmap, bitmapWidth, bitmapHeight;
 
 
-		this.project( scene, camera );
-
 		if ( this.autoClear ) {
 		if ( this.autoClear ) {
 
 
 			this.clear();
 			this.clear();
 
 
 		}
 		}
 
 
+		_renderList = _projector.projectScene( scene, camera );
+
 		_context.setTransform( 1, 0, 0, - 1, _widthHalf, _heightHalf );
 		_context.setTransform( 1, 0, 0, - 1, _widthHalf, _heightHalf );
 
 
 		/* DEBUG
 		/* DEBUG
@@ -75,9 +82,17 @@ THREE.CanvasRenderer = function () {
 		_context.fillRect( _clipRect.getX(), _clipRect.getY(), _clipRect.getWidth(), _clipRect.getHeight() );
 		_context.fillRect( _clipRect.getX(), _clipRect.getY(), _clipRect.getWidth(), _clipRect.getHeight() );
 		*/
 		*/
 
 
-		for ( e = 0, el = this.renderList.length; e < el; e++ ) {
+		_enableLighting = scene.lights.length > 0;
 
 
-			element = this.renderList[ e ];
+		if ( _enableLighting ) {
+
+			calculateAmbientLight( scene, _ambientLight );
+
+		}
+
+		for ( e = 0, el = _renderList.length; e < el; e++ ) {
+
+			element = _renderList[ e ];
 
 
 			_bboxRect.empty();
 			_bboxRect.empty();
 
 
@@ -91,6 +106,21 @@ THREE.CanvasRenderer = function () {
 
 
 					if ( material instanceof THREE.ParticleCircleMaterial ) {
 					if ( material instanceof THREE.ParticleCircleMaterial ) {
 
 
+						if ( _enableLighting ) {
+
+							_light.copyRGB( _ambientLight );
+							calculateLight( scene, element, _light );
+
+							_color.copyRGBA( material.color );
+							_color.multiplySelfRGB( _light );
+							_color.updateStyleString();
+
+						} else {
+
+							_color = material.color;
+
+						}
+
 						width = element.scale.x * _widthHalf;
 						width = element.scale.x * _widthHalf;
 						height = element.scale.y * _heightHalf;
 						height = element.scale.y * _heightHalf;
 
 
@@ -111,7 +141,7 @@ THREE.CanvasRenderer = function () {
 						_context.arc( 0, 0, 1, 0, pi2, true );
 						_context.arc( 0, 0, 1, 0, pi2, true );
 						_context.closePath();
 						_context.closePath();
 
 
-						_context.fillStyle = material.color.__styleString;
+						_context.fillStyle = _color.__styleString;
 						_context.fill();
 						_context.fill();
 
 
 						_context.restore();
 						_context.restore();
@@ -191,11 +221,26 @@ THREE.CanvasRenderer = function () {
 
 
 					if ( material instanceof THREE.LineColorMaterial ) {
 					if ( material instanceof THREE.LineColorMaterial ) {
 
 
+						if ( _enableLighting ) {
+
+							_light.copyRGB( _ambientLight );
+							calculateLight( scene, element, _light );
+
+							_color.copyRGBA( material.color );
+							_color.multiplySelfRGB( _light );
+							_color.updateStyleString();
+
+						} else {
+
+							_color = material.color;
+
+						}
+
 						_context.lineWidth = material.lineWidth;
 						_context.lineWidth = material.lineWidth;
 						_context.lineJoin = "round";
 						_context.lineJoin = "round";
 						_context.lineCap = "round";
 						_context.lineCap = "round";
 
 
-						_context.strokeStyle = material.color.__styleString;
+						_context.strokeStyle = _color.__styleString;
 						_context.stroke();
 						_context.stroke();
 
 
 						_bboxRect.inflate( _context.lineWidth );
 						_bboxRect.inflate( _context.lineWidth );
@@ -238,6 +283,21 @@ THREE.CanvasRenderer = function () {
 
 
 					if ( material instanceof THREE.MeshColorFillMaterial ) {
 					if ( material instanceof THREE.MeshColorFillMaterial ) {
 
 
+						if ( _enableLighting ) {
+
+							_light.copyRGB( _ambientLight );
+							calculateFaceLight( scene, element, _light );
+
+							_color.copyRGBA( material.color );
+							_color.multiplySelfRGB( _light );
+							_color.updateStyleString();
+
+						} else {
+
+							_color = material.color;
+
+						}
+
 						_context.beginPath();
 						_context.beginPath();
 						_context.moveTo( v1x, v1y );
 						_context.moveTo( v1x, v1y );
 						_context.lineTo( v2x, v2y );
 						_context.lineTo( v2x, v2y );
@@ -245,11 +305,26 @@ THREE.CanvasRenderer = function () {
 						_context.lineTo( v1x, v1y );
 						_context.lineTo( v1x, v1y );
 						_context.closePath();
 						_context.closePath();
 
 
-						_context.fillStyle = material.color.__styleString;
+						_context.fillStyle = _color.__styleString;
 						_context.fill();
 						_context.fill();
 
 
 					} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
 					} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
 
 
+						if ( _enableLighting ) {
+
+							_light.copyRGB( _ambientLight );
+							calculateFaceLight( scene, element, _light );
+
+							_color.copyRGBA( material.color );
+							_color.multiplySelfRGB( _light );
+							_color.updateStyleString();
+
+						} else {
+
+							_color = material.color;
+
+						}
+
 						_context.beginPath();
 						_context.beginPath();
 						_context.moveTo( v1x, v1y );
 						_context.moveTo( v1x, v1y );
 						_context.lineTo( v2x, v2y );
 						_context.lineTo( v2x, v2y );
@@ -261,13 +336,28 @@ THREE.CanvasRenderer = function () {
 						_context.lineJoin = "round";
 						_context.lineJoin = "round";
 						_context.lineCap = "round";
 						_context.lineCap = "round";
 
 
-						_context.strokeStyle = material.color.__styleString;
+						_context.strokeStyle = _color.__styleString;
 						_context.stroke();
 						_context.stroke();
 
 
 						_bboxRect.inflate( _context.lineWidth );
 						_bboxRect.inflate( _context.lineWidth );
 
 
 					} else if ( material instanceof THREE.MeshFaceColorFillMaterial ) {
 					} else if ( material instanceof THREE.MeshFaceColorFillMaterial ) {
 
 
+						if ( _enableLighting ) {
+
+							_light.copyRGB( _ambientLight );
+							calculateFaceLight( scene, element, _light );
+
+							_color.copyRGBA( element.color );
+							_color.multiplySelfRGB( _light );
+							_color.updateStyleString();
+
+						} else {
+
+							_color = element.color;
+
+						}
+
 						_context.beginPath();
 						_context.beginPath();
 						_context.moveTo( v1x, v1y );
 						_context.moveTo( v1x, v1y );
 						_context.lineTo( v2x, v2y );
 						_context.lineTo( v2x, v2y );
@@ -275,11 +365,26 @@ THREE.CanvasRenderer = function () {
 						_context.lineTo( v1x, v1y );
 						_context.lineTo( v1x, v1y );
 						_context.closePath();
 						_context.closePath();
 
 
-						_context.fillStyle = element.color.__styleString;
+						_context.fillStyle = _color.__styleString;
 						_context.fill();
 						_context.fill();
 
 
 					} else if ( material instanceof THREE.MeshFaceColorStrokeMaterial ) {
 					} else if ( material instanceof THREE.MeshFaceColorStrokeMaterial ) {
 
 
+						if ( _enableLighting ) {
+
+							_light.copyRGB( _ambientLight );
+							calculateFaceLight( scene, element, _light );
+
+							_color.copyRGBA( element.color );
+							_color.multiplySelfRGB( _light );
+							_color.updateStyleString();
+
+						} else {
+
+							_color = element.color;
+
+						}
+
 						_context.beginPath();
 						_context.beginPath();
 						_context.moveTo( v1x, v1y );
 						_context.moveTo( v1x, v1y );
 						_context.lineTo( v2x, v2y );
 						_context.lineTo( v2x, v2y );
@@ -291,7 +396,7 @@ THREE.CanvasRenderer = function () {
 						_context.lineJoin = "round";
 						_context.lineJoin = "round";
 						_context.lineCap = "round";
 						_context.lineCap = "round";
 
 
-						_context.strokeStyle = element.color.__styleString;
+						_context.strokeStyle = _color.__styleString;
 						_context.stroke();
 						_context.stroke();
 
 
 						_bboxRect.inflate( _context.lineWidth );
 						_bboxRect.inflate( _context.lineWidth );
@@ -310,7 +415,6 @@ THREE.CanvasRenderer = function () {
 							_context.moveTo( v1x, v1y );
 							_context.moveTo( v1x, v1y );
 							_context.lineTo( v2x, v2y );
 							_context.lineTo( v2x, v2y );
 							_context.lineTo( v3x, v3y );
 							_context.lineTo( v3x, v3y );
-							_context.lineTo( v4x, v4y );
 							_context.lineTo( v1x, v1y );
 							_context.lineTo( v1x, v1y );
 							_context.closePath();
 							_context.closePath();
 
 
@@ -385,6 +489,21 @@ THREE.CanvasRenderer = function () {
 
 
 					if ( material instanceof THREE.MeshColorFillMaterial ) {
 					if ( material instanceof THREE.MeshColorFillMaterial ) {
 
 
+						if ( _enableLighting ) {
+
+							_light.copyRGB( _ambientLight );
+							calculateFaceLight( scene, element, _light );
+
+							_color.copyRGBA( material.color );
+							_color.multiplySelfRGB( _light );
+							_color.updateStyleString();
+
+						} else {
+
+							_color = material.color;
+
+						}
+
 						_context.beginPath();
 						_context.beginPath();
 						_context.moveTo( v1x, v1y );
 						_context.moveTo( v1x, v1y );
 						_context.lineTo( v2x, v2y );
 						_context.lineTo( v2x, v2y );
@@ -393,12 +512,27 @@ THREE.CanvasRenderer = function () {
 						_context.lineTo( v1x, v1y );
 						_context.lineTo( v1x, v1y );
 						_context.closePath();
 						_context.closePath();
 
 
-						_context.fillStyle = material.color.__styleString;
+						_context.fillStyle = _color.__styleString;
 						_context.fill();
 						_context.fill();
 
 
 
 
 					} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
 					} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
 
 
+						if ( _enableLighting ) {
+
+							_light.copyRGB( _ambientLight );
+							calculateFaceLight( scene, element, _light );
+
+							_color.copyRGBA( material.color );
+							_color.multiplySelfRGB( _light );
+							_color.updateStyleString();
+
+						} else {
+
+							_color = material.color;
+
+						}
+
 						_context.beginPath();
 						_context.beginPath();
 						_context.moveTo( v1x, v1y );
 						_context.moveTo( v1x, v1y );
 						_context.lineTo( v2x, v2y );
 						_context.lineTo( v2x, v2y );
@@ -411,13 +545,28 @@ THREE.CanvasRenderer = function () {
 						_context.lineJoin = "round";
 						_context.lineJoin = "round";
 						_context.lineCap = "round";
 						_context.lineCap = "round";
 
 
-						_context.strokeStyle = material.color.__styleString;
+						_context.strokeStyle = _color.__styleString;
 						_context.stroke();
 						_context.stroke();
 
 
 						_bboxRect.inflate( _context.lineWidth );
 						_bboxRect.inflate( _context.lineWidth );
 
 
 					} else if ( material instanceof THREE.MeshFaceColorFillMaterial ) {
 					} else if ( material instanceof THREE.MeshFaceColorFillMaterial ) {
 
 
+						if ( _enableLighting ) {
+
+							_light.copyRGB( _ambientLight );
+							calculateFaceLight( scene, element, _light );
+
+							_color.copyRGBA( element.color );
+							_color.multiplySelfRGB( _light );
+							_color.updateStyleString();
+
+						} else {
+
+							_color = element.color;
+
+						}
+
 						_context.beginPath();
 						_context.beginPath();
 						_context.moveTo( v1x, v1y );
 						_context.moveTo( v1x, v1y );
 						_context.lineTo( v2x, v2y );
 						_context.lineTo( v2x, v2y );
@@ -426,11 +575,26 @@ THREE.CanvasRenderer = function () {
 						_context.lineTo( v1x, v1y );
 						_context.lineTo( v1x, v1y );
 						_context.closePath();
 						_context.closePath();
 
 
-						_context.fillStyle = element.color.__styleString;
+						_context.fillStyle = _color.__styleString;
 						_context.fill();
 						_context.fill();
 
 
 					} else if ( material instanceof THREE.MeshFaceColorStrokeMaterial ) {
 					} else if ( material instanceof THREE.MeshFaceColorStrokeMaterial ) {
 
 
+						if ( _enableLighting ) {
+
+							_light.copyRGB( _ambientLight );
+							calculateFaceLight( scene, element, _light );
+
+							_color.copyRGBA( element.color );
+							_color.multiplySelfRGB( _light );
+							_color.updateStyleString();
+
+						} else {
+
+							_color = element.color;
+
+						}
+
 						_context.beginPath();
 						_context.beginPath();
 						_context.moveTo( v1x, v1y );
 						_context.moveTo( v1x, v1y );
 						_context.lineTo( v2x, v2y );
 						_context.lineTo( v2x, v2y );
@@ -443,7 +607,7 @@ THREE.CanvasRenderer = function () {
 						_context.lineJoin = "round";
 						_context.lineJoin = "round";
 						_context.lineCap = "round";
 						_context.lineCap = "round";
 
 
-						_context.strokeStyle = element.color.__styleString;
+						_context.strokeStyle = _color.__styleString;
 						_context.stroke();
 						_context.stroke();
 
 
 						_bboxRect.inflate( _context.lineWidth );
 						_bboxRect.inflate( _context.lineWidth );
@@ -513,7 +677,96 @@ THREE.CanvasRenderer = function () {
 
 
 	};
 	};
 
 
-	function drawTexturedTriangle( bitmap, v1x, v1y, v2x, v2y, v3x, v3y, uv1u, uv1v, uv2u, uv2v, uv3u, uv3v )  {
+	function calculateAmbientLight( scene, color ) {
+
+		var l, ll, light;
+
+		color.setRGBA( 1, 1, 1, 1 );
+
+		for ( l = 0, ll = scene.lights.length; l < ll; l++ ) {
+
+			light = scene.lights[ l ];
+
+			if ( light instanceof THREE.AmbientLight ) {
+
+				color.r *= light.color.r;
+				color.g *= light.color.g;
+				color.b *= light.color.b;
+
+			}
+
+		}
+
+	}
+
+	function calculateLight( scene, element, color ) {
+
+		var l, ll, light;
+
+		for ( l = 0, ll = scene.lights.length; l < ll; l++ ) {
+
+			light = scene.lights[ l ];
+
+			if ( light instanceof THREE.DirectionalLight ) {
+
+				color.r += light.color.r;
+				color.g += light.color.g;
+				color.b += light.color.b;
+
+			} else if ( light instanceof THREE.PointLight ) {
+
+				color.r += light.color.r;
+				color.g += light.color.g;
+				color.b += light.color.b;
+
+			}
+
+		}
+
+	}
+
+	function calculateFaceLight( scene, element, color ) {
+
+		var l, ll, light, amount;
+
+		for ( l = 0, ll = scene.lights.length; l < ll; l++ ) {
+
+			light = scene.lights[ l ];
+
+			if ( light instanceof THREE.DirectionalLight ) {
+
+				amount = element.normalWorld.dot( light.position ) * light.intensity;
+
+				if ( amount > 0 ) {
+
+					color.r += light.color.r * amount;
+					color.g += light.color.g * amount;
+					color.b += light.color.b * amount;
+
+				}
+
+			} else if ( light instanceof THREE.PointLight ) {
+
+				_vector3.sub( light.position, element.centroidWorld );
+				_vector3.normalize();
+
+				amount = element.normalWorld.dot( _vector3 ) * light.intensity;
+
+				if ( amount > 0 ) {
+
+					color.r += light.color.r * amount;
+					color.g += light.color.g * amount;
+					color.b += light.color.b * amount;
+
+				}
+
+			}
+
+		}
+
+	}
+
+	function drawTexturedTriangle( bitmap, v1x, v1y, v2x, v2y, v3x, v3y, uv1u, uv1v, uv2u, uv2v, uv3u, uv3v ) {
 
 
 		// Textured triangle drawing by Thatcher Ulrich.
 		// Textured triangle drawing by Thatcher Ulrich.
 		// http://tulrich.com/geekstuff/canvas/jsgl.js
 		// http://tulrich.com/geekstuff/canvas/jsgl.js
@@ -546,10 +799,13 @@ THREE.CanvasRenderer = function () {
 
 
 	}
 	}
 
 
+	// Hide anti-alias gaps
+
 	function expand( a, b ) {
 	function expand( a, b ) {
 
 
 		_vector2.sub( b, a );
 		_vector2.sub( b, a );
 		_vector2.unit();
 		_vector2.unit();
+		_vector2.multiplyScalar( 0.75 );
 
 
 		b.addSelf( _vector2 );
 		b.addSelf( _vector2 );
 		a.subSelf( _vector2 );
 		a.subSelf( _vector2 );
@@ -557,6 +813,3 @@ THREE.CanvasRenderer = function () {
 	}
 	}
 
 
 };
 };
-
-THREE.CanvasRenderer.prototype = new THREE.Renderer();
-THREE.CanvasRenderer.prototype.constructor = THREE.CanvasRenderer;

+ 6 - 7
src/renderers/DOMRenderer.js

@@ -6,7 +6,9 @@ THREE.DOMRenderer = function () {
 
 
 	THREE.Renderer.call( this );
 	THREE.Renderer.call( this );
 
 
-	var _div = document.createElement( 'div' ),
+	var _renderList = null,
+	_projector = new THREE.Projector(),
+	_div = document.createElement( 'div' ),
 	_width, _height, _widthHalf, _heightHalf;
 	_width, _height, _widthHalf, _heightHalf;
 
 
 	this.domElement = _div;
 	this.domElement = _div;
@@ -22,11 +24,11 @@ THREE.DOMRenderer = function () {
 
 
 		var e, el, m, ml, element, material, dom, v1x, v1y;
 		var e, el, m, ml, element, material, dom, v1x, v1y;
 
 
-		this.project( scene, camera );
+		_renderList = _projector.projectScene( scene, camera );
 
 
-		for ( e = 0, el = this.renderList.length; e < el; e++ ) {
+		for ( e = 0, el = _renderList.length; e < el; e++ ) {
 
 
-			element = this.renderList[ e ];
+			element = _renderList[ e ];
 
 
 			if ( element instanceof THREE.RenderableParticle ) {
 			if ( element instanceof THREE.RenderableParticle ) {
 
 
@@ -53,6 +55,3 @@ THREE.DOMRenderer = function () {
 	};
 	};
 
 
 }
 }
-
-THREE.DOMRenderer.prototype = new THREE.Renderer();
-THREE.DOMRenderer.prototype.constructor = THREE.DOMRenderer;

+ 230 - 0
src/renderers/Projector.js

@@ -0,0 +1,230 @@
+/**
+ * @author mr.doob / http://mrdoob.com/
+ * @author supereggbert / http://www.paulbrunt.co.uk/
+ */
+
+THREE.Projector = function() {
+
+	var _renderList = null,
+	_face3, _face3Count, _face3Pool = [],
+	_face4, _face4Count, _face4Pool = [],
+	_line, _lineCount, _linePool = [],
+	_particle, _particleCount, _particlePool = [],
+
+	_vector4 = new THREE.Vector4(),
+	_projScreenMatrix = new THREE.Matrix4(),
+	_projScreenObjectMatrix = new THREE.Matrix4();
+
+	this.projectScene = function ( scene, camera ) {
+
+		var o, ol, v, vl, f, fl, objects, object, objectMatrix,
+		vertices, vertex, vertexPositionScreen, vertex2,
+		faces, face, v1, v2, v3, v4;
+
+		_renderList = [];
+		_face3Count = 0, _face4Count = 0, _lineCount = 0, _particleCount = 0;
+
+		if( camera.autoUpdateMatrix ) {
+
+			camera.updateMatrix();
+
+		}
+
+		_projScreenMatrix.multiply( camera.projectionMatrix, camera.matrix );
+
+		objects = scene.objects;
+
+		for ( o = 0, ol = objects.length; o < ol; o++ ) {
+
+			object = objects[ o ];
+			objectMatrix = object.matrix;
+
+			if( object.autoUpdateMatrix ) {
+
+				object.updateMatrix();
+
+			}
+
+			if ( object instanceof THREE.Mesh ) {
+
+				_projScreenObjectMatrix.multiply( _projScreenMatrix, objectMatrix );
+
+				// vertices
+
+				vertices = object.geometry.vertices;
+
+				for ( v = 0, vl = vertices.length; v < vl; v++ ) {
+
+					vertex = vertices[ v ];
+
+					vertexPositionScreen = vertex.positionScreen;
+					vertexPositionScreen.copy( vertex.position );
+					_projScreenObjectMatrix.transform( vertexPositionScreen );
+
+					vertex.__visible = vertexPositionScreen.z > 0 && vertexPositionScreen.z < 1;
+
+				}
+
+				// faces
+
+				faces = object.geometry.faces;
+
+				for ( f = 0, fl = faces.length; f < fl; f++ ) {
+
+					face = faces[ f ];
+
+					if ( face instanceof THREE.Face3 ) {
+
+						v1 = vertices[ face.a ]; v2 = vertices[ face.b ]; v3 = vertices[ face.c ];
+
+						if ( v1.__visible && v2.__visible && v3.__visible ) {
+
+							if ( ( object.doubleSided || ( object.flipSided !=
+							   ( v3.positionScreen.x - v1.positionScreen.x ) * ( v2.positionScreen.y - v1.positionScreen.y ) -
+							   ( v3.positionScreen.y - v1.positionScreen.y ) * ( v2.positionScreen.x - v1.positionScreen.x ) < 0 ) ) ) {
+
+								_face3 = _face3Pool[ _face3Count ] = _face3Pool[ _face3Count ] || new THREE.RenderableFace3();
+								_face3.v1.copy( v1.positionScreen );
+								_face3.v2.copy( v2.positionScreen );
+								_face3.v3.copy( v3.positionScreen );
+
+								_face3.centroidWorld.copy( face.centroid );
+								object.matrix.transform( _face3.centroidWorld );
+
+								_face3.normalWorld.copy( face.normal );
+								object.matrixRotation.transform( _face3.normalWorld );
+
+								_face3.z = Math.max( v1.positionScreen.z, Math.max( v2.positionScreen.z, v3.positionScreen.z ) );
+
+								_face3.material = object.material;
+								_face3.overdraw = object.overdraw;
+								_face3.uvs = object.geometry.uvs[ f ];
+								_face3.color = face.color;
+
+								_renderList.push( _face3 );
+
+								_face3Count ++;
+
+							}
+
+						}
+
+					} else if ( face instanceof THREE.Face4 ) {
+
+						v1 = vertices[ face.a ]; v2 = vertices[ face.b ]; v3 = vertices[ face.c ]; v4 = vertices[ face.d ];
+
+						if ( v1.__visible && v2.__visible && v3.__visible && v4.__visible ) {
+
+							if ( ( object.doubleSided || ( object.flipSided !=
+							   ( ( v4.positionScreen.x - v1.positionScreen.x ) * ( v2.positionScreen.y - v1.positionScreen.y ) -
+							   ( v4.positionScreen.y - v1.positionScreen.y ) * ( v2.positionScreen.x - v1.positionScreen.x ) < 0 ||
+							   ( v2.positionScreen.x - v3.positionScreen.x ) * ( v4.positionScreen.y - v3.positionScreen.y ) -
+							   ( v2.positionScreen.y - v3.positionScreen.y ) * ( v4.positionScreen.x - v3.positionScreen.x ) < 0 ) ) ) ) {
+
+								_face4 = _face4Pool[ _face4Count ] = _face4Pool[ _face4Count ] || new THREE.RenderableFace4();
+								_face4.v1.copy( v1.positionScreen );
+								_face4.v2.copy( v2.positionScreen );
+								_face4.v3.copy( v3.positionScreen );
+								_face4.v4.copy( v4.positionScreen );
+
+								_face4.centroidWorld.copy( face.centroid );
+								object.matrix.transform( _face4.centroidWorld );
+
+								_face4.normalWorld.copy( face.normal );
+								object.matrixRotation.transform( _face4.normalWorld );
+
+								_face4.z = Math.max( v1.positionScreen.z, Math.max( v2.positionScreen.z, Math.max( v3.positionScreen.z, v4.positionScreen.z ) ) );
+
+								_face4.material = object.material;
+								_face4.overdraw = object.overdraw;
+								_face4.uvs = object.geometry.uvs[ f ];
+								_face4.color = face.color;
+
+								_renderList.push( _face4 );
+
+								_face4Count ++;
+
+							}
+
+						}
+
+					}
+
+				}
+
+			} else if ( object instanceof THREE.Line ) {
+
+				_projScreenObjectMatrix.multiply( _projScreenMatrix, objectMatrix );
+
+				vertices = object.geometry.vertices;
+
+				for ( v = 0, vl = vertices.length; v < vl; v++ ) {
+
+					vertex = vertices[ v ];
+
+					vertexPositionScreen = vertex.positionScreen;
+					vertexPositionScreen.copy( vertex.position );
+					_projScreenObjectMatrix.transform( vertexPositionScreen );
+
+					vertex.__visible = vertexPositionScreen.z > 0 && vertexPositionScreen.z < 1;
+
+					if ( v > 0 ) {
+
+						vertex2 = object.geometry.vertices[ v - 1 ];
+
+						if ( vertex.__visible && vertex2.__visible ) {
+
+							_line = _linePool[ _lineCount ] = _linePool[ _lineCount ] || new THREE.RenderableLine();
+							_line.v1.copy( vertex.positionScreen );
+							_line.v2.copy( vertex2.positionScreen );
+							_line.z = Math.max( vertex.positionScreen.z, vertex2.positionScreen.z );
+							_line.material = object.material;
+
+							_renderList.push( _line );
+
+							_lineCount ++;
+
+						}
+					}
+				}
+
+			} else if ( object instanceof THREE.Particle ) {
+
+				_vector4.set( object.position.x, object.position.y, object.position.z, 1 );
+
+				camera.matrix.transform( _vector4 );
+				camera.projectionMatrix.transform( _vector4 );
+
+				object.screen.set( _vector4.x / _vector4.w, _vector4.y / _vector4.w, _vector4.z / _vector4.w );
+
+				if ( object.screen.z > 0 && object.screen.z < 1 ) {
+
+					_particle = _particlePool[ _particleCount ] = _particlePool[ _particleCount ] || new THREE.RenderableParticle();
+					_particle.x = object.screen.x;
+					_particle.y = object.screen.y;
+					_particle.z = object.screen.z;
+
+					_particle.rotation = object.rotation.z;
+
+					_particle.scale.x = object.scale.x * Math.abs( _vector4.x / _vector4.w - ( _vector4.x + camera.projectionMatrix.n11 ) / ( _vector4.w + camera.projectionMatrix.n14 ) );
+					_particle.scale.y = object.scale.y * Math.abs( _vector4.y / _vector4.w - ( _vector4.y + camera.projectionMatrix.n22 ) / ( _vector4.w + camera.projectionMatrix.n24 ) );
+					_particle.material = object.material;
+					_particle.color = object.color;
+
+					_renderList.push( _particle );
+
+					_particleCount ++;
+
+				}
+
+			}
+
+		}
+
+		_renderList.sort( function ( a, b ) { return b.z - a.z; } );
+
+		return _renderList;
+
+	};
+
+};

+ 0 - 225
src/renderers/Renderer.js

@@ -1,225 +0,0 @@
-/**
- * @author mr.doob / http://mrdoob.com/
- * @author supereggbert / http://www.paulbrunt.co.uk/
- */
-
-THREE.Renderer = function() {
-
-	var face3Pool = [],
-	face4Pool = [],
-	linePool = [],
-	particlePool = [],
-
-	vector4 = new THREE.Vector4(),
-	projViewMatrix = new THREE.Matrix4();
-	projViewObjMatrix = new THREE.Matrix4();
-
-	function painterSort( a, b ) {
-
-		return b.z - a.z;
-
-	}
-
-	this.renderList = null;
-
-	this.project = function (scene, camera) {
-
-		var o, ol, v, vl, f, fl, vertex, vertex2, face, object, v1, v2, v3, v4,
-		face3count = 0, face4count = 0, lineCount = 0, particleCount = 0;
-
-		this.renderList = [];
-
-		if( camera.autoUpdateMatrix ) {
-
-			camera.updateMatrix();
-
-		}
-		
-		projViewMatrix.multiply( camera.projectionMatrix, camera.matrix );
-
-		for ( o = 0, ol = scene.objects.length; o < ol; o++ ) {
-
-			object = scene.objects[ o ];
-
-			if( object.autoUpdateMatrix ) {
-
-				object.updateMatrix();
-
-			}
-
-			if ( object instanceof THREE.Mesh ) {
-
-				projViewObjMatrix.multiply( projViewMatrix, object.matrix );
-
-				// vertices
-
-				for ( v = 0, vl = object.geometry.vertices.length; v < vl; v++ ) {
-
-					vertex = object.geometry.vertices[ v ];
-					vertex.screen.copy( vertex.position );
-
-					projViewObjMatrix.transform( vertex.screen );
-
-					vertex.__visible = vertex.screen.z > 0 && vertex.screen.z < 1;
-
-				}
-
-				// faces
-
-				for ( f = 0, fl = object.geometry.faces.length; f < fl; f++ ) {
-
-					face = object.geometry.faces[ f ];
-
-					if ( face instanceof THREE.Face3 ) {
-
-						v1 = object.geometry.vertices[ face.a ];
-						v2 = object.geometry.vertices[ face.b ];
-						v3 = object.geometry.vertices[ face.c ];
-
-						if ( v1.__visible && v2.__visible && v3.__visible &&
-						   ( object.doubleSided || ( object.flipSided !=
-						   ( v3.screen.x - v1.screen.x ) * ( v2.screen.y - v1.screen.y ) -
-						   ( v3.screen.y - v1.screen.y ) * ( v2.screen.x - v1.screen.x ) < 0 ) ) ) {
-
-							if ( !face3Pool[ face3count ] ) {
-
-								face3Pool[ face3count ] = new THREE.RenderableFace3();
-
-							}
-
-							face3Pool[ face3count ].v1.copy( v1.screen );
-							face3Pool[ face3count ].v2.copy( v2.screen );
-							face3Pool[ face3count ].v3.copy( v3.screen );
-							face3Pool[ face3count ].z = Math.max( v1.screen.z, Math.max( v2.screen.z, v3.screen.z ) );
-
-							face3Pool[ face3count ].material = object.material;
-							face3Pool[ face3count ].overdraw = object.overdraw;
-							face3Pool[ face3count ].uvs = object.geometry.uvs[ f ];
-							face3Pool[ face3count ].color = face.color;
-
-							this.renderList.push(face3Pool[face3count]);
-
-							face3count++;
-						}
-
-					} else if ( face instanceof THREE.Face4 ) {
-
-						v1 = object.geometry.vertices[ face.a ];
-						v2 = object.geometry.vertices[ face.b ];
-						v3 = object.geometry.vertices[ face.c ];
-						v4 = object.geometry.vertices[ face.d ];
-
-						if ( v1.__visible && v2.__visible && v3.__visible && v4.__visible &&
-						   ( object.doubleSided || ( object.flipSided !=
-						   ( ( v4.screen.x - v1.screen.x ) * ( v2.screen.y - v1.screen.y ) -
-						   ( v4.screen.y - v1.screen.y ) * ( v2.screen.x - v1.screen.x ) < 0 ||
-						   ( v2.screen.x - v3.screen.x ) * ( v4.screen.y - v3.screen.y ) -
-						   ( v2.screen.y - v3.screen.y ) * ( v4.screen.x - v3.screen.x ) < 0 ) ) ) ) {
-
-							if ( !face4Pool[ face4count ] ) {
-
-								face4Pool[ face4count ] = new THREE.RenderableFace4();
-
-							}
-
-							face4Pool[ face4count ].v1.copy( v1.screen );
-							face4Pool[ face4count ].v2.copy( v2.screen );
-							face4Pool[ face4count ].v3.copy( v3.screen );
-							face4Pool[ face4count ].v4.copy( v4.screen );
-							face4Pool[ face4count ].z = Math.max( v1.screen.z, Math.max( v2.screen.z, Math.max( v3.screen.z, v4.screen.z ) ) );
-
-							face4Pool[ face4count ].material = object.material;
-							face4Pool[ face4count ].overdraw = object.overdraw;
-							face4Pool[ face4count ].uvs = object.geometry.uvs[ f ];
-							face4Pool[ face4count ].color = face.color;
-
-							this.renderList.push( face4Pool[ face4count ] );
-
-							face4count++;
-						}
-
-					}
-
-				}
-
-			} else if ( object instanceof THREE.Line ) {
-
-				projViewObjMatrix.multiply( projViewMatrix, object.matrix );
-
-				for ( v = 0, vl = object.geometry.vertices.length; v < vl; v++ ) {
-
-					vertex = object.geometry.vertices[ v ];
-					vertex.screen.copy( vertex.position );
-
-					projViewObjMatrix.transform( vertex.screen );
-
-					vertex.__visible = vertex.screen.z > 0 && vertex.screen.z < 1;
-
-					if ( v > 0 ) {
-
-						vertex2 = object.geometry.vertices[ v - 1 ];
-
-						if ( vertex.__visible && vertex2.__visible ) {
-
-							if ( !linePool[ lineCount ] ) {
-
-								linePool[ lineCount ] = new THREE.RenderableLine();
-
-							}
-
-							linePool[ lineCount ].v1.copy( vertex.screen );
-							linePool[ lineCount ].v2.copy( vertex2.screen );
-							linePool[ lineCount ].z = Math.max( vertex.screen.z, vertex2.screen.z );
-							linePool[ lineCount ].material = object.material;
-
-							this.renderList.push( linePool[lineCount] );
-
-							lineCount++;
-
-						}
-					}
-				}
-
-			} else if ( object instanceof THREE.Particle ) {
-
-				vector4.set( object.position.x, object.position.y, object.position.z, 1 );
-
-				camera.matrix.transform( vector4 );
-				camera.projectionMatrix.transform( vector4 );
-
-				object.screen.set( vector4.x / vector4.w, vector4.y / vector4.w, vector4.z / vector4.w );
-
-				if ( object.screen.z > 0 && object.screen.z < 1 ) {
-
-					if ( !particlePool[ particleCount ] ) {
-
-						particlePool[ particleCount ] = new THREE.RenderableParticle();
-
-					}
-
-					particlePool[ particleCount ].x = object.screen.x;
-					particlePool[ particleCount ].y = object.screen.y;
-					particlePool[ particleCount ].z = object.screen.z;
-
-					particlePool[ particleCount ].rotation = object.rotation.z;
-
-					particlePool[ particleCount ].scale.x = object.scale.x * Math.abs( vector4.x / vector4.w - ( vector4.x + camera.projectionMatrix.n11 ) / ( vector4.w + camera.projectionMatrix.n14 ) );
-					particlePool[ particleCount ].scale.y = object.scale.y * Math.abs( vector4.y / vector4.w - ( vector4.y + camera.projectionMatrix.n22 ) / ( vector4.w + camera.projectionMatrix.n24 ) );
-					particlePool[ particleCount ].material = object.material;
-					particlePool[ particleCount ].color = object.color;
-
-					this.renderList.push( particlePool[ particleCount ] );
-
-					particleCount++;
-
-				}
-
-			}
-
-		}
-
-		this.renderList.sort( painterSort );
-
-	};
-
-};

+ 150 - 13
src/renderers/SVGRenderer.js

@@ -4,12 +4,20 @@
 
 
 THREE.SVGRenderer = function () {
 THREE.SVGRenderer = function () {
 
 
-	THREE.Renderer.call( this );
-
-	var _svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
+	var _renderList = null,
+	_projector = new THREE.Projector(),
+	_svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'),
 	_width, _height, _widthHalf, _heightHalf,
 	_width, _height, _widthHalf, _heightHalf,
 	_clipRect = new THREE.Rectangle(),
 	_clipRect = new THREE.Rectangle(),
 	_bboxRect = new THREE.Rectangle(),
 	_bboxRect = new THREE.Rectangle(),
+
+	_enableLighting = false,
+	_color = new THREE.Color( 0xffffffff ),
+	_light = new THREE.Color( 0xffffffff ),
+	_ambientLight = new THREE.Color( 0xffffffff ),
+
+	_vector3 = new THREE.Vector3(), // Needed for PointLight
+
 	_svgPathPool = [], _svgCirclePool = [],
 	_svgPathPool = [], _svgCirclePool = [],
 	_quality = 1;
 	_quality = 1;
 
 
@@ -63,11 +71,19 @@ THREE.SVGRenderer = function () {
 
 
 		}
 		}
 
 
-		this.project( scene, camera );
+		_renderList = _projector.projectScene( scene, camera );
+
+		_enableLighting = scene.lights.length > 0;
 
 
-		for ( e = 0, el = this.renderList.length; e < el; e++ ) {
+		if ( _enableLighting ) {
 
 
-			element = this.renderList[ e ];
+			calculateAmbientLight( scene, _ambientLight );
+
+		}
+
+		for ( e = 0, el = _renderList.length; e < el; e++ ) {
+
+			element = _renderList[ e ];
 
 
 			for ( m = 0, ml = element.material.length; m < ml; m++ ) {
 			for ( m = 0, ml = element.material.length; m < ml; m++ ) {
 
 
@@ -135,23 +151,84 @@ THREE.SVGRenderer = function () {
 
 
 				}
 				}
 
 
+
 				// TODO: Move out of materials loop
 				// TODO: Move out of materials loop
 
 
 				if ( material instanceof THREE.MeshColorFillMaterial ) {
 				if ( material instanceof THREE.MeshColorFillMaterial ) {
 
 
-					svgNode.setAttribute( 'style', 'fill: ' + material.color.__styleString );
+					if ( _enableLighting ) {
+
+						_light.copyRGB( _ambientLight );
+						calculateFaceLight( scene, element, _light );
+
+						_color.copyRGBA( material.color );
+						_color.multiplySelfRGB( _light );
+						_color.updateStyleString();
+
+					} else {
+
+							_color = material.color;
+
+					}
+
+					svgNode.setAttribute( 'style', 'fill: ' + _color.__styleString );
 
 
 				} else if ( material instanceof THREE.MeshFaceColorFillMaterial ) {
 				} else if ( material instanceof THREE.MeshFaceColorFillMaterial ) {
 
 
-					svgNode.setAttribute( 'style', 'fill: ' + element.color.__styleString );
+					if ( _enableLighting ) {
+
+						_light.copyRGB( _ambientLight );
+						calculateFaceLight( scene, element, _light );
+
+						_color.copyRGBA( element.color );
+						_color.multiplySelfRGB( _light );
+						_color.updateStyleString();
+
+					} else {
+
+							_color = element.color;
+
+					}
+
+					svgNode.setAttribute( 'style', 'fill: ' + _color.__styleString );
 
 
 				} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
 				} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
 
 
-					svgNode.setAttribute( 'style', 'fill: none; stroke: ' + material.color.__styleString + '; stroke-width: ' + material.lineWidth + '; stroke-linecap: round; stroke-linejoin: round' );
+					if ( _enableLighting ) {
+
+						_light.copyRGB( _ambientLight );
+						calculateFaceLight( scene, element, _light );
+
+						_color.copyRGBA( material.color );
+						_color.multiplySelfRGB( _light );
+						_color.updateStyleString();
+
+					} else {
+
+							_color = material.color;
+
+					}
+
+					svgNode.setAttribute( 'style', 'fill: none; stroke: ' + _color.__styleString + '; stroke-width: ' + material.lineWidth + '; stroke-linecap: round; stroke-linejoin: round' );
 
 
 				} else if ( material instanceof THREE.MeshFaceColorStrokeMaterial ) {
 				} else if ( material instanceof THREE.MeshFaceColorStrokeMaterial ) {
 
 
-					svgNode.setAttribute( 'style', 'fill: none; stroke: ' + element.color.__styleString + '; stroke-width: ' + material.lineWidth + '; stroke-linecap: round; stroke-linejoin: round' );
+					if ( _enableLighting ) {
+
+						_light.copyRGB( _ambientLight );
+						calculateFaceLight( scene, element, _light );
+
+						_color.copyRGBA( element.color );
+						_color.multiplySelfRGB( _light );
+						_color.updateStyleString();
+
+					} else {
+
+						_color = element.color;
+
+					}
+
+					svgNode.setAttribute( 'style', 'fill: none; stroke: ' + _color.__styleString + '; stroke-width: ' + material.lineWidth + '; stroke-linecap: round; stroke-linejoin: round' );
 
 
 				}
 				}
 
 
@@ -163,6 +240,69 @@ THREE.SVGRenderer = function () {
 
 
 	};
 	};
 
 
+	function calculateAmbientLight( scene, color ) {
+
+		var l, ll, light;
+
+		color.setRGBA( 1, 1, 1, 1 );
+
+		for ( l = 0, ll = scene.lights.length; l < ll; l++ ) {
+
+			light = scene.lights[ l ];
+
+			if ( light instanceof THREE.AmbientLight ) {
+
+				color.r *= light.color.r;
+				color.g *= light.color.g;
+				color.b *= light.color.b;
+
+			}
+
+		}
+
+	}
+
+	function calculateFaceLight( scene, element, color ) {
+
+		var l, ll, light, amount;
+
+		for ( l = 0, ll = scene.lights.length; l < ll; l++ ) {
+
+			light = scene.lights[ l ];
+
+			if ( light instanceof THREE.DirectionalLight ) {
+
+				amount = element.normalWorld.dot( light.position ) * light.intensity;
+
+				if ( amount > 0 ) {
+
+					color.r += light.color.r * amount;
+					color.g += light.color.g * amount;
+					color.b += light.color.b * amount;
+
+				}
+
+			} else if ( light instanceof THREE.PointLight ) {
+
+				_vector3.sub( light.position, element.centroidWorld );
+				_vector3.normalize();
+
+				amount = element.normalWorld.dot( _vector3 ) * light.intensity;
+
+				if ( amount > 0 ) {
+
+					color.r += light.color.r * amount;
+					color.g += light.color.g * amount;
+					color.b += light.color.b * amount;
+
+				}
+
+			}
+
+		}
+
+	}
+
 	function getPathNode( id ) {
 	function getPathNode( id ) {
 
 
 		if ( _svgPathPool[ id ] == null ) {
 		if ( _svgPathPool[ id ] == null ) {
@@ -204,6 +344,3 @@ THREE.SVGRenderer = function () {
 	}
 	}
 
 
 };
 };
-
-THREE.SVGRenderer.prototype = new THREE.Renderer();
-THREE.SVGRenderer.prototype.constructor = THREE.CanvasRenderer;

+ 5 - 3
src/renderers/WebGLRenderer.js

@@ -30,7 +30,7 @@ THREE.WebGLRenderer = function () {
 
 
 	this.render = function ( scene, camera ) {
 	this.render = function ( scene, camera ) {
 
 
-		var face, faceColor, object, material, normal, lightColor, lightDirection, light,
+		var face, faceColor, object, material, normal, lightColor, lightPosition, light,
 		vertexArray, faceArray, colorArray, normalArray, vertexIndex,
 		vertexArray, faceArray, colorArray, normalArray, vertexIndex,
 		o, ol, f, fl, m, ml, i, v1, v2, v3, v4,
 		o, ol, f, fl, m, ml, i, v1, v2, v3, v4,
 		l, ll;
 		l, ll;
@@ -56,8 +56,8 @@ THREE.WebGLRenderer = function () {
 			} else if( light instanceof THREE.DirectionalLight ) {
 			} else if( light instanceof THREE.DirectionalLight ) {
 
 
 				lightColor = light.color;
 				lightColor = light.color;
-				lightDirection = light.direction;
-				_gl.uniform3f( _program.lightingDirection, lightDirection.x, lightDirection.y, lightDirection.z );
+				lightPosition = light.position;
+				_gl.uniform3f( _program.lightingDirection, lightPosition.x, lightPosition.y, lightPosition.z );
 				_gl.uniform3f( _program.directionalColor, lightColor.r, lightColor.g, lightColor.b );
 				_gl.uniform3f( _program.directionalColor, lightColor.r, lightColor.g, lightColor.b );
 
 
 			}
 			}
@@ -161,6 +161,8 @@ THREE.WebGLRenderer = function () {
 
 
 				}
 				}
 
 
+				camera.autoUpdateMatrix && camera.updateMatrix();
+				object.autoUpdateMatrix && object.updateMatrix();
 
 
 				viewMatrix.multiply( camera.matrix, object.matrix );
 				viewMatrix.multiply( camera.matrix, object.matrix );
 
 

+ 3 - 0
src/renderers/renderables/RenderableFace3.js

@@ -8,6 +8,9 @@ THREE.RenderableFace3 = function () {
 	this.v2 = new THREE.Vector2();
 	this.v2 = new THREE.Vector2();
 	this.v3 = new THREE.Vector2();
 	this.v3 = new THREE.Vector2();
 
 
+	this.centroidWorld = new THREE.Vector3();
+	this.normalWorld = new THREE.Vector3();
+
 	this.z = null;
 	this.z = null;
 
 
 	this.color = null;
 	this.color = null;

+ 3 - 0
src/renderers/renderables/RenderableFace4.js

@@ -9,6 +9,9 @@ THREE.RenderableFace4 = function () {
 	this.v3 = new THREE.Vector2();
 	this.v3 = new THREE.Vector2();
 	this.v4 = new THREE.Vector2();
 	this.v4 = new THREE.Vector2();
 
 
+	this.centroidWorld = new THREE.Vector3();
+	this.normalWorld = new THREE.Vector3();
+
 	this.z = null;
 	this.z = null;
 
 
 	this.color = null;
 	this.color = null;

+ 6 - 5
utils/Builder.py

@@ -19,13 +19,14 @@ files.append('core/Face4.js')
 files.append('core/UV.js')
 files.append('core/UV.js')
 files.append('core/Geometry.js')
 files.append('core/Geometry.js')
 files.append('cameras/Camera.js')
 files.append('cameras/Camera.js')
-files.append('objects/Object3D.js')
-files.append('objects/Line.js')
-files.append('objects/Mesh.js')
-files.append('objects/Particle.js')
 files.append('lights/Light.js')
 files.append('lights/Light.js')
 files.append('lights/AmbientLight.js')
 files.append('lights/AmbientLight.js')
 files.append('lights/DirectionalLight.js')
 files.append('lights/DirectionalLight.js')
+files.append('lights/PointLight.js')
+files.append('objects/Object3D.js')
+files.append('objects/Particle.js')
+files.append('objects/Line.js')
+files.append('objects/Mesh.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/MeshBitmapUVMappingMaterial.js')
 files.append('materials/MeshBitmapUVMappingMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
@@ -36,7 +37,7 @@ files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('materials/ParticleDOMMaterial.js')
 files.append('materials/ParticleDOMMaterial.js')
 files.append('scenes/Scene.js')
 files.append('scenes/Scene.js')
-files.append('renderers/Renderer.js')
+files.append('renderers/Projector.js')
 files.append('renderers/DOMRenderer.js')
 files.append('renderers/DOMRenderer.js')
 files.append('renderers/CanvasRenderer.js')
 files.append('renderers/CanvasRenderer.js')
 files.append('renderers/SVGRenderer.js')
 files.append('renderers/SVGRenderer.js')

+ 6 - 5
utils/BuilderCanvas.py

@@ -19,13 +19,14 @@ files.append('core/Face4.js')
 files.append('core/UV.js')
 files.append('core/UV.js')
 files.append('core/Geometry.js')
 files.append('core/Geometry.js')
 files.append('cameras/Camera.js')
 files.append('cameras/Camera.js')
-files.append('objects/Object3D.js')
-files.append('objects/Line.js')
-files.append('objects/Mesh.js')
-files.append('objects/Particle.js')
 files.append('lights/Light.js')
 files.append('lights/Light.js')
 files.append('lights/AmbientLight.js')
 files.append('lights/AmbientLight.js')
 files.append('lights/DirectionalLight.js')
 files.append('lights/DirectionalLight.js')
+files.append('lights/PointLight.js')
+files.append('objects/Object3D.js')
+files.append('objects/Particle.js')
+files.append('objects/Line.js')
+files.append('objects/Mesh.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/MeshBitmapUVMappingMaterial.js')
 files.append('materials/MeshBitmapUVMappingMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
@@ -35,7 +36,7 @@ files.append('materials/MeshFaceColorStrokeMaterial.js')
 files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('scenes/Scene.js')
 files.append('scenes/Scene.js')
-files.append('renderers/Renderer.js')
+files.append('renderers/Projector.js')
 files.append('renderers/CanvasRenderer.js')
 files.append('renderers/CanvasRenderer.js')
 files.append('renderers/renderables/RenderableFace3.js')
 files.append('renderers/renderables/RenderableFace3.js')
 files.append('renderers/renderables/RenderableFace4.js')
 files.append('renderers/renderables/RenderableFace4.js')

+ 1 - 1
utils/BuilderDOM.py

@@ -22,7 +22,7 @@ files.append('objects/Object3D.js')
 files.append('objects/Particle.js')
 files.append('objects/Particle.js')
 files.append('materials/ParticleDOMMaterial.js')
 files.append('materials/ParticleDOMMaterial.js')
 files.append('scenes/Scene.js')
 files.append('scenes/Scene.js')
-files.append('renderers/Renderer.js')
+files.append('renderers/Projector.js')
 files.append('renderers/DOMRenderer.js')
 files.append('renderers/DOMRenderer.js')
 files.append('renderers/renderables/RenderableParticle.js')
 files.append('renderers/renderables/RenderableParticle.js')
 
 

+ 6 - 5
utils/BuilderDebug.py

@@ -19,13 +19,14 @@ files.append('core/Face4.js')
 files.append('core/UV.js')
 files.append('core/UV.js')
 files.append('core/Geometry.js')
 files.append('core/Geometry.js')
 files.append('cameras/Camera.js')
 files.append('cameras/Camera.js')
-files.append('objects/Object3D.js')
-files.append('objects/Line.js')
-files.append('objects/Mesh.js')
-files.append('objects/Particle.js')
 files.append('lights/Light.js')
 files.append('lights/Light.js')
 files.append('lights/AmbientLight.js')
 files.append('lights/AmbientLight.js')
 files.append('lights/DirectionalLight.js')
 files.append('lights/DirectionalLight.js')
+files.append('lights/PointLight.js')
+files.append('objects/Object3D.js')
+files.append('objects/Particle.js')
+files.append('objects/Line.js')
+files.append('objects/Mesh.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/MeshBitmapUVMappingMaterial.js')
 files.append('materials/MeshBitmapUVMappingMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
@@ -36,7 +37,7 @@ files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('materials/ParticleDOMMaterial.js')
 files.append('materials/ParticleDOMMaterial.js')
 files.append('scenes/Scene.js')
 files.append('scenes/Scene.js')
-files.append('renderers/Renderer.js')
+files.append('renderers/Projector.js')
 files.append('renderers/DOMRenderer.js')
 files.append('renderers/DOMRenderer.js')
 files.append('renderers/CanvasRenderer.js')
 files.append('renderers/CanvasRenderer.js')
 files.append('renderers/SVGRenderer.js')
 files.append('renderers/SVGRenderer.js')

+ 6 - 6
utils/BuilderSVG.py

@@ -19,14 +19,14 @@ files.append('core/Face4.js')
 files.append('core/UV.js')
 files.append('core/UV.js')
 files.append('core/Geometry.js')
 files.append('core/Geometry.js')
 files.append('cameras/Camera.js')
 files.append('cameras/Camera.js')
-files.append('objects/Object3D.js')
-files.append('objects/Line.js')
-files.append('objects/Mesh.js')
-files.append('objects/Particle.js')
 files.append('lights/Light.js')
 files.append('lights/Light.js')
 files.append('lights/AmbientLight.js')
 files.append('lights/AmbientLight.js')
 files.append('lights/DirectionalLight.js')
 files.append('lights/DirectionalLight.js')
-files.append('materials/LineColorMaterial.js')
+files.append('lights/PointLight.js')
+files.append('objects/Object3D.js')
+files.append('objects/Particle.js')
+files.append('objects/Line.js')
+files.append('objects/Mesh.js')
 files.append('materials/MeshBitmapUVMappingMaterial.js')
 files.append('materials/MeshBitmapUVMappingMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorStrokeMaterial.js')
 files.append('materials/MeshColorStrokeMaterial.js')
@@ -35,7 +35,7 @@ files.append('materials/MeshFaceColorStrokeMaterial.js')
 files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('scenes/Scene.js')
 files.append('scenes/Scene.js')
-files.append('renderers/Renderer.js')
+files.append('renderers/Projector.js')
 files.append('renderers/SVGRenderer.js')
 files.append('renderers/SVGRenderer.js')
 files.append('renderers/renderables/RenderableFace3.js')
 files.append('renderers/renderables/RenderableFace3.js')
 files.append('renderers/renderables/RenderableFace4.js')
 files.append('renderers/renderables/RenderableFace4.js')

+ 5 - 4
utils/BuilderWebGL.py

@@ -19,13 +19,14 @@ files.append('core/Face4.js')
 files.append('core/UV.js')
 files.append('core/UV.js')
 files.append('core/Geometry.js')
 files.append('core/Geometry.js')
 files.append('cameras/Camera.js')
 files.append('cameras/Camera.js')
-files.append('objects/Object3D.js')
-files.append('objects/Line.js')
-files.append('objects/Mesh.js')
-files.append('objects/Particle.js')
 files.append('lights/Light.js')
 files.append('lights/Light.js')
 files.append('lights/AmbientLight.js')
 files.append('lights/AmbientLight.js')
 files.append('lights/DirectionalLight.js')
 files.append('lights/DirectionalLight.js')
+files.append('lights/PointLight.js')
+files.append('objects/Object3D.js')
+files.append('objects/Particle.js')
+files.append('objects/Line.js')
+files.append('objects/Mesh.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/MeshBitmapUVMappingMaterial.js')
 files.append('materials/MeshBitmapUVMappingMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')

+ 1 - 1
utils/REVISION

@@ -1 +1 @@
-17
+18

+ 80 - 0
utils/exporters/blender/2.54/scripts/op/io_mesh_threejs/__init__.py

@@ -0,0 +1,80 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# To support reload properly, try to access a package var, if it's there, reload everything
+if "bpy" in locals():
+    import sys
+    reload(sys.modules.get("io_mesh_threejs.export_threejs", sys))
+
+
+import bpy
+from bpy.props import *
+from io_utils import ExportHelper
+
+
+class ExportTHREEJS(bpy.types.Operator, ExportHelper):
+    '''This script exports the selected object for the three.js engine.'''
+    bl_idname = "export.threejs"
+    bl_label = "Export Three.js"
+    
+    filename_ext = ".js"
+
+    use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply Modifiers to the exported mesh", default=True)
+    use_normals = BoolProperty(name="Normals", description="Export Normals for smooth and hard shaded faces", default=True)
+    use_uv_coords = BoolProperty(name="UVs", description="Exort the active UV layer", default=True)
+    use_colors = BoolProperty(name="Vertex Colors", description="Exort the active vertex color layer", default=True)
+
+    @classmethod
+    def poll(cls, context):
+        return context.active_object != None
+
+    def execute(self, context):
+        print("Selected: " + context.active_object.name)
+
+        if not self.properties.filepath:
+            raise Exception("filename not set")
+
+        filepath = self.filepath
+        import io_mesh_threejs.export_threejs
+        return io_mesh_threejs.export_threejs.save(self, context, **self.properties)
+
+    def draw(self, context):
+        layout = self.layout
+
+        row = layout.row()
+        row.prop(self.properties, "use_modifiers")
+        row.prop(self.properties, "use_normals")
+        row = layout.row()
+        row.prop(self.properties, "use_uv_coords")
+        row.prop(self.properties, "use_colors")
+
+
+def menu_func(self, context):
+    default_path = bpy.data.filepath.replace(".blend", ".js")
+    self.layout.operator(ExportTHREEJS.bl_idname, text="Three.js (.js)").filepath = default_path
+
+
+def register():
+    bpy.types.INFO_MT_file_export.append(menu_func)
+
+
+def unregister():
+    bpy.types.INFO_MT_file_export.remove(menu_func)
+
+if __name__ == "__main__":
+    register()

+ 176 - 0
utils/exporters/blender/2.54/scripts/op/io_mesh_threejs/export_threejs.py

@@ -0,0 +1,176 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  This program is free software; you can redistribute it and/or
+#  modify it under the terms of the GNU General Public License
+#  as published by the Free Software Foundation; either version 2
+#  of the License, or (at your option) any later version.
+#
+#  This program is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with this program; if not, write to the Free Software Foundation,
+#  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+# Based on export_ply.py
+# Contributors: Mr.doob, Kikko, alteredq
+
+"""
+This script exports the selected object for the three.js engine.
+"""
+
+import bpy
+import os
+import os.path
+
+def save(operator, context, filepath="", use_modifiers=True, use_normals=True, use_uv_coords=True, use_colors=True):
+
+    def rvec3d(v):
+        return round(v[0], 6), round(v[1], 6), round(v[2], 6)
+
+    def rvec2d(v):
+        return round(v[0], 6), round(v[1], 6)
+
+    scene = context.scene
+    obj = context.object
+
+    if not filepath.lower().endswith('.js'):
+        filepath += '.js'
+
+    classname = os.path.basename(filepath).split(".")[0]
+
+    if not obj:
+        raise Exception("Error, Select 1 active object")
+
+    file = open(filepath, 'w')
+
+    if scene.objects.active:
+        bpy.ops.object.mode_set(mode='OBJECT')
+
+    if use_modifiers:
+        mesh = obj.create_mesh(scene, True, 'PREVIEW')
+    else:
+        mesh = obj.data
+
+    if not mesh:
+        raise Exception("Error, could not get mesh data from active object")
+
+    # mesh.transform(obj.matrix_world) # XXX
+
+    faceUV = (len(mesh.uv_textures) > 0)
+    vertexUV = (len(mesh.sticky) > 0)
+    vertexColors = len(mesh.vertex_colors) > 0
+
+    if (not faceUV) and (not vertexUV):
+        use_uv_coords = False
+    if not vertexColors:
+        use_colors = False
+
+    if not use_uv_coords:
+        faceUV = vertexUV = False
+    if not use_colors:
+        vertexColors = False
+
+    if faceUV:
+        active_uv_layer = mesh.uv_textures.active
+        if not active_uv_layer:
+            use_uv_coords = False
+            faceUV = None
+        else:
+            active_uv_layer = active_uv_layer.data
+
+    if vertexColors:
+        active_col_layer = mesh.vertex_colors.active
+        if not active_col_layer:
+            use_colors = False
+            vertexColors = None
+        else:
+            active_col_layer = active_col_layer.data
+
+    # incase
+    color = uvcoord = uvcoord_key = normal = normal_key = None
+
+    file.write('// Generated with Blender 2.54 exporter\n')
+    file.write('// http://github.com/mrdoob/three.js/tree/master/utils/exporters/blender\n\n')
+
+    file.write('var %s = function () {\n\n' % classname)
+
+    file.write('\tvar scope = this;\n\n')
+
+    file.write('\tTHREE.Geometry.call( this );\n\n')
+
+    for v in mesh.vertices:
+        file.write('\tv( %.6f, %.6f, %.6f );\n' % (v.co.x, v.co.z, -v.co.y)) # co
+
+    file.write('\n')
+
+    if use_normals:
+        for f in mesh.faces:
+            if len(f.vertices) == 3:
+                file.write('\tf3( %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.vertices[0], f.vertices[1], f.vertices[2], f.normal[0], f.normal[1], f.normal[2]))
+            else:
+                file.write('\tf4( %d, %d, %d, %d, %.6f, %.6f, %.6f );\n' % (f.vertices[0], f.vertices[1], f.vertices[2], f.vertices[3], f.normal[0], f.normal[1], f.normal[2]))
+
+    else:
+        for f in mesh.faces:
+            if len(f.vertices) == 3:
+                file.write('\tf3( %d, %d, %d );\n' % (f.vertices[0], f.vertices[1], f.vertices[2]))
+            else:
+                file.write('\tf4( %d, %d, %d, %d );\n' % (f.vertices[0], f.vertices[1], f.vertices[2], f.vertices[3]))
+
+    face_index_pairs = [ (face, index) for index, face in enumerate(mesh.faces)]
+
+    if use_uv_coords:
+        file.write('\n')
+        for f, f_index in face_index_pairs:
+            tface = mesh.uv_textures[0].data[f_index]
+            if len(f.vertices) == 3:
+                file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (tface.uv1[0], 1.0-tface.uv1[1], tface.uv2[0], 1.0-tface.uv2[1], tface.uv3[0], 1.0-tface.uv3[1]))
+            else:
+                file.write('\tuv( %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f );\n' % (tface.uv1[0], 1.0-tface.uv1[1], tface.uv2[0], 1.0-tface.uv2[1], tface.uv3[0], 1.0-tface.uv3[1], tface.uv4[0], 1.0-tface.uv4[1]))
+
+    file.write('\n')
+
+    file.write('\tfunction v( x, y, z ) {\n\n')
+    file.write('\t\tscope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );\n\n')
+    file.write('\t}\n\n')
+
+    file.write('\tfunction f3( a, b, c, nx, ny, nz ) {\n\n')
+    file.write('\t\tscope.faces.push( new THREE.Face3( a, b, c, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n')
+    file.write('\t}\n\n')
+
+    file.write('\tfunction f4( a, b, c, d, nx, ny, nz ) {\n\n')
+    file.write('\t\tscope.faces.push( new THREE.Face4( a, b, c, d, nx && ny && nz ? new THREE.Vector3( nx, ny, nz ) : null ) );\n\n')
+    file.write('\t}\n\n')
+
+    file.write('\tfunction uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {\n\n')
+    file.write('\t\tvar uv = [];\n')
+    file.write('\t\tuv.push( new THREE.UV( u1, v1 ) );\n')
+    file.write('\t\tuv.push( new THREE.UV( u2, v2 ) );\n')
+    file.write('\t\tuv.push( new THREE.UV( u3, v3 ) );\n')
+    file.write('\t\tif ( u4 && v4 ) uv.push( new THREE.UV( u4, v4 ) );\n')
+    file.write('\t\tscope.uvs.push( uv );\n')
+    file.write('\t}\n\n')
+
+    file.write('\tthis.computeCentroids();\n')
+
+    if not use_normals:
+        file.write('\tthis.computeNormals();\n')
+
+    file.write('\n}\n\n')
+
+    file.write('%s.prototype = new THREE.Geometry();\n' % classname)
+    file.write('%s.prototype.constructor = %s;' % (classname, classname))
+
+    file.close()
+
+    print("writing", filepath, "done")
+
+    if use_modifiers:
+        bpy.data.meshes.remove(mesh)
+
+    return {'FINISHED'}

+ 0 - 0
utils/exporters/export_threejs_2.53b.py → utils/exporters/blender/export_threejs_2.53b.py


+ 0 - 0
utils/exporters/export_threejs_2.5a2.py → utils/exporters/blender/export_threejs_2.5a2.py


部分文件因为文件数量过多而无法显示