Browse Source

Merge remote branch 'upstream/master'

Julian Walker 14 years ago
parent
commit
592ea71e48

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


File diff suppressed because it is too large
+ 0 - 0
build/ThreeDebug.js


+ 2 - 2
examples/camera_free.html

@@ -57,8 +57,8 @@
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
 
-		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 

+ 1 - 2
examples/camera_orthographic.html

@@ -16,8 +16,7 @@
 	<body>
 
 		<script type="text/javascript" src="../build/Three.js"></script>
-
-		<script type="text/javascript" src="geometry/primitives/Cube.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Cube.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 

+ 0 - 176
examples/geometry/cube.html

@@ -1,176 +0,0 @@
-<!DOCTYPE HTML>
-<html lang="en">
-	<head>
-		<title>three.js - geometry - cube</title>
-		<meta charset="utf-8">
-		<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>		
-		<style type="text/css">
-			body
-			{
-				font-family: Monospace;
-				background-color: #f0f0f0;
-				margin: 0px;
-				overflow: hidden;
-			}
-		</style>
-	</head>
-	<body>
-
-		<script type="text/javascript" src="../../build/three.js"></script>
-		<script type="text/javascript" src="http://github.com/mrdoob/stats.js/raw/master/build/stats.js"></script>
-
-		<script type="text/javascript">
-
-			var SCREEN_WIDTH = window.innerWidth;
-			var SCREEN_HEIGHT = window.innerHeight;
-
-			var container;
-			var stats;
-
-			var camera;
-			var scene;
-			var renderer;
-
-			var cube, plane;
-			
-			var targetRotation = 0;
-			var targetRotationOnMouseDown = 0;
-
-			var mouseX = 0;
-			var mouseXOnMouseDown = 0;
-
-			var windowHalfX = window.innerWidth / 2;
-			var windowHalfY = window.innerHeight / 2;
-
-			init();
-			setInterval(loop, 1000/60);
-
-			function init()
-			{
-				container = document.createElement('div');
-				document.body.appendChild(container);
-				
-				var info = document.createElement('div');
-				info.style.position = 'absolute';
-				info.style.top = '10px';
-				info.style.width = '100%';
-				info.style.textAlign = 'center';
-				info.innerHTML = 'Drag to spin the cube';
-				container.appendChild(info);
-			
-				camera = new Camera(0, 150, 400);
-				camera.focus = 300;
-				camera.target.y = 150;
-				camera.updateMatrix();
-
-				scene = new Scene();
-
-				// Cube
-
-				geometry = new Cube(200, 200, 200);
-
-				for (var i = 0; i < geometry.faces.length; i++)
-					geometry.faces[i].color.setRGBA( Math.floor( Math.random() * 128), Math.floor( Math.random() * 128 + 128), Math.floor( Math.random() * 128 + 128), 255 );
-								
-				cube = new Mesh(geometry, new FaceColorMaterial());
-				cube.position.y = 150;
-				cube.updateMatrix();
-				scene.add(cube);
-				
-				// Plane
-				
-				plane = new Mesh(new Plane(200, 200), new ColorMaterial(0xe0e0e0));
-				plane.rotation.x = 90 * (Math.PI / 180);
-				plane.updateMatrix();
-				scene.add(plane);
-				
-				renderer = new CanvasRenderer();
-				renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
-
-				container.appendChild(renderer.viewport);
-
-				stats = new Stats();
-				stats.domElement.style.position = 'absolute';
-				stats.domElement.style.top = '0px';
-				container.appendChild(stats.domElement);
-				
-				document.addEventListener('mousedown', onDocumentMouseDown, false);
-				document.addEventListener('touchstart', onDocumentTouchStart, false);
-				document.addEventListener('touchmove', onDocumentTouchMove, false);
-			}
-
-			//
-
-			function onDocumentMouseDown( event )
-			{
-				event.preventDefault();
-				
-				document.addEventListener('mousemove', onDocumentMouseMove, false);
-				document.addEventListener('mouseup', onDocumentMouseUp, false);
-				document.addEventListener('mouseout', onDocumentMouseOut, false);
-				
-				mouseXOnMouseDown = event.clientX - windowHalfX;
-				targetRotationOnMouseDown = targetRotation;
-			}
-
-			function onDocumentMouseMove( event )
-			{
-				mouseX = event.clientX - windowHalfX;
-				
-				targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.02;
-			}
-			
-			function onDocumentMouseUp( event )
-			{
-				document.removeEventListener('mousemove', onDocumentMouseMove, false);
-				document.removeEventListener('mouseup', onDocumentMouseUp, false);
-				document.removeEventListener('mouseout', onDocumentMouseOut, false);
-			}
-			
-			function onDocumentMouseOut( event )
-			{
-				document.removeEventListener('mousemove', onDocumentMouseMove, false);
-				document.removeEventListener('mouseup', onDocumentMouseUp, false);
-				document.removeEventListener('mouseout', onDocumentMouseOut, false);
-			}
-			
-			function onDocumentTouchStart( event )
-			{
-				if(event.touches.length == 1)
-				{
-					event.preventDefault();
-
-					mouseXOnMouseDown = event.touches[0].pageX - windowHalfX;
-					targetRotationOnMouseDown = targetRotation;
-				}
-			}
-
-			function onDocumentTouchMove( event )
-			{
-				if(event.touches.length == 1)
-				{
-					event.preventDefault();
-					
-					mouseX = event.touches[0].pageX - windowHalfX;
-					targetRotation = targetRotationOnMouseDown + (mouseX - mouseXOnMouseDown) * 0.05;
-				}
-			}
-
-			//
-
-			function loop()
-			{
-				cube.rotation.y += (targetRotation - cube.rotation.y) * 0.05;
-				cube.updateMatrix();
-				
-				plane.rotation.z = -cube.rotation.y;
-				plane.updateMatrix();
-				
-				renderer.render(scene, camera);
-				stats.update();
-			}
-	
-		</script>
-
-	</body>
-</html>

+ 6 - 13
examples/geometry_cube.html

@@ -16,23 +16,16 @@
 	<body>
 
 		<script type="text/javascript" src="../build/Three.js"></script>
-
-		<script type="text/javascript" src="geometry/primitives/Cube.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Cube.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 
 		<script type="text/javascript">
 
-			var SCREEN_WIDTH = window.innerWidth;
-			var SCREEN_HEIGHT = window.innerHeight;
-
-			var container;
-			var stats;
+			var container, stats;
 
-			var camera;
-			var scene;
-			var renderer;
+			var camera, scene, renderer;
 
 			var cube, plane;
 
@@ -61,7 +54,7 @@
 				info.innerHTML = 'Drag to spin the cube';
 				container.appendChild( info );
 
