Browse Source

updating dev.

Jono Brandel 13 years ago
parent
commit
30d4cbbb43
100 changed files with 4654 additions and 966 deletions
  1. 129 159
      build/three.min.js
  2. 42 52
      docs/api/core/Matrix4.html
  3. 11 15
      docs/api/extras/geometries/CubeGeometry.html
  4. 3 1
      docs/index.html
  5. 244 0
      editor/index.html
  6. 132 12
      editor/js/UI.js
  7. 0 0
      editor/js/libs/signals.min.js
  8. 16 0
      editor/js/ui/Menubar.js
  9. 98 0
      editor/js/ui/Sidebar.Outliner.js
  10. 70 40
      editor/js/ui/Sidebar.Properties.Geometry.js
  11. 401 0
      editor/js/ui/Sidebar.Properties.Material.js
  12. 154 0
      editor/js/ui/Sidebar.Properties.Object3D.js
  13. 0 0
      editor/js/ui/Sidebar.Properties.js
  14. 0 0
      editor/js/ui/Sidebar.js
  15. 11 13
      editor/js/ui/Viewport.js
  16. 1 1
      examples/canvas_materials_depth.html
  17. 73 115
      examples/js/Cloth.js
  18. 27 27
      examples/js/ShaderExtras.js
  19. 3 6
      examples/js/ShaderGodRays.js
  20. 58 12
      examples/js/ShaderSkin.js
  21. 85 14
      examples/js/ShaderTerrain.js
  22. 4 4
      examples/js/effects/AnaglyphEffect.js
  23. 4 4
      examples/js/effects/ParallaxBarrierEffect.js
  24. 11 13
      examples/js/loaders/ColladaLoader.js
  25. 474 0
      examples/js/loaders/MTLLoader.js
  26. 10 10
      examples/js/loaders/OBJLoader.js
  27. 490 0
      examples/js/loaders/OBJMTLLoader.js
  28. 7 6
      examples/js/loaders/STLLoader.js
  29. 822 188
      examples/js/loaders/UTF8Loader.js
  30. 6 6
      examples/js/loaders/VTKLoader.js
  31. 8 7
      examples/js/loaders/ctm/CTMLoader.js
  32. 3 3
      examples/js/postprocessing/BloomPass.js
  33. 1 1
      examples/js/postprocessing/DotScreenPass.js
  34. 1 1
      examples/js/postprocessing/FilmPass.js
  35. 1 1
      examples/js/postprocessing/SavePass.js
  36. 1 1
      examples/js/postprocessing/ShaderPass.js
  37. 1 1
      examples/js/postprocessing/TexturePass.js
  38. 153 0
      examples/js/renderers/CSS3DRenderer.js
  39. 1 1
      examples/js/renderers/DOMRenderer.js
  40. 14 8
      examples/js/renderers/SVGRenderer.js
  41. 1 1
      examples/js/renderers/SoftwareRenderer.js
  42. 1 1
      examples/js/renderers/SoftwareRenderer2.js
  43. 1 1
      examples/js/renderers/SoftwareRenderer3.js
  44. 4 4
      examples/misc_camera_fly.html
  45. 102 0
      examples/misc_css3d.html
  46. 12 6
      examples/misc_ubiquity_test.html
  47. BIN
      examples/models/utf8/James_Body_Lores.jpg
  48. BIN
      examples/models/utf8/James_EyeLashBotTran.png
  49. BIN
      examples/models/utf8/James_EyeLashTopTran.png
  50. BIN
      examples/models/utf8/James_Eye_Green.jpg
  51. BIN
      examples/models/utf8/James_Eye_Inner_Green.jpg
  52. BIN
      examples/models/utf8/James_Face_Color_Hair_Lores.jpg
  53. BIN
      examples/models/utf8/James_Mouth_Gum_Lores.jpg
  54. BIN
      examples/models/utf8/James_Tongue_Lores.jpg
  55. BIN
      examples/models/utf8/MCasShoe1TEX_Lores.jpg
  56. BIN
      examples/models/utf8/MJeans1TEX_Lores.jpg
  57. BIN
      examples/models/utf8/MTshirt3TEX_Lores.jpg
  58. BIN
      examples/models/utf8/Nail_Hand_01_Lores.jpg
  59. 107 0
      examples/models/utf8/ben.js
  60. BIN
      examples/models/utf8/ben.utf8
  61. 107 0
      examples/models/utf8/ben_dds.js
  62. BIN
      examples/models/utf8/dds/James_Body_Lores.dds
  63. BIN
      examples/models/utf8/dds/James_EyeLashBotTran.dds
  64. BIN
      examples/models/utf8/dds/James_EyeLashTopTran.dds
  65. BIN
      examples/models/utf8/dds/James_Eye_Green.dds
  66. BIN
      examples/models/utf8/dds/James_Eye_Inner_Green.dds
  67. BIN
      examples/models/utf8/dds/James_Face_Color_Hair_Lores.dds
  68. BIN
      examples/models/utf8/dds/James_Mouth_Gum_Lores.dds
  69. BIN
      examples/models/utf8/dds/James_Tongue_Lores.dds
  70. BIN
      examples/models/utf8/dds/MCasShoe1TEX_Lores.dds
  71. BIN
      examples/models/utf8/dds/MJeans1TEX_Lores.dds
  72. BIN
      examples/models/utf8/dds/MTshirt3TEX_Lores.dds
  73. BIN
      examples/models/utf8/dds/Nail_Hand_01_Lores.dds
  74. BIN
      examples/models/utf8/hand.jpg
  75. 27 0
      examples/models/utf8/hand.js
  76. BIN
      examples/models/utf8/hand.utf8
  77. 20 8
      examples/obj/blenderscene/scene.Cube.js
  78. 10 5
      examples/obj/blenderscene/scene.Monkey.js
  79. 20 8
      examples/obj/blenderscene/scene.Plane.js
  80. 194 194
      examples/obj/blenderscene/scene.js
  81. BIN
      examples/obj/lightmap/lightmap-ao-shadow.png
  82. 123 0
      examples/obj/lightmap/lightmap.js
  83. 4 0
      examples/obj/lightmap/readme.txt
  84. BIN
      examples/obj/lightmap/rocks.jpg
  85. BIN
      examples/obj/lightmap/stone.jpg
  86. BIN
      examples/obj/male02/01_-_Default1noCulling.dds
  87. 87 0
      examples/obj/male02/Male02_dds.js
  88. BIN
      examples/obj/male02/male-02-1noCulling.dds
  89. 56 0
      examples/obj/male02/male02_dds.mtl
  90. BIN
      examples/obj/male02/orig_02_-_Defaul1noCulling.dds
  91. 208 16
      examples/scenes/test_scene.js
  92. BIN
      examples/textures/compressed/disturb_dxt1_mip.dds
  93. BIN
      examples/textures/compressed/disturb_dxt1_nomip.dds
  94. BIN
      examples/textures/compressed/explosion_dxt5_mip.dds
  95. BIN
      examples/textures/compressed/hepatica_dxt3_mip.dds
  96. BIN
      examples/textures/cube/escher/dds/nx.dds
  97. BIN
      examples/textures/cube/escher/dds/ny.dds
  98. BIN
      examples/textures/cube/escher/dds/nz.dds
  99. BIN
      examples/textures/cube/escher/dds/px.dds
  100. BIN
      examples/textures/cube/escher/dds/py.dds

File diff suppressed because it is too large
+ 129 - 159
build/three.min.js


+ 42 - 52
docs/api/core/Matrix4.html

@@ -135,50 +135,6 @@
 		Flattens this matrix into supplied *flat* array starting from *offset* position in the array.
 		</div>
 
-		<h3>.setTranslation( [page:Float x], [page:Float y], [page:Float z] ) [page:Matrix4]</h3>
-		<div>
-		Sets this matrix as translation transform.
-		</div>
-
-		<h3>.setScale( [page:Float x], [page:Float y], [page:Float z] ) [page:Matrix4]</h3>
-		<div>
-		Sets this matrix as scale transform.
-		</div>
-
-		<h3>.makeRotationX( [page:Float theta] ) [page:Matrix4]</h3>
-		<div>
-		theta — Rotation angle in radians.
-		</div>
-		<div>
-		Sets this matrix as rotation transform around x axis by *theta* radians.
-		</div>
-
-		<h3>.makeRotationY( [page:Float theta] ) [page:Matrix4]</h3>
-		<div>
-		theta — Rotation angle in radians.
-		</div>
-		<div>
-		Sets this matrix as rotation transform around y axis by *theta* radians.
-		</div>
-
-		<h3>.makeRotationZ( [page:Float theta] ) [page:Matrix4]</h3>
-		<div>
-		theta — Rotation angle in radians.
-		</div>
-		<div>
-		Sets this matrix as rotation transform around z axis by *theta* radians.
-		</div>
-
-		<h3>.makeRotationAxis( [page:Vector3 axis], [page:Float theta] ) [page:Matrix4]</h3>
-		<div>
-		axis — Rotation axis.
-		theta — Rotation angle in radians.
-		</div>
-		<div>
-		Sets this matrix as rotation transform around *axis* by *angle* radians.<br />
-		Based on [link:http://www.gamedev.net/reference/articles/article1199.asp].
-		</div>
-
 		<h3>.setPosition( [page:Vector3 v] ) [page:Matrix4]</h3>
 		<div>
 		Sets the position component for this matrix from vector *v*.
@@ -280,19 +236,48 @@
 		Translates this matrix by vector *v*.
 		</div>
 
-		<h3>.clone() [page:Matrix4]</h3>
+		<h3>.makeTranslation( [page:Float x], [page:Float y], [page:Float z] ) [page:Matrix4]</h3>
 		<div>
-		Clones this matrix.
+		Sets this matrix as translation transform.
 		</div>
 
+		<h3>.makeRotationX( [page:Float theta] ) [page:Matrix4]</h3>
+		<div>
+		theta — Rotation angle in radians.
+		</div>
+		<div>
+		Sets this matrix as rotation transform around x axis by *theta* radians.
+		</div>
 
-		<h2>Static methods</h2>
+		<h3>.makeRotationY( [page:Float theta] ) [page:Matrix4]</h3>
+		<div>
+		theta — Rotation angle in radians.
+		</div>
+		<div>
+		Sets this matrix as rotation transform around y axis by *theta* radians.
+		</div>
 
-		<h3>.makeInvert3x3( [page:Matrix4 m] ) [page:Matrix3]</h3>
+		<h3>.makeRotationZ( [page:Float theta] ) [page:Matrix4]</h3>
 		<div>
-		Inverts just the rotation submatrix of matrix *m*.<br />
-		Note: this method returns a reference to the internal 3x3 matrix, make a copy or clone it if you don't use it right away.<br />
-		Based on [link:http://code.google.com/p/webgl-mjs/].
+		theta — Rotation angle in radians.
+		</div>
+		<div>
+		Sets this matrix as rotation transform around z axis by *theta* radians.
+		</div>
+
+		<h3>.makeRotationAxis( [page:Vector3 axis], [page:Float theta] ) [page:Matrix4]</h3>
+		<div>
+		axis — Rotation axis.
+		theta — Rotation angle in radians.
+		</div>
+		<div>
+		Sets this matrix as rotation transform around *axis* by *angle* radians.<br />
+		Based on [link:http://www.gamedev.net/reference/articles/article1199.asp].
+		</div>
+
+		<h3>.makeScale( [page:Float x], [page:Float y], [page:Float z] ) [page:Matrix4]</h3>
+		<div>
+		Sets this matrix as scale transform.
 		</div>
 
 		<h3>.makeFrustum( [page:Float left], [page:Float right], [page:Float bottom], [page:Float top], [page:Float near], [page:Float far] ) [page:Matrix4]</h3>
@@ -305,11 +290,16 @@
 		Creates a perspective projection matrix.
 		</div>
 
-		<h3>.makeOrtho( [page:Float left], [page:Float right], [page:Float bottom], [page:Float top], [page:Float near], [page:Float far] ) [page:Matrix4]</h3>
+		<h3>.makeOrthographic( [page:Float left], [page:Float right], [page:Float bottom], [page:Float top], [page:Float near], [page:Float far] ) [page:Matrix4]</h3>
 		<div>
 		Creates an orthographic projection matrix.
 		</div>
 
+		<h3>.clone() [page:Matrix4]</h3>
+		<div>
+		Clones this matrix.
+		</div>
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 11 - 15
docs/api/extras/geometries/CubeGeometry.html

@@ -7,29 +7,25 @@
 		<link type="text/css" rel="stylesheet" href="../../../page.css" />
 	</head>
 	<body>
-		<h1>[name]</h1>
+		<h1>CubeGeometry</h1>
 
-		<div class="desc">todo</div>
+		<div class="desc">CubeGeometry is the quadrilateral primitive geometry class. It is typically used for creating a cube or irregular quadrilateral of the dimensions provided within the (optional) 'width', 'height', & 'depth' constructor arguments.</div>
 
 
 		<h2>Constructor</h2>
 
-		<h3>[name]()</h3>
-
-
-		<h2>Properties</h2>
-
-		<h3>.[page:Vector3 todo]</h3>
-
-
-		<h2>Methods</h2>
-
-		<h3>.todo( [page:Vector3 todo] )</h3>
+		<h3>[name]([page:Float width], [page:Float height], [page:Float depth], [page:Integer segmentsWidth], [page:Integer segmentsHeight], [page:Integer segmentsDepth], [page:Array materials], [page:Array sides])</h3>
 		<div>
-		todo — todo<br />
+		width — Width of the sides on the X axis.<br />
+		height — Height of the sides on the Y axis.<br />
+		depth — Depth of the sides on the Z axis.<br />
+		segmentsWidth — Number of segmented faces along the width of the sides.<br />
+		segmentsHeight — Number of segmented faces along the height of the sides.<br />
+		segmentsDepth — Number of segmented faces along the depth of the sides.<br />
+		materials — An array containing six [page:Material]s.<br />
+		sides — An array containig six [page:Boolean]s defining whether the side needs to be created.
 		</div>
 
-
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 3 - 1
docs/index.html

@@ -84,7 +84,7 @@
 
 		<script src="list.js"></script>
 		<script>
-			var REVISION = '51dev';
+			var REVISION = '50';
 
 			var panel = document.getElementById( 'panel' );
 			var viewer = document.getElementById( 'viewer' );
@@ -117,6 +117,8 @@
 
 				var path = pages[ name ];
 
+				window.document.title = 'three.js - documentation - ' + name;
+
 				window.location.hash = name;
 				viewer.src = 'api/' + path + '.html';
 

+ 244 - 0
editor/index.html

@@ -0,0 +1,244 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js editor</title>
+		<style>
+			body {
+				font-family: Arial, sans-serif;
+				font-size: 14px;
+				margin: 0;
+				overflow: hidden;
+			}
+
+			hr {
+				border: 0px;
+				border-top: 1px solid #ccc;
+			}
+
+		</style>
+	</head>
+	<body>
+
+		<script src="../build/three.min.js"></script>
+		<script src="../examples/js/loaders/ColladaLoader.js"></script>
+		<script src="../examples/js/loaders/OBJLoader.js"></script>
+		<script src="../examples/js/loaders/STLLoader.js"></script>
+		<script src="../examples/js/loaders/UTF8Loader.js"></script>
+		<script src="../examples/js/loaders/VTKLoader.js"></script>
+
+		<script src="js/libs/signals.min.js"></script>
+
+		<script src="js/UI.js"></script>
+		<script src="js/ui/Menubar.js"></script>
+		<script src="js/ui/Viewport.js"></script>
+		<script src="js/ui/Sidebar.js"></script>
+		<script src="js/ui/Sidebar.Outliner.js"></script>
+		<script src="js/ui/Sidebar.Properties.js"></script>
+		<script src="js/ui/Sidebar.Properties.Object3D.js"></script>
+		<script src="js/ui/Sidebar.Properties.Geometry.js"></script>
+		<script src="js/ui/Sidebar.Properties.Material.js"></script>
+
+		<script>
+
+			window.URL = window.URL || window.webkitURL;
+			window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
+
+			var SIGNALS = signals;
+
+			var signals = {
+
+				sceneCreated: new SIGNALS.Signal(),
+				sceneChanged: new SIGNALS.Signal(),
+				objectAdded: new SIGNALS.Signal(),
+				objectSelected: new SIGNALS.Signal(),
+				objectChanged: new SIGNALS.Signal(),
+				materialChanged: new SIGNALS.Signal(),
+				windowResize: new SIGNALS.Signal()
+
+			};
+
+			//
+
+			var menubar = new Menubar( signals );
+			menubar.setWidth( '100%' );
+			menubar.setHeight( '32px' );
+			document.body.appendChild( menubar.dom );
+
+			var sidebar = new Sidebar( signals );
+			sidebar.setLeft( '-webkit-calc(100% - 300px)', '-moz-calc(100% - 300px)', 'calc(100% - 300px)' );
+			sidebar.setTop( '32px' );
+			sidebar.setHeight( '-webkit-calc(100% - 32px)', '-moz-calc(100% - 32px)', 'calc(100% - 32px)' );
+			document.body.appendChild( sidebar.dom );
+
+			var viewport = new Viewport( signals );
+			viewport.setTop( '32px' );
+			viewport.setWidth( '-webkit-calc(100% - 300px)', '-moz-calc(100% - 300px)', 'calc(100% - 300px)' );
+			viewport.setHeight( '-webkit-calc(100% - 32px)', '-moz-calc(100% - 32px)', 'calc(100% - 32px)' );
+			document.body.appendChild( viewport.dom );
+
+			document.addEventListener( 'drop', function ( event ) {
+
+				event.preventDefault();
+
+				var file = event.dataTransfer.files[ 0 ];
+				var extension = file.name.split( '.' ).pop().toLowerCase();
+				var reader = new FileReader();
+
+				reader.onload = function ( event ) {
+
+					parseFile( event.target.result, extension );
+
+				};
+
+				reader.readAsText( file );
+
+			}, false );
+
+			var parseFile = function ( contents, extension ) {
+
+				switch ( extension ) {
+
+					case 'dae':
+
+						var parser = new DOMParser();
+						var xml = parser.parseFromString( contents, 'text/xml' );
+
+						// TODO: Update ColladaLoader
+
+						var loader = new THREE.ColladaLoader();
+						loader.parse( xml, function ( collada ) {
+
+							signals.objectAdded.dispatch( collada.scene );
+							signals.objectSelected.dispatch( collada.scene );
+
+						} );
+
+						break;
+
+					case 'js':
+
+						// 2.0
+
+						if ( contents.indexOf( 'postMessage' ) !== -1 ) {
+
+							var blob = new Blob( [ contents ], { type: 'text/javascript' } );
+							var url = URL.createObjectURL( blob );
+
+							var worker = new Worker( url );
+
+							worker.onmessage = function ( event ) {
+
+								event.data.metadata = { 'format': 2 };
+								parseFile( JSON.stringify( event.data ), extension );
+
+							};
+
+							worker.postMessage( new Date().getTime() );
+
+							return;
+
+						}
+
+						// 3.0
+
+						var data = JSON.parse( contents );
+
+						if ( data.metadata === undefined ) data.metadata = { type: 'geometry' }; // 2.0
+						if ( data.metadata.type === undefined ) data.metadata.type = 'geometry'; // 3.0
+
+						if ( data.metadata.type === 'geometry' ) {
+
+							var geometry = new THREE.GeometryLoader().parse( data );
+							var material = new THREE.MeshLambertMaterial();
+
+							var mesh = new THREE.Mesh( geometry, material );
+
+							signals.objectAdded.dispatch( mesh );
+							signals.objectSelected.dispatch( mesh );
+
+						} else if ( data.metadata.type === 'scene' ) {
+
+							new THREE.SceneLoader().parse( data, function ( scene ) {
+
+								signals.objectAdded.dispatch( scene );
+								signals.objectSelected.dispatch( scene );
+
+							}, '' );
+
+						}
+
+						break;
+
+					case 'obj':
+
+						var object = new THREE.OBJLoader().parse( contents );
+
+						signals.objectAdded.dispatch( object );
+						signals.objectSelected.dispatch( object );
+
+						break;
+
+					case 'stl':
+
+						var geometry = new THREE.STLLoader().parse( contents );
+						var material = new THREE.MeshLambertMaterial();
+
+						var mesh = new THREE.Mesh( geometry, material );
+
+						signals.objectAdded.dispatch( mesh );
+						signals.objectSelected.dispatch( mesh );
+
+						break;
+
+					case 'utf8':
+
+						var geometry = new THREE.UTF8Loader().parse( contents );
+						var material = new THREE.MeshLambertMaterial();
+
+						var mesh = new THREE.Mesh( geometry, material );
+
+						signals.objectAdded.dispatch( mesh );
+						signals.objectSelected.dispatch( mesh );
+
+						break;
+
+					case 'vtk':
+
+						var geometry = new THREE.VTKLoader().parse( contents );
+						var material = new THREE.MeshLambertMaterial();
+
+						var mesh = new THREE.Mesh( geometry, material );
+
+						signals.objectAdded.dispatch( mesh );
+						signals.objectSelected.dispatch( mesh );
+
+						break;
+
+				}
+
+			}
+
+			/*
+
+			var geometry = new THREE.SphereGeometry( 75, 25, 15 );
+			var material = new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } );
+			var mesh = new THREE.Mesh( geometry, material );
+
+			signals.objectAdded.dispatch( mesh );
+			signals.objectSelected.dispatch( mesh );
+
+			*/
+
+			var onWindowResize = function ( event ) {
+
+				signals.windowResize.dispatch();
+
+			};
+
+			onWindowResize();
+
+			window.addEventListener( 'resize', onWindowResize, false );
+
+		</script>
+	</body>
+</html>

+ 132 - 12
gui/js/UI.js → editor/js/UI.js

@@ -256,7 +256,7 @@ UI.Text = function ( position ) {
 
 UI.Text.prototype = Object.create( UI.Element.prototype );
 
-UI.Text.prototype.setText = function ( value ) {
+UI.Text.prototype.setValue = function ( value ) {
 
 	this.dom.textContent = value;
 
@@ -264,6 +264,133 @@ UI.Text.prototype.setText = function ( value ) {
 
 };
 
+// Select
+
+UI.Select = function ( position ) {
+
+	UI.Element.call( this );
+
+	var scope = this;
+
+	this.dom = document.createElement( 'select' );
+	this.dom.style.position = position || 'relative';
+	this.dom.style.width = '64px';
+	this.dom.style.height = '16px';
+	this.dom.style.border = '0px';
+	this.dom.style.padding = '0px';
+
+	this.onChangeCallback = null;
+
+	this.dom.addEventListener( 'change', function ( event ) {
+
+		if ( scope.onChangeCallback ) scope.onChangeCallback();
+
+	}, false );
+
+	return this;
+
+};
+
+UI.Select.prototype = Object.create( UI.Element.prototype );
+
+UI.Select.prototype.setMultiple = function ( boolean ) {
+
+	this.dom.multiple = boolean;
+
+	return this;
+
+};
+
+UI.Select.prototype.setOptions = function ( options ) {
+
+	while ( this.dom.children.length > 0 ) {
+
+		this.dom.removeChild( this.dom.firstChild );
+
+	}
+
+	for ( var key in options ) {
+
+		var option = document.createElement( 'option' );
+		option.value = key;
+		option.innerHTML = options[ key ];
+		this.dom.appendChild( option );
+
+	}
+
+	return this;
+
+};
+
+UI.Select.prototype.getValue = function () {
+
+	return this.dom.value;
+
+};
+
+UI.Select.prototype.setValue = function ( value ) {
+
+	this.dom.value = value;
+
+	return this;
+
+};
+
+UI.Select.prototype.onChange = function ( callback ) {
+
+	this.onChangeCallback = callback;
+
+	return this;
+
+};
+
+// Checkbox
+
+UI.Checkbox = function ( position ) {
+
+	UI.Element.call( this );
+
+	var scope = this;
+
+	this.dom = document.createElement( 'input' );
+	this.dom.type = 'checkbox';
+	this.dom.style.position = position || 'relative';
+
+	this.onChangeCallback = null;
+
+	this.dom.addEventListener( 'change', function ( event ) {
+
+		if ( scope.onChangeCallback ) scope.onChangeCallback();
+
+	}, false );
+
+	return this;
+
+};
+
+UI.Checkbox.prototype = Object.create( UI.Element.prototype );
+
+UI.Checkbox.prototype.getValue = function () {
+
+	return this.dom.checked;
+
+};
+
+UI.Checkbox.prototype.setValue = function ( value ) {
+
+	this.dom.checked = value;
+
+	return this;
+
+};
+
+UI.Checkbox.prototype.onChange = function ( callback ) {
+
+	this.onChangeCallback = callback;
+
+	return this;
+
+};
 
 // Color
 
@@ -413,17 +540,10 @@ UI.Number.prototype.setValue = function ( value ) {
 
 };
 
-UI.Number.prototype.setMin = function ( value ) {
-
-	this.min = value;
-
-	return this;
-
-};
-
-UI.Number.prototype.setMax = function ( value ) {
+UI.Number.prototype.setRange = function ( min, max ) {
 
-	this.max = value;
+	this.min = min;
+	this.max = max;
 
 	return this;
 
@@ -493,7 +613,7 @@ UI.Button = function ( position ) {
 
 UI.Button.prototype = Object.create( UI.Element.prototype );
 
-UI.Button.prototype.setText = function ( value ) {
+UI.Button.prototype.setLabel = function ( value ) {
 
 	this.dom.textContent = value;
 

+ 0 - 0
gui/js/libs/signals.min.js → editor/js/libs/signals.min.js


+ 16 - 0
editor/js/ui/Menubar.js

@@ -0,0 +1,16 @@
+var Menubar = function ( signals ) {
+
+	var container = new UI.Panel( 'absolute' );
+	container.setBackgroundColor( '#eee' );
+
+	var options = new UI.Panel();
+	options.setMargin( '8px' );
+	options.add( new UI.Text().setValue( 'File' ).setColor( '#666' ).setMarginRight( '20px' ) );
+	options.add( new UI.Text().setValue( 'Edit' ).setColor( '#666' ).setMarginRight( '20px' ) );
+	options.add( new UI.Text().setValue( 'Add' ).setColor( '#666' ).setMarginRight( '20px' ) );
+	options.add( new UI.Text().setValue( 'Help' ).setColor( '#666' ).setMarginRight( '20px' ) );
+	container.add( options );
+
+	return container;
+
+}

+ 98 - 0
editor/js/ui/Sidebar.Outliner.js

@@ -0,0 +1,98 @@
+Sidebar.Outliner = function ( signals ) {
+
+	var objects = {
+
+		'PerspectiveCamera': THREE.PerspectiveCamera,
+		'PointLight': THREE.PointLight,
+		'DirectionalLight': THREE.DirectionalLight,
+		'Mesh': THREE.Mesh,
+		'Object3D': THREE.Object3D
+
+	};
+
+	var selected = null;
+
+	var container = new UI.Panel();
+	container.setPadding( '8px' );
+	container.setBorderTop( '1px solid #ccc' );
+
+	container.add( new UI.Text().setValue( 'SCENE' ).setColor( '#666' ) );
+	container.add( new UI.Break(), new UI.Break() );
+
+	var sceneGraph = new UI.Select().setMultiple( true ).setWidth( '100%' ).setHeight('140px').setColor( '#444' ).setFontSize( '12px' ).onChange( update );
+	container.add( sceneGraph );
+
+	container.add( new UI.Break(), new UI.Break() );
+
+	var scene = null;
+
+	function update() {
+
+		var id = parseInt( sceneGraph.getValue() );
+
+		for ( var i in scene.children ) {
+
+			var object = scene.children[ i ];
+
+			if ( object.id === id ) {
+
+				signals.objectSelected.dispatch( object );
+				return;
+
+			}
+
+		}
+
+	}
+
+	function getObjectInstanceName( object ) {
+
+		for ( var key in objects ) {
+
+			if ( object instanceof objects[ key ] ) return key;
+
+		}
+
+	}
+
+	// events
+
+	signals.sceneCreated.add( function ( object ) {
+
+		scene = object;
+
+	} );
+
+	signals.sceneChanged.add( function ( object ) {
+
+		scene = object;
+
+		var options = {};
+
+		( function createList( object, pad ) {
+
+			for ( var key in object.children ) {
+
+				var child = object.children[ key ];
+
+				options[ child.id ] = pad + '+ ' + object.name + ' [' + getObjectInstanceName( child ) + ']';
+
+				createList( child, pad + '&nbsp;&nbsp;&nbsp;' );
+
+			}
+
+		} )( scene, '' );
+
+		sceneGraph.setOptions( options );
+
+	} );
+
+	signals.objectSelected.add( function ( object ) {
+
+		sceneGraph.setValue( object !== null ? object.id: null );
+
+	} );
+
+	return container;
+
+}

+ 70 - 40
gui/js/ui/Sidebar.Properties.Geometry.js → editor/js/ui/Sidebar.Properties.Geometry.js

@@ -1,30 +1,74 @@
 Sidebar.Properties.Geometry = function ( signals ) {
 
+	var geometries = {
+
+		"ConvexGeometry": THREE.ConvexGeometry,
+		"CubeGeometry": THREE.CubeGeometry,
+		"CylinderGeometry": THREE.CylinderGeometry,
+		"ExtrudeGeometry": THREE.ExtrudeGeometry,
+		"IcosahedronGeometry": THREE.IcosahedronGeometry,
+		"LatheGeometry": THREE.LatheGeometry,
+		"OctahedronGeometry": THREE.OctahedronGeometry,
+		"ParametricGeometry": THREE.ParametricGeometry,
+		"PlaneGeometry": THREE.PlaneGeometry,
+		"PolyhedronGeometry": THREE.PolyhedronGeometry,
+		"SphereGeometry": THREE.SphereGeometry,
+		"TetrahedronGeometry": THREE.TetrahedronGeometry,
+		"TextGeometry": THREE.TextGeometry,
+		"TorusGeometry": THREE.TorusGeometry,
+		"TorusKnotGeometry": THREE.TorusKnotGeometry,
+		"TubeGeometry": THREE.TubeGeometry,
+		"Geometry": THREE.Geometry
+
+	};
+
 	var container = new UI.Panel();
 	container.setDisplay( 'none' );
 
-	container.add( new UI.Text().setText( 'GEOMETRY' ).setColor( '#666' ) );
-	container.add( new UI.Button( 'absolute' ).setRight( '0px' ).setText( 'Export' ).onClick( exportGeometry ) );
+	container.add( new UI.Text().setValue( 'GEOMETRY' ).setColor( '#666' ) );
+	container.add( new UI.Button( 'absolute' ).setRight( '0px' ).setLabel( 'Export' ).onClick( exportGeometry ) );
 	container.add( new UI.Break(), new UI.Break() );
 
-	container.add( new UI.Text().setText( 'Name' ).setColor( '#666' ) );
+	// name
+
+	var geometryNameRow = new UI.Panel();
 	var geometryName = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
-	container.add( geometryName );
-	container.add( new UI.HorizontalRule() );
 
-	container.add( new UI.Text().setText( 'Class' ).setColor( '#666' ) );
+	geometryNameRow.add( new UI.Text().setValue( 'Name' ).setColor( '#666' ) );
+	geometryNameRow.add( geometryName );
+
+	container.add( geometryNameRow );
+
+	// class
+
+	var geometryClassRow = new UI.Panel();
 	var geometryClass = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
-	container.add( geometryClass );
-	container.add( new UI.HorizontalRule() );
 
-	container.add( new UI.Text().setText( 'Vertices' ).setColor( '#666' ) );
-	var verticesCount = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
-	container.add( verticesCount );
-	container.add( new UI.HorizontalRule() );
+	geometryClassRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Class' ).setColor( '#666' ) );
+	geometryClassRow.add( geometryClass );
+
+	container.add( geometryClassRow );
+
+	// vertices
+
+	var geometryVerticesRow = new UI.Panel();
+	var geometryVertices = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
+
+	geometryVerticesRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Vertices' ).setColor( '#666' ) );
+	geometryVerticesRow.add( geometryVertices );
+
+	container.add( geometryVerticesRow );
+
+	// faces
+
+	var geometryFacesRow = new UI.Panel();
+	var geometryFaces = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
+
+	geometryFacesRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Faces' ).setColor( '#666' ) );
+	geometryFacesRow.add( geometryFaces );
+
+	container.add( geometryFacesRow );
 
-	container.add( new UI.Text().setText( 'Faces' ).setColor( '#666' ) );
-	var facesCount = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
-	container.add( facesCount );
 	container.add( new UI.Break(), new UI.Break(), new UI.Break() );
 
 	//
@@ -39,10 +83,10 @@ Sidebar.Properties.Geometry = function ( signals ) {
 
 			container.setDisplay( 'block' );
 
-			geometryName.setText( object.geometry.name );
-			geometryClass.setText( getGeometryInstanceName( object.geometry ) );
-			verticesCount.setText( object.geometry.vertices.length );
-			facesCount.setText( object.geometry.faces.length );
+			geometryName.setValue( object.geometry.name );
+			geometryClass.setValue( getGeometryInstanceName( object.geometry ) );
+			geometryVertices.setValue( object.geometry.vertices.length );
+			geometryFaces.setValue( object.geometry.faces.length );
 
 		} else {
 
@@ -56,25 +100,11 @@ Sidebar.Properties.Geometry = function ( signals ) {
 
 	function getGeometryInstanceName( geometry ) {
 
-		// TODO: Is there a way of doing this automatically?
-
-		if ( geometry instanceof THREE.ConvexGeometry ) return "ConvexGeometry";
-		if ( geometry instanceof THREE.CubeGeometry ) return "CubeGeometry";
-		if ( geometry instanceof THREE.CylinderGeometry ) return "CylinderGeometry";
-		if ( geometry instanceof THREE.ExtrudeGeometry ) return "ExtrudeGeometry";
-		if ( geometry instanceof THREE.IcosahedronGeometry ) return "IcosahedronGeometry";
-		if ( geometry instanceof THREE.LatheGeometry ) return "LatheGeometry";
-		if ( geometry instanceof THREE.OctahedronGeometry ) return "OctahedronGeometry";
-		if ( geometry instanceof THREE.ParametricGeometry ) return "ParametricGeometry";
-		if ( geometry instanceof THREE.PlaneGeometry ) return "PlaneGeometry";
-		if ( geometry instanceof THREE.PolyhedronGeometry ) return "PolyhedronGeometry";
-		if ( geometry instanceof THREE.SphereGeometry ) return "SphereGeometry";
-		if ( geometry instanceof THREE.TetrahedronGeometry ) return "TetrahedronGeometry";
-		if ( geometry instanceof THREE.TextGeometry ) return "TextGeometry";
-		if ( geometry instanceof THREE.TorusGeometry ) return "TorusGeometry";
-		if ( geometry instanceof THREE.TorusKnotGeometry ) return "TorusKnotGeometry";
-		if ( geometry instanceof THREE.TubeGeometry ) return "TubeGeometry";
-		if ( geometry instanceof THREE.Geometry ) return "Geometry";
+		for ( var key in geometries ) {
+
+			if ( geometry instanceof geometries[ key ] ) return key;
+
+		}
 
 	}
 
@@ -110,8 +140,8 @@ Sidebar.Properties.Geometry = function ( signals ) {
 			var hasFaceVertexColor = face.vertexColors[ 0 ] !== undefined;
 
 			var faceType = 0;
-			
-			faceType = setBit( faceType, 0, ! isTriangle );			
+
+			faceType = setBit( faceType, 0, ! isTriangle );
 			// faceType = setBit( faceType, 1, hasMaterial );
 			// faceType = setBit( faceType, 2, hasFaceUv );
 			// faceType = setBit( faceType, 3, hasFaceVertexUv );

+ 401 - 0
editor/js/ui/Sidebar.Properties.Material.js

@@ -0,0 +1,401 @@
+Sidebar.Properties.Material = function ( signals ) {
+
+	var materials = {
+
+		'LineBasicMaterial': THREE.LineBasicMaterial,
+		'MeshBasicMaterial': THREE.MeshBasicMaterial,
+		'MeshDepthMaterial': THREE.MeshDepthMaterial,
+		'MeshFaceMaterial': THREE.MeshFaceMaterial,
+		'MeshLambertMaterial': THREE.MeshLambertMaterial,
+		'MeshNormalMaterial': THREE.MeshNormalMaterial,
+		'MeshPhongMaterial': THREE.MeshPhongMaterial,
+		'ParticleBasicMaterial': THREE.ParticleBasicMaterial,
+		'ParticleCanvasMaterial': THREE.ParticleCanvasMaterial,
+		'ParticleDOMMaterial': THREE.ParticleDOMMaterial,
+		'ShaderMaterial': THREE.ShaderMaterial,
+		'Material': THREE.Material
+
+	};
+
+	var container = new UI.Panel();
+	container.setDisplay( 'none' );
+
+	container.add( new UI.Text().setValue( 'MATERIAL' ).setColor( '#666' ) );
+	container.add( new UI.Break(), new UI.Break() );
+
+	// name
+
+	var materialNameRow = new UI.Panel();
+	var materialName = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
+
+	materialNameRow.add( new UI.Text().setValue( 'Name' ).setColor( '#666' ) );
+	materialNameRow.add( materialName );
+
+	container.add( materialNameRow );
+
+	// class
+
+	var materialClassRow = new UI.Panel();
+	var materialClass = new UI.Select( 'absolute' ).setOptions( {
+
+		'LineBasicMaterial': 'LineBasicMaterial',
+		'MeshBasicMaterial': 'MeshBasicMaterial',
+		'MeshDepthMaterial': 'MeshDepthMaterial',
+		'MeshFaceMaterial': 'MeshFaceMaterial',
+		'MeshLambertMaterial': 'MeshLambertMaterial',
+		'MeshNormalMaterial': 'MeshNormalMaterial',
+		'MeshPhongMaterial': 'MeshPhongMaterial'
+
+	} ).setLeft( '90px' ).setWidth( '180px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( update );
+
+	materialClassRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Class' ).setColor( '#666' ) );
+	materialClassRow.add( materialClass );
+
+	container.add( materialClassRow );
+
+	// color
+
+	var materialColorRow = new UI.Panel();
+	var materialColor = new UI.Color( 'absolute' ).setLeft( '90px' ).onChange( update );
+
+	materialColorRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Color' ).setColor( '#666' ) );
+	materialColorRow.add( materialColor );
+
+	container.add( materialColorRow );
+
+	// ambient
+
+	var materialAmbientRow = new UI.Panel();
+	var materialAmbient = new UI.Color( 'absolute' ).setLeft( '90px' ).onChange( update );
+
+	materialAmbientRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Ambient' ).setColor( '#666' ) );
+	materialAmbientRow.add( materialAmbient );
+
+	container.add( materialAmbientRow );
+
+	// emissive
+
+	var materialEmissiveRow = new UI.Panel();
+	var materialEmissive = new UI.Color( 'absolute' ).setLeft( '90px' ).onChange( update );
+
+	materialEmissiveRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Emissive' ).setColor( '#666' ) );
+	materialEmissiveRow.add( materialEmissive );
+
+	container.add( materialEmissiveRow );
+
+	// specular
+
+	var materialSpecularRow = new UI.Panel();
+	var materialSpecular = new UI.Color( 'absolute' ).setLeft( '90px' ).onChange( update );
+
+	materialSpecularRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Specular' ).setColor( '#666' ) );
+	materialSpecularRow.add( materialSpecular );
+
+	container.add( materialSpecularRow );
+
+	// shininess
+
+	var materialShininessRow = new UI.Panel();
+	var materialShininess = new UI.Number( 'absolute' ).setValue( 30 ).setLeft( '90px' ).onChange( update );
+
+	materialShininessRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Shininess' ).setColor( '#666' ) );
+	materialShininessRow.add( materialShininess );
+
+	container.add( materialShininessRow );
+
+	// map
+
+	var materialMapRow = new UI.Panel();
+	var materialMap = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
+
+	materialMapRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Map' ).setColor( '#666' ) );
+	materialMapRow.add( materialMap );
+
+	container.add( materialMapRow );
+
+	// light map
+
+	var materialLightMapRow = new UI.Panel();
+	var materialLightMap = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
+
+	materialLightMapRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Light Map' ).setColor( '#666' ) );
+	materialLightMapRow.add( materialLightMap );
+
+	container.add( materialLightMapRow );
+
+	// bump map
+
+	var materialBumpMapRow = new UI.Panel();
+	var materialBumpMap = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
+
+	materialBumpMapRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Bump Map' ).setColor( '#666' ) );
+	materialBumpMapRow.add( materialBumpMap );
+
+	container.add( materialBumpMapRow );
+
+	// normal map
+
+	var materialNormalMapRow = new UI.Panel();
+	var materialNormalMap = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
+
+	materialNormalMapRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Normal Map' ).setColor( '#666' ) );
+	materialNormalMapRow.add( materialNormalMap );
+
+	container.add( materialNormalMapRow );
+
+	// specular map
+
+	var materialSpecularMapRow = new UI.Panel();
+	var materialSpecularMap = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
+
+	materialSpecularMapRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Specular Map' ).setColor( '#666' ) );
+	materialSpecularMapRow.add( materialSpecularMap );
+
+	container.add( materialSpecularMapRow );
+
+	// env map
+
+	var materialEnvMapRow = new UI.Panel();
+	var materialEnvMap = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' ).setFontSize( '12px' );
+
+	materialEnvMapRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Env Map' ).setColor( '#666' ) );
+	materialEnvMapRow.add( materialEnvMap );
+
+	container.add( materialEnvMapRow );
+
+	// opacity
+
+	var materialOpacityRow = new UI.Panel();
+	var materialOpacity = new UI.Number( 'absolute' ).setLeft( '90px' ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update );
+
+	materialOpacityRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Opacity' ).setColor( '#666' ) );
+	materialOpacityRow.add( materialOpacity );
+
+	container.add( materialOpacityRow );
+
+	// transparent
+
+	var materialTransparentRow = new UI.Panel();
+	var materialTransparent = new UI.Checkbox( 'absolute' ).setValue( false ).setLeft( '90px' ).onChange( update );
+
+	materialTransparentRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Transparent' ).setColor( '#666' ) );
+	materialTransparentRow.add( materialTransparent );
+
+	container.add( materialTransparentRow );
+
+	// wireframe
+
+	var materialWireframeRow = new UI.Panel();
+	var materialWireframe = new UI.Checkbox( 'absolute' ).setValue( false ).setLeft( '90px' ).onChange( update );
+	var materialWireframeLinewidth = new UI.Number( 'absolute' ).setValue( 1 ).setLeft( '120px' ).setRange( 0, 100 ).onChange( update );
+
+	materialWireframeRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Wireframe' ).setColor( '#666' ) );
+	materialWireframeRow.add( materialWireframe );
+	materialWireframeRow.add( materialWireframeLinewidth );
+
+	container.add( materialWireframeRow );
+
+
+
+	//
+
+	var selected = null;
+
+	function update() {
+
+		var material = selected.material;
+
+		if ( material ) {
+
+			if ( material instanceof materials[ materialClass.getValue() ] == false ) {
+
+				material = new materials[ materialClass.getValue() ]();
+				selected.material = material;
+
+			}
+
+			if ( material.color !== undefined ) {
+
+				material.color.setHex( parseInt( materialColor.getValue().substr( 1 ), 16 ) );
+
+			}
+
+			if ( material.ambient !== undefined ) {
+
+				material.ambient.setHex( parseInt( materialAmbient.getValue().substr( 1 ), 16 ) );
+
+			}
+
+			if ( material.emissive !== undefined ) {
+
+				material.emissive.setHex( parseInt( materialEmissive.getValue().substr( 1 ), 16 ) );
+
+			}
+
+			if ( material.specular !== undefined ) {
+
+				material.specular.setHex( parseInt( materialSpecular.getValue().substr( 1 ), 16 ) );
+
+			}
+
+			if ( material.shininess !== undefined ) {
+
+				material.shininess = materialShininess.getValue();
+
+			}
+
+			if ( material.opacity !== undefined ) {
+
+				material.opacity = materialOpacity.getValue();
+
+			}
+
+			if ( material.transparent !== undefined ) {
+
+				material.transparent = materialTransparent.getValue();
+
+			}
+
+			if ( material.wireframe !== undefined ) {
+
+				material.wireframe = materialWireframe.getValue();
+
+			}
+
+			if ( material.wireframeLinewidth !== undefined ) {
+
+				material.wireframeLinewidth = materialWireframeLinewidth.getValue();
+
+			}
+
+			updateRows();
+
+			signals.materialChanged.dispatch( material );
+
+		}
+
+	};
+
+	function updateRows() {
+
+		var material = selected.material;
+
+		materialColorRow.setDisplay( material.color !== undefined ? '' : 'none' );
+		materialAmbientRow.setDisplay( material.ambient !== undefined ? '' : 'none' );
+		materialEmissiveRow.setDisplay( material.emissive !== undefined ? '' : 'none' );
+		materialSpecularRow.setDisplay( material.specular !== undefined ? '' : 'none' );
+		materialShininessRow.setDisplay( material.shininess !== undefined ? '' : 'none' );
+		materialMapRow.setDisplay( material.map !== undefined ? '' : 'none' );
+		materialLightMapRow.setDisplay( material.lightMap !== undefined ? '' : 'none' );
+		materialBumpMapRow.setDisplay( material.bumpMap !== undefined ? '' : 'none' );
+		materialNormalMapRow.setDisplay( material.normalMap !== undefined ? '' : 'none' );
+		materialSpecularMapRow.setDisplay( material.specularMap !== undefined ? '' : 'none' );
+		materialEnvMapRow.setDisplay( material.envMap !== undefined ? '' : 'none' );
+		materialOpacityRow.setDisplay( material.opacity !== undefined ? '' : 'none' );
+		materialTransparentRow.setDisplay( material.transparent !== undefined ? '' : 'none' );
+		materialWireframeRow.setDisplay( material.wireframe !== undefined ? '' : 'none' );
+
+	};
+
+	function getMaterialInstanceName( material ) {
+
+		for ( var key in materials ) {
+
+			if ( material instanceof materials[ key ] ) return key;
+
+		}
+
+	}
+
+	// events
+
+	signals.objectSelected.add( function ( object ) {
+
+		if ( object && object.material ) {
+
+			selected = object;
+
+			container.setDisplay( '' );
+
+			var material = object.material;
+
+			materialName.setValue( material.name );
+			materialClass.setValue( getMaterialInstanceName( material ) );
+
+			if ( material.color !== undefined ) {
+
+				materialColor.setValue( '#' + material.color.getHex().toString( 16 ) );
+
+			}
+
+			if ( material.ambient !== undefined ) {
+
+				materialAmbient.setValue( '#' + material.ambient.getHex().toString( 16 ) );
+
+			}
+
+			if ( material.emissive !== undefined ) {
+
+				materialEmissive.setValue( '#' + material.emissive.getHex().toString( 16 ) );
+
+			}
+
+			if ( material.specular !== undefined ) {
+
+				materialSpecular.setValue( '#' + material.specular.getHex().toString( 16 ) );
+
+			}
+
+			if ( material.shininess !== undefined ) {
+
+				materialShininess.setValue( material.shininess );
+
+			}
+
+			/*
+			if ( material.map !== undefined ) {
+
+				materialMap.setValue( material.map );
+
+			}
+			*/
+
+			if ( material.opacity !== undefined ) {
+
+				materialOpacity.setValue( material.opacity );
+
+			}
+
+			if ( material.transparent !== undefined ) {
+
+				materialTransparent.setValue( material.transparent );
+
+			}
+
+			if ( material.wireframe !== undefined ) {
+
+				materialWireframe.setValue( material.wireframe );
+
+			}
+
+			if ( material.wireframeLinewidth !== undefined ) {
+
+				materialWireframeLinewidth.setValue( material.wireframeLinewidth );
+
+			}
+
+			updateRows();
+
+		} else {
+
+			selected = null;
+
+			container.setDisplay( 'none' );
+
+		}
+
+	} );
+
+	return container;
+
+}

+ 154 - 0
editor/js/ui/Sidebar.Properties.Object3D.js

@@ -0,0 +1,154 @@
+Sidebar.Properties.Object3D = function ( signals ) {
+
+	var objects = {
+
+		'PerspectiveCamera': THREE.PerspectiveCamera,
+		'PointLight': THREE.PointLight,
+		'DirectionalLight': THREE.DirectionalLight,
+		'Mesh': THREE.Mesh,
+		'Object3D': THREE.Object3D
+
+	};
+
+	var container = new UI.Panel();
+	container.setDisplay( 'none' );
+
+	var objectType = new UI.Text().setColor( '#666' );
+	container.add( objectType );
+	container.add( new UI.Break(), new UI.Break() );
+
+	// name
+
+	var objectNameRow = new UI.Panel();
+	var objectName = new UI.Text( 'absolute' ).setLeft( '90px' ).setColor( '#444' );
+
+	objectNameRow.add( new UI.Text().setValue( 'Name' ).setColor( '#666' ) );
+	objectNameRow.add( objectName );
+
+	container.add( objectNameRow );
+
+	// position
+
+	var objectPositionRow = new UI.Panel();
+	var objectPositionX = new UI.Number( 'absolute' ).setLeft( '90px' ).setWidth( '50px' ).onChange( update );
+	var objectPositionY = new UI.Number( 'absolute' ).setLeft( '150px' ).setWidth( '50px' ).onChange( update );
+	var objectPositionZ = new UI.Number( 'absolute' ).setLeft( '210px' ).setWidth( '50px' ).onChange( update );
+
+	objectPositionRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Position' ).setColor( '#666' ) );
+	objectPositionRow.add( objectPositionX, objectPositionY, objectPositionZ );
+
+	container.add( objectPositionRow );
+
+	// rotation
+
+	var objectRotationRow = new UI.Panel();
+	var objectRotationX = new UI.Number( 'absolute' ).setLeft( '90px' ).setWidth( '50px' ).onChange( update );
+	var objectRotationY = new UI.Number( 'absolute' ).setLeft( '150px' ).setWidth( '50px' ).onChange( update );
+	var objectRotationZ = new UI.Number( 'absolute' ).setLeft( '210px' ).setWidth( '50px' ).onChange( update );
+
+	objectRotationRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Rotation' ).setColor( '#666' ) );
+	objectRotationRow.add( objectRotationX, objectRotationY, objectRotationZ );
+
+	container.add( objectRotationRow );
+
+	// scale
+
+	var objectScaleRow = new UI.Panel();
+	var objectScaleX = new UI.Number( 'absolute' ).setValue( 1 ).setLeft( '90px' ).setWidth( '50px' ).onChange( update );
+	var objectScaleY = new UI.Number( 'absolute' ).setValue( 1 ).setLeft( '150px' ).setWidth( '50px' ).onChange( update );
+	var objectScaleZ = new UI.Number( 'absolute' ).setValue( 1 ).setLeft( '210px' ).setWidth( '50px' ).onChange( update );
+
+	objectScaleRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Scale' ).setColor( '#666' ) );
+	objectScaleRow.add( objectScaleX, objectScaleY, objectScaleZ );
+
+	container.add( objectScaleRow );
+
+	// visible
+
+	var objectVisibleRow = new UI.Panel();
+	var objectVisible = new UI.Checkbox( 'absolute' ).setLeft( '90px' ).onChange( update );
+
+	objectVisibleRow.add( new UI.HorizontalRule(), new UI.Text().setValue( 'Visible' ).setColor( '#666' ) );
+	objectVisibleRow.add( objectVisible );
+
+	container.add( objectVisibleRow );
+
+	container.add( new UI.Break(), new UI.Break() );
+
+	//
+
+	var selected = null;
+
+	function update() {
+
+		if ( selected ) {
+
+			selected.position.x = objectPositionX.getValue();
+			selected.position.y = objectPositionY.getValue();
+			selected.position.z = objectPositionZ.getValue();
+
+			selected.rotation.x = objectRotationX.getValue();
+			selected.rotation.y = objectRotationY.getValue();
+			selected.rotation.z = objectRotationZ.getValue();
+
+			selected.scale.x = objectScaleX.getValue();
+			selected.scale.y = objectScaleY.getValue();
+			selected.scale.z = objectScaleZ.getValue();
+
+			selected.visible = objectVisible.getValue();
+
+			signals.objectChanged.dispatch( selected );
+
+		}
+
+	}
+
+	function getObjectInstanceName( object ) {
+
+		for ( var key in objects ) {
+
+			if ( object instanceof objects[ key ] ) return key;
+
+		}
+
+	}
+
+	// events
+
+	signals.objectSelected.add( function ( object ) {
+
+		selected = object;
+
+		if ( object ) {
+
+			container.setDisplay( 'block' );
+
+			objectType.setValue( getObjectInstanceName( object ).toUpperCase() );
+
+			objectName.setValue( object.name );
+
+			objectPositionX.setValue( object.position.x );
+			objectPositionY.setValue( object.position.y );
+			objectPositionZ.setValue( object.position.z );
+
+			objectRotationX.setValue( object.rotation.x );
+			objectRotationY.setValue( object.rotation.y );
+			objectRotationZ.setValue( object.rotation.z );
+
+			objectScaleX.setValue( object.scale.x );
+			objectScaleY.setValue( object.scale.y );
+			objectScaleZ.setValue( object.scale.z );
+
+			objectVisible.setValue( object.visible );
+
+		} else {
+
+			container.setDisplay( 'none' );
+
+		}
+
+	} );
+
+	return container;
+
+}

+ 0 - 0
gui/js/ui/Sidebar.Properties.js → editor/js/ui/Sidebar.Properties.js


+ 0 - 0
gui/js/ui/Sidebar.js → editor/js/ui/Sidebar.js


+ 11 - 13
gui/js/ui/Viewport.js → editor/js/ui/Viewport.js

@@ -46,7 +46,6 @@ var Viewport = function ( signals ) {
 	camera.lookAt( scene.position );
 	scene.add( camera );
 
-	/*
 	var controls = new THREE.TrackballControls( camera, container.dom );
 	controls.rotateSpeed = 1.0;
 	controls.zoomSpeed = 1.2;
@@ -56,10 +55,11 @@ var Viewport = function ( signals ) {
 	controls.staticMoving = true;
 	controls.dynamicDampingFactor = 0.3;
 	controls.addEventListener( 'change', render );
-	*/
 
+	/*
 	var controls = new THREE.OrbitControls( camera, container.dom );
 	controls.addEventListener( 'change', render );
+	*/
 
 	var light = new THREE.DirectionalLight( 0xffffff );
 	light.position.set( 1, 0.5, 0 ).normalize();
@@ -69,6 +69,7 @@ var Viewport = function ( signals ) {
 	light.position.set( - 1, - 0.5, 0 ).normalize();
 	scene.add( light );
 
+	signals.sceneChanged.dispatch( scene );
 
 	// object picking
 
@@ -86,7 +87,7 @@ var Viewport = function ( signals ) {
 		projector.unprojectVector( vector, camera );
 
 		var ray = new THREE.Ray( camera.position, vector.subSelf( camera.position ).normalize() );
-		var intersects = ray.intersectObjects( objects );
+		var intersects = ray.intersectObjects( objects, true );
 
 		if ( intersects.length ) {
 
@@ -117,26 +118,23 @@ var Viewport = function ( signals ) {
 		scene.add( object );
 		render();
 
+		signals.sceneChanged.dispatch( scene );
+
 	} );
 
 	signals.objectChanged.add( function ( object ) {
 
-		object.updateMatrix();
-		object.updateMatrixWorld();
-
-		selectionBox.matrixWorld.copy( object.matrixWorld );
-
 		render();
 
 	} );
 
-	signals.objectSelected.add( function ( object ) {
+	var selected = null;
 
-		if ( object === null ) {
+	signals.objectSelected.add( function ( object ) {
 
-			selectionBox.visible = false;
+		selectionBox.visible = false;
 
-		} else if ( object.geometry ) {
+		if ( object !== null && object.geometry ) {
 
 			var geometry = object.geometry;
 
@@ -182,7 +180,7 @@ var Viewport = function ( signals ) {
 
 			selectionBox.geometry.verticesNeedUpdate = true;
 
-			selectionBox.matrixWorld.copy( object.matrixWorld );
+			selectionBox.matrixWorld = object.matrixWorld;
 
 			selectionBox.visible = true;
 

+ 1 - 1
examples/canvas_materials_depth.html

@@ -71,7 +71,7 @@
 				// Cubes
 
 				geometry = new THREE.CubeGeometry( 100, 100, 100 );
-				material = new THREE.MeshDepthMaterial( { near: 1, far: 2000, overdraw: true } );
+				material = new THREE.MeshDepthMaterial( { overdraw: true } );
 
 				for ( var i = 0; i < 20; i ++ ) {
 

+ 73 - 115
examples/js/Cloth.js

@@ -1,26 +1,5 @@
 /*
- * Aug 3 2012
- *
- * Since I started working for a new startup not too long ago,
- * I commute between home and work for over 2 hours a day.
- * Although this means less time on three.js,
- * I try getting a little coding on the train.
- *
- * This set of experiments started from a simple hook's law doodle,
- * to spring simulation, string simulation, and I realized
- * I once again stepped onto physics and particle simulation, 
- * this time, more specifically soft body physics.
- *
- * Based on the "Advanced Character Physics" article,
- * this experiment attempts to use a "massless"
- * cloth simulation model. It's somewhat similiar 
- * but simplier to most cloth simulations I found.
- *
- * This was coded out fairly quickly, so expect more to come
- * meanwhile feel free to experiment yourself and share
- *
- * Cheers,
- * Graphics Noob (aka @Blurspline, zz85)
+ * Cloth Simulation using a relaxed constrains solver
  */
 
 // Suggested Readings
@@ -31,14 +10,56 @@
 // http://cg.alexandra.dk/tag/spring-mass-system/
 // Real-time Cloth Animation http://www.darwin3d.com/gamedev/articles/col0599.pdf
 
-var DAMPING = 0.01;
+var DAMPING = 0.03;
 var DRAG = 1 - DAMPING;
 var MASS = .1;
-var restDistance = 25; //
+var restDistance = 25;
+
+
+var xSegs = 10; //
+var ySegs = 10; //
+
+var clothFunction = plane(restDistance * xSegs, restDistance * ySegs);
+
+var cloth = new Cloth(xSegs, ySegs);
+
+var GRAVITY = 981 * 1.4; // 
+var gravity = new THREE.Vector3( 0, -GRAVITY, 0 ).multiplyScalar(MASS);
+
+
+var TIMESTEP = 18 / 1000;
+var TIMESTEP_SQ = TIMESTEP * TIMESTEP;
+
+var pins = [];
+
+
+var wind = true;
+var windStrength = 2;
+var windForce = new THREE.Vector3(0,0,0);
+
+var ballPosition = new THREE.Vector3(0, -45, 0);
+var ballSize = 60; //40
+
+var tmpForce = new THREE.Vector3();
+
+var lastTime;
+
+
+function plane(width, height) {
+
+	return function(u, v) {
+		var x = (u-0.5) * width;
+		var y = (v+0.5) * height;
+		var z = 0;
+
+		return new THREE.Vector3(x, y, z);
+	};
+}
 
 function Particle(x, y, z, mass) {
-	this.position = new THREE.Vector3(x, y, z); // position
-	this.previous = new THREE.Vector3(x, y, z); // previous
+	this.position = clothFunction(x, y); // position
+	this.previous = clothFunction(x, y); // previous
+	this.original = clothFunction(x, y); 
 	this.a = new THREE.Vector3(0, 0, 0); // acceleration
 	this.mass = mass;
 	this.invMass = 1 / mass;
@@ -78,12 +99,6 @@ function satisifyConstrains(p1, p2, distance) {
 	var correctionHalf = correction.multiplyScalar(0.5);
 	p1.position.addSelf(correctionHalf);
 	p2.position.subSelf(correctionHalf);
-
-	// float difference = (restingDistance - d) / d
-	// im1 = 1 / p1.mass // inverse mass quantities
-	// im2 = 1 / p2.mass
-	// p1.position += delta * (im1 / (im1 + im2)) * stiffness * difference
-
 }
 
 
@@ -102,7 +117,7 @@ function Cloth(w, h) {
 	for (v=0;v<=h;v++) {
 		for (u=0;u<=w;u++) {
 			particles.push(
-				new Particle((u - w/2) * restDistance, (v - h/2) * -restDistance, 0, MASS)
+				new Particle(u/w, v/h, 0, MASS)
 			);
 		}
 	}
@@ -148,7 +163,7 @@ function Cloth(w, h) {
 	// While many system uses shear and bend springs,
 	// the relax constrains model seem to be just fine
 	// using structural springs.
-	// // Shear
+	// Shear
 	// var diagonalDist = Math.sqrt(restDistance * restDistance * 2);
 
 
@@ -171,54 +186,6 @@ function Cloth(w, h) {
 	// }
 
 
-	// // Bend
-
-	// var wlen = restDistance * 2;
-	// var hlen = restDistance * 2;
-	// diagonalDist = Math.sqrt(wlen * wlen + hlen * hlen);
-
-	// for (v=0;v<h-1;v++) {
-	// 	for (u=0;u<w-1;u++) {
-	// 		constrains.push([
-	// 			particles[index(u, v)],
-	// 			particles[index(u+2, v)],
-	// 			wlen
-	// 		]);
-
-	// 		constrains.push([
-	// 			particles[index(u, v)],
-	// 			particles[index(u, v+2)],
-	// 			hlen
-	// 		]);
-
-	// 		constrains.push([
-	// 			particles[index(u, v)],
-	// 			particles[index(u+2, v+2)],
-	// 			diagonalDist
-	// 		]);
-
-	// 		constrains.push([
-	// 			particles[index(u, v+2)],
-	// 			particles[index(u+2, v+2)],
-	// 			wlen
-	// 		]);
-
-	// 		constrains.push([
-	// 			particles[index(u+2, v+2)],
-	// 			particles[index(u+2, v+2)],
-	// 			hlen
-	// 		]);
-
-	// 		constrains.push([
-	// 			particles[index(u+2, v)],
-	// 			particles[index(u, v+2)],
-	// 			diagonalDist
-	// 		]);
-
-	// 	}
-	// }
-
-
 	this.particles = particles;
 	this.constrains = constrains;
 
@@ -226,32 +193,15 @@ function Cloth(w, h) {
 		return u + v * (w + 1);
 	}
 
+	this.index = index;
 
 }
 
-var cloth = new Cloth();
-
-var GRAVITY = 981; // 
-var gravity = new THREE.Vector3( 0, -GRAVITY, 0 ).multiplyScalar(MASS);
-
-
-var TIMESTEP = 14 / 1000;
-var TIMESTEP_SQ = TIMESTEP * TIMESTEP;
-
-var pins = [true];
-pins[cloth.w] = true;
-
-
-var wind = true;
-var windStrength = 2;
-var windForce = new THREE.Vector3(0,0,0);
-
-var ballPosition = new THREE.Vector3(0, -45, 0);
-var ballSize = 60; //40
-
-var tmpForce = new THREE.Vector3();
-
-function simulate() {
+function simulate(time) {
+	if (!lastTime) {
+		lastTime = time;
+		return;
+	}
 	
 	var i, il, particles, particle, pt, constrains, constrain;
 
@@ -276,7 +226,7 @@ function simulate() {
 			;i<il;i++) {
 		particle = particles[i];
 		particle.addForce(gravity);
-		// particle.addForce(windForce);
+
 		particle.integrate(TIMESTEP_SQ);
 	}
 
@@ -292,8 +242,8 @@ function simulate() {
 	// Ball Constrains
 
 
-	ballPosition.z = -Math.sin(Date.now()/300) * 90 ; //+ 40;
-	ballPosition.x = Math.cos(Date.now()/200) * 70
+	ballPosition.z = -Math.sin(Date.now()/600) * 90 ; //+ 40;
+	ballPosition.x = Math.cos(Date.now()/400) * 70
 
 	if (sphere.visible)
 	for (particles = cloth.particles, i=0, il = particles.length
@@ -308,15 +258,23 @@ function simulate() {
 		}
 	}
 
-	// Pin Constrains
-
-	for (i=0, il=cloth.w;i<=il;i++) {
-		if (pins[i]) {
-			particle = particles[i];
-			particle.previous.set((i - cloth.w/2) * restDistance,  -cloth.h/2 * -restDistance, 0);
-			particle.position.copy(particle.previous);
+	// Floor Constains
+	for (particles = cloth.particles, i=0, il = particles.length
+			;i<il;i++) {
+		particle = particles[i];
+		pos = particle.position;
+		if (pos.y < -250) {
+			pos.y = -250;
 		}
 	}
 
+	// Pin Constrains
+	for (i=0, il=pins.length;i<il;i++) {
+		var xy = pins[i];
+		var p = particles[xy];
+		p.position.copy(p.original);
+		p.previous.copy(p.original);
+	}
+
 
 }

+ 27 - 27
examples/js/ShaderExtras.js

@@ -39,7 +39,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			tDiffuse: { type: "t", value: 0, texture: null },
+			tDiffuse: { type: "t", value: null },
 			opacity:  { type: "f", value: 1.0 }
 
 		},
@@ -86,7 +86,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			"tDiffuse" : 		{ type: "t", value: 0, texture: null },
+			"tDiffuse" : 		{ type: "t", value: null },
 			"uImageIncrement" : { type: "v2", value: new THREE.Vector2( 0.001953125, 0.0 ) },
 			"cKernel" : 		{ type: "fv1", value: [] }
 
@@ -165,7 +165,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			tDiffuse:   { type: "t", value: 0, texture: null },
+			tDiffuse:   { type: "t", value: null },
 			time: 	    { type: "f", value: 0.0 },
 			nIntensity: { type: "f", value: 0.5 },
 			sIntensity: { type: "f", value: 0.05 },
@@ -253,8 +253,8 @@ THREE.ShaderExtras = {
 
 	'bokeh'	: {
 
-	uniforms: { tColor:   { type: "t", value: 0, texture: null },
-				tDepth:   { type: "t", value: 1, texture: null },
+	uniforms: { tColor:   { type: "t", value: null },
+				tDepth:   { type: "t", value: null },
 				focus:    { type: "f", value: 1.0 },
 				aspect:   { type: "f", value: 1.0 },
 				aperture: { type: "f", value: 0.025 },
@@ -367,8 +367,8 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			tColor:   { type: "t", value: 0, texture: null },
-			tDepth:   { type: "t", value: 1, texture: null },
+			tColor:   { type: "t", value: null },
+			tDepth:   { type: "t", value: null },
 			focus:    { type: "f", value: 1.0 },
 			maxblur:  { type: "f", value: 1.0 }
 
@@ -424,7 +424,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			tDiffuse: { type: "t", value: 0, texture: null },
+			tDiffuse: { type: "t", value: null },
 			amount:   { type: "f", value: 1.0 }
 
 		},
@@ -477,7 +477,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			tDiffuse: { type: "t", value: 0, texture: null },
+			tDiffuse: { type: "t", value: null },
 			tSize:    { type: "v2", value: new THREE.Vector2( 256, 256 ) },
 			center:   { type: "v2", value: new THREE.Vector2( 0.5, 0.5 ) },
 			angle:	  { type: "f", value: 1.57 },
@@ -544,7 +544,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			tDiffuse: { type: "t", value: 0, texture: null },
+			tDiffuse: { type: "t", value: null },
 			offset:   { type: "f", value: 1.0 },
 			darkness: { type: "f", value: 1.0 }
 
@@ -606,7 +606,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			tDiffuse: { type: "t", value: 0, texture: null },
+			tDiffuse: { type: "t", value: null },
 			opacity:  { type: "f", value: 1.0 }
 
 		},
@@ -669,7 +669,7 @@ THREE.ShaderExtras = {
 
 		uniforms : {
 
-			"tDiffuse": 		{ type: "t", value: 0, texture: null },
+			"tDiffuse": 		{ type: "t", value: null },
 			"screenWidth": 		{ type: "f", value: 1024 },
 			"screenHeight": 	{ type: "f", value: 1024 },
 			"sampleDistance": 	{ type: "f", value: 0.94 },
@@ -764,7 +764,7 @@ THREE.ShaderExtras = {
 
 		uniforms : {
 
-			"texture": 	{ type: "t", value: 0, texture: null },
+			"texture": 	{ type: "t", value: null },
 			"delta": 	{ type: "v2", value:new THREE.Vector2( 1, 1 )  }
 
 		},
@@ -871,7 +871,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			"tDiffuse": { type: "t", value: 0, texture: null },
+			"tDiffuse": { type: "t", value: null },
 			"h": 		{ type: "f", value: 1.0 / 512.0 }
 
 		},
@@ -923,7 +923,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			"tDiffuse": { type: "t", value: 0, texture: null },
+			"tDiffuse": { type: "t", value: null },
 			"v": 		{ type: "f", value: 1.0 / 512.0 }
 
 		},
@@ -984,7 +984,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			"tDiffuse": { type: "t", value: 0, texture: null },
+			"tDiffuse": { type: "t", value: null },
 			"h": 		{ type: "f", value: 1.0 / 512.0 },
 			"r": 		{ type: "f", value: 0.35 }
 
@@ -1040,7 +1040,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			"tDiffuse": { type: "t", value: 0, texture: null },
+			"tDiffuse": { type: "t", value: null },
 			"v": 		{ type: "f", value: 1.0 / 512.0 },
 			"r": 		{ type: "f", value: 0.35 }
 
@@ -1100,8 +1100,8 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			tDiffuse1: { type: "t", value: 0, texture: null },
-			tDiffuse2: { type: "t", value: 1, texture: null },
+			tDiffuse1: { type: "t", value: null },
+			tDiffuse2: { type: "t", value: null },
 			mixRatio:  { type: "f", value: 0.5 },
 			opacity:   { type: "f", value: 1.0 }
 
@@ -1153,7 +1153,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			"tDiffuse": 	{ type: "t", value: 0, texture: null },
+			"tDiffuse": 	{ type: "t", value: null },
 			"resolution": 	{ type: "v2", value: new THREE.Vector2( 1 / 1024, 1 / 512 )  }
 
 		},
@@ -1249,7 +1249,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			"tDiffuse": 	{ type: "t", value: 0, texture: null }
+			"tDiffuse": 	{ type: "t", value: null }
 
 		},
 
@@ -1297,7 +1297,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			"tDiffuse" : 	{ type: "t", value: 0, texture: null },
+			"tDiffuse" : 	{ type: "t", value: null },
 			"powRGB" :		{ type: "v3", value: new THREE.Vector3( 2, 2, 2 ) },
 			"mulRGB" :		{ type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
 
@@ -1345,7 +1345,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			"heightMap"	: { type: "t", value: 0, texture: null },
+			"heightMap"	: { type: "t", value: null },
 			"resolution": { type: "v2", value: new THREE.Vector2( 512, 512 ) },
 			"scale"		: { type: "v2", value: new THREE.Vector2( 1, 1 ) },
 			"height"	: { type: "f", value: 0.05 }
@@ -1405,8 +1405,8 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			"tDiffuse": 	{ type: "t", value: 0, texture: null },
-			"tDepth":   	{ type: "t", value: 1, texture: null },
+			"tDiffuse": 	{ type: "t", value: null },
+			"tDepth":   	{ type: "t", value: null },
 			"size": 		{ type: "v2", value: new THREE.Vector2( 512, 512 ) },
 			"cameraNear":	{ type: "f", value: 1 },
 			"cameraFar":	{ type: "f", value: 100 },
@@ -1655,7 +1655,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			tDiffuse: { type: "t", value: 0, texture: null },
+			tDiffuse: { type: "t", value: null },
 			color:    { type: "c", value: new THREE.Color( 0xffffff ) }
 
 		},
@@ -1704,7 +1704,7 @@ THREE.ShaderExtras = {
 
 		uniforms: {
 
-			tDiffuse: { type: "t", value: 0, texture: null },
+			tDiffuse: { type: "t", value: null },
 			opacity:  { type: "f", value: 1.0 }
 
 		},

+ 3 - 6
examples/js/ShaderGodRays.js

@@ -45,8 +45,7 @@ THREE.ShaderGodRays = {
 
 			tInput: {
 				type: "t",
-				value: 0,
-				texture: null
+				value: null
 			},
 
 			fStepSize: {
@@ -148,14 +147,12 @@ THREE.ShaderGodRays = {
 
 			tColors: {
 				type: "t",
-				value: 0,
-				texture: null
+				value: null
 			},
 
 			tGodRays: {
 				type: "t",
-				value: 1,
-				texture: null
+				value: null
 			},
 
 			fGodRayIntensity: {

+ 58 - 12
examples/js/ShaderSkin.js

@@ -14,7 +14,7 @@ THREE.ShaderSkin = {
 	//		- diffuse map
 	//		- bump map
 	//		- specular map
-	//		- point and directional lights (use with "lights: true" material option)
+	//		- point, directional and hemisphere lights (use with "lights: true" material option)
 	//		- fog (use with "fog: true" material option)
 	//		- shadow maps
 	//
@@ -33,8 +33,8 @@ THREE.ShaderSkin = {
 			"enableBump"	: { type: "i", value: 0 },
 			"enableSpecular": { type: "i", value: 0 },
 
-			"tDiffuse"	: { type: "t", value: 0, texture: null },
-			"tBeckmann"	: { type: "t", value: 1, texture: null },
+			"tDiffuse"	: { type: "t", value: null },
+			"tBeckmann"	: { type: "t", value: null },
 
 			"uDiffuseColor":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
 			"uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) },
@@ -44,10 +44,10 @@ THREE.ShaderSkin = {
 			"uRoughness": 	  		{ type: "f", value: 0.15 },
 			"uSpecularBrightness": 	{ type: "f", value: 0.75 },
 
-			"bumpMap"	: { type: "t", value: 2, texture: null },
+			"bumpMap"	: { type: "t", value: null },
 			"bumpScale" : { type: "f", value: 1 },
 
-			"specularMap" : { type: "t", value: 3, texture: null },
+			"specularMap" : { type: "t", value: null },
 
 			"offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
 
@@ -92,6 +92,14 @@ THREE.ShaderSkin = {
 
 			"#endif",
 
+			"#if MAX_HEMI_LIGHTS > 0",
+
+				"uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
+				"uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
+				"uniform vec3 hemisphereLightPosition[ MAX_HEMI_LIGHTS ];",
+
+			"#endif",
+
 			"#if MAX_POINT_LIGHTS > 0",
 
 				"uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
@@ -239,6 +247,38 @@ THREE.ShaderSkin = {
 
 				"#endif",
 
+				// hemisphere lights
+
+				"#if MAX_HEMI_LIGHTS > 0",
+
+					"vec3 hemiTotal = vec3( 0.0 );",
+
+					"for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
+
+						"vec4 lPosition = viewMatrix * vec4( hemisphereLightPosition[ i ], 1.0 );",
+						"vec3 lVector = normalize( lPosition.xyz + vViewPosition.xyz );",
+
+						"float dotProduct = dot( normal, lVector );",
+						"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
+
+						"hemiTotal += uDiffuseColor * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
+
+						// specular (sky light)
+
+						"float hemiSpecularWeight = 0.0;",
+						"hemiSpecularWeight += KS_Skin_Specular( normal, lVector, viewPosition, uRoughness, uSpecularBrightness );",
+
+						// specular (ground light)
+
+						"vec3 lVectorGround = normalize( -lPosition.xyz + vViewPosition.xyz );",
+						"hemiSpecularWeight += KS_Skin_Specular( normal, lVectorGround, viewPosition, uRoughness, uSpecularBrightness );",
+
+						"specularTotal += uSpecularColor * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight ) * hemiSpecularWeight * specularStrength;",
+
+					"}",
+
+				"#endif",
+
 				// all lights contribution summation
 
 				"vec3 totalLight = vec3( 0.0 );",
@@ -251,6 +291,10 @@ THREE.ShaderSkin = {
 					"totalLight += pointTotal;",
 				"#endif",
 
+				"#if MAX_HEMI_LIGHTS > 0",
+					"totalLight += hemiTotal;",
+				"#endif",
+
 				"gl_FragColor.xyz = gl_FragColor.xyz * ( totalLight + ambientLightColor * uAmbientColor ) + specularTotal;",
 
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
@@ -275,6 +319,8 @@ THREE.ShaderSkin = {
 			"void main() {",
 
 				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+				"vec4 mPosition = modelMatrix * vec4( position, 1.0 );",
+
 				"vViewPosition = -mvPosition.xyz;",
 
 				"vNormal = normalMatrix * normal;",
@@ -317,15 +363,15 @@ THREE.ShaderSkin = {
 
 			"passID": { type: "i", value: 0 },
 
-			"tDiffuse"	: { type: "t", value: 0, texture: null },
-			"tNormal"	: { type: "t", value: 1, texture: null },
+			"tDiffuse"	: { type: "t", value: null },
+			"tNormal"	: { type: "t", value: null },
 
-			"tBlur1"	: { type: "t", value: 2, texture: null },
-			"tBlur2"	: { type: "t", value: 3, texture: null },
-			"tBlur3"	: { type: "t", value: 4, texture: null },
-			"tBlur4"	: { type: "t", value: 5, texture: null },
+			"tBlur1"	: { type: "t", value: null },
+			"tBlur2"	: { type: "t", value: null },
+			"tBlur3"	: { type: "t", value: null },
+			"tBlur4"	: { type: "t", value: null },
 
-			"tBeckmann"	: { type: "t", value: 6, texture: null },
+			"tBeckmann"	: { type: "t", value: null },
 
 			"uNormalScale": { type: "f", value: 1.0 },
 

+ 85 - 14
examples/js/ShaderTerrain.js

@@ -9,7 +9,8 @@ THREE.ShaderTerrain = {
 	//	Dynamic terrain shader
 	//		- Blinn-Phong
 	//		- height + normal + diffuse1 + diffuse2 + specular + detail maps
-	//		- point and directional lights (use with "lights: true" material option)
+	//		- point, directional and hemisphere lights (use with "lights: true" material option)
+	//		- shadow maps receiving
 	 ------------------------------------------------------------------------- */
 
 	'terrain' : {
@@ -18,6 +19,7 @@ THREE.ShaderTerrain = {
 
 			THREE.UniformsLib[ "fog" ],
 			THREE.UniformsLib[ "lights" ],
+			THREE.UniformsLib[ "shadowmap" ],
 
 			{
 
@@ -26,12 +28,12 @@ THREE.ShaderTerrain = {
 			"enableSpecular"  : { type: "i", value: 0 },
 			"enableReflection": { type: "i", value: 0 },
 
-			"tDiffuse1"	   : { type: "t", value: 0, texture: null },
-			"tDiffuse2"	   : { type: "t", value: 1, texture: null },
-			"tDetail"	   : { type: "t", value: 2, texture: null },
-			"tNormal"	   : { type: "t", value: 3, texture: null },
-			"tSpecular"	   : { type: "t", value: 4, texture: null },
-			"tDisplacement": { type: "t", value: 5, texture: null },
+			"tDiffuse1"	   : { type: "t", value: null },
+			"tDiffuse2"	   : { type: "t", value: null },
+			"tDetail"	   : { type: "t", value: null },
+			"tNormal"	   : { type: "t", value: null },
+			"tSpecular"	   : { type: "t", value: null },
+			"tDisplacement": { type: "t", value: null },
 
 			"uNormalScale": { type: "f", value: 1.0 },
 
@@ -87,18 +89,31 @@ THREE.ShaderTerrain = {
 			"uniform vec3 ambientLightColor;",
 
 			"#if MAX_DIR_LIGHTS > 0",
+
 				"uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
 				"uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
+
+			"#endif",
+
+			"#if MAX_HEMI_LIGHTS > 0",
+
+				"uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
+				"uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
+				"uniform vec3 hemisphereLightPosition[ MAX_HEMI_LIGHTS ];",
+
 			"#endif",
 
 			"#if MAX_POINT_LIGHTS > 0",
+
 				"uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
 				"uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
 				"uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
+
 			"#endif",
 
 			"varying vec3 vViewPosition;",
 
+			THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
 			THREE.ShaderChunk[ "fog_pars_fragment" ],
 
 			"void main() {",
@@ -206,6 +221,47 @@ THREE.ShaderTerrain = {
 
 				"#endif",
 
+				// hemisphere lights
+
+				"#if MAX_HEMI_LIGHTS > 0",
+
+					"vec3 hemiDiffuse  = vec3( 0.0 );",
+					"vec3 hemiSpecular = vec3( 0.0 );" ,
+
+					"for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
+
+						"vec4 lPosition = viewMatrix * vec4( hemisphereLightPosition[ i ], 1.0 );",
+						"vec3 lVector = normalize( lPosition.xyz + vViewPosition.xyz );",
+
+						// diffuse
+
+						"float dotProduct = dot( normal, lVector );",
+						"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
+
+						"hemiDiffuse += uDiffuseColor * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
+
+						// specular (sky light)
+
+						"float hemiSpecularWeight = 0.0;",
+
+						"vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );",
+						"float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;",
+						"hemiSpecularWeight += specularTex.r * max( pow( hemiDotNormalHalfSky, uShininess ), 0.0 );",
+
+						// specular (ground light)
+
+						"vec3 lVectorGround = normalize( -lPosition.xyz + vViewPosition.xyz );",
+
+						"vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );",
+						"float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
+						"hemiSpecularWeight += specularTex.r * max( pow( hemiDotNormalHalfGround, uShininess ), 0.0 );",
+
+						"hemiSpecular += uSpecularColor * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight ) * hemiSpecularWeight * hemiDiffuseWeight;",
+
+					"}",
+
+				"#endif",
+
 				// all lights contribution summation
 
 				"vec3 totalDiffuse = vec3( 0.0 );",
@@ -218,6 +274,13 @@ THREE.ShaderTerrain = {
 
 				"#endif",
 
+				"#if MAX_HEMI_LIGHTS > 0",
+
+					"totalDiffuse += hemiDiffuse;",
+					"totalSpecular += hemiSpecular;",
+
+				"#endif",
+
 				"#if MAX_POINT_LIGHTS > 0",
 
 					"totalDiffuse += pointDiffuse;",
@@ -228,6 +291,7 @@ THREE.ShaderTerrain = {
 				//"gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor) + totalSpecular;",
 				"gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor + totalSpecular );",
 
+				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
@@ -258,11 +322,9 @@ THREE.ShaderTerrain = {
 
 			"varying vec3 vViewPosition;",
 
-			"void main() {",
-
-				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+			THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
 
-				"vViewPosition = -mvPosition.xyz;",
+			"void main() {",
 
 				"vNormal = normalize( normalMatrix * normal );",
 
@@ -285,18 +347,27 @@ THREE.ShaderTerrain = {
 
 					"vec3 dv = texture2D( tDisplacement, uvBase ).xyz;",
 					"float df = uDisplacementScale * dv.x + uDisplacementBias;",
-					"vec4 displacedPosition = vec4( vNormal.xyz * df, 0.0 ) + mvPosition;",
-					"gl_Position = projectionMatrix * displacedPosition;",
+					"vec3 displacedPosition = normal * df + position;",
+
+					"vec4 mPosition = modelMatrix * vec4( displacedPosition, 1.0 );",
+					"vec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );",
 
 				"#else",
 
-					"gl_Position = projectionMatrix * mvPosition;",
+					"vec4 mPosition = modelMatrix * vec4( position, 1.0 );",
+					"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
 
 				"#endif",
 
+				"gl_Position = projectionMatrix * mvPosition;",
+
+				"vViewPosition = -mvPosition.xyz;",
+
 				"vec3 normalTex = texture2D( tNormal, uvBase ).xyz * 2.0 - 1.0;",
 				"vNormal = normalMatrix * normalTex;",
 
+				THREE.ShaderChunk[ "shadowmap_vertex" ],
+
 			"}"
 
 		].join("\n")

+ 4 - 4
examples/js/effects/AnaglyphEffect.js

@@ -32,8 +32,8 @@ THREE.AnaglyphEffect = function ( renderer ) {
 
 		uniforms: {
 
-			"mapLeft": { type: "t", value: 0, texture: _renderTargetL },
-			"mapRight": { type: "t", value: 1, texture: _renderTargetR }
+			"mapLeft": { type: "t", value: _renderTargetL },
+			"mapRight": { type: "t", value: _renderTargetR }
 
 		},
 
@@ -82,8 +82,8 @@ THREE.AnaglyphEffect = function ( renderer ) {
 		_renderTargetL = new THREE.WebGLRenderTarget( width, height, _params );
 		_renderTargetR = new THREE.WebGLRenderTarget( width, height, _params );
 
-		_material.uniforms[ "mapLeft" ].texture = _renderTargetL;
-		_material.uniforms[ "mapRight" ].texture = _renderTargetR;
+		_material.uniforms[ "mapLeft" ].value = _renderTargetL;
+		_material.uniforms[ "mapRight" ].value = _renderTargetR;
 
 		renderer.setSize( width, height );
 

+ 4 - 4
examples/js/effects/ParallaxBarrierEffect.js

@@ -32,8 +32,8 @@ THREE.ParallaxBarrierEffect = function ( renderer ) {
 
 		uniforms: {
 
-			"mapLeft": { type: "t", value: 0, texture: _renderTargetL },
-			"mapRight": { type: "t", value: 1, texture: _renderTargetR }
+			"mapLeft": { type: "t", value: _renderTargetL },
+			"mapRight": { type: "t", value: _renderTargetR }
 
 		},
 
@@ -84,8 +84,8 @@ THREE.ParallaxBarrierEffect = function ( renderer ) {
 		_renderTargetL = new THREE.WebGLRenderTarget( width, height, _params );
 		_renderTargetR = new THREE.WebGLRenderTarget( width, height, _params );
 
-		_material.uniforms[ "mapLeft" ].texture = _renderTargetL;
-		_material.uniforms[ "mapRight" ].texture = _renderTargetR;
+		_material.uniforms[ "mapLeft" ].value = _renderTargetL;
+		_material.uniforms[ "mapRight" ].value = _renderTargetR;
 
 		renderer.setSize( width, height );
 

+ 11 - 13
examples/js/loaders/ColladaLoader.js

@@ -60,21 +60,19 @@ THREE.ColladaLoader = function () {
 
 		if ( document.implementation && document.implementation.createDocument ) {
 
-			var req = new XMLHttpRequest();
+			var request = new XMLHttpRequest();
 
-			if ( req.overrideMimeType ) req.overrideMimeType( "text/xml" );
+			request.onreadystatechange = function() {
 
-			req.onreadystatechange = function() {
+				if( request.readyState == 4 ) {
 
-				if( req.readyState == 4 ) {
+					if( request.status == 0 || request.status == 200 ) {
 
-					if( req.status == 0 || req.status == 200 ) {
 
-
-						if ( req.responseXML ) {
+						if ( request.responseXML ) {
 
 							readyCallbackFunc = readyCallback;
-							parse( req.responseXML, undefined, url );
+							parse( request.responseXML, undefined, url );
 
 						} else {
 
@@ -84,17 +82,17 @@ THREE.ColladaLoader = function () {
 
 					}
 
-				} else if ( req.readyState == 3 ) {
+				} else if ( request.readyState == 3 ) {
 
 					if ( progressCallback ) {
 
 						if ( length == 0 ) {
 
-							length = req.getResponseHeader( "Content-Length" );
+							length = request.getResponseHeader( "Content-Length" );
 
 						}
 
-						progressCallback( { total: length, loaded: req.responseText.length } );
+						progressCallback( { total: length, loaded: request.responseText.length } );
 
 					}
 
@@ -102,8 +100,8 @@ THREE.ColladaLoader = function () {
 
 			}
 
-			req.open( "GET", url, true );
-			req.send( null );
+			request.open( "GET", url, true );
+			request.send( null );
 
 		} else {
 

+ 474 - 0
examples/js/loaders/MTLLoader.js

@@ -0,0 +1,474 @@
+/**
+ * Loads a Wavefront .mtl file specifying materials
+ *
+ * @author angelxuanchang
+ */
+
+THREE.MTLLoader = function( baseUrl, options ) {
+
+    THREE.EventTarget.call( this );
+    this.baseUrl = baseUrl;
+    this.options = options;
+
+};
+
+THREE.MTLLoader.prototype = {
+
+    /**
+     * Loads a MTL file
+     *
+     * Loading progress is indicated by the following events:
+     *   "load" event (successful loading): type = 'load', content = THREE.MTLLoader.MaterialCreator
+     *   "error" event (error loading): type = 'load', message
+     *   "progress" event (progress loading): type = 'progress', loaded, total
+     *
+     * @param url - location of MTL file
+     */
+    load: function( url ) {
+
+        var scope = this;
+        var xhr = new XMLHttpRequest();
+
+        function onloaded( event ) {
+
+            if ( event.target.status === 200 || event.target.status === 0 ) {
+
+                var materialCreator = scope.parse( event.target.responseText );
+
+                // Notify caller, that I'm done
+
+                scope.dispatchEvent( { type: 'load', content: materialCreator } );
+
+            } else {
+
+                scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']',
+                    response: event.target.responseText } );
+
+            }
+
+        }
+
+        xhr.addEventListener( 'load', onloaded, false );
+
+        xhr.addEventListener( 'progress', function ( event ) {
+
+            scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
+
+        }, false );
+
+        xhr.addEventListener( 'error', function () {
+
+            scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
+
+        }, false );
+
+        xhr.open( 'GET', url, true );
+        xhr.send( null );
+    },
+
+    /**
+     * Parses loaded MTL file
+     * @param text - Content of MTL file
+     * @return {THREE.MTLLoader.MaterialCreator}
+     */
+    parse: function( text ) {
+
+        var lines = text.split( "\n" );
+        var info = {};
+        var delimiter_pattern = /\s+/;
+        var materialsInfo = {};
+
+			for ( var i = 0; i < lines.length; i ++ ) {
+
+			var line = lines[ i ];
+            line = line.trim();
+
+            if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
+
+                // Blank line or comment ignore
+                continue;
+
+            }
+
+            var pos = line.indexOf( ' ' );
+
+			var key = ( pos >= 0 ) ? line.substring( 0, pos) : line;
+            key = key.toLowerCase();
+
+            var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : "";
+            value = value.trim();
+
+            if ( key === "newmtl" ) {
+
+                // New material
+
+                info = { name: value };
+                materialsInfo[ value ] = info;
+
+            } else if ( info ) {
+
+                if ( key === "ka" || key === "kd" || key === "ks" ) {
+
+                    var ss = value.split( delimiter_pattern, 3 );
+                    info[ key ] = [ parseFloat( ss[0] ), parseFloat( ss[1] ), parseFloat( ss[2] ) ];
+
+                } else {
+
+                    info[ key ] = value;
+
+                }
+
+            }
+
+        }
+
+        var materialCreator = new THREE.MTLLoader.MaterialCreator( this.baseUrl, this.options );
+        materialCreator.setMaterials( materialsInfo );
+        return materialCreator;
+
+    }
+
+};
+
+/**
+ * Create a new THREE-MTLLoader.MaterialCreator
+ * @param baseUrl - Url relative to which textures are loaded
+ * @param options - Set of options on how to construct the materials
+ *                  side: Which side to apply the material
+ *                        THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
+ *                  wrap: What type of wrapping to apply for textures
+ *                        THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
+ *                  normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
+ *                                Default: false, assumed to be already normalized
+ *                  ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
+ *                                  Default: false
+ *                  invertTransparency: If transparency need to be inverted (inversion is needed if d = 0 is fully opaque)
+ *                                      Default: false (d = 1 is fully opaque)
+ * @constructor
+ */
+THREE.MTLLoader.MaterialCreator = function( baseUrl, options ) {
+
+    THREE.EventTarget.call( this );
+    this.baseUrl = baseUrl;
+    this.options = options;
+    this.materialsInfo = {};
+    this.materials = {};
+    this.materialsArray = [];
+    this.nameLookup = {};
+
+    this.side = ( this.options && this.options.side )? this.options.side: THREE.FrontSide;
+    this.wrap = ( this.options && this.options.wrap )? this.options.wrap: THREE.RepeatWrapping;
+
+};
+
+THREE.MTLLoader.MaterialCreator.prototype = {
+
+    setMaterials: function( materialsInfo ) {
+
+        this.materialsInfo = this.convert( materialsInfo );
+        this.materials = {};
+        this.materialsArray = [];
+        this.nameLookup = {};
+
+    },
+
+    convert: function( materialsInfo ) {
+
+        if ( !this.options ) return materialsInfo;
+
+        var converted = {};
+
+        for ( var mn in materialsInfo ) {
+
+            // Convert materials info into normalized form based on options
+
+            var mat = materialsInfo[ mn ];
+
+            var covmat = {};
+
+            converted[ mn ] = covmat;
+
+            for ( var prop in mat ) {
+
+                var save = true;
+                var value = mat[ prop ];
+                var lprop = prop.toLowerCase();
+
+                switch ( lprop ) {
+
+                    case 'kd':
+                    case 'ka':
+                    case 'ks':
+
+                        // Diffuse color (color under white light) using RGB values
+
+                        if ( this.options && this.options.normalizeRGB ) {
+
+                            value =  [ value[0]/255, value[1]/255, value[2]/255 ];
+
+                        }
+
+                        if ( this.options && this.options.ignoreZeroRGBs ) {
+
+                            if ( value[0] === 0.0 && value[1] === 0.0 && value[1] === 0.0 ) {
+
+                                // ignore
+
+                                save = false;
+
+                            }
+                        }
+
+                        break;
+
+                    case 'd':
+
+                        // According to MTL format (http://paulbourke.net/dataformats/mtl/):
+                        //   d is dissolve for current material
+                        //   factor of 1.0 is fully opaque, a factor of 0 is fully dissolved (completely transparent)
+
+                        if ( this.options && this.options.invertTransparency ) {
+
+                            value = 1 - value;
+
+                        }
+
+                        break;
+
+                    default:
+
+                        break;
+                }
+
+                if ( save ) {
+
+                    covmat[lprop] = value;
+
+                }
+
+            }
+
+        }
+
+        return converted;
+
+    },
+
+    preload: function () {
+
+        for ( var mn in this.materialsInfo ) {
+
+            this.create( mn );
+
+        }
+
+    },
+
+    getIndex: function( materialName ) {
+
+        return this.nameLookup[ materialName ];
+
+    },
+
+    getAsArray: function() {
+
+        var index = 0;
+
+        for ( var mn in this.materialsInfo ) {
+
+            this.materialsArray[ index ] = this.create( mn );
+            this.nameLookup[ mn ] = index;
+            index ++;
+
+        }
+
+        return this.materialsArray;
+
+    },
+
+    create: function ( materialName ) {
+
+        if ( this.materials[ materialName ] === undefined ) {
+
+            this.createMaterial_( materialName );
+
+        }
+
+        return this.materials[ materialName ];
+
+    },
+
+    createMaterial_: function ( materialName ) {
+
+        // Create material
+
+        var mat = this.materialsInfo[ materialName ];
+        var params = {
+
+            name: materialName,
+            side: this.side
+
+        };
+
+        for ( var prop in mat ) {
+
+            var value = mat[ prop ];
+
+            switch ( prop.toLowerCase() ) {
+
+                // Ns is material specular exponent
+
+                case 'kd':
+
+					// Diffuse color (color under white light) using RGB values
+
+					params[ 'diffuse' ] = new THREE.Color().setRGB( value[0], value[1], value[2] );
+
+					break;
+
+                case 'ka':
+
+                    // Ambient color (color under shadow) using RGB values
+
+                    params[ 'ambient' ] = new THREE.Color().setRGB( value[0], value[1], value[2] );
+
+					break;
+
+                case 'ks':
+
+                    // Specular color (color when light is reflected from shiny surface) using RGB values
+                    params[ 'specular' ] = new THREE.Color().setRGB( value[0], value[1], value[2] );
+
+                    break;
+
+                case 'map_kd':
+
+                    // Diffuse texture map
+
+                    params[ 'map' ] = THREE.MTLLoader.loadTexture( this.baseUrl + value );
+                    params[ 'map' ].wrapS = this.wrap;
+                    params[ 'map' ].wrapT = this.wrap;
+
+					break;
+
+                case 'ns':
+
+                    // The specular exponent (defines the focus of the specular highlight)
+                    // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
+
+					params['shininess'] = value;
+
+					break;
+
+                case 'd':
+
+                    // According to MTL format (http://paulbourke.net/dataformats/mtl/):
+                    //   d is dissolve for current material
+                    //   factor of 1.0 is fully opaque, a factor of 0 is fully dissolved (completely transparent)
+
+                    if ( value < 1 ) {
+
+                        params['transparent'] = true;
+                        params['opacity'] = value;
+
+                    }
+
+                    break;
+
+                default:
+                    break;
+
+            }
+
+        }
+
+        if ( params[ 'diffuse' ] ) {
+
+            if ( !params[ 'ambient' ]) params[ 'ambient' ] = params[ 'diffuse' ];
+            params[ 'color' ] = params[ 'diffuse' ];
+
+        }
+
+        this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
+        return this.materials[ materialName ];
+
+    }
+
+};
+
+THREE.MTLLoader.loadTexture = function ( url, mapping, onLoad, onError ) {
+
+	var isCompressed = url.toLowerCase().endsWith( ".dds" );
+
+	if ( isCompressed ) {
+
+		var texture = THREE.ImageUtils.loadCompressedTexture( url, mapping, onLoad, onError );
+
+	} else {
+
+		var image = new Image();
+		var texture = new THREE.Texture( image, mapping );
+
+		var loader = new THREE.ImageLoader();
+
+		loader.addEventListener( 'load', function ( event ) {
+
+			texture.image = THREE.MTLLoader.ensurePowerOfTwo_( event.content );
+			texture.needsUpdate = true;
+			if ( onLoad ) onLoad( texture );
+
+		} );
+
+		loader.addEventListener( 'error', function ( event ) {
+
+			if ( onError ) onError( event.message );
+
+		} );
+
+		loader.crossOrigin = this.crossOrigin;
+		loader.load( url, image );
+
+	}
+
+	return texture;
+
+};
+
+THREE.MTLLoader.ensurePowerOfTwo_ = function ( image ) {
+
+    if ( ! THREE.MTLLoader.isPowerOfTwo_( image.width ) || ! THREE.MTLLoader.isPowerOfTwo_( image.height ) ) {
+
+        var canvas = document.createElement( "canvas" );
+        canvas.width = THREE.MTLLoader.nextHighestPowerOfTwo_( image.width );
+        canvas.height = THREE.MTLLoader.nextHighestPowerOfTwo_( image.height );
+
+        var ctx = canvas.getContext("2d");
+        ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height );
+        return canvas;
+
+    }
+
+    return image;
+
+};
+
+THREE.MTLLoader.isPowerOfTwo_ = function ( x ) {
+
+	return ( x & ( x - 1 ) ) === 0;
+
+};
+
+THREE.MTLLoader.nextHighestPowerOfTwo_ = function( x ) {
+
+    --x;
+
+    for ( var i = 1; i < 32; i <<= 1 ) {
+
+        x = x | x >> i;
+
+    }
+
+    return x + 1;
+
+};
+

+ 10 - 10
examples/js/loaders/OBJLoader.js

@@ -15,28 +15,28 @@ THREE.OBJLoader.prototype = {
 	load: function ( url ) {
 
 		var scope = this;
-		var xhr = new XMLHttpRequest();
+		var request = new XMLHttpRequest();
 
-		xhr.addEventListener( 'load', function ( event ) {
+		request.addEventListener( 'load', function ( event ) {
 
 			scope.dispatchEvent( { type: 'load', content: scope.parse( event.target.responseText ) } );
 
 		}, false );
 
-		xhr.addEventListener( 'progress', function ( event ) {
+		request.addEventListener( 'progress', function ( event ) {
 
 			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
 
 		}, false );
 
-		xhr.addEventListener( 'error', function () {
+		request.addEventListener( 'error', function () {
 
 			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
 
 		}, false );
 
-		xhr.open( 'GET', url, true );
-		xhr.send( null );
+		request.open( 'GET', url, true );
+		request.send( null );
 
 	},
 
@@ -141,7 +141,7 @@ THREE.OBJLoader.prototype = {
 				// ["f 1 2 3", "1", "2", "3", undefined]
 
 				if ( result[ 4 ] === undefined ) {
-			
+
 					geometry.faces.push( face3(
 						parseInt( result[ 1 ] ) - 1,
 						parseInt( result[ 2 ] ) - 1,
@@ -170,7 +170,7 @@ THREE.OBJLoader.prototype = {
 				// ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3", undefined, undefined, undefined]
 
 				if ( result[ 10 ] === undefined ) {
-			
+
 					geometry.faces.push( face3(
 						parseInt( result[ 2 ] ) - 1,
 						parseInt( result[ 5 ] ) - 1,
@@ -212,7 +212,7 @@ THREE.OBJLoader.prototype = {
 				// ["f 1/1/1 2/2/2 3/3/3", " 1/1/1", "1", "1", "1", " 2/2/2", "2", "2", "2", " 3/3/3", "3", "3", "3", undefined, undefined, undefined, undefined]
 
 				if ( result[ 13 ] === undefined ) {
-			
+
 					geometry.faces.push( face3(
 						parseInt( result[ 2 ] ) - 1,
 						parseInt( result[ 6 ] ) - 1,
@@ -266,7 +266,7 @@ THREE.OBJLoader.prototype = {
 				// ["f 1//1 2//2 3//3", " 1//1", "1", "1", " 2//2", "2", "2", " 3//3", "3", "3", undefined, undefined, undefined]
 
 				if ( result[ 10 ] === undefined ) {
-			
+
 					geometry.faces.push( face3(
 						parseInt( result[ 2 ] ) - 1,
 						parseInt( result[ 5 ] ) - 1,

+ 490 - 0
examples/js/loaders/OBJMTLLoader.js

@@ -0,0 +1,490 @@
+/**
+ * Loads a Wavefront .obj file with materials
+ *
+ * @author mrdoob / http://mrdoob.com/
+ * @author angelxuanchang
+ */
+
+THREE.OBJMTLLoader = function ( ) {
+
+	THREE.EventTarget.call( this );
+
+};
+
+THREE.OBJMTLLoader.prototype = {
+
+	constructor: THREE.OBJMTLLoader,
+
+    /**
+     * Load a Wavefront OBJ file with materials (MTL file)
+     *
+     * Loading progress is indicated by the following events:
+     *   "load" event (successful loading): type = 'load', content = THREE.Object3D
+     *   "error" event (error loading): type = 'load', message
+     *   "progress" event (progress loading): type = 'progress', loaded, total
+     *
+     * If the MTL file cannot be loaded, then a MeshLambertMaterial is used as a default
+     * @param url - Location of OBJ file to load
+     * @param mtlfileurl - MTL file to load (optional, if not specified, attempts to use MTL specified in OBJ file)
+     * @param options - Options on how to interpret the material (see THREE.MTLLoader.MaterialCreator )
+     *
+     */
+
+	load: function ( url, mtlfileurl, options ) {
+
+		var scope = this;
+		var xhr = new XMLHttpRequest();
+
+        var mtlDone;  // Is the MTL done (true if no MTL, error loading MTL, or MTL actually loaded)
+        var obj3d;    // Loaded model (from obj file)
+        var materialsCreator;  // Material creator is created when MTL file is loaded
+
+        // Loader for MTL
+
+        var mtlLoader = new THREE.MTLLoader( url.substr( 0, url.lastIndexOf( "/" ) + 1 ), options );
+        mtlLoader.addEventListener( 'load', waitReady );
+        mtlLoader.addEventListener( 'error', waitReady );
+
+        // Try to load mtlfile
+
+        if ( mtlfileurl ) {
+
+            mtlLoader.load( mtlfileurl );
+            mtlDone = false;
+
+        } else {
+
+            mtlDone = true;
+
+        }
+
+        function waitReady( event ) {
+
+            if ( event.type === 'load' ) {
+
+                if ( event.content instanceof THREE.MTLLoader.MaterialCreator ) {
+
+                    // MTL file is loaded
+
+                    mtlDone = true;
+                    materialsCreator = event.content;
+                    materialsCreator.preload();
+
+                } else {
+
+                    // OBJ file is loaded
+
+                    if ( event.target.status === 200 || event.target.status === 0 ) {
+
+                        var objContent = event.target.responseText;
+
+                        if ( mtlfileurl ) {
+
+                            // Parse with passed in MTL file
+
+                            obj3d = scope.parse( objContent );
+
+                        } else {
+
+                            // No passed in MTL file, look for mtlfile in obj file
+
+                            obj3d = scope.parse( objContent, function( mtlfile ) {
+
+                                mtlDone = false;
+                                mtlLoader.load( mtlLoader.baseUrl + mtlfile );
+
+                            } );
+
+                        }
+
+                    } else {
+
+                        // Error loading OBJ file....
+
+                        scope.dispatchEvent( {
+                            type: 'error',
+                            message: 'Couldn\'t load URL [' + url + ']',
+                            response: event.target.responseText } );
+
+                    }
+
+                }
+
+            } else if ( event.type === 'error' ) {
+
+                // MTL failed to load -- oh well, we will just not have material ...
+
+                mtlDone = true;
+
+            }
+
+            if ( mtlDone && obj3d ) {
+
+                // MTL file is loaded and OBJ file is loaded
+                // Apply materials to model
+
+                if ( materialsCreator ) {
+
+                    THREE.SceneUtils.traverseHierarchy( obj3d, function( node ) {
+
+						if ( node instanceof THREE.Mesh ) {
+
+							if ( node.material.name ) {
+
+								var material = materialsCreator.create( node.material.name );
+								if  (material ) node.material = material;
+							}
+						}
+
+					} );
+
+                }
+
+                // Notify listeners
+
+                scope.dispatchEvent( { type: 'load', content: obj3d } );
+            }
+
+        }
+
+        xhr.addEventListener( 'load', waitReady, false );
+
+		xhr.addEventListener( 'progress', function ( event ) {
+
+			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
+
+		}, false );
+
+		xhr.addEventListener( 'error', function () {
+
+			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
+
+		}, false );
+
+		xhr.open( 'GET', url, true );
+		xhr.send( null );
+
+    },
+
+    /**
+     * Parses loaded .obj file
+     * @param data - content of .obj file
+     * @param mtllibCallback - callback to handle mtllib declaration (optional)
+     * @return {THREE.Object3D} - Object3D (with default material)
+     */
+	parse: function ( data, mtllibCallback ) {
+
+        function vector( x, y, z ) {
+
+			return new THREE.Vector3( x, y, z );
+
+		}
+
+		function uv( u, v ) {
+
+			return new THREE.UV( u, v );
+
+		}
+
+		function face3( a, b, c, normals ) {
+
+			return new THREE.Face3( a, b, c, normals );
+
+		}
+
+		function face4( a, b, c, d, normals ) {
+
+			return new THREE.Face4( a, b, c, d, normals );
+
+		}
+
+        function finalize_mesh( group, mesh_info ) {
+
+            mesh_info.geometry.computeCentroids();
+            mesh_info.geometry.computeFaceNormals();
+            mesh_info.geometry.computeBoundingSphere();
+            group.add( new THREE.Mesh( mesh_info.geometry, mesh_info.material ) );
+
+        }
+
+		var vertices = [];
+		var normals = [];
+		var uvs = [];
+
+        // v float float float
+
+        var vertex_pattern = /v( +[\d|\.|\+|\-|e]+)( [\d|\.|\+|\-|e]+)( [\d|\.|\+|\-|e]+)/;
+
+		// vn float float float
+
+        var normal_pattern = /vn( +[\d|\.|\+|\-|e]+)( [\d|\.|\+|\-|e]+)( [\d|\.|\+|\-|e]+)/;
+
+		// vt float float
+
+        var uv_pattern = /vt( +[\d|\.|\+|\-|e]+)( [\d|\.|\+|\-|e]+)/;
+
+		// f vertex vertex vertex ...
+
+        var face_pattern1 = /f( +[\d]+)( [\d]+)( [\d]+)( [\d]+)?/;
+
+		// f vertex/uv vertex/uv vertex/uv ...
+
+        var face_pattern2 = /f( +([\d]+)\/([\d]+))( ([\d]+)\/([\d]+))( ([\d]+)\/([\d]+))( ([\d]+)\/([\d]+))?/;
+
+		// f vertex/uv/normal vertex/uv/normal vertex/uv/normal ...
+
+        var face_pattern3 = /f( +([\d]+)\/([\d]+)\/([\d]+))( ([\d]+)\/([\d]+)\/([\d]+))( ([\d]+)\/([\d]+)\/([\d]+))( ([\d]+)\/([\d]+)\/([\d]+))?/;
+
+		// f vertex//normal vertex//normal vertex//normal ...
+
+        var face_pattern4 = /f( +([\d]+)\/\/([\d]+))( ([\d]+)\/\/([\d]+))( ([\d]+)\/\/([\d]+))( ([\d]+)\/\/([\d]+))?/;
+
+        var final_model = new THREE.Object3D();
+
+		var geometry = new THREE.Geometry();
+        geometry.vertices = vertices;
+
+		var cur_mesh = {
+
+            material: new THREE.MeshLambertMaterial(),
+            geometry: geometry
+
+        };
+
+        var lines = data.split( "\n" );
+
+        for ( var i = 0; i < lines.length; i ++ ) {
+
+            var line = lines[ i ];
+            line = line.trim();
+
+            // temporary variable storing pattern matching result
+
+            var result;
+
+            if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
+
+                continue;
+
+            } else if ( ( result = vertex_pattern.exec( line ) ) !== null ) {
+
+                // ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
+
+                vertices.push( vector(
+                    parseFloat( result[ 1 ] ),
+                    parseFloat( result[ 2 ] ),
+                    parseFloat( result[ 3 ] )
+                ) );
+
+            } else if ( ( result = normal_pattern.exec( line ) ) !== null ) {
+
+				// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
+
+				normals.push( vector(
+                    parseFloat( result[ 1 ] ),
+                    parseFloat( result[ 2 ] ),
+                    parseFloat( result[ 3 ] )
+                ) );
+
+            } else if ( ( result = uv_pattern.exec( line ) ) !== null ) {
+
+                // ["vt 0.1 0.2", "0.1", "0.2"]
+
+                uvs.push( uv(
+                    parseFloat( result[ 1 ] ),
+                    parseFloat( result[ 2 ] )
+                ) );
+
+            } else if ( ( result = face_pattern1.exec( line ) ) !== null ) {
+
+                // ["f 1 2 3", "1", "2", "3", undefined]
+
+                if ( result[ 4 ] === undefined ) {
+
+                    geometry.faces.push( face3(
+                        parseInt( result[ 1 ] ) - 1,
+                        parseInt( result[ 2 ] ) - 1,
+                        parseInt( result[ 3 ] ) - 1
+                    ) );
+
+                } else {
+
+                    geometry.faces.push( face4(
+                        parseInt( result[ 1 ] ) - 1,
+                        parseInt( result[ 2 ] ) - 1,
+                        parseInt( result[ 3 ] ) - 1,
+                        parseInt( result[ 4 ] ) - 1
+                    ) );
+
+                }
+
+            } else if ( ( result = face_pattern2.exec( line ) ) !== null ) {
+
+                // ["f 1/1 2/2 3/3", " 1/1", "1", "1", " 2/2", "2", "2", " 3/3", "3", "3", undefined, undefined, undefined]
+
+                if ( result[ 10 ] === undefined ) {
+
+                    geometry.faces.push( face3(
+                        parseInt( result[ 2 ] ) - 1,
+                        parseInt( result[ 5 ] ) - 1,
+                        parseInt( result[ 8 ] ) - 1
+                    ) );
+
+                    geometry.faceVertexUvs[ 0 ].push( [
+                        uvs[ parseInt( result[ 3 ] ) - 1 ],
+                        uvs[ parseInt( result[ 6 ] ) - 1 ],
+                        uvs[ parseInt( result[ 9 ] ) - 1 ]
+                    ] );
+
+                } else {
+
+                    geometry.faces.push( face4(
+                        parseInt( result[ 2 ] ) - 1,
+                        parseInt( result[ 5 ] ) - 1,
+                        parseInt( result[ 8 ] ) - 1,
+                        parseInt( result[ 11 ] ) - 1
+                    ) );
+
+                    geometry.faceVertexUvs[ 0 ].push( [
+                        uvs[ parseInt( result[ 3 ] ) - 1 ],
+                        uvs[ parseInt( result[ 6 ] ) - 1 ],
+                        uvs[ parseInt( result[ 9 ] ) - 1 ],
+                        uvs[ parseInt( result[ 12 ] ) - 1 ]
+                    ] );
+
+                }
+
+            } else if ( ( result = face_pattern3.exec( line ) ) !== null ) {
+
+                // ["f 1/1/1 2/2/2 3/3/3", " 1/1/1", "1", "1", "1", " 2/2/2", "2", "2", "2", " 3/3/3", "3", "3", "3", undefined, undefined, undefined, undefined]
+
+                if ( result[ 13 ] === undefined ) {
+
+                    geometry.faces.push( face3(
+                        parseInt( result[ 2 ] ) - 1,
+                        parseInt( result[ 6 ] ) - 1,
+                        parseInt( result[ 10 ] ) - 1,
+                        [
+                            normals[ parseInt( result[ 4 ] ) - 1 ],
+                            normals[ parseInt( result[ 8 ] ) - 1 ],
+                            normals[ parseInt( result[ 12 ] ) - 1 ]
+                        ]
+                    ) );
+
+                    geometry.faceVertexUvs[ 0 ].push( [
+                        uvs[ parseInt( result[ 3 ] ) - 1 ],
+                        uvs[ parseInt( result[ 7 ] ) - 1 ],
+                        uvs[ parseInt( result[ 11 ] ) - 1 ]
+                    ] );
+
+                } else {
+
+                    geometry.faces.push( face4(
+                        parseInt( result[ 2 ] ) - 1,
+                        parseInt( result[ 6 ] ) - 1,
+                        parseInt( result[ 10 ] ) - 1,
+                        parseInt( result[ 14 ] ) - 1,
+                        [
+                            normals[ parseInt( result[ 4 ] ) - 1 ],
+                            normals[ parseInt( result[ 8 ] ) - 1 ],
+                            normals[ parseInt( result[ 12 ] ) - 1 ],
+                            normals[ parseInt( result[ 16 ] ) - 1 ]
+                        ]
+                    ) );
+
+                    geometry.faceVertexUvs[ 0 ].push( [
+                        uvs[ parseInt( result[ 3 ] ) - 1 ],
+                        uvs[ parseInt( result[ 7 ] ) - 1 ],
+                        uvs[ parseInt( result[ 11 ] ) - 1 ],
+                        uvs[ parseInt( result[ 15 ] ) - 1 ]
+                    ] );
+
+                }
+
+            } else if ( ( result = face_pattern4.exec( line ) ) !== null ) {
+
+                // ["f 1//1 2//2 3//3", " 1//1", "1", "1", " 2//2", "2", "2", " 3//3", "3", "3", undefined, undefined, undefined]
+
+                if ( result[ 10 ] === undefined ) {
+
+                    geometry.faces.push( face3(
+                        parseInt( result[ 2 ] ) - 1,
+                        parseInt( result[ 5 ] ) - 1,
+                        parseInt( result[ 8 ] ) - 1,
+                        [
+                            normals[ parseInt( result[ 3 ] ) - 1 ],
+                            normals[ parseInt( result[ 6 ] ) - 1 ],
+                            normals[ parseInt( result[ 9 ] ) - 1 ]
+                        ]
+                    ) );
+
+                } else {
+
+                    geometry.faces.push( face4(
+                        parseInt( result[ 2 ] ) - 1,
+                        parseInt( result[ 5 ] ) - 1,
+                        parseInt( result[ 8 ] ) - 1,
+                        parseInt( result[ 11 ] ) - 1,
+                        [
+                            normals[ parseInt( result[ 3 ] ) - 1 ],
+                            normals[ parseInt( result[ 6 ] ) - 1 ],
+                            normals[ parseInt( result[ 9 ] ) - 1 ],
+                            normals[ parseInt( result[ 12 ] ) - 1 ]
+                        ]
+                    ) );
+
+                }
+
+            } else if ( line.startsWith( "usemtl " ) ) {
+
+                var material_name = line.substring( 7 );
+                material_name = material_name.trim();
+
+                var material = new THREE.MeshLambertMaterial();
+                material.name = material_name;
+
+                if ( geometry.faces.length > 0 ) {
+
+                    // Finalize previous geometry and add to model
+
+                    finalize_mesh( final_model, cur_mesh );
+                    geometry = new THREE.Geometry();
+                    geometry.vertices = vertices;
+
+                    cur_mesh = {  geometry: geometry };
+
+                }
+
+                cur_mesh.material = material;
+                //material_index = materialsCreator.getIndex( material_name );
+
+            } else if ( line.startsWith( "g " ) ) {
+
+                // Polygon group for object
+
+                var group_name = line.substring( 2 );
+                group_name = group_name.trim();
+
+            } else if ( line.startsWith( "o " ) ) {
+
+                // Object
+                var object_name = line.substring(2);
+                //object_name = $.trim(object_name);
+            } else if (line.startsWith("s ")) {
+                // Smooth shading
+            } else if (line.startsWith("mtllib ")) {
+                // mtl file
+                if (mtllibCallback) {
+                    var mtlfile = line.substring(7);
+                    mtlfile = $.trim(mtlfile);
+                    mtllibCallback(mtlfile);
+                }
+            } else {
+                console.error("Unhandled line " + line);
+            }
+        }
+        finalize_mesh(final_model, cur_mesh);
+		return final_model;
+	}
+};
+

+ 7 - 6
examples/js/loaders/STLLoader.js

@@ -31,28 +31,28 @@ THREE.STLLoader.prototype = {
 	load: function ( url ) {
 
 		var scope = this;
-		var xhr = new XMLHttpRequest();
+		var request = new XMLHttpRequest();
 
-		xhr.addEventListener( 'load', function ( event ) {
+		request.addEventListener( 'load', function ( event ) {
 
 			scope.dispatchEvent( { type: 'load', content: scope.parse( event.target.responseText ) } );
 
 		}, false );
 
-		xhr.addEventListener( 'progress', function ( event ) {
+		request.addEventListener( 'progress', function ( event ) {
 
 			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
 
 		}, false );
 
-		xhr.addEventListener( 'error', function () {
+		request.addEventListener( 'error', function () {
 
 			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
 
 		}, false );
 
-		xhr.open( 'GET', url, true );
-		xhr.send( null );
+		request.open( 'GET', url, true );
+		request.send( null );
 
 	},
 
@@ -93,6 +93,7 @@ THREE.STLLoader.prototype = {
 		}
 
 		geometry.computeCentroids();
+		geometry.computeBoundingSphere();
 
 		return geometry;
 

+ 822 - 188
examples/js/loaders/UTF8Loader.js

@@ -1,326 +1,960 @@
 /**
- * Loader for UTF8 encoded models generated by:
+ * Loader for UTF8 version2 (after r51) encoded models generated by:
  *	http://code.google.com/p/webgl-loader/
  *
- * Limitations:
- *  - number of vertices < 65536 (this is after optimizations in compressor, input OBJ may have even less)
- *	- models must have normals and texture coordinates
- *  - texture coordinates must be only from <0,1>
- *  - no materials support yet
- *  - models are scaled and offset (copy numbers from compressor and use them as parameters in UTF8Loader.load() )
- *
- * @author alteredq / http://alteredqualia.com/
- * @author won3d / http://twitter.com/won3d
+ * Code to load/decompress mesh is taken from r100 of this webgl-loader
  */
 
 THREE.UTF8Loader = function () {};
 
-THREE.UTF8Loader.prototype.load = function ( url, callback, metadata ) {
+/**
+ * Load UTF8 encoded model
+ * @param jsonUrl - URL from which to load json containing information about model
+ * @param callback - Callback(THREE.Object3D) on successful loading of model
+ * @param options - options on how to load model (see THREE.MTLLoader.MaterialCreator for basic options)
+ *                  Additional options include
+ *                   geometryBase: Base url from which to load referenced geometries
+ *                   materialBase: Base url from which to load referenced textures
+ */
 
-	var xhr = new XMLHttpRequest(),
-		callbackProgress = null,
+THREE.UTF8Loader.prototype.load = function ( jsonUrl, callback, options ) {
 
-		scale = metadata.scale !== undefined ? metadata.scale : 1,
-		offsetX = metadata.offsetX !== undefined ? metadata.offsetX : 0,
-		offsetY = metadata.offsetY !== undefined ? metadata.offsetY : 0,
-		offsetZ = metadata.offsetZ !== undefined ? metadata.offsetZ : 0;
+    this.downloadModelJson( jsonUrl, options, callback );
 
-	var length = 0;
+};
 
-	xhr.onreadystatechange = function() {
+// BufferGeometryCreator
 
-		if ( xhr.readyState == 4 ) {
+THREE.UTF8Loader.BufferGeometryCreator = function () {
+};
 
-			if ( xhr.status == 200 || xhr.status == 0 ) {
+THREE.UTF8Loader.BufferGeometryCreator.prototype.create = function ( attribArray, indexArray ) {
 
-				THREE.UTF8Loader.prototype.createModel( xhr.responseText, callback, scale, offsetX, offsetY, offsetZ );
+	var ntris = indexArray.length / 3;
 
-			} else {
+	var geometry = new THREE.BufferGeometry();
 
-				console.error( "THREE.UTF8Loader: Couldn't load [" + url + "] [" + xhr.status + "]" );
+	var positionArray = new Float32Array( 3 * 3 * ntris );
+	var normalArray = new Float32Array( 3 * 3 * ntris );
+	var uvArray = new Float32Array( 2 * 3 * ntris );
 
-			}
+	var i, j, offset;
+	var x, y, z;
+	var u, v;
 
-		} else if ( xhr.readyState == 3 ) {
+	var end = attribArray.length;
+	var stride = 8;
 
-			if ( callbackProgress ) {
+	// extract positions
 
-				if ( length == 0 ) {
+	j = 0;
+	offset = 0;
 
-					length = xhr.getResponseHeader( "Content-Length" );
+	for( i = offset; i < end; i += stride ) {
 
-				}
+		x = attribArray[ i ];
+		y = attribArray[ i + 1 ];
+		z = attribArray[ i + 2 ];
 
-				callbackProgress( { total: length, loaded: xhr.responseText.length } );
+		positionArray[ j++ ] = x;
+		positionArray[ j++ ] = y;
+		positionArray[ j++ ] = z;
 
-			}
+	}
 
-		} else if ( xhr.readyState == 2 ) {
+	// extract uvs
 
-			length = xhr.getResponseHeader( "Content-Length" );
+	j = 0;
+	offset = 3;
 
-		}
+	for( i = offset; i < end; i += stride ) {
+
+		u = attribArray[ i ];
+		v = attribArray[ i + 1 ];
+
+		uvArray[ j++ ] = u;
+		uvArray[ j++ ] = v;
 
 	}
 
-	xhr.open( "GET", url, true );
-	xhr.send( null );
+	// extract normals
+
+	j = 0;
+	offset = 5;
+
+	for( i = offset; i < end; i += stride ) {
+
+		x = attribArray[ i ];
+		y = attribArray[ i + 1 ];
+		z = attribArray[ i + 2 ];
+
+		normalArray[ j++ ] = x;
+		normalArray[ j++ ] = y;
+		normalArray[ j++ ] = z;
+
+	}
+
+	// create attributes
+
+	var attributes = geometry.attributes;
+
+	attributes[ "index" ]    = { itemSize: 1, array: indexArray, numItems: indexArray.length };
+	attributes[ "position" ] = { itemSize: 3, array: positionArray, numItems: positionArray.length };
+	attributes[ "normal" ]   = { itemSize: 3, array: normalArray, numItems: normalArray.length };
+	attributes[ "uv" ] 		 = { itemSize: 2, array: uvArray, numItems: uvArray.length };
+
+	// create offsets
+	// (all triangles should fit in a single chunk)
+
+	geometry.offsets = [ { start: 0, count: indexArray.length, index: 0 } ];
+
+	geometry.computeBoundingSphere();
+
+	return geometry;
+
+};
+
+// GeometryCreator
+
+THREE.UTF8Loader.GeometryCreator = function () {
+};
+
+THREE.UTF8Loader.GeometryCreator.prototype = {
+
+    create: function ( attribArray, indexArray ) {
+
+        var geometry = new THREE.Geometry();
+
+        this.init_vertices( geometry, attribArray, 8, 0 );
+
+        var uvs = this.init_uvs( attribArray, 8, 3 );
+        var normals = this.init_normals( attribArray, 8, 5 );
+
+        this.init_faces( geometry, normals, uvs, indexArray );
+
+        geometry.computeCentroids();
+        geometry.computeFaceNormals();
+
+        return geometry;
+
+    },
+
+    init_vertices: function ( scope, data, stride, offset ) {
+
+        var i, x, y, z;
+		var end = data.length;
+
+        for( i = offset; i < end; i += stride ) {
+
+            x = data[ i ];
+            y = data[ i + 1 ];
+            z = data[ i + 2 ];
+
+            this.addVertex( scope, x, y, z );
+
+        }
+
+    },
+
+    init_normals: function( data, stride, offset ) {
+
+        var normals = [];
+
+        var i, x, y, z;
+		var end = data.length;
+
+        for( i = offset; i < end; i += stride ) {
+
+            // Assumes already normalized to <-1,1> (unlike previous version of UTF8Loader)
+
+            x = data[ i ];
+            y = data[ i + 1 ];
+            z = data[ i + 2 ];
+
+            normals.push( x, y, z );
+
+        }
+
+        return normals;
+
+    },
+
+    init_uvs: function( data, stride, offset ) {
+
+        var uvs = [];
+
+        var i, u, v;
+		var end = data.length;
+
+        for( i = offset; i < end; i += stride ) {
+
+            // Assumes uvs are already normalized (unlike previous version of UTF8Loader)
+            // uvs can be negative, need to set wrap for texture map later on ...
+
+            u = data[ i ];
+            v = data[ i + 1 ];
+
+            uvs.push( u, v );
+        }
+
+        return uvs;
+
+    },
+
+    init_faces: function( scope, normals, uvs, indices ) {
+
+        var i,
+            a, b, c,
+            u1, v1, u2, v2, u3, v3;
+
+		var end = indices.length;
+
+        var m = 0; // all faces defaulting to material 0
+
+        for( i = 0; i < end; i += 3 ) {
+
+            a = indices[ i ];
+            b = indices[ i + 1 ];
+            c = indices[ i + 2 ];
+
+            this.f3n( scope, normals, a, b, c, m, a, b, c );
+
+            u1 = uvs[ a * 2 ];
+            v1 = uvs[ a * 2 + 1 ];
+
+            u2 = uvs[ b * 2 ];
+            v2 = uvs[ b * 2 + 1 ];
+
+            u3 = uvs[ c * 2 ];
+            v3 = uvs[ c * 2 + 1 ];
+
+            this.uv3( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3 );
+
+        }
+
+    },
+
+    addVertex: function ( scope, x, y, z ) {
+
+        scope.vertices.push( new THREE.Vector3( x, y, z ) );
+
+    },
+
+    f3n: function( scope, normals, a, b, c, mi, nai, nbi, nci ) {
+
+        var nax = normals[ nai * 3 ],
+            nay = normals[ nai * 3 + 1 ],
+            naz = normals[ nai * 3 + 2 ],
+
+            nbx = normals[ nbi * 3 ],
+            nby = normals[ nbi * 3 + 1 ],
+            nbz = normals[ nbi * 3 + 2 ],
+
+            ncx = normals[ nci * 3 ],
+            ncy = normals[ nci * 3 + 1 ],
+            ncz = normals[ nci * 3 + 2 ];
+
+        var na = new THREE.Vector3( nax, nay, naz ),
+            nb = new THREE.Vector3( nbx, nby, nbz ),
+            nc = new THREE.Vector3( ncx, ncy, ncz );
+
+        scope.faces.push( new THREE.Face3( a, b, c, [ na, nb, nc ], null, mi ) );
+
+    },
+
+    uv3: function ( where, u1, v1, u2, v2, u3, v3 ) {
+
+        var uv = [];
+        uv.push( new THREE.UV( u1, v1 ) );
+        uv.push( new THREE.UV( u2, v2 ) );
+        uv.push( new THREE.UV( u3, v3 ) );
+        where.push( uv );
+
+    }
 
 };
 
-// UTF-8 decoder from webgl-loader
+
+// UTF-8 decoder from webgl-loader (r100)
 // http://code.google.com/p/webgl-loader/
 
-// Copyright 2011 Google Inc. All Rights Reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you
-// may not use this file except in compliance with the License. You
-// may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-// implied. See the License for the specific language governing
-// permissions and limitations under the License.
+// Model manifest description. Contains objects like:
+// name: {
+//   materials: { 'material_name': { ... } ... },
+//   decodeParams: {
+//     decodeOffsets: [ ... ],
+//     decodeScales: [ ... ],
+//   },
+//   urls: {
+//     'url': [
+//       { material: 'material_name',
+//         attribRange: [#, #],
+//         indexRange: [#, #],
+//         names: [ 'object names' ... ],
+//         lengths: [#, #, # ... ]
+//       }
+//     ],
+//     ...
+//   }
+// }
+
+var DEFAULT_DECODE_PARAMS = {
+
+    decodeOffsets: [-4095, -4095, -4095, 0, 0, -511, -511, -511],
+    decodeScales: [1/8191, 1/8191, 1/8191, 1/1023, 1/1023, 1/1023, 1/1023, 1/1023]
+
+    // TODO: normal decoding? (see walt.js)
+    // needs to know: input, output (from vertex format!)
+    //
+    // Should split attrib/index.
+    // 1) Decode position and non-normal attributes.
+    // 2) Decode indices, computing normals
+    // 3) Maybe normalize normals? Only necessary for refinement, or fixed?
+    // 4) Maybe refine normals? Should this be part of regular refinement?
+    // 5) Morphing
 
-THREE.UTF8Loader.prototype.decompressMesh = function ( str ) {
+};
 
-	var num_verts = str.charCodeAt( 0 );
+// Triangle strips!
 
-	if ( num_verts >= 0xE000 ) {
+// TODO: will it be an optimization to specialize this method at
+// runtime for different combinations of stride, decodeOffset and
+// decodeScale?
 
-		num_verts -= 0x0800;
+THREE.UTF8Loader.prototype.decompressAttribsInner_ = function ( str, inputStart, inputEnd,
+                                                                  output, outputStart, stride,
+                                                                  decodeOffset, decodeScale ) {
 
-	}
+    var prev = 0;
 
-	num_verts ++;
+    for ( var j = inputStart; j < inputEnd; j ++ ) {
 
-	var attribs_out = new Float32Array( 8 * num_verts );
+        var code = str.charCodeAt( j );
+        prev += ( code >> 1 ) ^ ( -( code & 1 ) );
 
-	var offset = 1;
+        output[ outputStart ] = decodeScale * ( prev + decodeOffset );
+        outputStart += stride;
 
-	for ( var i = 0; i < 8; i ++ ) {
+    }
 
-		var prev_attrib = 0;
+};
 
-		for ( var j = 0; j < num_verts; ++ j ) {
+THREE.UTF8Loader.prototype.decompressIndices_ = function( str, inputStart, numIndices,
+                                                            output, outputStart ) {
 
-			var code = str.charCodeAt( j + offset );
+	var highest = 0;
 
-			prev_attrib += ( code >> 1 ) ^ ( - ( code & 1 ) );
+    for ( var i = 0; i < numIndices; i ++ ) {
 
-			attribs_out[ 8 * j + i ] = prev_attrib;
+        var code = str.charCodeAt( inputStart ++ );
 
-		}
+        output[ outputStart ++ ] = highest - code;
 
-		offset += num_verts;
+        if ( code === 0 ) {
 
-	}
+            highest ++;
 
-	var num_indices = str.length - offset;
+        }
 
-	var indices_out = new Uint16Array( num_indices );
+    }
 
-	var index_high_water_mark = 0;
+};
 
-	for ( var i = 0; i < num_indices; i ++ ) {
+THREE.UTF8Loader.prototype.decompressAABBs_ = function ( str, inputStart, numBBoxen,
+                                                           decodeOffsets, decodeScales ) {
+    var numFloats = 6 * numBBoxen;
 
-		var code = str.charCodeAt( i + offset );
+    var inputEnd = inputStart + numFloats;
+    var outputStart = 0;
 
-		indices_out[ i ] = index_high_water_mark - code;
+    var bboxen = new Float32Array( numFloats );
 
-		if ( code == 0 ) {
+    for ( var i = inputStart; i < inputEnd; i += 6 ) {
 
-			index_high_water_mark ++;
+        var minX = str.charCodeAt(i + 0) + decodeOffsets[0];
+        var minY = str.charCodeAt(i + 1) + decodeOffsets[1];
+        var minZ = str.charCodeAt(i + 2) + decodeOffsets[2];
 
-		}
+        var radiusX = (str.charCodeAt(i + 3) + 1) >> 1;
+        var radiusY = (str.charCodeAt(i + 4) + 1) >> 1;
+        var radiusZ = (str.charCodeAt(i + 5) + 1) >> 1;
 
-	}
+        bboxen[ outputStart++ ] = decodeScales[0] * (minX + radiusX);
+        bboxen[ outputStart++ ] = decodeScales[1] * (minY + radiusY);
+        bboxen[ outputStart++ ] = decodeScales[2] * (minZ + radiusZ);
+
+        bboxen[ outputStart++ ] = decodeScales[0] * radiusX;
+        bboxen[ outputStart++ ] = decodeScales[1] * radiusY;
+        bboxen[ outputStart++ ] = decodeScales[2] * radiusZ;
+
+    }
+
+    return bboxen;
+
+};
+
+THREE.UTF8Loader.prototype.decompressMesh =  function ( str, meshParams, decodeParams, name, idx, callback ) {
+
+    // Extract conversion parameters from attribArrays.
+
+    var stride = decodeParams.decodeScales.length;
+
+    var decodeOffsets = decodeParams.decodeOffsets;
+    var decodeScales = decodeParams.decodeScales;
+
+    var attribStart = meshParams.attribRange[0];
+    var numVerts = meshParams.attribRange[1];
+
+    // Decode attributes.
+
+    var inputOffset = attribStart;
+    var attribsOut = new Float32Array( stride * numVerts );
+
+    for (var j = 0; j < stride; j ++ ) {
+
+        var end = inputOffset + numVerts;
+
+		var decodeScale = decodeScales[j];
+
+        if ( decodeScale ) {
+
+            // Assume if decodeScale is never set, simply ignore the
+            // attribute.
+
+            this.decompressAttribsInner_( str, inputOffset, end,
+                attribsOut, j, stride,
+                decodeOffsets[j], decodeScale );
+        }
+
+        inputOffset = end;
+
+    }
+
+    var indexStart = meshParams.indexRange[ 0 ];
+    var numIndices = 3 * meshParams.indexRange[ 1 ];
+
+    var indicesOut = new Uint16Array( numIndices );
+
+    this.decompressIndices_( str, inputOffset, numIndices, indicesOut, 0 );
+
+    // Decode bboxen.
+
+    var bboxen = undefined;
+    var bboxOffset = meshParams.bboxes;
+
+    if ( bboxOffset ) {
+
+        bboxen = this.decompressAABBs_( str, bboxOffset, meshParams.names.length, decodeOffsets, decodeScales );
+    }
+
+    callback( name, idx, attribsOut, indicesOut, bboxen, meshParams );
+
+};
+
+THREE.UTF8Loader.prototype.copyAttrib = function ( stride, attribsOutFixed, lastAttrib, index ) {
+
+    for ( var j = 0; j < stride; j ++ ) {
+
+        lastAttrib[ j ] = attribsOutFixed[ stride * index + j ];
+
+    }
+
+};
+
+THREE.UTF8Loader.prototype.decodeAttrib2 = function ( str, stride, decodeOffsets, decodeScales, deltaStart,
+                                                        numVerts, attribsOut, attribsOutFixed, lastAttrib,
+                                                        index ) {
+
+    for ( var j = 0; j < 5; j ++ ) {
+
+        var code = str.charCodeAt( deltaStart + numVerts*j + index );
+        var delta = ( code >> 1) ^ (-(code & 1));
 
-	return [ attribs_out, indices_out ];
+        lastAttrib[ j ] += delta;
+        attribsOutFixed[ stride * index + j ] = lastAttrib[ j ];
+        attribsOut[ stride * index + j ] = decodeScales[ j ] * ( lastAttrib[ j ] + decodeOffsets[ j ] );
+    }
 
 };
 
-THREE.UTF8Loader.prototype.createModel = function ( data, callback, scale, offsetX, offsetY, offsetZ ) {
+THREE.UTF8Loader.prototype.accumulateNormal = function ( i0, i1, i2, attribsOutFixed, crosses ) {
 
-	var Model = function ( texture_path ) {
+    var p0x = attribsOutFixed[ 8*i0 ];
+    var p0y = attribsOutFixed[ 8*i0 + 1 ];
+    var p0z = attribsOutFixed[ 8*i0 + 2 ];
 
-		//var s = (new Date).getTime();
+    var p1x = attribsOutFixed[ 8*i1 ];
+    var p1y = attribsOutFixed[ 8*i1 + 1 ];
+    var p1z = attribsOutFixed[ 8*i1 + 2 ];
 
-		var scope = this;
+    var p2x = attribsOutFixed[ 8*i2 ];
+    var p2y = attribsOutFixed[ 8*i2 + 1 ];
+    var p2z = attribsOutFixed[ 8*i2 + 2 ];
 
-		scope.materials = [];
+    p1x -= p0x;
+    p1y -= p0y;
+    p1z -= p0z;
 
-		THREE.Geometry.call( this );
+    p2x -= p0x;
+    p2y -= p0y;
+    p2z -= p0z;
 
-		var buffers = THREE.UTF8Loader.prototype.decompressMesh( data );
+    p0x = p1y*p2z - p1z*p2y;
+    p0y = p1z*p2x - p1x*p2z;
+    p0z = p1x*p2y - p1y*p2x;
 
-		var normals = [],
-			uvs = [];
+    crosses[ 3*i0 ]     += p0x;
+    crosses[ 3*i0 + 1 ] += p0y;
+    crosses[ 3*i0 + 2 ] += p0z;
 
-		init_vertices( buffers[ 0 ], 8, 0 );
-		init_uvs( buffers[ 0 ], 8, 3 );
-		init_normals( buffers[ 0 ], 8, 5 );
+    crosses[ 3*i1 ]     += p0x;
+    crosses[ 3*i1 + 1 ] += p0y;
+    crosses[ 3*i1 + 2 ] += p0z;
 
-		init_faces( buffers[ 1 ] );
+    crosses[ 3*i2 ]     += p0x;
+    crosses[ 3*i2 + 1 ] += p0y;
+    crosses[ 3*i2 + 2 ] += p0z;
 
-		this.computeCentroids();
-		this.computeFaceNormals();
-		//this.computeTangents();
+};
+
+THREE.UTF8Loader.prototype.decompressMesh2 = function( str, meshParams, decodeParams, name, idx, callback ) {
+
+    var MAX_BACKREF = 96;
+
+    // Extract conversion parameters from attribArrays.
+
+    var stride = decodeParams.decodeScales.length;
+
+	var decodeOffsets = decodeParams.decodeOffsets;
+    var decodeScales = decodeParams.decodeScales;
+
+    var deltaStart = meshParams.attribRange[ 0 ];
+    var numVerts = meshParams.attribRange[ 1 ];
+
+    var codeStart = meshParams.codeRange[ 0 ];
+    var codeLength = meshParams.codeRange[ 1 ];
+
+    var numIndices = 3 * meshParams.codeRange[ 2 ];
+
+    var indicesOut = new Uint16Array( numIndices );
+
+    var crosses = new Int32Array( 3 * numVerts );
+
+    var lastAttrib = new Uint16Array( stride );
+
+    var attribsOutFixed = new Uint16Array( stride * numVerts );
+    var attribsOut = new Float32Array( stride * numVerts );
+
+    var highest = 0;
+    var outputStart = 0;
+
+    for ( var i = 0; i < numIndices; i += 3 ) {
+
+        var code = str.charCodeAt( codeStart ++ );
+
+        var max_backref = Math.min( i, MAX_BACKREF );
+
+        if ( code < max_backref ) {
+
+            // Parallelogram
+
+            var winding = code % 3;
+            var backref = i - ( code - winding );
+            var i0, i1, i2;
+
+            switch ( winding ) {
+
+                case 0:
+
+                    i0 = indicesOut[ backref + 2 ];
+                    i1 = indicesOut[ backref + 1 ];
+                    i2 = indicesOut[ backref + 0 ];
+                    break;
+
+                case 1:
+
+                    i0 = indicesOut[ backref + 0 ];
+                    i1 = indicesOut[ backref + 2 ];
+                    i2 = indicesOut[ backref + 1 ];
+                    break;
+
+                case 2:
+
+                    i0 = indicesOut[ backref + 1 ];
+                    i1 = indicesOut[ backref + 0 ];
+                    i2 = indicesOut[ backref + 2 ];
+                    break;
+
+            }
+
+            indicesOut[ outputStart ++ ] = i0;
+            indicesOut[ outputStart ++ ] = i1;
+
+            code = str.charCodeAt( codeStart ++ );
+
+            var index = highest - code;
+            indicesOut[ outputStart ++ ] = index;
+
+            if ( code === 0 ) {
+
+                for (var j = 0; j < 5; j ++ ) {
+
+                    var deltaCode = str.charCodeAt( deltaStart + numVerts * j + highest );
+
+                    var prediction = ((deltaCode >> 1) ^ (-(deltaCode & 1))) +
+                        attribsOutFixed[stride*i0 + j] +
+                        attribsOutFixed[stride*i1 + j] -
+                        attribsOutFixed[stride*i2 + j];
+
+                    lastAttrib[j] = prediction;
+
+                    attribsOutFixed[ stride * highest + j ] = prediction;
+                    attribsOut[ stride * highest + j ] = decodeScales[ j ] * ( prediction + decodeOffsets[ j ] );
+
+                }
+
+                highest ++;
+
+            } else {
+
+                this.copyAttrib( stride, attribsOutFixed, lastAttrib, index );
+
+            }
+
+            this.accumulateNormal( i0, i1, index, attribsOutFixed, crosses );
+
+        } else {
+
+            // Simple
+
+            var index0 = highest - ( code - max_backref );
+
+            indicesOut[ outputStart ++ ] = index0;
+
+            if ( code === max_backref ) {
+
+                this.decodeAttrib2( str, stride, decodeOffsets, decodeScales, deltaStart,
+                    numVerts, attribsOut, attribsOutFixed, lastAttrib,
+                    highest ++ );
+
+            } else {
+
+                this.copyAttrib(stride, attribsOutFixed, lastAttrib, index0);
+
+            }
+
+            code = str.charCodeAt( codeStart ++ );
+
+            var index1 = highest - code;
+            indicesOut[ outputStart ++ ] = index1;
+
+            if ( code === 0 ) {
+
+                this.decodeAttrib2( str, stride, decodeOffsets, decodeScales, deltaStart,
+                    numVerts, attribsOut, attribsOutFixed, lastAttrib,
+                    highest ++ );
+
+            } else {
+
+                this.copyAttrib( stride, attribsOutFixed, lastAttrib, index1 );
+
+            }
+
+            code = str.charCodeAt( codeStart ++ );
+
+            var index2 = highest - code;
+            indicesOut[ outputStart ++ ] = index2;
+
+            if ( code === 0 ) {
+
+                for ( var j = 0; j < 5; j ++ ) {
+
+                    lastAttrib[ j ] = ( attribsOutFixed[ stride * index0 + j ] + attribsOutFixed[ stride * index1 + j ] ) / 2;
+
+                }
+
+                this.decodeAttrib2( str, stride, decodeOffsets, decodeScales, deltaStart,
+                    numVerts, attribsOut, attribsOutFixed, lastAttrib,
+                    highest ++ );
+
+            } else {
+
+                this.copyAttrib( stride, attribsOutFixed, lastAttrib, index2 );
 
-		//var e = (new Date).getTime();
+            }
 
-		//console.log( "utf8 data parse time: " + (e-s) + " ms" );
+            this.accumulateNormal( index0, index1, index2, attribsOutFixed, crosses );
 
-		function init_vertices( data, stride, offset ) {
+        }
 
-			var i, x, y, z,
-				end = data.length;
+    }
 
-			for( i = offset; i < end; i += stride ) {
+    for ( var i = 0; i < numVerts; i ++ ) {
 
-				x = data[ i ];
-				y = data[ i + 1 ];
-				z = data[ i + 2 ];
+        var nx = crosses[ 3*i ];
+        var ny = crosses[ 3*i + 1 ];
+        var nz = crosses[ 3*i + 2 ];
 
-				// fix scale and offsets
+        var norm = 511.0 / Math.sqrt( nx*nx + ny*ny + nz*nz );
 
-				x = ( x / 16383 ) * scale;
-				y = ( y / 16383 ) * scale;
-				z = ( z / 16383 ) * scale;
+        var cx = str.charCodeAt( deltaStart + 5*numVerts + i );
+        var cy = str.charCodeAt( deltaStart + 6*numVerts + i );
+        var cz = str.charCodeAt( deltaStart + 7*numVerts + i );
 
-				x += offsetX;
-				y += offsetY;
-				z += offsetZ;
+        attribsOut[ stride*i + 5 ] = norm*nx + ((cx >> 1) ^ (-(cx & 1)));
+        attribsOut[ stride*i + 6 ] = norm*ny + ((cy >> 1) ^ (-(cy & 1)));
+        attribsOut[ stride*i + 7 ] = norm*nz + ((cz >> 1) ^ (-(cz & 1)));
+    }
 
-				vertex( scope, x, y, z );
+    callback( name, idx, attribsOut, indicesOut, undefined, meshParams );
 
-			}
+};
+
+THREE.UTF8Loader.prototype.downloadMesh = function ( path, name, meshEntry, decodeParams, callback ) {
+
+    var loader = this;
+    var idx = 0;
+
+    function onprogress( req, e ) {
+
+        while ( idx < meshEntry.length ) {
+
+            var meshParams = meshEntry[ idx ];
+            var indexRange = meshParams.indexRange;
+
+            if ( indexRange ) {
+
+                var meshEnd = indexRange[ 0 ] + 3 * indexRange[ 1 ];
+
+                if ( req.responseText.length < meshEnd ) break;
+
+                loader.decompressMesh( req.responseText, meshParams, decodeParams, name, idx, callback );
+
+            } else {
+
+                var codeRange = meshParams.codeRange;
+                var meshEnd = codeRange[ 0 ] + codeRange[ 1 ];
+
+                if ( req.responseText.length < meshEnd ) break;
+
+                loader.decompressMesh2( req.responseText, meshParams, decodeParams, name, idx, callback );
+            }
+
+            ++idx;
+
+        }
+
+    };
 
-		};
+    getHttpRequest( path, function( req, e ) {
 
-		function init_normals( data, stride, offset ) {
+        if ( req.status === 200 || req.status === 0 ) {
 
-			var i, x, y, z,
-				end = data.length;
+            onprogress( req, e );
 
-			for( i = offset; i < end; i += stride ) {
+        }
 
-				x = data[ i ];
-				y = data[ i + 1 ];
-				z = data[ i + 2 ];
+        // TODO: handle errors.
 
-				// normalize to <-1,1>
+    }, onprogress );
 
-				x = ( x - 512 ) / 511;
-				y = ( y - 512 ) / 511;
-				z = ( z - 512 ) / 511;
+};
+
+THREE.UTF8Loader.prototype.downloadMeshes = function ( path, meshUrlMap, decodeParams, callback ) {
+
+    for ( var url in meshUrlMap ) {
 
-				normals.push( x, y, z );
+        var meshEntry = meshUrlMap[url];
+        this.downloadMesh( path + url, url, meshEntry, decodeParams, callback );
 
-			}
+    }
+
+};
 
-		};
+THREE.UTF8Loader.prototype.createMeshCallback = function( materialBaseUrl, loadModelInfo, allDoneCallback ) {
 
-		function init_uvs( data, stride, offset ) {
+	var nCompletedUrls = 0;
+    var nExpectedUrls = 0;
 
-			var i, u, v,
-				end = data.length;
+    var expectedMeshesPerUrl = {};
+    var decodedMeshesPerUrl = {};
 
-			for( i = offset; i < end; i += stride ) {
+	var modelParts = {};
 
-				u = data[ i ];
-				v = data[ i + 1 ];
+	var meshUrlMap = loadModelInfo.urls;
 
-				// normalize to <0,1>
+    for ( var url in meshUrlMap ) {
 
-				u /= 1023;
-				v /= 1023;
+        expectedMeshesPerUrl[ url ] = meshUrlMap[ url ].length;
+        decodedMeshesPerUrl[ url ] = 0;
 
-				uvs.push( u, v );
+		nExpectedUrls ++;
 
-			}
+        modelParts[ url ] = new THREE.Object3D();
 
-		};
+    }
 
-		function init_faces( indices ) {
+    var model = new THREE.Object3D();
 
-			var i,
-				a, b, c,
-				u1, v1, u2, v2, u3, v3,
-				m,
-				end = indices.length;
+    // Prepare materials first...
 
-			m = 0; // all faces defaulting to material 0
+    var materialCreator = new THREE.MTLLoader.MaterialCreator( materialBaseUrl, loadModelInfo.options );
+    materialCreator.setMaterials( loadModelInfo.materials );
 
-			for( i = 0; i < end; i += 3 ) {
+    materialCreator.preload();
 
-				a = indices[ i ];
-				b = indices[ i + 1 ];
-				c = indices[ i + 2 ];
+	// Create callback for creating mesh parts
 
-				f3n( scope, normals, a, b, c, m, a, b, c );
+    var geometryCreator = new THREE.UTF8Loader.GeometryCreator();
+	var bufferGeometryCreator = new THREE.UTF8Loader.BufferGeometryCreator();
 
-				u1 = uvs[ a * 2 ];
-				v1 = uvs[ a * 2 + 1 ];
+	var meshCallback = function( name, idx, attribArray, indexArray, bboxen, meshParams ) {
 
-				u2 = uvs[ b * 2 ];
-				v2 = uvs[ b * 2 + 1 ];
+        // Got ourselves a new mesh
 
-				u3 = uvs[ c * 2 ];
-				v3 = uvs[ c * 2 + 1 ];
+        // name identifies this part of the model (url)
+        // idx is the mesh index of this mesh of the part
+        // attribArray defines the vertices
+        // indexArray defines the faces
+        // bboxen defines the bounding box
+        // meshParams contains the material info
 
-				uv3( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3 );
+		var useBuffers = loadModelInfo.options.useBuffers !== undefined ? loadModelInfo.options.useBuffers : true;
 
-			}
+		if ( useBuffers ) {
 
+			var geometry = bufferGeometryCreator.create( attribArray, indexArray );
+
+		} else {
+
+			var geometry = geometryCreator.create( attribArray, indexArray );
 
 		}
 
-	};
+        var material = materialCreator.create( meshParams.material );
+
+		var mesh = new THREE.Mesh( geometry, material );
+        modelParts[ name ].add( mesh );
+
+        //model.add(new THREE.Mesh(geometry, material));
+
+        decodedMeshesPerUrl[ name ] ++;
+
+        if ( decodedMeshesPerUrl[ name ] === expectedMeshesPerUrl[ name ] ) {
+
+            nCompletedUrls ++;
+
+            model.add( modelParts[ name ] );
+
+            if ( nCompletedUrls === nExpectedUrls ) {
+
+                // ALL DONE!!!
+
+                allDoneCallback( model );
+
+            }
 
-	function vertex ( scope, x, y, z ) {
+        }
 
-		scope.vertices.push( new THREE.Vector3( x, y, z ) );
+    };
 
-	};
+	return meshCallback;
 
-	function f3n ( scope, normals, a, b, c, mi, nai, nbi, nci ) {
+};
+
+THREE.UTF8Loader.prototype.downloadModel = function ( geometryBase, materialBase, model, callback ) {
+
+    var meshCallback = this.createMeshCallback( materialBase, model, callback );
+    this.downloadMeshes( geometryBase, model.urls, model.decodeParams, meshCallback );
+
+};
+
+THREE.UTF8Loader.prototype.downloadModelJson = function ( jsonUrl, options, callback ) {
+
+    getJsonRequest( jsonUrl, function( loaded ) {
+
+        if ( ! loaded.decodeParams ) {
+
+            if ( options && options.decodeParams ) {
+
+                loaded.decodeParams = options.decodeParams;
+
+            } else {
+
+                loaded.decodeParams = DEFAULT_DECODE_PARAMS;
+
+            }
+
+        }
+
+        loaded.options = options;
+
+        var geometryBase = jsonUrl.substr( 0, jsonUrl.lastIndexOf( "/" ) + 1 );
+        var materialBase = geometryBase;
+
+        if ( options && options.geometryBase ) {
 
-		var nax = normals[ nai * 3     ],
-			nay = normals[ nai * 3 + 1 ],
-			naz = normals[ nai * 3 + 2 ],
+            geometryBase = options.geometryBase;
 
-			nbx = normals[ nbi * 3     ],
-			nby = normals[ nbi * 3 + 1 ],
-			nbz = normals[ nbi * 3 + 2 ],
+            if ( geometryBase.charAt( geometryBase.length - 1 ) !== "/" ) {
 
-			ncx = normals[ nci * 3     ],
-			ncy = normals[ nci * 3 + 1 ],
-			ncz = normals[ nci * 3 + 2 ];
+                geometryBase = geometryBase + "/";
 
-		var na = new THREE.Vector3( nax, nay, naz ),
-			nb = new THREE.Vector3( nbx, nby, nbz ),
-			nc = new THREE.Vector3( ncx, ncy, ncz );
+            }
 
-		scope.faces.push( new THREE.Face3( a, b, c, [ na, nb, nc ], null, mi ) );
+        }
 
-	};
+        if ( options && options.materialBase ) {
 
-	function uv3 ( where, u1, v1, u2, v2, u3, v3 ) {
+            materialBase = options.materialBase;
 
-		var uv = [];
-		uv.push( new THREE.UV( u1, v1 ) );
-		uv.push( new THREE.UV( u2, v2 ) );
-		uv.push( new THREE.UV( u3, v3 ) );
-		where.push( uv );
+            if ( materialBase.charAt( materialBase.length - 1 ) !== "/" ) {
 
-	};
+                materialBase = materialBase  + "/";
 
-	Model.prototype = Object.create( THREE.Geometry.prototype );
+            }
 
-	callback( new Model() );
+        }
+
+        this.downloadModel( geometryBase, materialBase, loaded, callback );
+
+    }.bind( this ) );
 
 };
+
+// XMLHttpRequest stuff
+
+function getHttpRequest( url, onload, opt_onprogress ) {
+
+    var LISTENERS = {
+
+        load: function( e ) { onload( req, e ); },
+        progress: function( e ) { opt_onprogress( req, e ); }
+
+    };
+
+    var req = new XMLHttpRequest();
+    addListeners( req, LISTENERS );
+
+    req.open( 'GET', url, true );
+    req.send( null );
+}
+
+function getJsonRequest( url, onjson ) {
+
+    getHttpRequest( url,
+        function( e ) { onjson( JSON.parse( e.responseText ) ); },
+        function() {} );
+
+}
+
+function addListeners( dom, listeners ) {
+
+    // TODO: handle event capture, object binding.
+
+    for ( var key in listeners ) {
+
+        dom.addEventListener( key, listeners[ key ] );
+
+    }
+}

+ 6 - 6
examples/js/loaders/VTKLoader.js

@@ -15,28 +15,28 @@ THREE.VTKLoader.prototype = {
 	load: function ( url ) {
 
 		var scope = this;
-		var xhr = new XMLHttpRequest();
+		var request = new XMLHttpRequest();
 
-		xhr.addEventListener( 'load', function ( event ) {
+		request.addEventListener( 'load', function ( event ) {
 
 			scope.dispatchEvent( { type: 'load', content: scope.parse( event.target.responseText ) } );
 
 		}, false );
 
-		xhr.addEventListener( 'progress', function ( event ) {
+		request.addEventListener( 'progress', function ( event ) {
 
 			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
 
 		}, false );
 
-		xhr.addEventListener( 'error', function () {
+		request.addEventListener( 'error', function () {
 
 			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
 
 		}, false );
 
-		xhr.open( 'GET', url, true );
-		xhr.send( null );
+		request.open( 'GET', url, true );
+		request.send( null );
 
 	},
 

+ 8 - 7
examples/js/loaders/ctm/CTMLoader.js

@@ -18,13 +18,13 @@ THREE.CTMLoader.prototype = Object.create( THREE.Loader.prototype );
 
 // Load multiple CTM parts defined in JSON
 
-THREE.CTMLoader.prototype.loadParts = function( url, callback, useWorker, useBuffers, basePath ) {
+THREE.CTMLoader.prototype.loadParts = function( url, callback, parameters ) {
 
 	var scope = this;
 
 	var xhr = new XMLHttpRequest();
 
-	basePath = basePath ? basePath : this.extractUrlBase( url );
+	var basePath = parameters.basePath ? parameters.basePath : this.extractUrlBase( url );
 
 	xhr.onreadystatechange = function() {
 
@@ -62,7 +62,8 @@ THREE.CTMLoader.prototype.loadParts = function( url, callback, useWorker, useBuf
 				// load joined CTM file
 
 				var partUrl = basePath + jsonObject.data;
-				scope.load( partUrl, callbackFinal, useWorker, useBuffers, jsonObject.offsets );
+				var parametersPart = { useWorker: parameters.useWorker, useBuffers: parameters.useBuffers, offsets: jsonObject.offsets };
+				scope.load( partUrl, callbackFinal, parametersPart );
 
 			}
 
@@ -82,11 +83,12 @@ THREE.CTMLoader.prototype.loadParts = function( url, callback, useWorker, useBuf
 //		- url (required)
 //		- callback (required)
 
-THREE.CTMLoader.prototype.load = function( url, callback, useWorker, useBuffers, offsets ) {
+THREE.CTMLoader.prototype.load = function( url, callback, parameters ) {
 
 	var scope = this;
 
-	offsets = offsets !== undefined ? offsets : [ 0 ];
+	var offsets = parameters.offsets !== undefined ? parameters.offsets : [ 0 ];
+	var useBuffers = parameters.useBuffers !== undefined ? parameters.useBuffers : true;
 
 	var xhr = new XMLHttpRequest(),
 		callbackProgress = null;
@@ -103,7 +105,7 @@ THREE.CTMLoader.prototype.load = function( url, callback, useWorker, useBuffers,
 
 				//var s = Date.now();
 
-				if ( useWorker ) {
+				if ( parameters.useWorker ) {
 
 					var worker = new Worker( "js/loaders/ctm/CTMWorker.js" );
 
@@ -136,7 +138,6 @@ THREE.CTMLoader.prototype.load = function( url, callback, useWorker, useBuffers,
 
 				} else {
 
-
 					for ( var i = 0; i < offsets.length; i ++ ) {
 
 						var stream = new CTM.Stream( binaryData );

+ 3 - 3
examples/js/postprocessing/BloomPass.js

@@ -67,7 +67,7 @@ THREE.BloomPass.prototype = {
 
 		THREE.EffectComposer.quad.material = this.materialConvolution;
 
-		this.convolutionUniforms[ "tDiffuse" ].texture = readBuffer;
+		this.convolutionUniforms[ "tDiffuse" ].value = readBuffer;
 		this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurX;
 
 		renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, this.renderTargetX, true );
@@ -75,7 +75,7 @@ THREE.BloomPass.prototype = {
 
 		// Render quad with blured scene into texture (convolution pass 2)
 
-		this.convolutionUniforms[ "tDiffuse" ].texture = this.renderTargetX;
+		this.convolutionUniforms[ "tDiffuse" ].value = this.renderTargetX;
 		this.convolutionUniforms[ "uImageIncrement" ].value = THREE.BloomPass.blurY;
 
 		renderer.render( THREE.EffectComposer.scene, THREE.EffectComposer.camera, this.renderTargetY, true );
@@ -84,7 +84,7 @@ THREE.BloomPass.prototype = {
 
 		THREE.EffectComposer.quad.material = this.materialScreen;
 
-		this.screenUniforms[ "tDiffuse" ].texture = this.renderTargetY;
+		this.screenUniforms[ "tDiffuse" ].value = this.renderTargetY;
 
 		if ( maskActive ) renderer.context.enable( renderer.context.STENCIL_TEST );
 

+ 1 - 1
examples/js/postprocessing/DotScreenPass.js

@@ -32,7 +32,7 @@ THREE.DotScreenPass.prototype = {
 
 	render: function ( renderer, writeBuffer, readBuffer, delta ) {
 
-		this.uniforms[ "tDiffuse" ].texture = readBuffer;
+		this.uniforms[ "tDiffuse" ].value = readBuffer;
 		this.uniforms[ "tSize" ].value.set( readBuffer.width, readBuffer.height );
 
 		THREE.EffectComposer.quad.material = this.material;

+ 1 - 1
examples/js/postprocessing/FilmPass.js

@@ -31,7 +31,7 @@ THREE.FilmPass.prototype = {
 
 	render: function ( renderer, writeBuffer, readBuffer, delta ) {
 
-		this.uniforms[ "tDiffuse" ].texture = readBuffer;
+		this.uniforms[ "tDiffuse" ].value = readBuffer;
 		this.uniforms[ "time" ].value += delta;
 
 		THREE.EffectComposer.quad.material = this.material;

+ 1 - 1
examples/js/postprocessing/SavePass.js

@@ -39,7 +39,7 @@ THREE.SavePass.prototype = {
 
 		if ( this.uniforms[ this.textureID ] ) {
 
-			this.uniforms[ this.textureID ].texture = readBuffer;
+			this.uniforms[ this.textureID ].value = readBuffer;
 
 		}
 

+ 1 - 1
examples/js/postprocessing/ShaderPass.js

@@ -30,7 +30,7 @@ THREE.ShaderPass.prototype = {
 
 		if ( this.uniforms[ this.textureID ] ) {
 
-			this.uniforms[ this.textureID ].texture = readBuffer;
+			this.uniforms[ this.textureID ].value = readBuffer;
 
 		}
 

+ 1 - 1
examples/js/postprocessing/TexturePass.js

@@ -9,7 +9,7 @@ THREE.TexturePass = function ( texture, opacity ) {
 	this.uniforms = THREE.UniformsUtils.clone( shader.uniforms );
 
 	this.uniforms[ "opacity" ].value = ( opacity !== undefined ) ? opacity : 1.0;
-	this.uniforms[ "tDiffuse" ].texture = texture;
+	this.uniforms[ "tDiffuse" ].value = texture;
 
 	this.material = new THREE.ShaderMaterial( {
 

+ 153 - 0
examples/js/renderers/CSS3DRenderer.js

@@ -0,0 +1,153 @@
+/**
+ * Based on http://www.emagix.net/academic/mscs-project/item/camera-sync-with-css3-and-webgl-threejs
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.CSS3DObject = function ( element ) {
+
+	THREE.Object3D.call( this );
+
+	this.element = element;
+	this.element.style.position = "absolute";
+	this.element.style.WebkitTransformStyle = 'preserve-3d';
+	this.element.style.MozTransformStyle = 'preserve-3d';
+	this.element.style.oTransformStyle = 'preserve-3d';
+
+};
+
+THREE.CSS3DObject.prototype = Object.create( THREE.Object3D.prototype );
+
+//
+
+THREE.CSS3DRenderer = function () {
+
+	console.log( 'THREE.CSS3DRenderer', THREE.REVISION );
+
+	var _width, _height;
+	var _widthHalf, _heightHalf;
+	var _projector = new THREE.Projector();
+
+	this.domElement = document.createElement( 'div' );
+
+	this.domElement.style.WebkitTransformStyle = 'preserve-3d';
+	this.domElement.style.WebkitPerspectiveOrigin = '50% 50%';
+
+	this.domElement.style.MozTransformStyle = 'preserve-3d';
+	this.domElement.style.MozPerspectiveOrigin = '50% 50%';
+
+	this.domElement.style.oTransformStyle = 'preserve-3d';
+	this.domElement.style.oPerspectiveOrigin = '50% 50%';
+
+	// TODO: Shouldn't it be possible to remove cameraElement?
+
+	this.cameraElement = document.createElement( 'div' );
+	this.cameraElement.style.WebkitTransformStyle = 'preserve-3d';
+	this.cameraElement.style.MozTransformStyle = 'preserve-3d';
+	this.cameraElement.style.oTransformStyle = 'preserve-3d';
+
+	this.domElement.appendChild( this.cameraElement );
+
+	this.setSize = function ( width, height ) {
+
+		_width = width;
+		_height = height;
+
+		_widthHalf = _width / 2;
+		_heightHalf = _height / 2;
+
+		this.domElement.style.width = width + 'px';
+		this.domElement.style.height = height + 'px';
+
+		this.cameraElement.style.width = width + 'px';
+		this.cameraElement.style.height = height + 'px';
+
+	};
+
+	var epsilon = function ( value ) {
+
+		return Math.abs( value ) < 0.000001 ? 0 : value;
+
+        }
+
+	var getCameraCSSMatrix = function ( matrix ) {
+
+		var elements = matrix.elements;
+
+		return 'matrix3d(' +
+			epsilon( elements[ 0 ] ) + ',' +
+			epsilon( - elements[ 1 ] ) + ',' +
+			epsilon( elements[ 2 ] ) + ',' +
+			epsilon( elements[ 3 ] ) + ',' +
+			epsilon( elements[ 4 ] ) + ',' +
+			epsilon( - elements[ 5 ] ) + ',' +
+			epsilon( elements[ 6 ] ) + ',' +
+			epsilon( elements[ 7 ] ) + ',' +
+			epsilon( elements[ 8 ] ) + ',' +
+			epsilon( - elements[ 9 ] ) + ',' +
+			epsilon( elements[ 10 ] ) + ',' +
+			epsilon( elements[ 11 ] ) + ',' +
+			epsilon( elements[ 12 ] ) + ',' +
+			epsilon( - elements[ 13 ] ) + ',' +
+			epsilon( elements[ 14 ] ) + ',' +
+			epsilon( elements[ 15 ] ) +
+		')';
+
+	}
+
+	var getObjectCSSMatrix = function ( matrix ) {
+
+		var elements = matrix.elements;
+
+		return 'translate3d(-50%,-50%,0) scale3d(1,-1,1) matrix3d(' +
+			epsilon( elements[ 0 ] ) + ',' +
+			epsilon( elements[ 1 ] ) + ',' +
+			epsilon( elements[ 2 ] ) + ',' +
+			epsilon( elements[ 3 ] ) + ',' +
+			epsilon( elements[ 4 ] ) + ',' +
+			epsilon( elements[ 5 ] ) + ',' +
+			epsilon( elements[ 6 ] ) + ',' +
+			epsilon( elements[ 7 ] ) + ',' +
+			epsilon( elements[ 8 ] ) + ',' +
+			epsilon( elements[ 9 ] ) + ',' +
+			epsilon( elements[ 10 ] ) + ',' +
+			epsilon( elements[ 11 ] ) + ',' +
+			epsilon( elements[ 12 ] ) + ',' +
+			epsilon( elements[ 13 ] ) + ',' +
+			epsilon( elements[ 14 ] ) + ',' +
+			epsilon( elements[ 15 ] ) +
+		')';
+
+	}
+
+	this.render = function ( scene, camera ) {
+
+		var fov = 0.5 / Math.tan( camera.fov * Math.PI / 360 ) * _height;
+
+		this.domElement.style.WebkitPerspective = fov + "px";
+		this.domElement.style.MozPerspective = fov + "px";
+		this.domElement.style.oPerspective = fov + "px";
+
+		var style = "translate3d(0,0," + fov + "px)" + getCameraCSSMatrix( camera.matrixWorldInverse ) + " translate3d(" + _widthHalf + "px," + _heightHalf + "px, 0)";
+
+		this.cameraElement.style.WebkitTransform = style;
+		this.cameraElement.style.MozTransform = style;
+		this.cameraElement.style.oTransform = style;
+
+		var objects = _projector.projectScene( scene, camera, false ).objects;
+
+		for ( var i = 0, il = objects.length; i < il; i ++ ) {
+
+			var object = objects[ i ].object;
+			var element = object.element;
+
+			style = getObjectCSSMatrix( object.matrixWorld );
+
+			element.style.WebkitTransform = style;
+			element.style.MozTransform = style;
+			element.style.oTransform = style;
+
+		}
+
+	};
+
+};

+ 1 - 1
examples/js/renderers/DOMRenderer.js

@@ -1,5 +1,5 @@
 /**
- * @author mr.doob / http://mrdoob.com/
+ * @author mrdoob / http://mrdoob.com/
  */
 
 THREE.DOMRenderer = function () {

+ 14 - 8
examples/js/renderers/SVGRenderer.js

@@ -1,5 +1,5 @@
 /**
- * @author mr.doob / http://mrdoob.com/
+ * @author mrdoob / http://mrdoob.com/
  */
 
 THREE.SVGRenderer = function () {
@@ -97,7 +97,7 @@ THREE.SVGRenderer = function () {
 		_this.info.render.vertices = 0;
 		_this.info.render.faces = 0;
 
-		_renderData = _projector.projectScene( scene, camera, this.sortElements );
+		_renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements );
 		_elements = _renderData.elements;
 		_lights = _renderData.lights;
 
@@ -350,15 +350,18 @@ THREE.SVGRenderer = function () {
 
 			if ( _enableLighting ) {
 
+				var diffuse = material.color;
+				var emissive = material.emissive;
+
 				_color.r = _ambientLight.r;
 				_color.g = _ambientLight.g;
 				_color.b = _ambientLight.b;
 
 				calculateLight( _lights, element.centroidWorld, element.normalWorld, _color );
 
-				_color.r = Math.max( 0, Math.min( material.color.r * _color.r, 1 ) );
-				_color.g = Math.max( 0, Math.min( material.color.g * _color.g, 1 ) );
-				_color.b = Math.max( 0, Math.min( material.color.b * _color.b, 1 ) );
+				_color.r = diffuse.r * _color.r + emissive.r;
+				_color.g = diffuse.g * _color.g + emissive.g;
+				_color.b = diffuse.b * _color.b + emissive.b;
 
 			} else {
 
@@ -407,15 +410,18 @@ THREE.SVGRenderer = function () {
 
 			if ( _enableLighting ) {
 
+				var diffuse = material.color;
+				var emissive = material.emissive;
+
 				_color.r = _ambientLight.r;
 				_color.g = _ambientLight.g;
 				_color.b = _ambientLight.b;
 
 				calculateLight( _lights, element.centroidWorld, element.normalWorld, _color );
 
-				_color.r = Math.max( 0, Math.min( material.color.r * _color.r, 1 ) );
-				_color.g = Math.max( 0, Math.min( material.color.g * _color.g, 1 ) );
-				_color.b = Math.max( 0, Math.min( material.color.b * _color.b, 1 ) );
+				_color.r = diffuse.r * _color.r + emissive.r;
+				_color.g = diffuse.g * _color.g + emissive.g;
+				_color.b = diffuse.b * _color.b + emissive.b;
 
 			} else {
 

+ 1 - 1
examples/js/renderers/SoftwareRenderer.js

@@ -1,5 +1,5 @@
 /**
- * @author mr.doob / http://mrdoob.com/
+ * @author mrdoob / http://mrdoob.com/
  */
 
 THREE.SoftwareRenderer = function () {

+ 1 - 1
examples/js/renderers/SoftwareRenderer2.js

@@ -1,5 +1,5 @@
 /**
- * @author mr.doob / http://mrdoob.com/
+ * @author mrdoob / http://mrdoob.com/
  */
 
 THREE.SoftwareRenderer2 = function () {

+ 1 - 1
examples/js/renderers/SoftwareRenderer3.js

@@ -1,5 +1,5 @@
 /**
- * @author mr.doob / http://mrdoob.com/
+ * @author mrdoob / http://mrdoob.com/
  */
 
 THREE.SoftwareRenderer3 = function () {

+ 4 - 4
examples/misc_camera_fly.html

@@ -117,11 +117,11 @@
 				var shader = THREE.ShaderUtils.lib[ "normal" ];
 				var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
 
-				uniforms[ "tNormal" ].texture = normalTexture;
-				uniforms[ "uNormalScale" ].value = 0.85;
+				uniforms[ "tNormal" ].value = normalTexture;
+				uniforms[ "uNormalScale" ].value.set( 0.85, 0.85 );
 
-				uniforms[ "tDiffuse" ].texture = planetTexture;
-				uniforms[ "tSpecular" ].texture = specularTexture;
+				uniforms[ "tDiffuse" ].value = planetTexture;
+				uniforms[ "tSpecular" ].value = specularTexture;
 
 				uniforms[ "enableAO" ].value = false;
 				uniforms[ "enableDiffuse" ].value = true;

+ 102 - 0
examples/misc_css3d.html

@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<html>
+	<head>
+		<meta charset="utf-8">
+		<style>
+			body {
+				background-color: #ffffff;
+				margin: 0;
+				overflow: hidden;
+			}
+		</style>
+	</head>
+	<body>
+		<script src="../build/three.min.js"></script>
+		<script src="js/renderers/CSS3DRenderer.js"></script>
+		<script>
+
+			var camera, scene, renderer;
+			var geometry, material, mesh;
+
+			var scene2, renderer2;
+
+			var controls;
+
+			init();
+			animate();
+
+			function init() {
+
+				camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 );
+				camera.position.set( 200, 200, 200 );
+
+				scene = new THREE.Scene();
+
+				geometry = new THREE.CubeGeometry( 200, 200, 200 );
+				material = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, wireframeLinewidth: 1 } );
+
+				mesh = new THREE.Mesh( geometry, material );
+				scene.add( mesh );
+
+				renderer = new THREE.CanvasRenderer();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				document.body.appendChild( renderer.domElement );
+
+				//
+
+				scene2 = new THREE.Scene();
+
+				renderer2 = new THREE.CSS3DRenderer();
+				renderer2.setSize( window.innerWidth, window.innerHeight );
+				renderer2.domElement.style.position = 'absolute';
+				renderer2.domElement.style.top = 0;
+				document.body.appendChild( renderer2.domElement );
+
+				for ( var i = 0; i < 20; i ++ ) {
+
+					var element = document.createElement( 'div' );
+					element.style.width = '100px';
+					element.style.height = '100px';
+					element.style.background = new THREE.Color( Math.random() * 0xffffff ).getContextStyle();
+					renderer2.cameraElement.appendChild( element );
+
+					var object = new THREE.CSS3DObject( element );
+					object.position.x = Math.random() * 200 - 100;
+					object.position.y = Math.random() * 200 - 100;
+					object.position.z = Math.random() * 200 - 100;
+					object.scale.x = Math.random() + 0.5;
+					object.scale.y = Math.random() + 0.5;
+					scene2.add( object );
+
+				}
+
+				controls = new THREE.TrackballControls( camera );
+
+				controls.rotateSpeed = 1.0;
+				controls.zoomSpeed = 1.2;
+				controls.panSpeed = 0.8;
+
+				controls.noZoom = false;
+				controls.noPan = false;
+
+				controls.staticMoving = false;
+				controls.dynamicDampingFactor = 0.3;
+
+				controls.keys = [ 65, 83, 68 ];
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				controls.update();
+
+				renderer.render( scene, camera );
+				renderer2.render( scene2, camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 12 - 6
examples/misc_ubiquity_test.html

@@ -17,20 +17,21 @@
 		<script src="../build/three.min.js"></script>
 
 		<script src="js/renderers/SVGRenderer.js"></script>
+		<script src="js/renderers/SoftwareRenderer3.js"></script>
 		<script src="js/Stats.js"></script>
 
 		<script src="obj/Qrcode.js"></script>
 
 		<script>
 
-			var SCREEN_WIDTH = window.innerWidth / 3;
-			var SCREEN_HEIGHT = window.innerHeight;
+			var SCREEN_WIDTH = window.innerWidth / 2;
+			var SCREEN_HEIGHT = window.innerHeight / 2;
 			var AMOUNT = 100;
 
 			var container, stats;
 
 			var camera, scene;
-			var canvasRenderer, svgRenderer, webglRenderer;
+			var canvasRenderer, svgRenderer, softwareRenderer, webglRenderer;
 
 			var mesh, group, qrcode;
 
@@ -144,9 +145,12 @@
 				svgRenderer.setQuality( 'low' );
 				container.appendChild( svgRenderer.domElement );
 
+				softwareRenderer = new THREE.SoftwareRenderer3();
+				softwareRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+				container.appendChild( softwareRenderer.domElement );
+
 				webglRenderer = new THREE.WebGLRenderer( { antialias: true } );
 				webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
-				// webglRenderer.setFaceCulling( 0 );
 				container.appendChild( webglRenderer.domElement );
 
 				stats = new Stats();
@@ -167,14 +171,15 @@
 				windowHalfX = window.innerWidth / 2;
 				windowHalfY = window.innerHeight / 2;
 
-				SCREEN_WIDTH = window.innerWidth / 3;
-				SCREEN_HEIGHT = window.innerHeight;
+				SCREEN_WIDTH = window.innerWidth / 2;
+				SCREEN_HEIGHT = window.innerHeight / 2;
 
 				camera.aspect = SCREEN_WIDTH / window.SCREEN_HEIGHT;
 				camera.updateProjectionMatrix();
 
 				canvasRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				svgRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+				softwareRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				webglRenderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 			}
@@ -212,6 +217,7 @@
 
 				canvasRenderer.render( scene, camera );
 				svgRenderer.render( scene, camera );
+				softwareRenderer.render( scene, camera );
 				webglRenderer.render( scene, camera );
 
 			}

BIN
examples/models/utf8/James_Body_Lores.jpg


BIN
examples/models/utf8/James_EyeLashBotTran.png


BIN
examples/models/utf8/James_EyeLashTopTran.png


BIN
examples/models/utf8/James_Eye_Green.jpg


BIN
examples/models/utf8/James_Eye_Inner_Green.jpg


BIN
examples/models/utf8/James_Face_Color_Hair_Lores.jpg


BIN
examples/models/utf8/James_Mouth_Gum_Lores.jpg


BIN
examples/models/utf8/James_Tongue_Lores.jpg


BIN
examples/models/utf8/MCasShoe1TEX_Lores.jpg


BIN
examples/models/utf8/MJeans1TEX_Lores.jpg


BIN
examples/models/utf8/MTshirt3TEX_Lores.jpg


BIN
examples/models/utf8/Nail_Hand_01_Lores.jpg


+ 107 - 0
examples/models/utf8/ben.js

@@ -0,0 +1,107 @@
+{
+  "materials": {
+    "gums": { "map_Kd": "James_Mouth_Gum_Lores.jpg" },
+    "tongue": { "map_Kd": "James_Tongue_Lores.jpg" },
+    "teethbottom": { "Kd": [251, 248, 248] },
+    "teethtop": { "Kd": [251, 248, 248] },
+    "topeyelashes": { "Kd": [66, 52, 42], "map_Kd": "James_EyeLashTopTran.png", "d": 0.999 },
+    "bottomeyelashes": { "Kd": [66, 52, 42], "map_Kd": "James_EyeLashBotTran.png", "d": 0.999 },
+    "head": { "map_Kd": "James_Face_Color_Hair_Lores.jpg", "Ks": [25,25,25], "Ns": 70 },
+    "eyetrans": { "Kd": [0, 0, 0] },
+    "pupil": { "Kd": [1, 1, 1] },
+    "iris": { "map_Kd": "James_Eye_Inner_Green.jpg" },
+    "eyeball": { "map_Kd": "James_Eye_Green.jpg" },
+    "pants": { "map_Kd": "MJeans1TEX_Lores.jpg", "Ks": [30,30,30], "Ns": 20 },
+    "tshirt3": { "map_Kd": "MTshirt3TEX_Lores.jpg", "Ks": [30,30,30], "Ns": 20 },
+    "skinbody": { "map_Kd": "James_Body_Lores.jpg", "Ks": [25,25,25], "Ns": 70 },
+    "fingernails": { "map_Kd": "Nail_Hand_01_Lores.jpg" },
+    "soleshoe": { "map_Kd": "MCasShoe1TEX_Lores.jpg" },
+    "sole": { "map_Kd": "MCasShoe1TEX_Lores.jpg" },
+    "laces": { "map_Kd": "MCasShoe1TEX_Lores.jpg" },
+    "bow": { "map_Kd": "MCasShoe1TEX_Lores.jpg" }
+  },
+  "decodeParams": {
+    "decodeOffsets": [-2533,-149,-6225,0,0,-511,-511,-511],
+    "decodeScales": [0.000043,0.000043,0.000043,0.000978,0.000978,0.001957,0.001957,0.001957]
+  },
+  "urls": {
+    "ben.utf8": [
+      { "material": "bottomeyelashes",
+        "attribRange": [0, 130],
+        "codeRange": [1040, 388, 192]
+      },
+      { "material": "bow",
+        "attribRange": [1428, 1848],
+        "codeRange": [16212, 6457, 3224]
+      },
+      { "material": "eyeball",
+        "attribRange": [22669, 3834],
+        "codeRange": [53341, 14697, 7284]
+      },
+      { "material": "eyetrans",
+        "attribRange": [68038, 5248],
+        "codeRange": [110022, 20180, 9964]
+      },
+      { "material": "fingernails",
+        "attribRange": [130202, 1023],
+        "codeRange": [138386, 2669, 1228]
+      },
+      { "material": "gums",
+        "attribRange": [141055, 1446],
+        "codeRange": [152623, 5270, 2624]
+      },
+      { "material": "head",
+        "attribRange": [157893, 2219],
+        "codeRange": [175645, 8353, 4168]
+      },
+      { "material": "iris",
+        "attribRange": [183998, 902],
+        "codeRange": [191214, 3332, 1664]
+      },
+      { "material": "laces",
+        "attribRange": [194546, 1016],
+        "codeRange": [202674, 3590, 1792]
+      },
+      { "material": "pants",
+        "attribRange": [206264, 8200],
+        "codeRange": [271864, 30625, 15293]
+      },
+      { "material": "pupil",
+        "attribRange": [302489, 148],
+        "codeRange": [303673, 581, 288]
+      },
+      { "material": "skinbody",
+        "attribRange": [304254, 4990],
+        "codeRange": [344174, 15770, 7830]
+      },
+      { "material": "sole",
+        "attribRange": [359944, 2588],
+        "codeRange": [380648, 9345, 4668]
+      },
+      { "material": "soleshoe",
+        "attribRange": [389993, 3164],
+        "codeRange": [415305, 10721, 5352]
+      },
+      { "material": "teethbottom",
+        "attribRange": [426026, 1235],
+        "codeRange": [435906, 3513, 1656]
+      },
+      { "material": "teethtop",
+        "attribRange": [439419, 1666],
+        "codeRange": [452747, 3937, 1816]
+      },
+      { "material": "tongue",
+        "attribRange": [456684, 845],
+        "codeRange": [463444, 3162, 1578]
+      },
+      { "material": "topeyelashes",
+        "attribRange": [466606, 130],
+        "codeRange": [467646, 388, 192]
+      },
+      { "material": "tshirt3",
+        "attribRange": [468034, 4283],
+        "codeRange": [502298, 14470, 7216]
+      }
+    ]
+  }
+}

BIN
examples/models/utf8/ben.utf8


+ 107 - 0
examples/models/utf8/ben_dds.js

@@ -0,0 +1,107 @@
+{
+  "materials": {
+    "gums": { "map_Kd": "dds/James_Mouth_Gum_Lores.dds" },
+    "tongue": { "map_Kd": "dds/James_Tongue_Lores.dds" },
+    "teethbottom": { "Kd": [251, 248, 248] },
+    "teethtop": { "Kd": [251, 248, 248] },
+    "topeyelashes": { "Kd": [66, 52, 42], "map_Kd": "dds/James_EyeLashTopTran.dds", "d": 0.999 },
+    "bottomeyelashes": { "Kd": [66, 52, 42], "map_Kd": "dds/James_EyeLashBotTran.dds", "d": 0.999 },
+    "head": { "map_Kd": "dds/James_Face_Color_Hair_Lores.dds", "Ks": [25,25,25], "Ns": 70 },
+    "eyetrans": { "Kd": [0, 0, 0] },
+    "pupil": { "Kd": [1, 1, 1] },
+    "iris": { "map_Kd": "dds/James_Eye_Inner_Green.dds" },
+    "eyeball": { "map_Kd": "dds/James_Eye_Green.dds" },
+    "pants": { "map_Kd": "dds/MJeans1TEX_Lores.dds", "Ks": [30,30,30], "Ns": 20 },
+    "tshirt3": { "map_Kd": "dds/MTshirt3TEX_Lores.dds", "Ks": [30,30,30], "Ns": 20 },
+    "skinbody": { "map_Kd": "dds/James_Body_Lores.dds", "Ks": [25,25,25], "Ns": 70 },
+    "fingernails": { "map_Kd": "dds/Nail_Hand_01_Lores.dds" },
+    "soleshoe": { "map_Kd": "dds/MCasShoe1TEX_Lores.dds" },
+    "sole": { "map_Kd": "dds/MCasShoe1TEX_Lores.dds" },
+    "laces": { "map_Kd": "dds/MCasShoe1TEX_Lores.dds" },
+    "bow": { "map_Kd": "dds/MCasShoe1TEX_Lores.dds" }
+  },
+  "decodeParams": {
+    "decodeOffsets": [-2533,-149,-6225,0,0,-511,-511,-511],
+    "decodeScales": [0.000043,0.000043,0.000043,0.000978,0.000978,0.001957,0.001957,0.001957]
+  },
+  "urls": {
+    "ben.utf8": [
+      { "material": "bottomeyelashes",
+        "attribRange": [0, 130],
+        "codeRange": [1040, 388, 192]
+      },
+      { "material": "bow",
+        "attribRange": [1428, 1848],
+        "codeRange": [16212, 6457, 3224]
+      },
+      { "material": "eyeball",
+        "attribRange": [22669, 3834],
+        "codeRange": [53341, 14697, 7284]
+      },
+      { "material": "eyetrans",
+        "attribRange": [68038, 5248],
+        "codeRange": [110022, 20180, 9964]
+      },
+      { "material": "fingernails",
+        "attribRange": [130202, 1023],
+        "codeRange": [138386, 2669, 1228]
+      },
+      { "material": "gums",
+        "attribRange": [141055, 1446],
+        "codeRange": [152623, 5270, 2624]
+      },
+      { "material": "head",
+        "attribRange": [157893, 2219],
+        "codeRange": [175645, 8353, 4168]
+      },
+      { "material": "iris",
+        "attribRange": [183998, 902],
+        "codeRange": [191214, 3332, 1664]
+      },
+      { "material": "laces",
+        "attribRange": [194546, 1016],
+        "codeRange": [202674, 3590, 1792]
+      },
+      { "material": "pants",
+        "attribRange": [206264, 8200],
+        "codeRange": [271864, 30625, 15293]
+      },
+      { "material": "pupil",
+        "attribRange": [302489, 148],
+        "codeRange": [303673, 581, 288]
+      },
+      { "material": "skinbody",
+        "attribRange": [304254, 4990],
+        "codeRange": [344174, 15770, 7830]
+      },
+      { "material": "sole",
+        "attribRange": [359944, 2588],
+        "codeRange": [380648, 9345, 4668]
+      },
+      { "material": "soleshoe",
+        "attribRange": [389993, 3164],
+        "codeRange": [415305, 10721, 5352]
+      },
+      { "material": "teethbottom",
+        "attribRange": [426026, 1235],
+        "codeRange": [435906, 3513, 1656]
+      },
+      { "material": "teethtop",
+        "attribRange": [439419, 1666],
+        "codeRange": [452747, 3937, 1816]
+      },
+      { "material": "tongue",
+        "attribRange": [456684, 845],
+        "codeRange": [463444, 3162, 1578]
+      },
+      { "material": "topeyelashes",
+        "attribRange": [466606, 130],
+        "codeRange": [467646, 388, 192]
+      },
+      { "material": "tshirt3",
+        "attribRange": [468034, 4283],
+        "codeRange": [502298, 14470, 7216]
+      }
+    ]
+  }
+}

BIN
examples/models/utf8/dds/James_Body_Lores.dds


BIN
examples/models/utf8/dds/James_EyeLashBotTran.dds


BIN
examples/models/utf8/dds/James_EyeLashTopTran.dds


BIN
examples/models/utf8/dds/James_Eye_Green.dds


BIN
examples/models/utf8/dds/James_Eye_Inner_Green.dds


BIN
examples/models/utf8/dds/James_Face_Color_Hair_Lores.dds


BIN
examples/models/utf8/dds/James_Mouth_Gum_Lores.dds


BIN
examples/models/utf8/dds/James_Tongue_Lores.dds


BIN
examples/models/utf8/dds/MCasShoe1TEX_Lores.dds


BIN
examples/models/utf8/dds/MJeans1TEX_Lores.dds


BIN
examples/models/utf8/dds/MTshirt3TEX_Lores.dds


BIN
examples/models/utf8/dds/Nail_Hand_01_Lores.dds


BIN
examples/models/utf8/hand.jpg


+ 27 - 0
examples/models/utf8/hand.js

@@ -0,0 +1,27 @@
+{
+  "materials": {
+    "preview": { "Kd": [184, 136, 234] },
+    "nails": { "Kd": [251, 238, 209], "map_Kd": "hand.jpg", "Ks": [30,30,30], "Ns": 100 },
+    "skin": { "Kd": [207, 181, 161],  "map_Kd": "hand.jpg", "Ks": [30,30,30], "Ns": 30 }
+  },
+  "decodeParams": {
+    "decodeOffsets": [-7473,-239,-8362,0,0,-511,-511,-511],
+    "decodeScales": [0.000050,0.000050,0.000050,0.000978,0.000978,0.001957,0.001957,0.001957]
+  },
+  "urls": {
+    "hand.utf8": [
+      { "material": "nails",
+        "attribRange": [0, 261],
+        "codeRange": [2088, 817, 404]
+      },
+      { "material": "preview",
+        "attribRange": [2905, 688],
+        "codeRange": [8409, 2570, 1280]
+      },
+      { "material": "skin",
+        "attribRange": [10979, 8899],
+        "codeRange": [82171, 31026, 15451]
+      }
+    ]
+  }
+}

BIN
examples/models/utf8/hand.utf8


+ 20 - 8
examples/obj/blenderscene/scene.Cube.js

@@ -2,15 +2,16 @@
 
     "metadata" :
     {
-        "formatVersion" : 3,
-        "generatedBy"   : "Blender 2.60 Exporter",
+        "formatVersion" : 3.1,
+        "generatedBy"   : "Blender 2.63 Exporter",
         "vertices"      : 8,
         "faces"         : 6,
         "normals"       : 0,
         "colors"        : 0,
-        "uvs"           : 0,
+        "uvs"           : [],
         "materials"     : 1,
-        "morphTargets"  : 0
+        "morphTargets"  : 0,
+        "bones"         : 0
     },
 
     "scale" : 1.000000,
@@ -19,16 +20,20 @@
 	"DbgColor" : 15658734,
 	"DbgIndex" : 0,
 	"DbgName" : "Material",
-	"colorAmbient" : [0.0, 0.0, 0.0],
+	"blending" : "NormalBlending",
+	"colorAmbient" : [0.6400000190734865, 0.10179081114814892, 0.126246120426746],
 	"colorDiffuse" : [0.6400000190734865, 0.10179081114814892, 0.126246120426746],
 	"colorSpecular" : [0.5, 0.5, 0.5],
+	"depthTest" : true,
+	"depthWrite" : true,
 	"shading" : "Lambert",
 	"specularCoef" : 50,
 	"transparency" : 1.0,
+	"transparent" : false,
 	"vertexColors" : false
 	}],
 
-    "vertices": [1.000000,1.000000,-1.000000,1.000000,-1.000000,-1.000000,-1.000000,-1.000000,-1.000000,-1.000000,1.000000,-1.000000,1.000000,1.000000,1.000000,0.999999,-1.000001,1.000000,-1.000000,-1.000000,1.000000,-1.000000,1.000000,1.000000],
+    "vertices": [1,1,-1,1,-1,-1,-1,-1,-1,-1,1,-1,1,1,1,0.999999,-1,1,-1,-1,1,-1,1,1],
 
     "morphTargets": [],
 
@@ -36,10 +41,17 @@
 
     "colors": [],
 
-    "uvs": [[]],
+    "uvs": [],
 
-    "faces": [3,0,1,2,3,0,3,4,7,6,5,0,3,0,4,5,1,0,3,1,5,6,2,0,3,2,6,7,3,0,3,4,0,3,7,0]
+    "faces": [3,0,1,2,3,0,3,4,7,6,5,0,3,0,4,5,1,0,3,1,5,6,2,0,3,2,6,7,3,0,3,4,0,3,7,0],
 
+    "bones" : [],
+
+    "skinIndices" : [],
+
+    "skinWeights" : [],
+
+    "animation" : {}
 
 
 }

File diff suppressed because it is too large
+ 10 - 5
examples/obj/blenderscene/scene.Monkey.js


+ 20 - 8
examples/obj/blenderscene/scene.Plane.js

@@ -2,15 +2,16 @@
 
     "metadata" :
     {
-        "formatVersion" : 3,
-        "generatedBy"   : "Blender 2.60 Exporter",
+        "formatVersion" : 3.1,
+        "generatedBy"   : "Blender 2.63 Exporter",
         "vertices"      : 4,
         "faces"         : 1,
         "normals"       : 0,
         "colors"        : 0,
-        "uvs"           : 0,
+        "uvs"           : [],
         "materials"     : 1,
-        "morphTargets"  : 0
+        "morphTargets"  : 0,
+        "bones"         : 0
     },
 
     "scale" : 1.000000,
@@ -19,16 +20,20 @@
 	"DbgColor" : 15658734,
 	"DbgIndex" : 0,
 	"DbgName" : "Material.001",
-	"colorAmbient" : [0.0, 0.0, 0.0],
+	"blending" : "NormalBlending",
+	"colorAmbient" : [0.14462547517754842, 0.6400000190734865, 0.24541190036254967],
 	"colorDiffuse" : [0.14462547517754842, 0.6400000190734865, 0.24541190036254967],
 	"colorSpecular" : [0.5, 0.5, 0.5],
+	"depthTest" : true,
+	"depthWrite" : true,
 	"shading" : "Lambert",
 	"specularCoef" : 50,
 	"transparency" : 1.0,
+	"transparent" : false,
 	"vertexColors" : false
 	}],
 
-    "vertices": [1.000000,1.000000,0.000000,1.000000,-1.000000,0.000000,-1.000000,-1.000000,0.000000,-1.000000,1.000000,0.000000],
+    "vertices": [1,1,0,1,-1,0,-1,-1,0,-1,1,0],
 
     "morphTargets": [],
 
@@ -36,10 +41,17 @@
 
     "colors": [],
 
-    "uvs": [[]],
+    "uvs": [],
 
-    "faces": [3,0,3,2,1,0]
+    "faces": [3,0,3,2,1,0],
 
+    "bones" : [],
+
+    "skinIndices" : [],
+
+    "skinWeights" : [],
+
+    "animation" : {}
 
 
 }

+ 194 - 194
examples/obj/blenderscene/scene.js

@@ -2,9 +2,9 @@
 
 "metadata" :
 {
-    "formatVersion" : 3,
+    "formatVersion" : 3.1,
     "sourceFile"    : "scene.blend",
-    "generatedBy"   : "Blender 2.60 Exporter",
+    "generatedBy"   : "Blender 2.63 Exporter",
     "objects"       : 27,
     "geometries"    : 3,
     "materials"     : 3,
@@ -21,378 +21,378 @@
         "geometry"  : "geo_Cube",
         "groups"    : [  ],
         "materials" : [ "Material" ],
-        "position"  : [ 10.623673, 0.321692, 3.370784 ],
-        "rotation"  : [ 0.005265, 0.056306, 1.566005 ],
-        "quaternion": [ 0.708568, -0.017992, 0.021809, 0.705076 ],
-        "scale"     : [ 8.310000, 0.120000, 4.930000 ],
+        "position"  : [ 10.6237, 0.321692, 3.37078 ],
+        "rotation"  : [ 0.00526525, 0.0563064, 1.566 ],
+        "quaternion": [ 0.708568, -0.0179916, 0.0218086, 0.705076 ],
+        "scale"     : [ 8.31, 0.12, 4.93 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.018" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ 1.702659, -5.860421, 0.680278 ],
-        "rotation"  : [ 1.413516, -0.081377, -3.079004 ],
-        "quaternion": [ 0.050177, -0.010617, -0.649485, -0.758643 ],
+        "position"  : [ 1.70266, -5.86042, 0.680278 ],
+        "rotation"  : [ 1.41352, -0.0813772, -3.079 ],
+        "quaternion": [ 0.0501767, -0.0106173, -0.649485, -0.758643 ],
         "scale"     : [ 0.435837, 0.435837, 0.435837 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.017" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ 0.081295, -5.808783, 0.639505 ],
-        "rotation"  : [ 1.413516, -0.081377, -3.079004 ],
-        "quaternion": [ 0.050177, -0.010617, -0.649485, -0.758643 ],
+        "position"  : [ 0.0812951, -5.80878, 0.639505 ],
+        "rotation"  : [ 1.41352, -0.0813772, -3.079 ],
+        "quaternion": [ 0.0501767, -0.0106173, -0.649485, -0.758643 ],
         "scale"     : [ 0.435837, 0.435837, 0.435837 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.016" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -1.569030, -5.747240, 0.619385 ],
-        "rotation"  : [ 1.413516, -0.081377, -3.079004 ],
-        "quaternion": [ 0.050177, -0.010617, -0.649485, -0.758643 ],
+        "position"  : [ -1.56903, -5.74724, 0.619385 ],
+        "rotation"  : [ 1.41352, -0.0813772, -3.079 ],
+        "quaternion": [ 0.0501767, -0.0106173, -0.649485, -0.758643 ],
         "scale"     : [ 0.435837, 0.435837, 0.435837 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.015" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -3.129120, -5.709269, 0.552267 ],
-        "rotation"  : [ 1.413516, -0.081377, -3.079004 ],
-        "quaternion": [ 0.050177, -0.010617, -0.649485, -0.758643 ],
+        "position"  : [ -3.12912, -5.70927, 0.552267 ],
+        "rotation"  : [ 1.41352, -0.0813772, -3.079 ],
+        "quaternion": [ 0.0501767, -0.0106173, -0.649485, -0.758643 ],
         "scale"     : [ 0.435837, 0.435837, 0.435837 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.014" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -6.386331, -3.004400, 0.382167 ],
-        "rotation"  : [ 1.646237, 0.058425, 1.670594 ],
-        "quaternion": [ 0.471896, 0.477057, 0.556810, 0.489585 ],
+        "position"  : [ -6.38633, -3.0044, 0.382167 ],
+        "rotation"  : [ 1.64624, 0.0584253, 1.67059 ],
+        "quaternion": [ 0.471896, 0.477057, 0.55681, 0.489585 ],
         "scale"     : [ 0.435837, 0.435837, 0.435837 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.013" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -6.499331, -1.593073, 0.471640 ],
-        "rotation"  : [ 1.646237, 0.058425, 1.670594 ],
-        "quaternion": [ 0.471896, 0.477057, 0.556810, 0.489585 ],
+        "position"  : [ -6.49933, -1.59307, 0.47164 ],
+        "rotation"  : [ 1.64624, 0.0584253, 1.67059 ],
+        "quaternion": [ 0.471896, 0.477057, 0.55681, 0.489585 ],
         "scale"     : [ 0.435837, 0.435837, 0.435837 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.012" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -6.629794, -0.234131, 0.533840 ],
-        "rotation"  : [ 1.646237, 0.058425, 1.670594 ],
-        "quaternion": [ 0.471896, 0.477057, 0.556810, 0.489585 ],
+        "position"  : [ -6.62979, -0.234131, 0.53384 ],
+        "rotation"  : [ 1.64624, 0.0584253, 1.67059 ],
+        "quaternion": [ 0.471896, 0.477057, 0.55681, 0.489585 ],
         "scale"     : [ 0.435837, 0.435837, 0.435837 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.011" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -6.713673, 1.008146, 0.629835 ],
-        "rotation"  : [ 1.646237, 0.058425, 1.670594 ],
-        "quaternion": [ 0.471896, 0.477057, 0.556810, 0.489585 ],
+        "position"  : [ -6.71367, 1.00815, 0.629835 ],
+        "rotation"  : [ 1.64624, 0.0584253, 1.67059 ],
+        "quaternion": [ 0.471896, 0.477057, 0.55681, 0.489585 ],
         "scale"     : [ 0.435837, 0.435837, 0.435837 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.010" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -2.010442, -24.343616, 1.387332 ],
-        "rotation"  : [ -1.621122, -2.949867, -0.136972 ],
-        "quaternion": [ 0.016439, -0.116140, -0.679574, -0.724169 ],
-        "scale"     : [ 9.160008, 9.160008, 9.160007 ],
+        "position"  : [ -2.01044, -24.3436, 1.38733 ],
+        "rotation"  : [ -1.62112, -2.94987, -0.136972 ],
+        "quaternion": [ 0.0164388, -0.11614, -0.679574, -0.724169 ],
+        "scale"     : [ 9.16001, 9.16001, 9.16001 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.009" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -4.292194, 7.975398, 1.826282 ],
-        "rotation"  : [ 1.594819, -0.080713, 0.213986 ],
-        "quaternion": [ 0.690920, 0.713888, 0.048328, 0.103242 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ -4.29219, 7.9754, 1.82628 ],
+        "rotation"  : [ 1.59482, -0.0807133, 0.213986 ],
+        "quaternion": [ 0.69092, 0.713888, 0.0483276, 0.103242 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.008" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ 2.151757, 8.065320, 1.891882 ],
-        "rotation"  : [ 1.594819, -0.080713, 0.213986 ],
-        "quaternion": [ 0.690920, 0.713888, 0.048328, 0.103242 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ 2.15176, 8.06532, 1.89188 ],
+        "rotation"  : [ 1.59482, -0.0807133, 0.213986 ],
+        "quaternion": [ 0.69092, 0.713888, 0.0483276, 0.103242 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.007" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -0.712512, 8.097841, 2.115002 ],
-        "rotation"  : [ 1.594819, -0.080713, 0.213986 ],
-        "quaternion": [ 0.690920, 0.713888, 0.048328, 0.103242 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ -0.712512, 8.09784, 2.115 ],
+        "rotation"  : [ 1.59482, -0.0807133, 0.213986 ],
+        "quaternion": [ 0.69092, 0.713888, 0.0483276, 0.103242 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Cube.005" : {
         "geometry"  : "geo_Cube",
         "groups"    : [  ],
         "materials" : [ "Material" ],
-        "position"  : [ -1.000975, 8.755547, 1.319482 ],
-        "rotation"  : [ 0.000000, -0.000000, 0.000000 ],
-        "quaternion": [ 1.000000, 0.000000, 0.000000, 0.000000 ],
-        "scale"     : [ 6.130000, 0.070000, 1.690000 ],
+        "position"  : [ -1.00097, 8.75555, 1.31948 ],
+        "rotation"  : [ 0, -0, 0 ],
+        "quaternion": [ 1, 0, 0, 0 ],
+        "scale"     : [ 6.13, 0.07, 1.69 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Cube.004" : {
         "geometry"  : "geo_Cube",
         "groups"    : [  ],
         "materials" : [ "Material" ],
-        "position"  : [ 2.484517, -7.486932, 2.724846 ],
-        "rotation"  : [ 0.220417, 0.075224, -0.181029 ],
-        "quaternion": [ 0.988791, 0.112836, 0.027288, -0.093898 ],
-        "scale"     : [ 0.350000, 0.890000, 3.309999 ],
+        "position"  : [ 2.48452, -7.48693, 2.72485 ],
+        "rotation"  : [ 0.220417, 0.0752244, -0.181029 ],
+        "quaternion": [ 0.988791, 0.112836, 0.0272876, -0.093898 ],
+        "scale"     : [ 0.35, 0.89, 3.31 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.006" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ 7.724935, 7.123103, 1.694883 ],
-        "rotation"  : [ 1.835590, -0.083161, 2.048913 ],
+        "position"  : [ 7.72494, 7.1231, 1.69488 ],
+        "rotation"  : [ 1.83559, -0.0831609, 2.04891 ],
         "quaternion": [ 0.287189, 0.433893, 0.664936, 0.535835 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.005" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -6.334642, 6.636147, 0.566791 ],
-        "rotation"  : [ 1.327136, 0.032561, -2.147285 ],
+        "position"  : [ -6.33464, 6.63615, 0.566791 ],
+        "rotation"  : [ 1.32714, 0.0325614, -2.14729 ],
         "quaternion": [ 0.366859, 0.304988, -0.535181, -0.697122 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.004" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -5.384042, -6.194087, 0.444915 ],
-        "rotation"  : [ 0.991213, -0.181430, -1.037108 ],
-        "quaternion": [ 0.782246, 0.371851, -0.303947, -0.396780 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ -5.38404, -6.19409, 0.444915 ],
+        "rotation"  : [ 0.991213, -0.18143, -1.03711 ],
+        "quaternion": [ 0.782246, 0.371851, -0.303947, -0.39678 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.003" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ 3.147747, -4.230884, 1.014840 ],
-        "rotation"  : [ -1.422281, 2.834549, 0.213809 ],
-        "quaternion": [ 0.046369, -0.179128, 0.733783, 0.653701 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ 3.14775, -4.23088, 1.01484 ],
+        "rotation"  : [ -1.42228, 2.83455, 0.213809 ],
+        "quaternion": [ 0.0463686, -0.179128, 0.733783, 0.653701 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.002" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -2.668043, -2.153389, 3.008879 ],
-        "rotation"  : [ 1.881970, -0.457870, 2.217052 ],
-        "quaternion": [ 0.091675, 0.470648, 0.644833, 0.595211 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ -2.66804, -2.15339, 3.00888 ],
+        "rotation"  : [ 1.88197, -0.45787, 2.21705 ],
+        "quaternion": [ 0.0916755, 0.470648, 0.644833, 0.595211 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Cube.003" : {
         "geometry"  : "geo_Cube",
         "groups"    : [  ],
         "materials" : [ "Material" ],
-        "position"  : [ -3.031251, -1.943665, 0.702044 ],
-        "rotation"  : [ 1.840852, 1.811250, -0.141131 ],
+        "position"  : [ -3.03125, -1.94366, 0.702044 ],
+        "rotation"  : [ 1.84085, 1.81125, -0.141131 ],
         "quaternion": [ 0.328619, 0.523567, 0.440581, -0.650981 ],
-        "scale"     : [ 1.781142, 0.361142, 0.231142 ],
+        "scale"     : [ 1.78114, 0.361142, 0.231142 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey.001" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ 1.245307, 0.137285, 0.620196 ],
-        "rotation"  : [ 2.339869, 0.286025, 1.394760 ],
-        "quaternion": [ 0.380330, 0.662839, 0.627894, 0.147451 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ 1.24531, 0.137285, 0.620196 ],
+        "rotation"  : [ 2.33987, 0.286025, 1.39476 ],
+        "quaternion": [ 0.38033, 0.662839, 0.627894, 0.147451 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Monkey" : {
         "geometry"  : "geo_Monkey",
         "groups"    : [  ],
         "materials" : [ "Material.002" ],
-        "position"  : [ -0.282500, 4.272932, 1.813606 ],
-        "rotation"  : [ 0.646062, 0.219349, 0.010569 ],
-        "quaternion": [ 0.942751, 0.314982, 0.105460, -0.029764 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ -0.2825, 4.27293, 1.81361 ],
+        "rotation"  : [ 0.646062, 0.219349, 0.0105691 ],
+        "quaternion": [ 0.942751, 0.314982, 0.10546, -0.0297641 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Cube.002" : {
         "geometry"  : "geo_Cube",
         "groups"    : [  ],
         "materials" : [ "Material" ],
-        "position"  : [ 0.042212, 0.199037, 5.536832 ],
-        "rotation"  : [ 0.000000, -0.000000, 0.000000 ],
-        "quaternion": [ 1.000000, 0.000000, 0.000000, 0.000000 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ 0.0422118, 0.199037, 5.53683 ],
+        "rotation"  : [ 0, -0, 0 ],
+        "quaternion": [ 1, 0, 0, 0 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Cube.001" : {
         "geometry"  : "geo_Cube",
         "groups"    : [  ],
         "materials" : [ "Material" ],
-        "position"  : [ -0.395497, 3.944532, 1.009696 ],
-        "rotation"  : [ 0.000000, -0.000000, 0.000000 ],
-        "quaternion": [ 1.000000, 0.000000, 0.000000, 0.000000 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ -0.395497, 3.94453, 1.0097 ],
+        "rotation"  : [ 0, -0, 0 ],
+        "quaternion": [ 1, 0, 0, 0 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Plane" : {
         "geometry"  : "geo_Plane",
         "groups"    : [  ],
         "materials" : [ "Material.001" ],
-        "position"  : [ 0.000000, -0.118260, 0.000000 ],
-        "rotation"  : [ 0.000000, -0.000000, 0.000000 ],
-        "quaternion": [ 1.000000, 0.000000, 0.000000, 0.000000 ],
-        "scale"     : [ 7.922787, 7.922787, 7.922787 ],
+        "position"  : [ 0, -0.11826, 0 ],
+        "rotation"  : [ 0, -0, 0 ],
+        "quaternion": [ 1, 0, 0, 0 ],
+        "scale"     : [ 7.92279, 7.92279, 7.92279 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     },
 
     "Cube" : {
         "geometry"  : "geo_Cube",
         "groups"    : [  ],
         "materials" : [ "Material" ],
-        "position"  : [ 3.651978, -0.000000, 1.071144 ],
-        "rotation"  : [ 0.220417, 0.075224, -0.181029 ],
-        "quaternion": [ 0.988791, 0.112836, 0.027288, -0.093898 ],
-        "scale"     : [ 1.000000, 1.000000, 1.000000 ],
+        "position"  : [ 3.65198, -1.49012e-08, 1.07114 ],
+        "rotation"  : [ 0.220417, 0.0752244, -0.181029 ],
+        "quaternion": [ 0.988791, 0.112836, 0.0272876, -0.093898 ],
+        "scale"     : [ 1, 1, 1 ],
         "visible"       : true,
-        "castsShadow"   : false,
-        "meshCollider"  : false,
-        "trigger"       : "None"
+        "castShadow"    : false,
+        "receiveShadow" : false,
+        "doubleSided"   : false
     }
 },
 
@@ -400,17 +400,17 @@
 "geometries" :
 {
     "geo_Cube" : {
-        "type" : "ascii_mesh",
+        "type" : "ascii",
         "url"  : "scene.Cube.js"
     },
 
     "geo_Monkey" : {
-        "type" : "ascii_mesh",
+        "type" : "ascii",
         "url"  : "scene.Monkey.js"
     },
 
     "geo_Plane" : {
-        "type" : "ascii_mesh",
+        "type" : "ascii",
         "url"  : "scene.Plane.js"
     }
 },
@@ -420,17 +420,17 @@
 {
     "Material" : {
         "type": "MeshLambertMaterial",
-        "parameters": { "color": 10688800, "opacity": 1 }
+        "parameters": { "color": 10688800, "opacity": 1, "blending": "NormalBlending" }
     },
 
     "Material.001" : {
         "type": "MeshLambertMaterial",
-        "parameters": { "color": 2401086, "opacity": 1 }
+        "parameters": { "color": 2401086, "opacity": 1, "blending": "NormalBlending" }
     },
 
     "Material.002" : {
         "type": "MeshLambertMaterial",
-        "parameters": { "color": 10711076, "opacity": 1 }
+        "parameters": { "color": 10711076, "opacity": 1, "blending": "NormalBlending" }
     }
 },
 
@@ -443,8 +443,8 @@
         "aspect": 1.333000,
         "near"  : 1.000000,
         "far"   : 10000.000000,
-        "position": [ 0.000000, 0.000000, 10.000000 ],
-        "target"  : [ 0.000000, 0.000000, 0.000000 ]
+        "position": [ 0, 0, 10 ],
+        "target"  : [ 0, 0, 0 ]
     }
 },
 
@@ -452,8 +452,8 @@
 "lights" :
 {
     "default_light": {
-        "type"		 : "directional",
-        "direction"	 : [ 0.000000, 1.000000, 1.000000 ],
+        "type"    	 : "directional",
+        "direction"	 : [ 0, 1, 1 ],
         "color" 	 : 16777215,
         "intensity"	 : 0.80
     }
@@ -462,14 +462,14 @@
 
 "transform" :
 {
-    "position"  : [ 0.000000, 0.000000, 0.000000 ],
-    "rotation"  : [ -1.570796, 0.000000, 0.000000 ],
-    "scale"     : [ 1.000000, 1.000000, 1.000000 ]
+    "position"  : [ 0, 0, 0 ],
+    "rotation"  : [ -1.5708, 0, 0 ],
+    "scale"     : [ 1, 1, 1 ]
 },
 
 "defaults" :
 {
-    "bgcolor" : [ 0.000000, 0.000000, 0.000000 ],
+    "bgcolor" : [ 0, 0, 0 ],
     "bgalpha" : 1.000000,
     "camera"  : "default_camera"
 }

BIN
examples/obj/lightmap/lightmap-ao-shadow.png


+ 123 - 0
examples/obj/lightmap/lightmap.js

@@ -0,0 +1,123 @@
+{
+
+    "metadata" :
+    {
+        "formatVersion" : 3.1,
+        "generatedBy"   : "Blender 2.63 Exporter",
+        "vertices"      : 20,
+        "faces"         : 13,
+        "normals"       : 0,
+        "colors"        : 0,
+        "uvs"           : 4,
+        "materials"     : 1,
+        "morphTargets"  : 0,
+        "bones"         : 0
+    },
+
+    "scale" : 1.000000,
+
+    "materials": [	{
+	"DbgColor" : 15658734,
+	"DbgIndex" : 0,
+	"DbgName" : "redstone",
+	"blending" : "NormalBlending",
+	"colorAmbient" : [0.8, 0.3736, 0.2799],
+	"colorDiffuse" : [0.8, 0.3736, 0.2799],
+	"colorSpecular" : [0.067, 0.067, 0.067],
+	"depthTest" : true,
+	"depthWrite" : true,
+	"mapLight" : "lightmap-ao-shadow.png",
+	"mapBump" : "stone.jpg",
+	"mapSpecular" : "stone.jpg",
+	"mapBumpRepeat" : [2, 2],
+	"mapSpecularRepeat" : [2, 2],
+	"mapBumpWrap" : ["repeat", "repeat"],
+	"mapSpecularWrap" : ["repeat", "repeat"],
+	"mapBumpScale" : 2,
+	"mapBumpAnisotropy": 4,
+	"mapSpecularAnisotropy": 4,
+	"mapLightAnisotropy": 4,
+	"shading" : "Phong",
+	"specularCoef" : 100,
+	"transparency" : 1.0,
+	"transparent" : false,
+	"vertexColors" : false
+	},
+
+	{
+	"DbgColor" : 15597568,
+	"DbgIndex" : 1,
+	"DbgName" : "floor",
+	"blending" : "NormalBlending",
+	"colorAmbient" : [0.8, 0.72, 0.6],
+	"colorDiffuse" : [0.8, 0.72, 0.6],
+	"colorSpecular" : [0.067, 0.067, 0.067],
+	"depthTest" : true,
+	"depthWrite" : true,
+	"mapLight" : "lightmap-ao-shadow.png",
+	"mapBump" : "stone.jpg",
+	"mapSpecular" : "stone.jpg",
+	"mapBumpRepeat" : [16, 16],
+	"mapSpecularRepeat" : [16, 16],
+	"mapBumpWrap" : ["repeat", "repeat"],
+	"mapSpecularWrap" : ["repeat", "repeat"],
+	"mapBumpScale" : 2,
+	"mapBumpAnisotropy": 4,
+	"mapSpecularAnisotropy": 4,
+	"mapLightAnisotropy": 4,
+	"shading" : "Phong",
+	"specularCoef" : 100,
+	"transparency" : 1.0,
+	"transparent" : false,
+	"vertexColors" : false
+	},
+
+	{
+	"DbgColor" : 15597568,
+	"DbgIndex" : 1,
+	"DbgName" : "stone",
+	"blending" : "NormalBlending",
+	"colorAmbient" : [0.8, 0.5184, 0.36],
+	"colorDiffuse" : [0.8, 0.5184, 0.36],
+	"colorSpecular" : [0.067, 0.067, 0.067],
+	"depthTest" : true,
+	"depthWrite" : true,
+	"mapLight" : "lightmap-ao-shadow.png",
+	"mapBump" : "rocks.jpg",
+	"mapSpecular" : "rocks.jpg",
+	"mapBumpRepeat" : [2, 2],
+	"mapSpecularRepeat" : [2, 2],
+	"mapBumpWrap" : ["repeat", "repeat"],
+	"mapSpecularWrap" : ["repeat", "repeat"],
+	"mapBumpScale" : 2,
+	"mapBumpAnisotropy": 4,
+	"mapSpecularAnisotropy": 4,
+	"mapLightAnisotropy": 4,
+	"shading" : "Phong",
+	"specularCoef" : 100,
+	"transparency" : 1.0,
+	"transparent" : false,
+	"vertexColors" : false
+	}],
+
+    "vertices": [1.85679,0.0125948,0.544906,1.85679,0.0125948,-0.544906,2.9466,0.0125948,-0.544906,2.9466,0.0125948,0.544906,1.85679,1.10241,0.544906,1.85679,1.10241,-0.544906,2.9466,1.10241,-0.544906,2.9466,1.10241,0.544906,-8.39711,-3.67049e-07,-8.39711,8.39711,-3.67049e-07,-8.39711,-8.39711,3.67049e-07,8.39711,8.39711,3.67049e-07,8.39711,1,0.0180082,-1,1,0.0180083,1,-1,0.0180083,1,-1,0.0180082,-1,1,2.01801,-1,0.999999,2.01801,1,-1,2.01801,1,-1,2.01801,-1],
+
+    "morphTargets": [],
+
+    "normals": [],
+
+    "colors": [],
+
+    "uvs": [[1,1,0,1,0,0,1,0],[0.001001,0.498999,0.248999,0.498999,0.248999,0.251001,0.001001,0.251001,0.498999,0.001001,0.251001,0.001001,0.251001,0.248999,0.498999,0.248999,0.498999,0.251001,0.251001,0.251001,0.251001,0.498999,0.498999,0.498999,0.501001,0.498999,0.748999,0.498999,0.748999,0.251001,0.501001,0.251001,0.748999,0.001001,0.501001,0.001001,0.501001,0.248999,0.748999,0.248999,0.498999,0.501001,0.251001,0.501001,0.251001,0.748999,0.498999,0.748999,0.001001,0.248999,0.248999,0.248999,0.248999,0.001001,0.001001,0.001001,0.248999,0.501001,0.001001,0.501001,0.001001,0.748999,0.248999,0.748999,0.748999,0.501001,0.501001,0.501001,0.501001,0.748999,0.748999,0.748999,0.748999,0.751001,0.501001,0.751001,0.501001,0.998999,0.748999,0.998999,0.498999,0.751001,0.251001,0.751001,0.251001,0.998999,0.498999,0.998999,0.248999,0.751001,0.001001,0.751001,0.001001,0.998999,0.248999,0.998999,0.998999,0.251001,0.751001,0.251001,0.751001,0.498999,0.998999,0.498999]],
+
+    "faces": [11,1,0,4,5,0,0,1,2,3,0,1,2,3,11,5,6,2,1,0,2,3,0,1,4,5,6,7,11,6,7,3,2,0,2,3,0,1,8,9,10,11,11,0,3,7,4,0,0,1,2,3,12,13,14,15,11,0,1,2,3,0,2,3,0,1,16,17,18,19,11,7,6,5,4,0,2,3,0,1,20,21,22,23,11,9,8,10,11,1,0,1,2,3,24,25,26,27,11,12,13,14,15,2,3,0,1,2,28,29,30,31,	11,16,19,18,17,2,3,0,1,2,32,33,34,35,11,12,16,17,13,2,3,0,1,2,36,37,38,39,11,13,17,18,14,2,3,0,1,2,40,41,42,43,11,14,18,19,15,2,3,0,1,2,44,45,46,47,11,16,12,15,19,2,3,0,1,2, 48,49,50,51],
+
+    "bones" : [],
+
+    "skinIndices" : [],
+
+    "skinWeights" : [],
+
+    "animation" : {}
+
+}

+ 4 - 0
examples/obj/lightmap/readme.txt

@@ -0,0 +1,4 @@
+Textures from:
+
+http://opengameart.org/node/7506
+http://opengameart.org/node/8038

BIN
examples/obj/lightmap/rocks.jpg


BIN
examples/obj/lightmap/stone.jpg


BIN
examples/obj/male02/01_-_Default1noCulling.dds


File diff suppressed because it is too large
+ 87 - 0
examples/obj/male02/Male02_dds.js


BIN
examples/obj/male02/male-02-1noCulling.dds


+ 56 - 0
examples/obj/male02/male02_dds.mtl

@@ -0,0 +1,56 @@
+# Material Count: 5
+newmtl _01_-_Default1noCulli__01_-_Default1noCulli
+Ns 154.901961
+Ka 0.000000 0.000000 0.000000
+Kd 0.640000 0.640000 0.640000
+Ks 0.165000 0.165000 0.165000
+Ni 1.000000
+d 1.000000
+illum 2
+map_Kd 01_-_Default1noCulling.dds
+
+
+newmtl FrontColorNoCullingID_male-02-1noCulling.JP
+Ns 154.901961
+Ka 0.000000 0.000000 0.000000
+Kd 0.800000 0.800000 0.800000
+Ks 0.165000 0.165000 0.165000
+Ni 1.000000
+d 1.000000
+illum 2
+map_Kd male-02-1noCulling.dds
+
+
+newmtl male-02-1noCullingID_male-02-1noCulling.JP
+Ns 154.901961
+Ka 0.000000 0.000000 0.000000
+Kd 0.640000 0.640000 0.640000
+Ks 0.165000 0.165000 0.165000
+Ni 1.000000
+d 1.000000
+illum 2
+map_Kd male-02-1noCulling.dds
+
+
+newmtl orig_02_-_Defaul1noCu_orig_02_-_Defaul1noCu
+Ns 154.901961
+Ka 0.000000 0.000000 0.000000
+Kd 0.640000 0.640000 0.640000
+Ks 0.165000 0.165000 0.165000
+Ni 1.000000
+d 1.000000
+illum 2
+map_Kd orig_02_-_Defaul1noCulling.dds
+
+
+newmtl FrontColorNoCullingID_orig_02_-_Defaul1noCu
+Ns 154.901961
+Ka 0.000000 0.000000 0.000000
+Kd 0.800000 0.800000 0.800000
+Ks 0.165000 0.165000 0.165000
+Ni 1.000000
+d 1.000000
+illum 2
+map_Kd orig_02_-_Defaul1noCulling.dds
+
+

BIN
examples/obj/male02/orig_02_-_Defaul1noCulling.dds


+ 208 - 16
examples/scenes/test_scene.js

@@ -1,7 +1,7 @@
 {
 
 	"metadata": {
-		"formatVersion": 3,
+		"formatVersion": 3.1,
 		"type" : "scene"
 	},
 
@@ -11,13 +11,15 @@
 
 		"cube1" : {
 			"geometry" : "cubeNormals",
-			"materials": [ "lambert_red" ],
+			"materials": [ "phong_red" ],
 			"position" : [ 0, 0, 0 ],
 			"rotation" : [ 0, -0.3, 0 ],
 			"scale"	   : [ 1, 1, 1 ],
 			"visible"  : true,
 			"properties" : {
-				"rotating" : true
+				"rotating" : true,
+				"rotateX"  : true,
+				"rotateY"  : true
 			}
 		},
 
@@ -57,6 +59,15 @@
 			"visible"  : true
 		},
 
+		"sphere_cube" : {
+			"geometry" : "sphere_uvs",
+			"materials": [ "phong_compressed_cube" ],
+			"position" : [ -30, -2, -15 ],
+			"rotation" : [ 0, 0, 0 ],
+			"scale"	   : [ 1.5, 1.5, 1.5 ],
+			"visible"  : true
+		},
+
 		"icosahedron" : {
 			"geometry" : "icosahedron",
 			"materials": [ "faceted_white" ],
@@ -66,7 +77,6 @@
 			"visible"  : true
 		},
 
-
 		"torus" : {
 			"geometry" : "torus",
 			"materials": [ "phong_orange" ],
@@ -145,12 +155,55 @@
 		"walt" : {
 			"geometry" : "WaltHead",
 			"materials": [ "lambert_cube" ],
-			"position" : [ -45, 10, 0 ],
-			"rotation" : [ 0, 0, 0 ],
+			"position" : [ -75, 10, -30 ],
+			"rotation" : [ 0, 0.5, 0 ],
 			"scale"	   : [ 0.5, 0.5, 0.5 ],
 			"visible"  : true
 		},
 
+		"ben" : {
+			"geometry" : "ben",
+			"materials": [ "phong_ben" ],
+			"position" : [ -45, -10, 0 ],
+			"rotation" : [ 0, 0.5, 0 ],
+			"scale"	   : [ 55, 55, 55 ],
+			"visible"  : true
+		},
+
+		"hand" : {
+			"geometry" : "hand",
+			"materials": [ "phong_hand" ],
+			"position" : [ -28, -1, 29 ],
+			"rotation" : [ 0, 0.5, 0 ],
+			"scale"	   : [ 12, 12, 12 ],
+			"visible"  : true,
+			"properties" : {
+				"rotating" : true,
+				"rotateY"  : true
+			}
+		},
+
+		"ninja" : {
+			"geometry" : "NinjaLo",
+			"materials": [ "phong_normal" ],
+			"position" : [ 75, 10, -30 ],
+			"rotation" : [ 0, -0.5, 0 ],
+			"scale"	   : [ 1.25, 1.25, 1.25 ],
+			"visible"  : true
+		},
+
+		"sittingBox" : {
+			"geometry" : "sittingBox",
+			"materials": [ "phong_morph" ],
+			"position" : [ -60, -10, 10 ],
+			"rotation" : [ 0, 0.5, 0 ],
+			"scale"	   : [ 23, 23, 23 ],
+			"visible"  : true,
+			"morph"	   : true,
+			"duration" : 8000,
+			"mirroredLoop" : true
+		},
+
 		"quad_bg" : {
 			"geometry" : "quad",
 			"materials": [ "textured_bg" ],
@@ -160,6 +213,24 @@
 			"visible"  : true
 		},
 
+		"quad_texture1" : {
+			"geometry" : "quad",
+			"materials": [ "textured_compressed_dxt3" ],
+			"position" : [ 15, -5, 20 ],
+			"rotation" : [ 0, 0, 0 ],
+			"scale"	   : [ 1, 1, 1 ],
+			"visible"  : true
+		},
+
+		"quad_texture2" : {
+			"geometry" : "quad",
+			"materials": [ "textured_compressed_dxt5" ],
+			"position" : [ 15, -5, 25 ],
+			"rotation" : [ 0, 0, 0 ],
+			"scale"	   : [ 1, 1, 1 ],
+			"visible"  : true
+		},
+
 		"ground" : {
 			"geometry" : "plane",
 			"materials": [ "basic_gray" ],
@@ -232,6 +303,13 @@
 			"segmentsHeight" : 16
 		},
 
+		"sphere_uvs": {
+			"type"    : "sphere",
+			"radius"  : 5,
+			"segmentsWidth"  : 32,
+			"segmentsHeight" : 16
+		},
+
 		"icosahedron": {
 			"type"    : "icosahedron",
 			"radius"  : 20,
@@ -265,17 +343,43 @@
 		},
 
 		"WaltHead": {
-			"type": "bin_mesh",
+			"type": "binary",
 			"url" : "obj/walt/WaltHead_bin.js"
 		},
 
+		"NinjaLo": {
+			"type": "binary",
+			"url" : "obj/ninja/NinjaLo_bin.js"
+		},
+
 		"veyron": {
-			"type": "bin_mesh",
+			"type": "binary",
 			"url" : "obj/veyron/VeyronNoUv_bin.js"
 		},
 
+		"sittingBox": {
+			"type": "ascii",
+			"url" : "models/animated/sittingBox.js"
+		},
+
+		"ben": {
+			"type": "ctm",
+			"url" : "models/ctm/ben.ctm",
+			"useWorkers" : true,
+			"useBuffers" : true
+		},
+
+		"hand": {
+			"type": "utf8",
+			"url" : "models/utf8/hand.utf8",
+			"scale"   : 0.815141,
+			"offsetX" : -0.371823,
+			"offsetY" : -0.011920,
+			"offsetZ" : -0.416061
+		},
+
 		"colorcube": {
-			"type": "embedded_mesh",
+			"type": "embedded",
 			"id"  : "cube_fvc"
 		}
 
@@ -336,9 +440,34 @@
 			"parameters": { "color": 16777215, "shading": "flat" }
 		},
 
-		"lambert_red": {
-			"type": "MeshLambertMaterial",
-			"parameters": { "color": 16711680 }
+		"phong_red": {
+			"type": "MeshPhongMaterial",
+			"parameters": { "color": 16711680, "specular": 16711680, "shininess": 25, "bumpMap": "texture_bump", "bumpScale": -0.75 }
+		},
+
+		"phong_ben": {
+			"type": "MeshPhongMaterial",
+			"parameters": { "color": 1118481, "ambient": 1118481, "specular": 5601245, "shininess": 12, "bumpMap": "texture_bump_repeat", "bumpScale": 0.125 }
+		},
+
+		"phong_hand": {
+			"type": "MeshPhongMaterial",
+			"parameters": { "color": 14531481, "ambient": 14531481, "specular": 2236962, "shininess": 40, "wrapAround": true, "wrapRGB": [ 0.15, 0.02, 0.01 ] }
+		},
+
+		"phong_normal": {
+			"type": "MeshPhongMaterial",
+			"parameters": { "color": 0, "specular": 16777215, "shininess": 25, "envMap": "cube_reflection", "reflectivity": 0.1, "lightMap": "texture_ao", "normalMap": "texture_normal", "normalScale": [ 1, -1 ], "displacementMap": "texture_displacement", "displacementScale": 2.436143, "displacementBias": -0.428408 }
+		},
+
+		"phong_morph": {
+			"type": "MeshPhongMaterial",
+			"parameters": { "color": 0, "ambient": 0, "specular": 16777215, "shininess": 50, "envMap": "cube_reflection", "reflectivity": 0.125, "combine": "MixOperation", "shading": "flat", "side": "double", "morphTargets": true, "morphNormals" : true }
+		},
+
+		"phong_compressed_cube": {
+			"type": "MeshPhongMaterial",
+			"parameters": { "color": 16777215, "envMap": "cube_compressed", "bumpMap": "texture_bump_repeat_2", "bumpScale": -0.1 }
 		},
 
 		"lambert_green": {
@@ -401,6 +530,16 @@
 			"parameters": { "color": 16777215, "map": "texture_bg" }
 		},
 
+		"textured_compressed_dxt3": {
+			"type": "MeshBasicMaterial",
+			"parameters": { "color": 16777215, "map": "texture_compressed_dxt3", "transparent": true }
+		},
+
+		"textured_compressed_dxt5": {
+			"type": "MeshBasicMaterial",
+			"parameters": { "color": 16777215, "map": "texture_compressed_dxt5", "transparent": true, "blending": "AdditiveBlending" }
+		},
+
 		"minecraft": {
 			"type": "MeshBasicMaterial",
 			"parameters": { "color": 16777215, "map": "texture_minecraft" }
@@ -436,8 +575,61 @@
 			"mapping": "CubeRefractionMapping"
 		},
 
+		"cube_compressed": {
+			"url": [ "textures/cube/Escher/dds/px.dds",
+					 "textures/cube/Escher/dds/nx.dds",
+					 "textures/cube/Escher/dds/py.dds",
+					 "textures/cube/Escher/dds/ny.dds",
+					 "textures/cube/Escher/dds/pz.dds",
+					 "textures/cube/Escher/dds/nz.dds"
+					]
+		},
+
 		"texture_bg": {
-			"url": "textures/cube/SwedishRoyalCastle/pz.jpg"
+			"url": "textures/cube/SwedishRoyalCastle/pz.jpg",
+			"anisotropy": 4
+		},
+
+		"texture_compressed_dxt3": {
+			"url": "textures/compressed/hepatica_dxt3_mip.dds",
+			"anisotropy": 4
+		},
+
+		"texture_compressed_dxt5": {
+			"url": "textures/compressed/explosion_dxt5_mip.dds",
+			"anisotropy": 4
+		},
+
+		"texture_bump": {
+			"url": "textures/water.jpg",
+			"anisotropy": 4
+		},
+
+		"texture_bump_repeat": {
+			"url": "textures/water.jpg",
+			"repeat" : [ 20, 20 ],
+			"anisotropy": 4
+		},
+
+		"texture_bump_repeat_2": {
+			"url": "textures/water.jpg",
+			"repeat" : [ 4, 2 ],
+			"anisotropy": 4
+		},
+
+		"texture_normal": {
+			"url": "textures/normal/ninja/normal.jpg",
+			"anisotropy": 4
+		},
+
+		"texture_ao": {
+			"url": "textures/normal/ninja/ao.jpg",
+			"anisotropy": 4
+		},
+
+		"texture_displacement": {
+			"url": "textures/normal/ninja/displacement.jpg",
+			"anisotropy": 4
 		},
 
 		"texture_minecraft": {
@@ -478,15 +670,15 @@
 			"type"		 : "directional",
 			"direction"	 : [0,1,1],
 			"color" 	 : 16777215,
-			"intensity"	 : 0.8
+			"intensity"	 : 1
 		},
 
 		"light2": {
 			"type"	  : "point",
 			"position": [0,0,0],
-			"color"   : 16777215
+			"color"   : 16777215,
+			"intensity"	 : 1.25
 		}
-
 	},
 
 	"fogs":	{

BIN
examples/textures/compressed/disturb_dxt1_mip.dds


BIN
examples/textures/compressed/disturb_dxt1_nomip.dds


BIN
examples/textures/compressed/explosion_dxt5_mip.dds


BIN
examples/textures/compressed/hepatica_dxt3_mip.dds


BIN
examples/textures/cube/escher/dds/nx.dds


BIN
examples/textures/cube/escher/dds/ny.dds


BIN
examples/textures/cube/escher/dds/nz.dds


BIN
examples/textures/cube/escher/dds/px.dds


BIN
examples/textures/cube/escher/dds/py.dds


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