-				camera = new THREE.Camera( 70, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
+				camera = new THREE.Camera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
 				camera.position.y = 150;
 				camera.position.z = 500;
 				camera.target.position.y = 150;
@@ -88,7 +81,7 @@
 				scene.addObject( plane );
 
 				renderer = new THREE.CanvasRenderer();
-				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+				renderer.setSize(  window.innerWidth, window.innerHeight );
 
 				container.appendChild( renderer.domElement );
 

+ 2 - 3
examples/geometry_earth.html

@@ -36,9 +36,8 @@
 		<script type="text/javascript" src="js/Stats.js"></script>
 
 		<script type="text/javascript" src="../build/Three.js"></script>
-
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script>
 
 		<script type="text/javascript">
 

+ 1 - 2
examples/geometry_large_mesh.html

@@ -45,8 +45,7 @@
 		<pre id="log"></pre>
 
 		<script type="text/javascript" src="../build/Three.js"></script>
-
-		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 

+ 1 - 2
examples/geometry_terrain.html

@@ -37,8 +37,7 @@
 		<script type="text/javascript" src="js/ImprovedNoise.js"></script>
 
 		<script type="text/javascript" src="../build/Three.js"></script>
-
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
 
 		<script type="text/javascript">
 

+ 1 - 1
examples/geometry_vr.html

@@ -31,7 +31,7 @@
 		<div id="info"><a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - vr demo. skybox by <a href="http://www.zfight.com/" target="_blank">Jochum Skoglund</a></div>
 
 		<script type="text/javascript" src="../build/Three.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
 
 		<script type="text/javascript">
 

+ 1 - 3
examples/interactive_cubes.html

@@ -15,9 +15,7 @@
 	<body>
 
 		<script type="text/javascript" src="../build/Three.js"></script>
-
-		<script type="text/javascript" src="geometry/primitives/Cube.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Cube.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 

+ 2 - 2
examples/interactive_voxelpainter.html

@@ -16,8 +16,8 @@
 
 		<script type="text/javascript" src="../build/Three.js"></script>
 
-		<script type="text/javascript" src="geometry/primitives/Cube.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Cube.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 

+ 2 - 4
examples/lights_pointlights_gl.html

@@ -82,11 +82,9 @@
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableFace4.js"></script>
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
-		<!--
 
-		-->
-		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script> 
-		
+		<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script> 
+
 		<script type="text/javascript" src="js/Stats.js"></script>
 
 		<script type="text/javascript">

+ 6 - 6
examples/lights_test.html

@@ -85,15 +85,15 @@
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
 		-->
-		
-		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
+
+		<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 
 		<script type="text/javascript">
 
-			var SCREEN_WIDTH = window.innerWidth/2;
+			var SCREEN_WIDTH = window.innerWidth / 2;
 			var SCREEN_HEIGHT = window.innerHeight;
 			var FLOOR = -250;
 
@@ -105,9 +105,9 @@
 			var canvasRenderer, webglRenderer;
 
 			var mesh, zmesh, lightMesh, geometry;
-			
+
 			var directionalLight, pointLight;
-			
+
 			var mouseX = 0;
 			var mouseY = 0;
 

+ 3 - 3
examples/materials_test.html → examples/materials_multimaterials.html

@@ -88,9 +88,9 @@
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableParticle.js"></script>
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
 		-->
-		
-		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
+
+		<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 

+ 1 - 1
examples/shader_test.html → examples/materials_shaders.html

@@ -88,7 +88,7 @@
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
 		-->
 		
-		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 

+ 2 - 2
examples/materials_video.html

@@ -16,9 +16,9 @@
 	<body>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
-		<script type="text/javascript" src="../build/Three.js"></script>
 
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
+		<script type="text/javascript" src="../build/Three.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
 
 		<video id="video" autoplay style="display:none">
 			<source src="textures/sintel.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>

+ 2 - 2
examples/obj_convert_test.html

@@ -90,8 +90,8 @@
 		-->
 		
 
-		<script type="text/javascript" src="geometry/primitives/Sphere.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Sphere.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 

+ 3 - 3
examples/test.html

@@ -56,9 +56,9 @@
 		<script type="text/javascript" src="../src/renderers/renderables/RenderableLine.js"></script>
 
 		<script type="text/javascript" src="geometry/Qrcode.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Cube.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Plane.js"></script>
-		<script type="text/javascript" src="geometry/primitives/Cylinder.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Cube.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Plane.js"></script>
+		<script type="text/javascript" src="../src/extras/primitives/Cylinder.js"></script>
 
 		<script type="text/javascript" src="js/Stats.js"></script>
 

+ 45 - 44
src/core/Rectangle.js

@@ -4,26 +4,25 @@
 
 THREE.Rectangle = function () {
 
-	var _x1, _y1, _x2, _y2,
-	_width, _height,
-	_isEmpty = true;
+	var _left, _top, _right, _bottom,
+	_width, _height, _isEmpty = true;
 
 	function resize() {
 
-		_width = _x2 - _x1;
-		_height = _y2 - _y1;
+		_width = _right - _left;
+		_height = _bottom - _top;
 
 	}
 
 	this.getX = function () {
 
-		return _x1;
+		return _left;
 
 	};
 
 	this.getY = function () {
 
-		return _y1;
+		return _top;
 
 	};
 
@@ -39,36 +38,36 @@ THREE.Rectangle = function () {
 
 	};
 
-	this.getX1 = function() {
+	this.getLeft = function() {
 
-		return _x1;
+		return _left;
 
 	};
 
-	this.getY1 = function() {
+	this.getTop = function() {
 
-		return _y1;
+		return _top;
 
 	};
 
-	this.getX2 = function() {
+	this.getRight = function() {
 
-		return _x2;
+		return _right;
 
 	};
 
-	this.getY2 = function() {
+	this.getBottom = function() {
 
-		return _y2;
+		return _bottom;
 
 	};
 
-	this.set = function ( x1, y1, x2, y2 ) {
+	this.set = function ( left, top, right, bottom ) {
 
 		_isEmpty = false;
 
-		_x1 = x1; _y1 = y1;
-		_x2 = x2; _y2 = y2;
+		_left = left; _top = top;
+		_right = right; _bottom = bottom;
 
 		resize();
 
@@ -79,15 +78,15 @@ THREE.Rectangle = function () {
 		if ( _isEmpty ) {
 
 			_isEmpty = false;
-			_x1 = x; _y1 = y;
-			_x2 = x; _y2 = y;
+			_left = x; _top = y;
+			_right = x; _bottom = y;
 
 		} else {
 
-			_x1 = Math.min( _x1, x );
-			_y1 = Math.min( _y1, y );
-			_x2 = Math.max( _x2, x );
-			_y2 = Math.max( _y2, y );
+			_left = Math.min( _left, x );
+			_top = Math.min( _top, y );
+			_right = Math.max( _right, x );
+			_bottom = Math.max( _bottom, y );
 
 		}
 
@@ -100,15 +99,15 @@ THREE.Rectangle = function () {
 		if ( _isEmpty ) {
 
 			_isEmpty = false;
-			_x1 = r.getX1(); _y1 = r.getY1();
-			_x2 = r.getX2(); _y2 = r.getY2();
+			_left = r.getLeft(); _top = r.getTop();
+			_right = r.getRight(); _bottom = r.getBottom();
 
 		} else {
 
-			_x1 = Math.min(_x1, r.getX1());
-			_y1 = Math.min(_y1, r.getY1());
-			_x2 = Math.max(_x2, r.getX2());
-			_y2 = Math.max(_y2, r.getY2());
+			_left = Math.min(_left, r.getLeft());
+			_top = Math.min(_top, r.getTop());
+			_right = Math.max(_right, r.getRight());
+			_bottom = Math.max(_bottom, r.getBottom());
 
 		}
 
@@ -118,35 +117,37 @@ THREE.Rectangle = function () {
 
 	this.inflate = function ( v ) {
 
-		_x1 -= v; _y1 -= v;
-		_x2 += v; _y2 += v;
+		_left -= v; _top -= v;
+		_right += v; _bottom += v;
 
 		resize();
 
 	};
 
-	this.minSelf = function( r ) {
+	this.minSelf = function ( r ) {
 
-		_x1 = Math.max( _x1, r.getX1() );
-		_y1 = Math.max( _y1, r.getY1() );
-		_x2 = Math.min( _x2, r.getX2() );
-		_y2 = Math.min( _y2, r.getY2() );
+		_left = Math.max( _left, r.getLeft() );
+		_top = Math.max( _top, r.getTop() );
+		_right = Math.min( _right, r.getRight() );
+		_bottom = Math.min( _bottom, r.getBottom() );
 
 		resize();
 
 	};
 
 	/*
-	this.containsPoint = function (x, y) {
+	this.contains = function ( x, y ) {
 
-		return x > _x1 && x < _x2 && y > _y1 && y < _y2;
+		return x > _left && x < _right && y > _top && y < _bottom;
 
-	}
+	};
 	*/
 
 	this.instersects = function ( r ) {
 
-		return Math.min( _x2, r.getX2() ) - Math.max( _x1, r.getX1() ) >= 0 && Math.min( _y2, r.getY2() ) - Math.max( _y1, r.getY1() ) >= 0;
+		// return this.contains( r.getLeft(), r.getTop() ) || this.contains( r.getRight(), r.getTop() ) || this.contains( r.getLeft(), r.getBottom() ) || this.contains( r.getRight(), r.getBottom() );
+
+		return Math.min( _right, r.getRight() ) - Math.max( _left, r.getLeft() ) >= 0 && Math.min( _bottom, r.getBottom() ) - Math.max( _top, r.getTop() ) >= 0;
 
 	};
 
@@ -154,8 +155,8 @@ THREE.Rectangle = function () {
 
 		_isEmpty = true;
 
-		_x1 = 0; _y1 = 0;
-		_x2 = 0; _y2 = 0;
+		_left = 0; _top = 0;
+		_right = 0; _bottom = 0;
 
 		resize();
 
@@ -169,7 +170,7 @@ THREE.Rectangle = function () {
 
 	this.toString = function () {
 
-		return "THREE.Rectangle (x1: " + _x1 + ", y1: " + _y2 + ", x2: " + _x2 + ", y1: " + _y1 + ", width: " + _width + ", height: " + _height + ")";
+		return "THREE.Rectangle ( left: " + _left + ", right: " + _right + ", top: " + _top + ", bottom: " + _bottom + ", width: " + _width + ", height: " + _height + " )";
 
 	};
 

+ 0 - 0
examples/geometry/primitives/Cube.js → src/extras/primitives/Cube.js


+ 0 - 0
examples/geometry/primitives/Cylinder.js → src/extras/primitives/Cylinder.js


+ 0 - 0
examples/geometry/primitives/Plane.js → src/extras/primitives/Plane.js


+ 0 - 0
examples/geometry/primitives/Sphere.js → src/extras/primitives/Sphere.js


+ 550 - 511
src/io/Loader.js

@@ -6,11 +6,11 @@ THREE.Loader = function() {
 };
 
 THREE.Loader.prototype = {
-	
+
 	// Load models generated by Blender exporter and original OBJ converter (converter_obj_three.py)
-	
+
 	loadAsciiOld: function( url, callback ) {
-		
+
 		var element = document.createElement( 'script' );
 		element.type = 'text/javascript';
 		element.onload = callback;
@@ -21,66 +21,66 @@ THREE.Loader.prototype = {
 
 	// Load models generated by slim OBJ converter with ASCII option (converter_obj_three_slim.py -t ascii)
 	//  - urlbase parameter is optional (it only applies to models with textures)
-	
+
 	loadAscii: function ( url, callback, urlbase ) {
-		
+
 		var s = (new Date).getTime(),
 			worker = new Worker( url );
 
 		worker.onmessage = function( event ) {
-		
+
 			THREE.Loader.prototype.createModel( event.data, callback, urlbase );
-			
+
 		};
-		
+
 		worker.postMessage( s );
-		
+
 	},
-	
+
 	// Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
 	//  - urlbase parameter is mandatory (it applies to all models, it tells where to find the file with binary buffers)
 	//  - binary models consist of two files: JS and BIN
-	
+
 	loadBinary: function( url, callback, urlbase ) {
-		
+
 		// #1 load JS part via web worker
-		
+
 		//  This isn't really necessary, JS part is tiny,
 		//  could be done by more ordinary means.
-		
+
 		var s = (new Date).getTime(),
 			worker = new Worker( url );
 
 		worker.onmessage = function( event ) {
-			
+
 			var materials = event.data.materials,
 				buffers = event.data.buffers;
-			
+
 			// #2 load BIN part via Ajax
-			
+
 			//  For some reason it is faster doing loading from here than from within the worker.
 			//  Maybe passing of ginormous string as message between threads is costly? 
 			//  Also, worker loading huge data by Ajax still freezes browser. Go figure, 
 			//  worker with baked ascii JSON data keeps browser more responsive.
-			
+
 			THREE.Loader.prototype.loadAjaxBuffers( buffers, materials, callback, urlbase );
-			
+
 		};
-		
+
 		worker.onerror = function (event) {
-			
+
 			alert( "worker.onerror: " + event.message + "\n" + event.data );
 			event.preventDefault();
-			
+
 		};
-		
+
 		worker.postMessage( s );
-		
+
 	},
 
 	// Binary AJAX parser based on Magi binary loader
 	// https://github.com/kig/magi
-	
+
 	// Should look more into HTML5 File API
 	// See also other suggestions by Gregg Tavares
 	// https://groups.google.com/group/o3d-discuss/browse_thread/thread/a8967bc9ce1e0978
@@ -89,59 +89,87 @@ THREE.Loader.prototype = {
 
 		var xhr = new XMLHttpRequest(),
 			url = urlbase + "/" + buffers;
-	
+
 		xhr.onreadystatechange = function() {
-	  
+
 			if ( xhr.readyState == 4 ) {
-				
+
 				if ( xhr.status == 200 || xhr.status == 0 ) {
-		  
+
 					THREE.Loader.prototype.createBinModel( xhr.responseText, callback, urlbase, materials );
-					
+
 				} else {
-		  
+
 					alert( "Couldn't load [" + url + "] [" + xhr.status + "]" );
-					
+
 				}
 			}
 		}
-		
+
 		xhr.open("GET", url, true);
 		xhr.overrideMimeType("text/plain; charset=x-user-defined");
 		xhr.setRequestHeader("Content-Type", "text/plain");
 		xhr.send(null);
-		
+
 	},
 
 	createBinModel: function ( data, callback, urlbase, materials ) {
-		
+
 		var Model = function ( urlbase ) {
-			
+
 			//var s = (new Date).getTime();
-			
+
 			var scope = this,
 				currentOffset = 0, 
 				md,
 				normals = [],
-				uvs = [];
+				uvs = [],
+				tri_b, tri_c, tri_m, tri_na, tri_nb, tri_nc,
+				quad_b, quad_c, quad_d, quad_m, quad_na, quad_nb, quad_nc, quad_nd,
+				tri_uvb, tri_uvc, quad_uvb, quad_uvc, quad_uvd;
+
 
-			
 			THREE.Geometry.call(this);
-			
+
 			THREE.Loader.prototype.init_materials( scope, materials, urlbase );
-			
+
 			md = parseMetaData( data, currentOffset );
 			currentOffset += md.header_bytes;
+
+			// cache offsets
+			
+			tri_b   = md.vertex_index_bytes, 
+			tri_c   = md.vertex_index_bytes*2, 
+			tri_m   = md.vertex_index_bytes*3,
+			tri_na  = md.vertex_index_bytes*3 + md.material_index_bytes,
+			tri_nb  = md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes,
+			tri_nc  = md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes*2,
+		
+			quad_b  = md.vertex_index_bytes,
+			quad_c  = md.vertex_index_bytes*2,
+			quad_d  = md.vertex_index_bytes*3,
+			quad_m  = md.vertex_index_bytes*4,
+			quad_na = md.vertex_index_bytes*4 + md.material_index_bytes,
+			quad_nb = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes,
+			quad_nc = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*2,
+			quad_nd = md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*3,
+		
+			tri_uvb = md.uv_index_bytes,
+			tri_uvc = md.uv_index_bytes * 2,
+		
+			quad_uvb = md.uv_index_bytes,
+			quad_uvc = md.uv_index_bytes * 2,
+			quad_uvd = md.uv_index_bytes * 3;
 			
 			currentOffset += init_vertices( currentOffset );
 			currentOffset += init_normals( currentOffset );
 			currentOffset += init_uvs( currentOffset );
-			
+
 			currentOffset += init_triangles_flat( currentOffset );
 			currentOffset += init_triangles_smooth( currentOffset );
 			currentOffset += init_triangles_flat_uv( currentOffset );
 			currentOffset += init_triangles_smooth_uv( currentOffset );
-			
+
 			currentOffset += init_quads_flat( currentOffset );
 			currentOffset += init_quads_smooth( currentOffset );
 			currentOffset += init_quads_flat_uv( currentOffset );
@@ -149,70 +177,70 @@ THREE.Loader.prototype = {
 
 			this.computeCentroids();
 			this.computeNormals();
-			
+
 			//var e = (new Date).getTime();
-			
+
 			//log( "binary data parse time: " + (e-s) + " ms" );
-			
+
 			function parseMetaData( data, offset ) {
-				
+
 				var metaData = {
-					
+
 					'signature'               :parseString( data, offset, 8 ),
 					'header_bytes'            :parseUChar8( data, offset + 8 ),
-					
+
 					'vertex_coordinate_bytes' :parseUChar8( data, offset + 9 ),
 					'normal_coordinate_bytes' :parseUChar8( data, offset + 10 ),
 					'uv_coordinate_bytes'     :parseUChar8( data, offset + 11 ),
-					
+
 					'vertex_index_bytes'      :parseUChar8( data, offset + 12 ),
 					'normal_index_bytes'      :parseUChar8( data, offset + 13 ),
 					'uv_index_bytes'          :parseUChar8( data, offset + 14 ),
 					'material_index_bytes'    :parseUChar8( data, offset + 15 ),
-				
+
 					'nvertices'    :parseUInt32( data, offset + 16 ),
 					'nnormals'     :parseUInt32( data, offset + 16 + 4*1 ),
 					'nuvs'         :parseUInt32( data, offset + 16 + 4*2 ),
-					
+
 					'ntri_flat'      :parseUInt32( data, offset + 16 + 4*3 ),
 					'ntri_smooth'    :parseUInt32( data, offset + 16 + 4*4 ),
 					'ntri_flat_uv'   :parseUInt32( data, offset + 16 + 4*5 ),
 					'ntri_smooth_uv' :parseUInt32( data, offset + 16 + 4*6 ),
-					
+
 					'nquad_flat'      :parseUInt32( data, offset + 16 + 4*7 ),
 					'nquad_smooth'    :parseUInt32( data, offset + 16 + 4*8 ),
 					'nquad_flat_uv'   :parseUInt32( data, offset + 16 + 4*9 ),
 					'nquad_smooth_uv' :parseUInt32( data, offset + 16 + 4*10 )
-					
+
 				};
 
 				/*
 				log( "signature: " + metaData.signature );
-				
+
 				log( "header_bytes: " + metaData.header_bytes );
 				log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes );
 				log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes );
 				log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes );
-				
+
 				log( "vertex_index_bytes: " + metaData.vertex_index_bytes );
 				log( "normal_index_bytes: " + metaData.normal_index_bytes );
 				log( "uv_index_bytes: " + metaData.uv_index_bytes );
 				log( "material_index_bytes: " + metaData.material_index_bytes );
-				
+
 				log( "nvertices: " + metaData.nvertices );
 				log( "nnormals: " + metaData.nnormals );
 				log( "nuvs: " + metaData.nuvs );
-				
+
 				log( "ntri_flat: " + metaData.ntri_flat );
 				log( "ntri_smooth: " + metaData.ntri_smooth );
 				log( "ntri_flat_uv: " + metaData.ntri_flat_uv );
 				log( "ntri_smooth_uv: " + metaData.ntri_smooth_uv );
-				
+
 				log( "nquad_flat: " + metaData.nquad_flat );
 				log( "nquad_smooth: " + metaData.nquad_smooth );
 				log( "nquad_flat_uv: " + metaData.nquad_flat_uv );
 				log( "nquad_smooth_uv: " + metaData.nquad_smooth_uv );
-				
+
 				var total = metaData.header_bytes
 						  + metaData.nvertices * metaData.vertex_coordinate_bytes * 3
 						  + metaData.nnormals * metaData.normal_coordinate_bytes * 3
@@ -227,734 +255,745 @@ THREE.Loader.prototype = {
 						  + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 );
 				log( "total bytes: " + total );
 				*/
-				
+
 				return metaData;
-				
+
 			}
-			
+
 			function parseString( data, offset, length ) {
-				
+
 				return data.substr( offset, length );
-				
+
 			}
-			
+
 			function parseFloat32( data, offset ) {
-				
+
 				var b3 = parseUChar8( data, offset ),
 					b2 = parseUChar8( data, offset + 1 ),
 					b1 = parseUChar8( data, offset + 2 ),
 					b0 = parseUChar8( data, offset + 3 ),
-				
+
 					sign = 1 - ( 2 * ( b0 >> 7 ) ),
 					exponent = ((( b0 << 1 ) & 0xff) | ( b1 >> 7 )) - 127,
 					mantissa = (( b1 & 0x7f ) << 16) | (b2 << 8) | b3;
-					
+
 					if (mantissa == 0 && exponent == -127)
 						return 0.0;
-					
+
 					return sign * ( 1 + mantissa * Math.pow( 2, -23 ) ) * Math.pow( 2, exponent );
 
 			}
-			
+
 			function parseUInt32( data, offset ) {
-				
+
 				var b0 = parseUChar8( data, offset ),
 					b1 = parseUChar8( data, offset + 1 ),
 					b2 = parseUChar8( data, offset + 2 ),
 					b3 = parseUChar8( data, offset + 3 );
-				
+
 				return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
 			}
-			
+
 			function parseUInt16( data, offset ) {
-				
+
 				var b0 = parseUChar8( data, offset ),
 					b1 = parseUChar8( data, offset + 1 );
-				
+
 				return (b1 << 8) + b0;
-				
+
 			}
-			
+
 			function parseSChar8( data, offset ) {
-				
+
 				var b = parseUChar8( data, offset );
 				return b > 127 ? b - 256 : b;
-				
+
 			}
-			
+
 			function parseUChar8( data, offset ) {
-				
+
 				return data.charCodeAt( offset ) & 0xff;
 			}
-			
+
 			function init_vertices( start ) {
-				
+
 				var i, x, y, z, 
-					stride = md.vertex_coordinate_bytes * 3;
-				
-				for( i = 0; i < md.nvertices; ++i ) {
-					
-					x = parseFloat32( data, start + i*stride );
-					y = parseFloat32( data, start + i*stride + md.vertex_coordinate_bytes );
-					z = parseFloat32( data, start + i*stride + md.vertex_coordinate_bytes*2 );
-					
+					stride = md.vertex_coordinate_bytes * 3,
+					end = start + md.nvertices * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					x = parseFloat32( data, i );
+					y = parseFloat32( data, i + md.vertex_coordinate_bytes );
+					z = parseFloat32( data, i + md.vertex_coordinate_bytes*2 );
+
 					THREE.Loader.prototype.v( scope, x, y, z );
-					
+
 				}
-				
+
 				return md.nvertices * stride;
-				
+
 			}
-			
+
 			function init_normals( start ) {
-				
+
 				var i, x, y, z, 
-					stride = md.normal_coordinate_bytes * 3;
-				
-				for( i = 0; i < md.nnormals; ++i ) {
-					
-					x = parseSChar8( data, start + i*stride );
-					y = parseSChar8( data, start + i*stride + md.normal_coordinate_bytes );
-					z = parseSChar8( data, start + i*stride + md.normal_coordinate_bytes*2 );
-					
+					stride = md.normal_coordinate_bytes * 3,
+					end = start + md.nnormals * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					x = parseSChar8( data, i );
+					y = parseSChar8( data, i + md.normal_coordinate_bytes );
+					z = parseSChar8( data, i + md.normal_coordinate_bytes*2 );
+
 					normals.push( x/127, y/127, z/127 );
-					
+
 				}
-				
+
 				return md.nnormals * stride;
-				
+
 			}
 
 			function init_uvs( start ) {
-				
+
 				var i, u, v, 
-					stride = md.uv_coordinate_bytes * 2;
-				
-				for( i = 0; i < md.nuvs; ++i ) {
-					
-					u = parseFloat32( data, start + i*stride );
-					v = parseFloat32( data, start + i*stride + md.uv_coordinate_bytes );
-					
+					stride = md.uv_coordinate_bytes * 2,
+					end = start + md.nuvs * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					u = parseFloat32( data, i );
+					v = parseFloat32( data, i + md.uv_coordinate_bytes );
+
 					uvs.push( u, v );
-					
+
 				}
 				
 				return md.nuvs * stride;
-				
-			}
+
+			}			
 			
-			function add_tri( start, i, stride ) {
-				
+			function add_tri( i ) {
+
 				var a, b, c, m;
-				
-				a = parseUInt32( data, start + i*stride );
-				b = parseUInt32( data, start + i*stride + md.vertex_index_bytes );
-				c = parseUInt32( data, start + i*stride + md.vertex_index_bytes*2 );
-				
-				m = parseUInt16( data, start + i*stride + md.vertex_index_bytes*3 );
-				
+
+				a = parseUInt32( data, i );
+				b = parseUInt32( data, i + tri_b );
+				c = parseUInt32( data, i + tri_c );
+
+				m = parseUInt16( data, i + tri_m );
+
 				THREE.Loader.prototype.f3( scope, a, b, c, m );
-				
+
 			}
-			
-			function add_tri_n( start, i, stride ) {
-				
+
+			function add_tri_n( i ) {
+
 				var a, b, c, m, na, nb, nc;
-				
-				a  = parseUInt32( data, start + i*stride );
-				b  = parseUInt32( data, start + i*stride + md.vertex_index_bytes );
-				c  = parseUInt32( data, start + i*stride + md.vertex_index_bytes*2 );
-				
-				m  = parseUInt16( data, start + i*stride + md.vertex_index_bytes*3 );
-				
-				na = parseUInt32( data, start + i*stride + md.vertex_index_bytes*3 + md.material_index_bytes );
-				nb = parseUInt32( data, start + i*stride + md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes );
-				nc = parseUInt32( data, start + i*stride + md.vertex_index_bytes*3 + md.material_index_bytes + md.normal_index_bytes*2 );
-				
+
+				a  = parseUInt32( data, i );
+				b  = parseUInt32( data, i + tri_b );
+				c  = parseUInt32( data, i + tri_c );
+
+				m  = parseUInt16( data, i + tri_m );
+
+				na = parseUInt32( data, i + tri_na );
+				nb = parseUInt32( data, i + tri_nb );
+				nc = parseUInt32( data, i + tri_nc );
+
 				THREE.Loader.prototype.f3n( scope, normals, a, b, c, m, na, nb, nc );
-			
+
 			}
-			
-			function add_quad( start, i, stride ) {
-				
+
+			function add_quad( i ) {
+
 				var a, b, c, d, m;
-				
-				a = parseUInt32( data, start + i*stride );
-				b = parseUInt32( data, start + i*stride + md.vertex_index_bytes );
-				c = parseUInt32( data, start + i*stride + md.vertex_index_bytes*2 );
-				d = parseUInt32( data, start + i*stride + md.vertex_index_bytes*3 );
-				
-				m = parseUInt16( data, start + i*stride + md.vertex_index_bytes*4 );
-				
+
+				a = parseUInt32( data, i );
+				b = parseUInt32( data, i + quad_b );
+				c = parseUInt32( data, i + quad_c );
+				d = parseUInt32( data, i + quad_d );
+
+				m = parseUInt16( data, i + quad_m );
+
 				THREE.Loader.prototype.f4( scope, a, b, c, d, m );
-				
+
 			}
-			
-			function add_quad_n( start, i, stride ) {
-				
+
+			function add_quad_n( i ) {
+
 				var a, b, c, d, m, na, nb, nc, nd;
-				
-				a  = parseUInt32( data, start + i*stride );
-				b  = parseUInt32( data, start + i*stride + md.vertex_index_bytes );
-				c  = parseUInt32( data, start + i*stride + md.vertex_index_bytes*2 );
-				d  = parseUInt32( data, start + i*stride + md.vertex_index_bytes*3 );
-				
-				m  = parseUInt16( data, start + i*stride + md.vertex_index_bytes*4 );
-				
-				na = parseUInt32( data, start + i*stride + md.vertex_index_bytes*4 + md.material_index_bytes );
-				nb = parseUInt32( data, start + i*stride + md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes );
-				nc = parseUInt32( data, start + i*stride + md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*2 );
-				nd = parseUInt32( data, start + i*stride + md.vertex_index_bytes*4 + md.material_index_bytes + md.normal_index_bytes*3 );
-				
+
+				a  = parseUInt32( data, i );
+				b  = parseUInt32( data, i + quad_b );
+				c  = parseUInt32( data, i + quad_c );
+				d  = parseUInt32( data, i + quad_d );
+
+				m  = parseUInt16( data, i + quad_m );
+
+				na = parseUInt32( data, i + quad_na );
+				nb = parseUInt32( data, i + quad_nb );
+				nc = parseUInt32( data, i + quad_nc );
+				nd = parseUInt32( data, i + quad_nd );
+
 				THREE.Loader.prototype.f4n( scope, normals, a, b, c, d, m, na, nb, nc, nd );
-			
+
 			}
-			
-			function add_uv3( start, i, stride, offset ) {
-				
+
+			function add_uv3( i ) {
+
 				var uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
-				
-				uva = parseUInt32( data, start + i*stride + offset );
-				uvb = parseUInt32( data, start + i*stride + offset + md.uv_index_bytes );
-				uvc = parseUInt32( data, start + i*stride + offset + md.uv_index_bytes * 2 );
-				
+
+				uva = parseUInt32( data, i );
+				uvb = parseUInt32( data, i + tri_uvb );
+				uvc = parseUInt32( data, i + tri_uvc );
+
 				u1 = uvs[ uva*2 ];
-				v1 = uvs[ uva*2 + 1];
-				
+				v1 = uvs[ uva*2 + 1 ];
+
 				u2 = uvs[ uvb*2 ];
-				v2 = uvs[ uvb*2 + 1];
-				
+				v2 = uvs[ uvb*2 + 1 ];
+
 				u3 = uvs[ uvc*2 ];
-				v3 = uvs[ uvc*2 + 1];
-				
-				THREE.Loader.prototype.uv( scope, u1, v1, u2, v2, u3, v3 );				
-				
+				v3 = uvs[ uvc*2 + 1 ];
+
+				THREE.Loader.prototype.uv( scope, u1, v1, u2, v2, u3, v3 );
+
 			}
-			
-			function add_uv4( start, i, stride, offset ) {
-				
+
+			function add_uv4( i ) {
+
 				var uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;
-				
-				uva = parseUInt32( data, start + i*stride + offset );
-				uvb = parseUInt32( data, start + i*stride + offset + md.uv_index_bytes );
-				uvc = parseUInt32( data, start + i*stride + offset + md.uv_index_bytes * 2 );
-				uvd = parseUInt32( data, start + i*stride + offset + md.uv_index_bytes * 3 );
-				
+
+				uva = parseUInt32( data, i );
+				uvb = parseUInt32( data, i + quad_uvb );
+				uvc = parseUInt32( data, i + quad_uvc );
+				uvd = parseUInt32( data, i + quad_uvd );
+
 				u1 = uvs[ uva*2 ];
-				v1 = uvs[ uva*2 + 1];
-				
+				v1 = uvs[ uva*2 + 1 ];
+
 				u2 = uvs[ uvb*2 ];
-				v2 = uvs[ uvb*2 + 1];
-				
+				v2 = uvs[ uvb*2 + 1 ];
+
 				u3 = uvs[ uvc*2 ];
-				v3 = uvs[ uvc*2 + 1];
+				v3 = uvs[ uvc*2 + 1 ];
 
 				u4 = uvs[ uvd*2 ];
-				v4 = uvs[ uvd*2 + 1];
-				
-				THREE.Loader.prototype.uv( scope, u1, v1, u2, v2, u3, v3, u4, v4 );				
-				
+				v4 = uvs[ uvd*2 + 1 ];
+
+				THREE.Loader.prototype.uv( scope, u1, v1, u2, v2, u3, v3, u4, v4 );
+
 			}
-			
+
 			function init_triangles_flat( start ) {
-				
-				var i, stride = md.vertex_index_bytes * 3 + md.material_index_bytes;
-				
-				for( i = 0; i < md.ntri_flat; ++i ) {
-					
-					add_tri( start, i, stride );
-					
+
+				var i, stride = md.vertex_index_bytes * 3 + md.material_index_bytes,
+					end = start + md.ntri_flat * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					add_tri( i );
+
 				}
-				
-				return md.ntri_flat * stride;
-				
+
+				return end - start;
+
 			}
 
 			function init_triangles_flat_uv( start ) {
-				
+
 				var i, offset = md.vertex_index_bytes * 3 + md.material_index_bytes,
-					stride = offset + md.uv_index_bytes * 3;
-				
-				for( i = 0; i < md.ntri_flat_uv; ++i ) {
-					
-					add_tri( start, i, stride );
-					add_uv3( start, i, stride, md.vertex_index_bytes*3 + md.material_index_bytes );
-					
+					stride = offset + md.uv_index_bytes * 3,
+					end = start + md.ntri_flat_uv * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					add_tri( i );
+					add_uv3( i + offset );
+
 				}
-				
-				return md.ntri_flat_uv * stride;
-				
+
+				return end - start;
+
 			}
-			
+
 			function init_triangles_smooth( start ) {
-			
-				var i, stride = md.vertex_index_bytes * 3 + md.material_index_bytes + md.normal_index_bytes * 3;
-				
-				for( i = 0; i < md.ntri_smooth; ++i ) {
-					
-					add_tri_n( start, i, stride );
-					
+
+				var i, stride = md.vertex_index_bytes * 3 + md.material_index_bytes + md.normal_index_bytes * 3,
+					end = start + md.ntri_smooth * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					add_tri_n( i );
+
 				}
-				
-				return md.ntri_smooth * stride;
-				
+
+				return end - start;
+
 			}
 
 			function init_triangles_smooth_uv( start ) {
-			
+
 				var i, offset = md.vertex_index_bytes * 3 + md.material_index_bytes + md.normal_index_bytes * 3,
-					stride = offset + md.uv_index_bytes * 3;
-				
-				for( i = 0; i < md.ntri_smooth_uv; ++i ) {
-					
-					add_tri_n( start, i, stride );
-					add_uv3( start, i, stride, offset );
-					
+					stride = offset + md.uv_index_bytes * 3,
+					end = start + md.ntri_smooth_uv * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					add_tri_n( i );
+					add_uv3( i + offset );
+
 				}
-				
-				return md.ntri_smooth * stride;
-				
+
+				return end - start;
+
 			}
 
 			function init_quads_flat( start ) {
-				
-				var i, stride = md.vertex_index_bytes * 4 + md.material_index_bytes;
-				
-				for( i = 0; i < md.nquad_flat; ++i ) {
-					
-					add_quad( start, i, stride );
-					
+
+				var i, stride = md.vertex_index_bytes * 4 + md.material_index_bytes,
+					end = start + md.nquad_flat * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					add_quad( i );
+
 				}
-				
-				return md.nquad_flat * stride;
-				
+
+				return end - start;
+
 			}
 
 			function init_quads_flat_uv( start ) {
-				
+
 				var i, offset = md.vertex_index_bytes * 4 + md.material_index_bytes,
-					stride = offset + md.uv_index_bytes * 4;
-				
-				for( i = 0; i < md.nquad_flat_uv; ++i ) {
-					
-					add_quad( start, i, stride );
-					add_uv4( start, i, offset );
-					
+					stride = offset + md.uv_index_bytes * 4,
+					end = start + md.nquad_flat_uv * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					add_quad( i );
+					add_uv4( i + offset );
+
 				}
-				
-				return md.nquad_flat * stride;
-				
+
+				return end - start;
+
 			}
 
 			function init_quads_smooth( start ) {
-				
-				var i, stride = md.vertex_index_bytes * 4 + md.material_index_bytes + md.normal_index_bytes * 4;
-				
-				for( i = 0; i < md.nquad_smooth; ++i ) {
-					
-					add_quad_n( start, i, stride );
+
+				var i, stride = md.vertex_index_bytes * 4 + md.material_index_bytes + md.normal_index_bytes * 4,
+					end = start + md.nquad_smooth * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					add_quad_n( i );
 				}
-				
-				return md.nquad_smooth * stride;
-				
+
+				return end - start;
+
 			}
 
 			function init_quads_smooth_uv( start ) {
-				
+
 				var i, offset = md.vertex_index_bytes * 4 + md.material_index_bytes + md.normal_index_bytes * 4, 
-					stride =  offset + md.uv_index_bytes * 4;
-				
-				for( i = 0; i < md.nquad_smooth_uv; ++i ) {
-					
-					add_quad_n( start, i, stride );
-					add_uv4( start, i, stride, offset );
-					
+					stride =  offset + md.uv_index_bytes * 4,
+					end = start + md.nquad_smooth_uv * stride;
+
+				for( i = start; i < end; i += stride ) {
+
+					add_quad_n( i );
+					add_uv4( i + offset );
+
 				}
-				
-				return md.nquad_smooth * stride;
-				
+
+				return end - start;
+
 			}
-			
+
 		}
-		
+
 		Model.prototype = new THREE.Geometry();
 		Model.prototype.constructor = Model;
-		
+
 		callback( new Model( urlbase ) );
-		
+
 	},
-	
+
 	createModel: function ( data, callback, urlbase ) {
-		
+
 		var Model = function ( urlbase ) {
-			
+
 			var scope = this;
 
 			THREE.Geometry.call(this);
-			
+
 			THREE.Loader.prototype.init_materials( scope, data.materials, urlbase );
-			
+
 			init_vertices();
 			init_faces();
-			
+
 			this.computeCentroids();
 			this.computeNormals();
-			
+
 			function init_vertices() {
-			
+
 				var i, l, x, y, z;
-				
-				for( i = 0, l = data.vertices.length/3; i < l; i++ ) {
-					
-					x = data.vertices[ i*3     ];
-					y = data.vertices[ i*3 + 1 ];
-					z = data.vertices[ i*3 + 2 ];
-					
+
+				for( i = 0, l = data.vertices.length; i < l; i += 3 ) {
+
+					x = data.vertices[ i     ];
+					y = data.vertices[ i + 1 ];
+					z = data.vertices[ i + 2 ];
+
 					THREE.Loader.prototype.v( scope, x, y, z );
-					
+
 				}
-			
+
 			}
 
 			function init_faces() {
-			
-				function add_tri( src, i, stride ) {
+
+				function add_tri( src, i ) {
 
 					var a, b, c, m;
-					
-					a = src[ i*stride     ];
-					b = src[ i*stride + 1 ];
-					c = src[ i*stride + 2 ];
-					
-					m = src[ i*stride + 3 ];
-					
+
+					a = src[ i ];
+					b = src[ i + 1 ];
+					c = src[ i + 2 ];
+
+					m = src[ i + 3 ];
+
 					THREE.Loader.prototype.f3( scope, a, b, c, m );
-					
+
 				}
 
-				function add_tri_n( src, i, stride ) {
-					
+				function add_tri_n( src, i ) {
+
 					var a, b, c, m, na, nb, nc;
-					
-					a  = src[ i*stride     ];
-					b  = src[ i*stride + 1 ];
-					c  = src[ i*stride + 2 ];
-					
-					m  = src[ i*stride + 3 ];
-					
-					na = src[ i*stride + 4 ];
-					nb = src[ i*stride + 5 ];
-					nc = src[ i*stride + 6 ];
-					
+
+					a  = src[ i ];
+					b  = src[ i + 1 ];
+					c  = src[ i + 2 ];
+
+					m  = src[ i + 3 ];
+
+					na = src[ i + 4 ];
+					nb = src[ i + 5 ];
+					nc = src[ i + 6 ];
+
 					THREE.Loader.prototype.f3n( scope, data.normals, a, b, c, m, na, nb, nc );
-					
+
 				}
-				
-				function add_quad( src, i, stride ) {
-					
+
+				function add_quad( src, i ) {
+
 					var a, b, c, d, m;
-					
-					a = src[ i*stride     ];
-					b = src[ i*stride + 1 ];
-					c = src[ i*stride + 2 ];
-					d = src[ i*stride + 3 ];
-					
-					m = src[ i*stride + 4 ];
-					
+
+					a = src[ i ];
+					b = src[ i + 1 ];
+					c = src[ i + 2 ];
+					d = src[ i + 3 ];
+
+					m = src[ i + 4 ];
+
 					THREE.Loader.prototype.f4( scope, a, b, c, d, m );
-					
+
 				}
 
-				function add_quad_n( src, i, stride ) {
-					
+				function add_quad_n( src, i ) {
+
 					var a, b, c, d, m, na, nb, nc, nd;
-					
-					a  = src[ i*stride     ];
-					b  = src[ i*stride + 1 ];
-					c  = src[ i*stride + 2 ];
-					d  = src[ i*stride + 3 ];
-					
-					m  = src[ i*stride + 4 ];
-
-					na = src[ i*stride + 5 ];
-					nb = src[ i*stride + 6 ];
-					nc = src[ i*stride + 7 ];
-					nd = src[ i*stride + 8 ];
-					
+
+					a  = src[ i ];
+					b  = src[ i + 1 ];
+					c  = src[ i + 2 ];
+					d  = src[ i + 3 ];
+
+					m  = src[ i + 4 ];
+
+					na = src[ i + 5 ];
+					nb = src[ i + 6 ];
+					nc = src[ i + 7 ];
+					nd = src[ i + 8 ];
+
 					THREE.Loader.prototype.f4n( scope, data.normals, a, b, c, d, m, na, nb, nc, nd );
-					
+
 				}
-				
-				function add_uv3( src, i, stride, offset ) {
-					
+
+				function add_uv3( src, i ) {
+
 					var uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
 
-					uva = src[ i*stride + offset ];
-					uvb = src[ i*stride + offset + 1 ];
-					uvc = src[ i*stride + offset + 2 ];
-					
-					u1 = data.uvs[ uva*2 ];
-					v1 = data.uvs[ uva*2 + 1 ];
-					
-					u2 = data.uvs[ uvb*2 ];
-					v2 = data.uvs[ uvb*2 + 1 ];
-					
-					u3 = data.uvs[ uvc*2 ];
-					v3 = data.uvs[ uvc*2 + 1 ];
-					
+					uva = src[ i ];
+					uvb = src[ i + 1 ];
+					uvc = src[ i + 2 ];
+
+					u1 = data.uvs[ uva * 2 ];
+					v1 = data.uvs[ uva * 2 + 1 ];
+
+					u2 = data.uvs[ uvb * 2 ];
+					v2 = data.uvs[ uvb * 2 + 1 ];
+
+					u3 = data.uvs[ uvc * 2 ];
+					v3 = data.uvs[ uvc * 2 + 1 ];
+
 					THREE.Loader.prototype.uv( scope, u1, v1, u2, v2, u3, v3 );
-					
+
 				}
-				
-				function add_uv4( src, i, stride, offset ) {
-					
+
+				function add_uv4( src, i ) {
+
 					var uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;
-					
-					uva = src[ i*stride + offset ];
-					uvb = src[ i*stride + offset + 1 ];
-					uvc = src[ i*stride + offset + 2 ];
-					uvd = src[ i*stride + offset + 3 ];
-					
-					u1 = data.uvs[ uva*2 ];
-					v1 = data.uvs[ uva*2 + 1 ];
-					
-					u2 = data.uvs[ uvb*2 ];
-					v2 = data.uvs[ uvb*2 + 1 ];
-					
-					u3 = data.uvs[ uvc*2 ];
-					v3 = data.uvs[ uvc*2 + 1 ];
-					
-					u4 = data.uvs[ uvd*2 ];
-					v4 = data.uvs[ uvd*2 + 1 ];
-					
+
+					uva = src[ i ];
+					uvb = src[ i + 1 ];
+					uvc = src[ i + 2 ];
+					uvd = src[ i + 3 ];
+
+					u1 = data.uvs[ uva * 2 ];
+					v1 = data.uvs[ uva * 2 + 1 ];
+
+					u2 = data.uvs[ uvb * 2 ];
+					v2 = data.uvs[ uvb * 2 + 1 ];
+
+					u3 = data.uvs[ uvc * 2 ];
+					v3 = data.uvs[ uvc * 2 + 1 ];
+
+					u4 = data.uvs[ uvd * 2 ];
+					v4 = data.uvs[ uvd * 2 + 1 ];
+
 					THREE.Loader.prototype.uv( scope, u1, v1, u2, v2, u3, v3, u4, v4 );
-					
+
 				}
-				
+
 				var i, l;
-				
-				for( i = 0, l = data.triangles.length/4; i < l; i++ ) {
-				
-					add_tri( data.triangles, i, 4 );
-					
+
+				for ( i = 0, l = data.triangles.length; i < l; i += 4 ) {
+
+					add_tri( data.triangles, i );
+
 				}
 
-				for( i = 0, l = data.triangles_uv.length/7; i < l; i++ ) {
-					
-					add_tri( data.triangles_uv, i, 7 );	
-					add_uv3( data.triangles_uv, i, 7, 4 );
-				
+				for ( i = 0, l = data.triangles_uv.length; i < l; i+= 7 ) {
+
+					add_tri( data.triangles_uv, i );
+					add_uv3( data.triangles_uv, i + 4 );
+
 				}
 
-				for( i = 0, l = data.triangles_n.length/7; i < l; i++ ) {
-					
-					add_tri_n( data.triangles_n, i, 7 );
-					
+				for ( i = 0, l = data.triangles_n.length; i < l; i += 7 ) {
+
+					add_tri_n( data.triangles_n, i );
+
 				}
 
-				for( i = 0, l = data.triangles_n_uv.length/10; i < l; i++ ) {
-					
-					add_tri_n( data.triangles_n_uv, i, 10 );
-					add_uv3( data.triangles_n_uv, i, 10, 7 );
-				
+				for ( i = 0, l = data.triangles_n_uv.length; i < l; i += 10 ) {
+
+					add_tri_n( data.triangles_n_uv, i );
+					add_uv3( data.triangles_n_uv, i + 7 );
+
 				}
 
-				
-				for( i = 0, l = data.quads.length/5; i < l; i++ ) {
-					
-					add_quad( data.quads, i, 5 );
-					
+
+				for ( i = 0, l = data.quads.length; i < l; i += 5 ) {
+
+					add_quad( data.quads, i );
+
 				}
 
-				for( i = 0, l = data.quads_uv.length/9; i < l; i++ ) {
-					
-					add_quad( data.quads_uv, i, 9 );
-					add_uv4( data.quads_uv, i, 9, 5 );
-				
+				for ( i = 0, l = data.quads_uv.length; i < l; i += 9 ) {
+
+					add_quad( data.quads_uv, i );
+					add_uv4( data.quads_uv, i + 5 );
+
 				}
 
-				for( i = 0, l = data.quads_n.length/9; i < l; i++ ) {
-					
-					add_quad_n( data.quads_n, i, 9 );
-					
+				for ( i = 0, l = data.quads_n.length; i < l; i += 9 ) {
+
+					add_quad_n( data.quads_n, i );
+
 				}
 
-				for( i = 0, l = data.quads_n_uv.length/13; i < l; i++ ) {
-					
-					add_quad_n( data.quads_n_uv, i, 13 );
-					add_uv4( data.quads_n_uv, i, 13, 9 );
-				
+				for ( i = 0, l = data.quads_n_uv.length; i < l; i += 13 ) {
+
+					add_quad_n( data.quads_n_uv, i );
+					add_uv4( data.quads_n_uv, i + 9 );
+
 				}
-				
-			}			
-			
+
+			}
+
 		}
 
 		Model.prototype = new THREE.Geometry();
 		Model.prototype.constructor = Model;
-		
+
 		callback( new Model( urlbase ) );
 
 	},
 
 	v: function( scope, x, y, z ) {
-	
+
 		scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
-	
+
 	},
-	
+
 	f3: function( scope, a, b, c, mi ) {
-		
+
 		var material = scope.materials[ mi ];
 		scope.faces.push( new THREE.Face3( a, b, c, null, material ) );
-		
+
 	},
-	
+
 	f4: function( scope, a, b, c, d, mi ) {
-		
+
 		var material = scope.materials[ mi ];
 		scope.faces.push( new THREE.Face4( a, b, c, d, null, material ) );
-		
+
 	},
-	
+
 	f3n: function( scope, normals, a, b, c, mi, na, nb, nc ) {
-		
+
 		var material = scope.materials[ mi ],
 			nax = normals[ na*3     ],
 			nay = normals[ na*3 + 1 ],
 			naz = normals[ na*3 + 2 ],
-		
+
 			nbx = normals[ nb*3     ],
 			nby = normals[ nb*3 + 1 ],
 			nbz = normals[ nb*3 + 2 ],
-		
+
 			ncx = normals[ nc*3     ],
 			ncy = normals[ nc*3 + 1 ],
 			ncz = normals[ nc*3 + 2 ];
-		
+
 		scope.faces.push( new THREE.Face3( a, b, c, 
 						  [new THREE.Vector3( nax, nay, naz ), 
 						   new THREE.Vector3( nbx, nby, nbz ), 
 						   new THREE.Vector3( ncx, ncy, ncz )], 
 						  material ) );
-		
+
 	},
-	
+
 	f4n: function( scope, normals, a, b, c, d, mi, na, nb, nc, nd ) {
-		
+
 		var material = scope.materials[ mi ],
 			nax = normals[ na*3     ],
 			nay = normals[ na*3 + 1 ],
 			naz = normals[ na*3 + 2 ],
-		
+
 			nbx = normals[ nb*3     ],
 			nby = normals[ nb*3 + 1 ],
 			nbz = normals[ nb*3 + 2 ],
-		
+
 			ncx = normals[ nc*3     ],
 			ncy = normals[ nc*3 + 1 ],
 			ncz = normals[ nc*3 + 2 ],
-		
+
 			ndx = normals[ nd*3     ],
 			ndy = normals[ nd*3 + 1 ],
 			ndz = normals[ nd*3 + 2 ];
-		
+
 		scope.faces.push( new THREE.Face4( a, b, c, d,
 						  [new THREE.Vector3( nax, nay, naz ), 
 						   new THREE.Vector3( nbx, nby, nbz ), 
 						   new THREE.Vector3( ncx, ncy, ncz ), 
 						   new THREE.Vector3( ndx, ndy, ndz )], 
 						  material ) );
-		
+
 	},
-	
+
 	uv: function( scope, u1, v1, u2, v2, u3, v3, u4, v4 ) {
-		
+
 		var uv = [];
 		uv.push( new THREE.UV( u1, v1 ) );
 		uv.push( new THREE.UV( u2, v2 ) );
 		uv.push( new THREE.UV( u3, v3 ) );
 		if ( u4 && v4 ) uv.push( new THREE.UV( u4, v4 ) );
 		scope.uvs.push( uv );
-		
+
 	},
-	
+
 	init_materials: function( scope, materials, urlbase ) {
-		
+
 		scope.materials = [];
-		
-		for( var i = 0; i < materials.length; ++i ) {
-			
+
+		for ( var i = 0; i < materials.length; ++i ) {
+
 			scope.materials[i] = [ THREE.Loader.prototype.createMaterial( materials[i], urlbase ) ];
-			
+
 		}
-		
+
 	},
-	
-	createMaterial: function( m, urlbase ) {
-	
+
+	createMaterial: function ( m, urlbase ) {
+
 		function is_pow2( n ) {
-			
+
 			var l = Math.log(n) / Math.LN2;
 			return Math.floor(l) == l;
-			
+
 		}
-		
+
 		function nearest_pow2( n ) {
-			
+
 			var l = Math.log(n) / Math.LN2;
 			return Math.pow( 2, Math.round(l) );
-			
+
 		}
 
 		var material, texture, image, color;
-		
-		if( m.map_diffuse && urlbase ) {
-			
+
+		if ( m.map_diffuse && urlbase ) {
+
 			texture = document.createElement( 'canvas' );
 			material = new THREE.MeshBitmapMaterial( texture );
-			
+
 			image = new Image();
 			image.onload = function () {
-				
+
 				if ( !is_pow2( this.width ) || !is_pow2( this.height ) ) {
-				
+
 					var w = nearest_pow2( this.width ),
 						h = nearest_pow2( this.height );
-					
+
 					material.bitmap.width = w;
 					material.bitmap.height = h;
 					material.bitmap.getContext("2d").drawImage( this, 0, 0, w, h );
-					
+
 				} else {
-					
+
 					material.bitmap = this;
-					
+
 				}
-				
+
 				material.loaded = 1;
-				
+
 			};
-			
+
 			image.src = urlbase + "/" + m.map_diffuse;
-			
-		} else if( m.col_diffuse ) {
-			
+
+		} else if ( m.col_diffuse ) {
+
 			color = (m.col_diffuse[0]*255 << 16) + (m.col_diffuse[1]*255 << 8) + m.col_diffuse[2]*255;
 			material = new THREE.MeshColorFillMaterial( color, m.transparency );
-			
-		} else if( m.a_dbg_color ) {
-			
+
+		} else if ( m.a_dbg_color ) {
+
 			material = new THREE.MeshColorFillMaterial( m.a_dbg_color );
-			
+
 		} else {
-			
+
 			material = new THREE.MeshColorFillMaterial( 0xeeeeee );
-			
+
 		}
 
 		return material;
-		
+
 	}
-	
-};
+
+};

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

@@ -100,7 +100,7 @@ def save(operator, context, filepath="", use_modifiers=True, use_normals=True, u
     # incase
     color = uvcoord = uvcoord_key = normal = normal_key = None
 
-    file.write('// Generated with Blender 2.54 exporter\n')
+    file.write('// Generated with Blender exporter (compatible with Blender 2.54 / 2.55)\n')
     file.write('// http://github.com/mrdoob/three.js/tree/master/utils/exporters/blender\n\n')
 
     file.write('var %s = function () {\n\n' % classname)

+ 6 - 0
utils/exporters/blender/2.54/scripts/op/io_mesh_threejs_slim/__init__.py

@@ -37,6 +37,9 @@ class ExportTHREEJSSlim(bpy.types.Operator, ExportHelper):
     use_modifiers = BoolProperty(name="Apply Modifiers", description="Apply modifiers to the exported mesh", default=True)
     use_normals = BoolProperty(name="Normals", description="Export normals", default=True)
     use_uv_coords = BoolProperty(name="UVs", description="Export texture coordinates", default=True)
+    
+    align_types = [("None","None","None"), ("Center","Center","Center"), ("Bottom","Bottom","Bottom"), ("Top","Top","Top")]
+    align_model = EnumProperty(name="Align model", description="Align model", items=align_types, default="Center")
 
     @classmethod
     def poll(cls, context):
@@ -57,9 +60,12 @@ class ExportTHREEJSSlim(bpy.types.Operator, ExportHelper):
 
         row = layout.row()
         row.prop(self.properties, "use_modifiers")
+        row = layout.row()
         row.prop(self.properties, "use_normals")
         row = layout.row()
         row.prop(self.properties, "use_uv_coords")
+        row = layout.row()
+        row.prop(self.properties, "align_model")
         
 
 def menu_func(self, context):

+ 126 - 35
utils/exporters/blender/2.54/scripts/op/io_mesh_threejs_slim/export_threejs_slim.py

@@ -41,9 +41,6 @@ import random
 # #####################################################
 # Configuration
 # #####################################################
-ALIGN = "center"    # center bottom top none
-SHADING = "smooth"  # smooth flat 
-TYPE = "ascii"      # ascii binary
 
 # default colors for debugging (each material gets one distinct color): 
 # white, red, green, blue, yellow, cyan, magenta
@@ -58,7 +55,7 @@ TEMPLATE_FILE_ASCII = """\
 //  faces: %(nface)d 
 //  materials: %(nmaterial)d
 //
-//  Generated with Blender 2.54 slim exporter
+//  Generated with Blender slim exporter (compatible with Blender 2.54 / 2.55)
 //  https://github.com/alteredq/three.js/tree/master/utils/exporters/blender/
 
 
@@ -131,6 +128,84 @@ def get_uv_indices(f, uvs, mesh):
         uv.append( uvs[veckey2d(i)] )
     return uv
 
+# #####################################################
+# Alignment
+# #####################################################
+def bbox(vertices):
+    """Compute bounding box of vertex array.
+    """
+    
+    if len(vertices)>0:
+        minx = maxx = vertices[0].co.x
+        miny = maxy = vertices[0].co.y
+        minz = maxz = vertices[0].co.z
+        
+        for v in vertices[1:]:
+            if v.co.x < minx:
+                minx = v.co.x
+            elif v.co.x > maxx:
+                maxx = v.co.x
+            
+            if v.co.y < miny:
+                miny = v.co.y
+            elif v.co.y > maxy:
+                maxy = v.co.y
+
+            if v.co.z < minz:
+                minz = v.co.z
+            elif v.co.z > maxz:
+                maxz = v.co.z
+
+        return { 'x':[minx,maxx], 'y':[miny,maxy], 'z':[minz,maxz] }
+    
+    else:
+        return { 'x':[0,0], 'y':[0,0], 'z':[0,0] }
+
+def translate(vertices, t):
+    """Translate array of vertices by vector t.
+    """
+    
+    for i in range(len(vertices)):
+        vertices[i].co.x += t[0]
+        vertices[i].co.y += t[1]
+        vertices[i].co.z += t[2]
+
+def center(vertices):
+    """Center model (middle of bounding box).
+    """
+    
+    bb = bbox(vertices)
+    
+    cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
+    cy = bb['y'][0] + (bb['y'][1] - bb['y'][0])/2.0
+    cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
+    
+    translate(vertices, [-cx,-cy,-cz])
+
+def top(vertices):
+    """Align top of the model with the floor (Y-axis) and center it around X and Z.
+    """
+    
+    bb = bbox(vertices)
+    
+    cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
+    cy = bb['y'][1]
+    cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
+    
+    translate(vertices, [-cx,-cy,-cz])
+    
+def bottom(vertices):
+    """Align bottom of the model with the floor (Y-axis) and center it around X and Z.
+    """
+    
+    bb = bbox(vertices)
+    
+    cx = bb['x'][0] + (bb['x'][1] - bb['x'][0])/2.0
+    cy = bb['y'][0] 
+    cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
+    
+    translate(vertices, [-cx,-cy,-cz])
+
 # #####################################################
 # Elements
 # #####################################################
@@ -378,31 +453,32 @@ def extract_materials(mesh, scene):
 
     materials = {}
     for m in mesh.materials:
-        materials[m.name] = {}
-        materials[m.name]['col_diffuse'] = [m.diffuse_intensity * m.diffuse_color[0], 
-                                            m.diffuse_intensity * m.diffuse_color[1], 
-                                            m.diffuse_intensity * m.diffuse_color[2]]
-                                            
-        materials[m.name]['col_specular'] = [m.specular_intensity * m.specular_color[0], 
-                                             m.specular_intensity * m.specular_color[1], 
-                                             m.specular_intensity * m.specular_color[2]]
-                                             
-        materials[m.name]['col_ambient'] = [m.ambient * world.ambient_color[0], 
-                                            m.ambient * world.ambient_color[1], 
-                                            m.ambient * world.ambient_color[2]]
-                                            
-        materials[m.name]['transparency'] = m.alpha
-        
-        # not sure about mapping values to Blinn-Phong shader
-        # Blender uses INT from [1,511] with default 0
-        # http://www.blender.org/documentation/blender_python_api_2_54_0/bpy.types.Material.html#bpy.types.Material.specular_hardness
-        materials[m.name]["specular_coef"] = m.specular_hardness 
-        
-        if m.active_texture:
-            fn = bpy.path.abspath(m.active_texture.image.filepath)
-            fn = os.path.normpath(fn)
-            fn_strip = os.path.basename(fn)
-            materials[m.name]['map_diffuse'] = fn_strip
+        if m:
+            materials[m.name] = {}
+            materials[m.name]['col_diffuse'] = [m.diffuse_intensity * m.diffuse_color[0], 
+                                                m.diffuse_intensity * m.diffuse_color[1], 
+                                                m.diffuse_intensity * m.diffuse_color[2]]
+                                                
+            materials[m.name]['col_specular'] = [m.specular_intensity * m.specular_color[0], 
+                                                 m.specular_intensity * m.specular_color[1], 
+                                                 m.specular_intensity * m.specular_color[2]]
+                                                 
+            materials[m.name]['col_ambient'] = [m.ambient * world.ambient_color[0], 
+                                                m.ambient * world.ambient_color[1], 
+                                                m.ambient * world.ambient_color[2]]
+                                                
+            materials[m.name]['transparency'] = m.alpha
+            
+            # not sure about mapping values to Blinn-Phong shader
+            # Blender uses INT from [1,511] with default 0
+            # http://www.blender.org/documentation/blender_python_api_2_54_0/bpy.types.Material.html#bpy.types.Material.specular_hardness
+            materials[m.name]["specular_coef"] = m.specular_hardness 
+            
+            if m.active_texture and m.active_texture.type == 'IMAGE':
+                fn = bpy.path.abspath(m.active_texture.image.filepath)
+                fn = os.path.normpath(fn)
+                fn_strip = os.path.basename(fn)
+                materials[m.name]['map_diffuse'] = fn_strip
             
     return materials
         
@@ -411,8 +487,13 @@ def generate_materials_string(mesh, scene):
     random.seed(42) # to get well defined color order for debug materials
 
     materials = {}
-    for i, m in enumerate(mesh.materials):
-        materials[m.name] = i
+    if mesh.materials:
+        for i, m in enumerate(mesh.materials):
+            if m:
+                materials[m.name] = i
+            else:
+                materials["undefined_dummy_%0d" % i] = i
+                
     
     if not materials:
         materials = { 'default':0 }
@@ -428,14 +509,24 @@ def generate_materials_string(mesh, scene):
 # #####################################################
 # ASCII exporter
 # #####################################################
-def generate_ascii_model(mesh, scene, use_normals, use_uv_coords):
+def generate_ascii_model(mesh, scene, use_normals, use_uv_coords, align_model):
+    
+    vertices = mesh.vertices[:]
+    
+    if align_model == 1:
+        center(vertices)
+    elif align_model == 2:
+        bottom(vertices)
+    elif align_model == 3:
+        top(vertices)
+    
     sfaces = sort_faces(mesh.faces, use_normals, use_uv_coords)
     
     normals = extract_vertex_normals(mesh, use_normals)
     uvs = extract_uvs(mesh, use_uv_coords)
     
     text = TEMPLATE_FILE_ASCII % {
-    "vertices"      : ",".join(generate_vertex(v) for v in mesh.vertices),
+    "vertices"      : ",".join(generate_vertex(v) for v in vertices),
     
     "triangles"     : ",".join(generate_triangle(f) for f in sfaces['triangles_flat']),
     "triangles_n"   : ",".join(generate_triangle_n(f, normals, mesh) for f in sfaces['triangles_smooth']),
@@ -462,7 +553,7 @@ def generate_ascii_model(mesh, scene, use_normals, use_uv_coords):
 # #####################################################
 # Main
 # #####################################################
-def save(operator, context, filepath="", use_modifiers=True, use_normals=True, use_uv_coords=True):
+def save(operator, context, filepath="", use_modifiers=True, use_normals=True, use_uv_coords=True, align_model=1):
 
     def rvec3d(v):
         return round(v[0], 6), round(v[1], 6), round(v[2], 6)
@@ -508,7 +599,7 @@ def save(operator, context, filepath="", use_modifiers=True, use_normals=True, u
         if not active_uv_layer:
             use_uv_coords = False
 
-    text = generate_ascii_model(mesh, scene, use_normals, use_uv_coords)
+    text = generate_ascii_model(mesh, scene, use_normals, use_uv_coords, align_model)
     file = open(filepath, 'w')
     file.write(text)
     file.close()

+ 1 - 1
utils/exporters/convert_obj_threejs.py

@@ -393,7 +393,7 @@ def bottom(vertices):
     cy = bb['y'][0] 
     cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
     
-    translate(vertices, [-cx,cy,-cz])
+    translate(vertices, [-cx,-cy,-cz])
 
 def normalize(v):
     """Normalize 3d vector"""

+ 1 - 1
utils/exporters/convert_obj_threejs_slim.py

@@ -314,7 +314,7 @@ def bottom(vertices):
     cy = bb['y'][0] 
     cz = bb['z'][0] + (bb['z'][1] - bb['z'][0])/2.0
     
-    translate(vertices, [-cx,cy,-cz])
+    translate(vertices, [-cx,-cy,-cz])
 
 def normalize(v):
     """Normalize 3d vector"""

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