Sfoglia il codice sorgente

Merged with mrdoob's branch. Got WebGLRenderer working again :)

Changed OBJ -> Three.js converter to use new materials system (eventual old models need to be reconverted).

Limitations:

  - one use case is now much slower
    - when a mesh has each face with different color (e.g. polyfield in examples/test.html)
    - before this used FaceColorFill material and in WebGLRenderer it was rendered fast with color attribute array
    - now when FaceColorFill material is gone, each face gets own VBO :(

  - material sorting uses Materials "toString" methods for hashing, so it's very important to keep these in a good shape
alteredq 14 anni fa
parent
commit
79ab4bf2e6

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


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


+ 2 - 3
examples/camera_free.html

@@ -39,11 +39,10 @@
 		<script type="text/javascript" src="../src/objects/Particle.js"></script>
 		<script type="text/javascript" src="../src/objects/Line.js"></script>
 		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshBitmapUVMappingMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorStrokeMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorFillMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorStrokeMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>

File diff suppressed because it is too large
+ 744 - 742
examples/geometry/Qrcode.js


+ 2 - 2
examples/geometry_cube.html

@@ -74,10 +74,10 @@
 
 				for (var i = 0; i < geometry.faces.length; i++) {
 
-					geometry.faces[i].color.setRGBA( Math.random() * 0.5, Math.random() * 0.5 + 0.5, Math.random() * 0.5 + 0.5, 1 );
+					geometry.faces[i].material = [ new THREE.MeshColorFillMaterial( Math.random() * 0xffffff, 1 ) ];
 				}
 
-				cube = new THREE.Mesh(geometry, new THREE.MeshFaceColorFillMaterial() );
+				cube = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial() );
 				cube.position.y = 150;
 				scene.addObject( cube );
 

+ 1 - 1
examples/geometry_earth.html

@@ -98,7 +98,7 @@
 				canvas.width = 32;
 				canvas.height = 32;
 
-				var material =  new THREE.MeshBitmapUVMappingMaterial( canvas );
+				var material =  new THREE.MeshBitmapMaterial( canvas );
 
 				var image = new Image();
 

+ 1 - 1
examples/geometry_terrain.html

@@ -145,7 +145,7 @@
 
 				var heightMap = height( 1024, 1024 );
 				var textureMap = shadow( heightMap );
-				var material = new THREE.MeshBitmapUVMappingMaterial( textureMap );
+				var material = new THREE.MeshBitmapMaterial( textureMap );
 
 				var quality = 20;
 				var quality1 = quality + 1;

+ 1 - 1
examples/geometry_vr.html

@@ -121,7 +121,7 @@
 
 			function loadTexture( path ) {
 
-				var material = new THREE.MeshBitmapUVMappingMaterial( texture_placeholder );
+				var material = new THREE.MeshBitmapMaterial( texture_placeholder );
 
 				var texture = new Image();
 

+ 10 - 11
examples/hci_clickcube.html

@@ -37,11 +37,10 @@
 		<script type="text/javascript" src="../src/lights/AmbientLight.js"></script>
 		<script type="text/javascript" src="../src/lights/DirectionalLight.js"></script>
 		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshBitmapUVMappingMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorStrokeMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorFillMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorStrokeMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
@@ -115,33 +114,33 @@
 
 				geometry = new ClickCube( 200, 200, 200, 
 					function ( s, c, o, f, p ) {
-						f.color.setRGBA( Math.random() * 0.5, Math.random() * 0.5, Math.random() * 0.5, opacity );
+						f.material = [ new THREE.MeshColorFillMaterial( Math.random() * 0xffffff, opacity ) ];
 						document.getElementById( "msg" ).innerHTML = "Click detected at " + p; 
 					});
 
 				for (var i = 0; i < geometry.faces.length; i++) {
-					geometry.faces[i].color.setRGBA( Math.random() * 0.5, Math.random() * 0.5, Math.random() * 0.5, opacity );
+					geometry.faces[i].material = [ new THREE.MeshColorFillMaterial( Math.random() * 0xffffff, opacity ) ];
 				}
 
-				cube = new THREE.Mesh( geometry, new THREE.MeshFaceColorFillMaterial() );
+				cube = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );
 				cube.position.y = 150;
 				scene.addObject(cube);
 
 				geometry2 = new ClickCube( 100, 100, 100, 
 						function ( s, c, o, f, p ) {
-							f.color.setRGBA( Math.random() * 0.5, Math.random() * 0.5, Math.random() * 0.5, opacity );
+							f.material = [ new THREE.MeshColorFillMaterial( Math.random() * 0xffffff, opacity ) ];
 							document.getElementById( "msg" ).innerHTML = "Click detected at " + p; 
 						});
 
 				for (var i = 0; i < geometry2.faces.length; i++) {
-					geometry2.faces[i].color.setRGBA( Math.random() * 0.5, Math.random() * 0.5, Math.random() * 0.5, opacity );
+					geometry2.faces[i].material = [ new THREE.MeshColorFillMaterial( Math.random() * 0xffffff, opacity ) ];
 				}
-				
-				cube2 = new THREE.Mesh( geometry2, new THREE.MeshFaceColorFillMaterial() );
+
+				cube2 = new THREE.Mesh( geometry2, new THREE.MeshFaceMaterial() );
 				cube2.position.y = 150;
 				cube2.position.z = 200;
 				scene.addObject(cube2);
-				
+
 				// Plane
 				renderer = new THREE.CanvasRenderer();
 				renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);

+ 4 - 5
examples/lights_test.html

@@ -39,11 +39,10 @@
         
         <div id="log"></div>
 
-        <script type="text/javascript" src="../build/Three.js"></script> 
 		<!--
+        <script type="text/javascript" src="../build/Three.js"></script> 
         -->
 
-		<!--
 		<script type="text/javascript" src="../src/Three.js"></script>
 		<script type="text/javascript" src="../src/core/Color.js"></script>
 		<script type="text/javascript" src="../src/core/Vector2.js"></script>
@@ -67,11 +66,10 @@
 		<script type="text/javascript" src="../src/objects/Line.js"></script>
 		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshPhongMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshBitmapUVMappingMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorStrokeMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorFillMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorStrokeMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
@@ -83,6 +81,7 @@
 		<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>

+ 20 - 21
examples/materials_test.html

@@ -69,11 +69,10 @@
 		<script type="text/javascript" src="../src/objects/Line.js"></script>
 		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshPhongMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshBitmapUVMappingMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorStrokeMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorFillMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorStrokeMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
@@ -221,14 +220,6 @@
                     
                     geometry = new Female02( "obj/female02" );
                     
-                    // full-mesh wireframe overlay
-                    //geometry.materials.push ( new THREE.MeshColorStrokeMaterial(0xff0000, 1, 1.5) );
-                    
-                    // full-mesh color overlay
-                    var colorOverlay = new THREE.MeshColorFillMaterial(0xff0000, 0.5)
-                    colorOverlay.decalIndex = 4;
-                    geometry.materials.push ( colorOverlay );
-                    
                     // PROCEDURAL TEXTURES (decals)
                     
                     var x1 = document.createElement( "canvas" );
@@ -258,18 +249,26 @@
                         xc2.fillRect(i*4, 5, 2, 54);
                     }
 
-                    var xm1 = new THREE.MeshBitmapUVMappingMaterial( x1 );
-                    xm1.loaded = 1;
-                    xm1.decalIndex = 0; // index of the original UV mapped material 
+                    var xm1 = new THREE.MeshBitmapMaterial( x1 );
+                    xm1.loaded = 1; // this is procedurally generated texture
 
-                    var xm2 = new THREE.MeshBitmapUVMappingMaterial( x2 );
-                    xm2.loaded = 1;
-                    xm2.decalIndex = 1; // index of the original UV mapped material 
+                    var xm2 = new THREE.MeshBitmapMaterial( x2 );
+                    xm2.loaded = 1; // this is procedurally generated texture
+                    
+                    geometry.materials[0].push ( xm1 ); // goes to faces with material 0
+                    geometry.materials[1].push ( xm2 ); // goes to faces with material 1
                     
-                    geometry.materials.push ( xm1 );
-                    geometry.materials.push ( xm2 );
+                    geometry.materials[4].push ( new THREE.MeshColorFillMaterial(0xff0000, 0.5) );
 
-                    zmesh = new THREE.Mesh( geometry, geometry.materials, 1 );
+                    var materials = [ new THREE.MeshFaceMaterial() ];
+                    
+                    // full-mesh wireframe overlay
+                    //materials.push( new THREE.MeshColorStrokeMaterial(0xff0000, 1, 1.5) );
+                    
+                    // full-mesh color overlay
+                    //materials.push( new THREE.MeshColorFillMaterial(0xff0000, 0.5) );
+                    
+                    zmesh = new THREE.Mesh( geometry, materials, 1 );
                     zmesh.position.x = -80;
                     zmesh.position.z = 50;
                     zmesh.position.y = FLOOR;
@@ -321,7 +320,7 @@
                     xc.font = "50pt arial bold";
                     xc.fillText(i, 10, 64);
                     
-                    var xm = new THREE.MeshBitmapUVMappingMaterial( x );
+                    var xm = new THREE.MeshBitmapMaterial( x );
                     xm.loaded = 1;
                     
                     mesh = new THREE.Mesh( new Plane( size, size ), xm );

+ 2 - 2
examples/materials_video.html

@@ -83,7 +83,7 @@
 				textureContext.fillStyle = '#000000';
 				textureContext.fillRect( 0, 0, 480, 204 );
 
-				var material = new THREE.MeshBitmapUVMappingMaterial( texture );
+				var material = new THREE.MeshBitmapMaterial( texture );
 
 				textureReflection = document.createElement( 'canvas' );
 				textureReflection.width = 480;
@@ -97,7 +97,7 @@
 				textureReflectionGradient.addColorStop( 0.2, 'rgba(240, 240, 240, 1)' );
 				textureReflectionGradient.addColorStop( 1, 'rgba(240, 240, 240, 0.8)' );
 
-				var materialReflection = new THREE.MeshBitmapUVMappingMaterial( textureReflection );
+				var materialReflection = new THREE.MeshBitmapMaterial( textureReflection );
 
 				//
 

+ 15 - 15
examples/obj/female02/female02.js

@@ -15859,18 +15859,18 @@ var Female02 = function ( urlbase ) {
         scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
     }
 
-    function f3( a, b, c, material ) {
-        var color = material_color(material);
-        scope.faces.push( new THREE.Face3( a, b, c, null, new THREE.Color(color), material ) );
+    function f3( a, b, c, mi ) {
+        var material = scope.materials[ mi ];
+        scope.faces.push( new THREE.Face3( a, b, c, null, material ) );
     }
 
-    function f4( a, b, c, d, material ) {
-        var color = material_color(material);
-        scope.faces.push( new THREE.Face4( a, b, c, d, null, new THREE.Color(color), material ) );
+    function f4( a, b, c, d, mi ) {
+        var material = scope.materials[ mi ];
+        scope.faces.push( new THREE.Face4( a, b, c, d, null, material ) );
     }
 
-    function f3n( a, b, c, material, n1, n2, n3 ) {
-        var color = material_color(material);
+    function f3n( a, b, c, mi, n1, n2, n3 ) {
+        var material = scope.materials[ mi ];
         var n1x = normals[n1][0];
         var n1y = normals[n1][1];
         var n1z = normals[n1][2];
@@ -15882,11 +15882,11 @@ var Female02 = function ( urlbase ) {
         var n3z = normals[n3][2];
         scope.faces.push( new THREE.Face3( a, b, c, 
                           [new THREE.Vector3( n1x, n1y, n1z ), new THREE.Vector3( n2x, n2y, n2z ), new THREE.Vector3( n3x, n3y, n3z )], 
-                          new THREE.Color(color), material ) );
+                          material ) );
     }
 
-    function f4n( a, b, c, d, material, n1, n2, n3, n4 ) {
-        var color = material_color(material);
+    function f4n( a, b, c, d, mi, n1, n2, n3, n4 ) {
+        var material = scope.materials[ mi ];
         var n1x = normals[n1][0];
         var n1y = normals[n1][1];
         var n1z = normals[n1][2];
@@ -15901,7 +15901,7 @@ var Female02 = function ( urlbase ) {
         var n4z = normals[n4][2];
         scope.faces.push( new THREE.Face4( a, b, c, d,
                           [new THREE.Vector3( n1x, n1y, n1z ), new THREE.Vector3( n2x, n2y, n2z ), new THREE.Vector3( n3x, n3y, n3z ), new THREE.Vector3( n4x, n4y, n4z )], 
-                          new THREE.Color(color), material ) );
+                          material ) );
     }
 
     function uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {
@@ -15916,7 +15916,7 @@ var Female02 = function ( urlbase ) {
     function init_materials() {
         scope.materials = [];
         for(var i=0; i<materials.length; ++i) {
-            scope.materials[i] = create_material( materials[i], urlbase );
+            scope.materials[i] = [ create_material( materials[i], urlbase ) ];
         }
     }
     
@@ -15936,7 +15936,7 @@ var Female02 = function ( urlbase ) {
         if( m.map_diffuse && urlbase ) {
             var texture = document.createElement( 'canvas' );
             
-            material = new THREE.MeshBitmapUVMappingMaterial( texture );
+            material = new THREE.MeshBitmapMaterial( texture );
             var image = new Image();
             
             image.onload = function () {
@@ -15965,7 +15965,7 @@ var Female02 = function ( urlbase ) {
             material = new THREE.MeshColorFillMaterial( m.a_dbg_color );
         }
         else {
-            material = new THREE.MeshFaceColorFillMaterial( );
+            material = new THREE.MeshColorFillMaterial( 0xffeeeeee );
         }
 
         return material;

+ 15 - 15
examples/obj/male02/male02.js

@@ -12859,18 +12859,18 @@ var Male02 = function ( urlbase ) {
         scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
     }
 
-    function f3( a, b, c, material ) {
-        var color = material_color(material);
-        scope.faces.push( new THREE.Face3( a, b, c, null, new THREE.Color(color), material ) );
+    function f3( a, b, c, mi ) {
+        var material = scope.materials[ mi ];
+        scope.faces.push( new THREE.Face3( a, b, c, null, material ) );
     }
 
-    function f4( a, b, c, d, material ) {
-        var color = material_color(material);
-        scope.faces.push( new THREE.Face4( a, b, c, d, null, new THREE.Color(color), material ) );
+    function f4( a, b, c, d, mi ) {
+        var material = scope.materials[ mi ];
+        scope.faces.push( new THREE.Face4( a, b, c, d, null, material ) );
     }
 
-    function f3n( a, b, c, material, n1, n2, n3 ) {
-        var color = material_color(material);
+    function f3n( a, b, c, mi, n1, n2, n3 ) {
+        var material = scope.materials[ mi ];
         var n1x = normals[n1][0];
         var n1y = normals[n1][1];
         var n1z = normals[n1][2];
@@ -12882,11 +12882,11 @@ var Male02 = function ( urlbase ) {
         var n3z = normals[n3][2];
         scope.faces.push( new THREE.Face3( a, b, c, 
                           [new THREE.Vector3( n1x, n1y, n1z ), new THREE.Vector3( n2x, n2y, n2z ), new THREE.Vector3( n3x, n3y, n3z )], 
-                          new THREE.Color(color), material ) );
+                          material ) );
     }
 
-    function f4n( a, b, c, d, material, n1, n2, n3, n4 ) {
-        var color = material_color(material);
+    function f4n( a, b, c, d, mi, n1, n2, n3, n4 ) {
+        var material = scope.materials[ mi ];
         var n1x = normals[n1][0];
         var n1y = normals[n1][1];
         var n1z = normals[n1][2];
@@ -12901,7 +12901,7 @@ var Male02 = function ( urlbase ) {
         var n4z = normals[n4][2];
         scope.faces.push( new THREE.Face4( a, b, c, d,
                           [new THREE.Vector3( n1x, n1y, n1z ), new THREE.Vector3( n2x, n2y, n2z ), new THREE.Vector3( n3x, n3y, n3z ), new THREE.Vector3( n4x, n4y, n4z )], 
-                          new THREE.Color(color), material ) );
+                          material ) );
     }
 
     function uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {
@@ -12916,7 +12916,7 @@ var Male02 = function ( urlbase ) {
     function init_materials() {
         scope.materials = [];
         for(var i=0; i<materials.length; ++i) {
-            scope.materials[i] = create_material( materials[i], urlbase );
+            scope.materials[i] = [ create_material( materials[i], urlbase ) ];
         }
     }
     
@@ -12936,7 +12936,7 @@ var Male02 = function ( urlbase ) {
         if( m.map_diffuse && urlbase ) {
             var texture = document.createElement( 'canvas' );
             
-            material = new THREE.MeshBitmapUVMappingMaterial( texture );
+            material = new THREE.MeshBitmapMaterial( texture );
             var image = new Image();
             
             image.onload = function () {
@@ -12965,7 +12965,7 @@ var Male02 = function ( urlbase ) {
             material = new THREE.MeshColorFillMaterial( m.a_dbg_color );
         }
         else {
-            material = new THREE.MeshFaceColorFillMaterial( );
+            material = new THREE.MeshColorFillMaterial( 0xffeeeeee );
         }
 
         return material;

+ 15 - 15
examples/obj/torus/Torus.js

@@ -1194,18 +1194,18 @@ var Torus = function ( urlbase ) {
         scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
     }
 
-    function f3( a, b, c, material ) {
-        var color = material_color(material);
-        scope.faces.push( new THREE.Face3( a, b, c, null, new THREE.Color(color), material ) );
+    function f3( a, b, c, mi ) {
+        var material = scope.materials[ mi ];
+        scope.faces.push( new THREE.Face3( a, b, c, null, material ) );
     }
 
-    function f4( a, b, c, d, material ) {
-        var color = material_color(material);
-        scope.faces.push( new THREE.Face4( a, b, c, d, null, new THREE.Color(color), material ) );
+    function f4( a, b, c, d, mi ) {
+        var material = scope.materials[ mi ];
+        scope.faces.push( new THREE.Face4( a, b, c, d, null, material ) );
     }
 
-    function f3n( a, b, c, material, n1, n2, n3 ) {
-        var color = material_color(material);
+    function f3n( a, b, c, mi, n1, n2, n3 ) {
+        var material = scope.materials[ mi ];
         var n1x = normals[n1][0];
         var n1y = normals[n1][1];
         var n1z = normals[n1][2];
@@ -1217,11 +1217,11 @@ var Torus = function ( urlbase ) {
         var n3z = normals[n3][2];
         scope.faces.push( new THREE.Face3( a, b, c, 
                           [new THREE.Vector3( n1x, n1y, n1z ), new THREE.Vector3( n2x, n2y, n2z ), new THREE.Vector3( n3x, n3y, n3z )], 
-                          new THREE.Color(color), material ) );
+                          material ) );
     }
 
-    function f4n( a, b, c, d, material, n1, n2, n3, n4 ) {
-        var color = material_color(material);
+    function f4n( a, b, c, d, mi, n1, n2, n3, n4 ) {
+        var material = scope.materials[ mi ];
         var n1x = normals[n1][0];
         var n1y = normals[n1][1];
         var n1z = normals[n1][2];
@@ -1236,7 +1236,7 @@ var Torus = function ( urlbase ) {
         var n4z = normals[n4][2];
         scope.faces.push( new THREE.Face4( a, b, c, d,
                           [new THREE.Vector3( n1x, n1y, n1z ), new THREE.Vector3( n2x, n2y, n2z ), new THREE.Vector3( n3x, n3y, n3z ), new THREE.Vector3( n4x, n4y, n4z )], 
-                          new THREE.Color(color), material ) );
+                          material ) );
     }
 
     function uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {
@@ -1251,7 +1251,7 @@ var Torus = function ( urlbase ) {
     function init_materials() {
         scope.materials = [];
         for(var i=0; i<materials.length; ++i) {
-            scope.materials[i] = create_material( materials[i], urlbase );
+            scope.materials[i] = [ create_material( materials[i], urlbase ) ];
         }
     }
     
@@ -1271,7 +1271,7 @@ var Torus = function ( urlbase ) {
         if( m.map_diffuse && urlbase ) {
             var texture = document.createElement( 'canvas' );
             
-            material = new THREE.MeshBitmapUVMappingMaterial( texture );
+            material = new THREE.MeshBitmapMaterial( texture );
             var image = new Image();
             
             image.onload = function () {
@@ -1300,7 +1300,7 @@ var Torus = function ( urlbase ) {
             material = new THREE.MeshColorFillMaterial( m.a_dbg_color );
         }
         else {
-            material = new THREE.MeshFaceColorFillMaterial( );
+            material = new THREE.MeshColorFillMaterial( 0xffeeeeee );
         }
 
         return material;

+ 8 - 9
examples/obj_convert_test.html

@@ -42,11 +42,10 @@
         
         <div id="log"></div>
 
-        <script type="text/javascript" src="../build/Three.js"></script> 
 		<!--
+        <script type="text/javascript" src="../build/Three.js"></script> 
         -->
 
-		<!--
 		<script type="text/javascript" src="../src/Three.js"></script>
 		<script type="text/javascript" src="../src/core/Color.js"></script>
 		<script type="text/javascript" src="../src/core/Vector2.js"></script>
@@ -70,11 +69,10 @@
 		<script type="text/javascript" src="../src/objects/Line.js"></script>
 		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshPhongMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshBitmapUVMappingMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorStrokeMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorFillMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorStrokeMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
@@ -86,6 +84,7 @@
 		<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>
+		<!--
         -->
 		
 
@@ -161,7 +160,7 @@
                 xc.fillStyle = "#555";
                 xc.fillRect(96, 96, 32, 32);
                 
-                var xm = new THREE.MeshBitmapUVMappingMaterial( x );
+                var xm = new THREE.MeshBitmapMaterial( x );
                 xm.loaded = 1;
                 
                 geometry = new Plane( 100, 100, 15, 10 );
@@ -245,7 +244,7 @@
                     // MESH
                     
                     geometry = new Male02( "obj/male02" );
-                    zmesh = new THREE.Mesh( geometry, geometry.materials, 1 );
+                    zmesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial(), 1 );
                     zmesh.position.x = 90;
                     zmesh.position.z = 50;
                     zmesh.position.y = FLOOR;
@@ -264,7 +263,7 @@
                     // MESH
                     
                     geometry = new Female02( "obj/female02" );
-                    zmesh = new THREE.Mesh( geometry, geometry.materials, 1 );
+                    zmesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial(), 1 );
                     zmesh.position.x = -80;
                     zmesh.position.z = 50;
                     zmesh.position.y = FLOOR;
@@ -317,7 +316,7 @@
                     xc.font = "50pt arial bold";
                     xc.fillText(i, 10, 64);
                     
-                    var xm = new THREE.MeshBitmapUVMappingMaterial( x );
+                    var xm = new THREE.MeshBitmapMaterial( x );
                     xm.loaded = 1;
                     
                     mesh = new THREE.Mesh( new Plane( size, size ), xm );

+ 2 - 3
examples/shader_test.html

@@ -69,11 +69,10 @@
 		<script type="text/javascript" src="../src/objects/Line.js"></script>
 		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshPhongMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshBitmapUVMappingMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorStrokeMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorFillMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorStrokeMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>

+ 10 - 11
examples/test.html

@@ -33,16 +33,15 @@
 		<script type="text/javascript" src="../src/lights/DirectionalLight.js"></script>
 		<script type="text/javascript" src="../src/lights/PointLight.js"></script>
 		<script type="text/javascript" src="../src/objects/Object3D.js"></script>
-		<script type="text/javascript" src="../src/objects/Mesh.js"></script>
 		<script type="text/javascript" src="../src/objects/Particle.js"></script>
 		<script type="text/javascript" src="../src/objects/Line.js"></script>
+		<script type="text/javascript" src="../src/objects/Mesh.js"></script>
 		<script type="text/javascript" src="../src/materials/LineColorMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshPhongMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshBitmapUVMappingMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorFillMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/MeshColorStrokeMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorFillMaterial.js"></script>
-		<script type="text/javascript" src="../src/materials/MeshFaceColorStrokeMaterial.js"></script>
+		<script type="text/javascript" src="../src/materials/MeshFaceMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleCircleMaterial.js"></script>
 		<script type="text/javascript" src="../src/materials/ParticleBitmapMaterial.js"></script>
 		<script type="text/javascript" src="../src/scenes/Scene.js"></script>
@@ -105,7 +104,7 @@
 
 				// QRCODE
 
-				qrcode = mesh = new THREE.Mesh(new Qrcode(), new THREE.MeshFaceColorFillMaterial());
+				qrcode = mesh = new THREE.Mesh( new Qrcode(), new THREE.MeshFaceMaterial() );
 				mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
 				mesh.updateMatrix();
 				scene.add(mesh);
@@ -156,22 +155,22 @@
 
 					var v = new THREE.Vector3( Math.random() * 1000 - 500, Math.random() * 1000 - 500, Math.random() * 1000 - 500 );
 
-					var v0 = new THREE.Vertex( new THREE.Vector3(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ) );
-					var v1 = new THREE.Vertex( new THREE.Vector3(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ) );
-					var v2 = new THREE.Vertex( new THREE.Vector3(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ) );
+					var v0 = new THREE.Vertex( new THREE.Vector3( Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ) );
+					var v1 = new THREE.Vertex( new THREE.Vector3( Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ) );
+					var v2 = new THREE.Vertex( new THREE.Vector3( Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ) );
 
 					v0.position.addSelf( v );
 					v1.position.addSelf( v );
 					v2.position.addSelf( v );
 
-					var face = new THREE.Face3( geometry.vertices.push( v0 ) - 1, geometry.vertices.push( v1 ) - 1, geometry.vertices.push( v2 ) - 1 );
-					face.color.setRGBA( Math.random(), Math.random(), Math.random(), 1 );
+					var face = new THREE.Face3( geometry.vertices.push( v0 ) - 1, geometry.vertices.push( v1 ) - 1, geometry.vertices.push( v2 ) - 1, null, new THREE.MeshColorFillMaterial( Math.random() * 0xffffff ) );
+
 					geometry.faces.push( face );
 				}
 
 				geometry.computeNormals();
 
-				mesh = new THREE.Mesh( geometry, new THREE.MeshFaceColorFillMaterial() );
+				mesh = new THREE.Mesh( geometry, [ new THREE.MeshFaceMaterial(), new THREE.MeshColorStrokeMaterial( 0xff0000, 0.5, 10 ) ] );
 				mesh.doubleSided = true;
 				mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
 				scene.add(mesh);

+ 4 - 14
src/core/Face3.js

@@ -2,32 +2,22 @@
  * @author mr.doob / http://mrdoob.com/
  */
 
-THREE.Face3 = function ( a, b, c, normal, color, material ) {
+THREE.Face3 = function ( a, b, c, normal, material ) {
 
 	this.a = a;
 	this.b = b;
 	this.c = c;
 
 	this.centroid = new THREE.Vector3();
-    this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
-
-	this.color = color || new THREE.Color( 0xff000000 );
+	this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
+    this.vertexNormals =  normal instanceof Array ? normal : [];
     
-	this.vertexNormals =  normal instanceof Array ? normal : [];
-    this.material = material || 0;
+	this.material = material instanceof Array ? material : [ material ];
 
 };
 
 THREE.Face3.prototype = {
 
-	// TODO: Dupe? (Geometry/computeCentroid)
-
-	getCenter : function(){
-
-		return this.a.clone().addSelf( this.b ).addSelf( this.c ).divideScalar( 3 );
-
-	},
-
 	toString: function () {
 
 		return 'THREE.Face3 ( ' + this.a + ', ' + this.b + ', ' + this.c + ' )';

+ 3 - 13
src/core/Face4.js

@@ -2,7 +2,7 @@
  * @author mr.doob / http://mrdoob.com/
  */
 
-THREE.Face4 = function ( a, b, c, d, normal, color, material ) {
+THREE.Face4 = function ( a, b, c, d, normal, material ) {
 
 	this.a = a;
 	this.b = b;
@@ -11,25 +11,15 @@ THREE.Face4 = function ( a, b, c, d, normal, color, material ) {
 
 	this.centroid = new THREE.Vector3();
 	this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
+    this.vertexNormals =  normal instanceof Array ? normal : [];
 
-	this.color = color || new THREE.Color( 0xff000000 );
+	this.material = material instanceof Array ? material : [ material ];
 
-	this.vertexNormals = normal instanceof Array ? normal : [];
-    this.material = material || 0;
-    
 };
 
 
 THREE.Face4.prototype = {
 
-	// TODO: Dupe? (Geometry/computeCentroid)
-
-	getCenter : function(){
-
-		return this.a.clone().addSelf( this.b ).addSelf( this.c ).addSelf( this.d ).divideScalar( 4 );
-
-	},
-
 	toString: function () {
 
 		return 'THREE.Face4 ( ' + this.a + ', ' + this.b + ', ' + this.c + ' ' + this.d + ' )';

+ 76 - 65
src/core/Geometry.js

@@ -58,86 +58,97 @@ THREE.Geometry.prototype = {
 
 			face = this.faces[ f ];
 
-            if ( useVertexNormals && face.vertexNormals.length  ) {
-                
-                // set face normal to average of vertex normals
-                
-                cb.set( 0, 0, 0 );
+			if ( useVertexNormals && face.vertexNormals.length  ) {
 
-                for ( n = 0, nl = face.normal.length; n < nl; n++ ) {
-                    cb.x += face.vertexNormals[n].x;
-                    cb.y += face.vertexNormals[n].y;
-                    cb.z += face.vertexNormals[n].z;
-                }
+				cb.set( 0, 0, 0 );
 
-                cb.x /= 3;
-                cb.y /= 3;
-                cb.z /= 3;
+				for ( n = 0, nl = face.normal.length; n < nl; n++ ) {
 
-                if ( !cb.isZero() ) {
+					cd.addSelf( face.vertexNormals[n] );
 
-                    cb.normalize();
+				}
 
-                }
+				cb.divideScalar( 3 );
 
-                face.normal.copy( cb );
-            }
-            
-            else {
-                
-                vA = this.vertices[ face.a ];
-                vB = this.vertices[ face.b ];
-                vC = this.vertices[ face.c ];
+				if ( ! cb.isZero() ) {
 
-                cb.sub( vC.position, vB.position );
-                ab.sub( vA.position, vB.position );
-                cb.crossSelf( ab );
+					cb.normalize();
 
-                if ( !cb.isZero() ) {
+				}
 
-                    cb.normalize();
+				face.normal.copy( cb );
 
-                }
+			} else {
 
-                face.normal.copy( cb );
-            }
+				vA = this.vertices[ face.a ];
+				vB = this.vertices[ face.b ];
+				vC = this.vertices[ face.c ];
+
+				cb.sub( vC.position, vB.position );
+				ab.sub( vA.position, vB.position );
+				cb.crossSelf( ab );
+
+				if ( !cb.isZero() ) {
+
+				    cb.normalize();
+
+				}
+
+				face.normal.copy( cb );
+
+			}
+
+		}
+
+	},
+
+	computeBoundingBox: function ( ) {
+
+		if ( this.vertices.length > 0 ) {
+
+			this.bbox = { 'x': [ this.vertices[ 0 ].position.x, this.vertices[ 0 ].position.x ],
+			'y': [ this.vertices[ 0 ].position.y, this.vertices[ 0 ].position.y ], 
+			'z': [ this.vertices[ 0 ].position.z, this.vertices[ 0 ].position.z ] };
+
+			for ( var v = 1, vl = this.vertices.length; v < vl; v++ ) {
+
+				vertex = this.vertices[ v ];
+
+				if ( vertex.position.x < this.bbox.x[ 0 ] ) {
+
+					this.bbox.x[ 0 ] = vertex.position.x;
+
+				} else if ( vertex.position.x > this.bbox.x[ 1 ] ) {
+
+					this.bbox.x[ 1 ] = vertex.position.x;
+
+				}
+
+				if ( vertex.position.y < this.bbox.y[ 0 ] ) {
+
+					this.bbox.y[ 0 ] = vertex.position.y;
+
+				} else if ( vertex.position.y > this.bbox.y[ 1 ] ) {
+
+					this.bbox.y[ 1 ] = vertex.position.y;
+
+				}
+
+				if ( vertex.position.z < this.bbox.z[ 0 ] ) {
+
+					this.bbox.z[ 0 ] = vertex.position.z;
+
+				} else if ( vertex.position.z > this.bbox.z[ 1 ] ) {
+
+					this.bbox.z[ 1 ] = vertex.position.z;
+
+				}
+
+			}
 
 		}
 
 	},
-    
-    computeBoundingBox: function ( ) {
-        
-        if ( this.vertices.length > 0 ) {
-            
-            this.bbox = { 'x': [ this.vertices[ 0 ].position.x, this.vertices[ 0 ].position.x ], 
-                          'y': [ this.vertices[ 0 ].position.y, this.vertices[ 0 ].position.y ], 
-                          'z': [ this.vertices[ 0 ].position.z, this.vertices[ 0 ].position.z ] };
-            
-            var v, vl;
-            
-            for ( v = 1, vl = this.vertices.length; v < vl; v++ ) {
-
-                vertex = this.vertices[ v ];
-                
-                if ( vertex.position.x < this.bbox.x[ 0 ] )
-                    this.bbox.x[ 0 ] = vertex.position.x;
-                else if ( vertex.position.x > this.bbox.x[ 1 ] )
-                    this.bbox.x[ 1 ] = vertex.position.x;
-
-                if ( vertex.position.y < this.bbox.y[ 0 ] )
-                    this.bbox.y[ 0 ] = vertex.position.y;
-                else if ( vertex.position.y > this.bbox.y[ 1 ] )
-                    this.bbox.y[ 1 ] = vertex.position.y;
-
-                if ( vertex.position.z < this.bbox.z[ 0 ] )
-                    this.bbox.z[ 0 ] = vertex.position.z;
-                else if ( vertex.position.z > this.bbox.z[ 1 ] )
-                    this.bbox.z[ 1 ] = vertex.position.z;
-
-            }
-        }
-    },
 
 	toString: function () {
 

+ 22 - 0
src/materials/MeshBitmapMaterial.js

@@ -0,0 +1,22 @@
+/**
+ * @author mr.doob / http://mrdoob.com/
+ */
+
+THREE.MeshBitmapMaterial = function ( bitmap, mode ) {
+
+	this.bitmap = bitmap;
+	this.mode = mode || THREE.MeshBitmapMaterialMode.UVMAPPING;
+    
+    this.id = THREE.MeshBitmapMaterialCounter.value++;
+    
+	this.toString = function () {
+
+		return 'THREE.MeshBitmapMaterial ( bitmap: ' + this.bitmap + ', mode: ' + this.mode + ', id: ' + this.id + ' )';
+
+	};
+
+};
+
+THREE.MeshBitmapMaterialCounter = { value:0 };
+
+THREE.MeshBitmapMaterialMode = { UVMAPPING: 0 };

+ 0 - 18
src/materials/MeshBitmapUVMappingMaterial.js

@@ -1,18 +0,0 @@
-/**
- * @author mr.doob / http://mrdoob.com/
- */
-
-THREE.MeshBitmapUVMappingMaterial = function ( bitmap ) {
-
-	this.bitmap = bitmap;
-
-    this.loaded = 0;
-    this.decalIndex = -1;
-    
-	this.toString = function () {
-
-		return 'THREE.MeshBitmapUVMappingMaterial ( bitmap: ' + this.bitmap + ' )';
-
-	};
-
-};

+ 0 - 13
src/materials/MeshFaceColorFillMaterial.js

@@ -1,13 +0,0 @@
-/**
- * @author mr.doob / http://mrdoob.com/
- */
-
-THREE.MeshFaceColorFillMaterial = function () {
-
-	this.toString = function () {
-
-		return 'THREE.MeshFaceColorFillMaterial ( )';
-
-	};
-
-};

+ 0 - 15
src/materials/MeshFaceColorStrokeMaterial.js

@@ -1,15 +0,0 @@
-/**
- * @author mr.doob / http://mrdoob.com/
- */
-
-THREE.MeshFaceColorStrokeMaterial = function ( lineWidth ) {
-
-	this.lineWidth = lineWidth || 1;
-
-	this.toString = function () {
-
-		return 'THREE.MeshFaceColorStrokeMaterial ( lineWidth: ' + this.lineWidth + ' )';
-
-	};
-
-};

+ 13 - 0
src/materials/MeshFaceMaterial.js

@@ -0,0 +1,13 @@
+/**
+ * @author mr.doob / http://mrdoob.com/
+ */
+
+THREE.MeshFaceMaterial = function () {
+
+	this.toString = function () {
+
+		return 'THREE.MeshFaceMaterial';
+
+	};
+
+};

+ 39 - 9
src/objects/Mesh.js

@@ -14,7 +14,7 @@ THREE.Mesh = function ( geometry, material, normUVs ) {
 
 	this.overdraw = false;
 
-    this.materialFaces = {};
+    this.materialFaceGroup = {};
         
     this.sortFacesByMaterial();
     if( normUVs ) this.normalizeUVs();
@@ -28,20 +28,50 @@ THREE.Mesh.prototype.constructor = THREE.Mesh;
 
 THREE.Mesh.prototype.sortFacesByMaterial = function () {
     
-    var f, fl, face, material;
+    // TODO
+        
+    // Should optimize by grouping faces with ColorFill / ColorStroke materials
+    // which could then use vertex color attributes instead of each being
+    // in its separate VBO
 
-    for ( f = 0, fl = this.geometry.faces.length; f < fl; f++ ) {
+    function materialHash( material ) {
+        
+        var i, l, hash_array = [];
 
+        for ( i = 0, l = material.length; i<l; i++ ) {
+            
+            if ( material[i] == undefined ) {
+                
+                hash_array.push( "undefined" );
+            
+            } else {
+                
+                hash_array.push( material[i].toString() );
+                
+            }
+        }
+
+        return hash_array.join("_");
+    }
+    
+    var i, f, fl, face, material;
+    
+    for ( f = 0, fl = this.geometry.faces.length; f < fl; f++ ) {
+        
         face = this.geometry.faces[ f ];
         material = face.material;
+        
+        hash = materialHash( material);
+        
+        if ( this.materialFaceGroup[ hash ] == undefined ) {
+            
+            this.materialFaceGroup[ hash ] = { 'faces': [], 'material': material };
+        }
 
-        if ( this.materialFaces[material] == undefined ) 
-            this.materialFaces[material] = { 'faces': [] };
-
-        this.materialFaces[material].faces.push( f );
-
+        this.materialFaceGroup[ hash ].faces.push( f );
+        
     }
-
+    
 }
     
 THREE.Mesh.prototype.normalizeUVs = function () {

+ 371 - 469
src/renderers/CanvasRenderer.js

@@ -19,10 +19,11 @@ THREE.CanvasRenderer = function () {
 	_light = new THREE.Color( 0xffffffff ),
 	_ambientLight = new THREE.Color( 0xffffffff ),
 
+	_pi2 = Math.PI * 2,
 	_vector2 = new THREE.Vector2(), // Needed for expand
 	_vector3 = new THREE.Vector3(), // Needed for PointLight
-	v5 = new THREE.Vector2(), v6 = new THREE.Vector2(), // Needed for latter splitting tris to quads
-	uv1 = new THREE.UV(), uv2 = new THREE.UV(), uv3 = new THREE.UV(), uv4 = new THREE.UV();
+	_uv1 = new THREE.UV(), _uv2 = new THREE.UV(), _uv3 = new THREE.UV(), _uv4 = new THREE.UV(),
+	v5 = new THREE.Vector2(), v6 = new THREE.Vector2(); // Needed for latter splitting tris to quads
 
 	this.domElement = _canvas;
 	this.autoClear = true;
@@ -49,36 +50,14 @@ THREE.CanvasRenderer = function () {
 			_context.setTransform( 1, 0, 0, - 1, _widthHalf, _heightHalf );
 			_context.clearRect( _clearRect.getX(), _clearRect.getY(), _clearRect.getWidth(), _clearRect.getHeight() );
 
-			/*
-			// Opera workaround
-			_context.setTransform( 1, 0, 0, 1, _widthHalf, _heightHalf );
-			_context.clearRect( _clearRect.getX(), - ( _clearRect.getHeight() + _clearRect.getY() ), _clearRect.getWidth(), _clearRect.getHeight() );
-			*/
-
 			_clearRect.empty();
 
 		}
 	};
 
-    this.isFullOverlay = function ( material, materialIndex, element ) {
-        
-        // these materials can be either the only material for whole mesh
-        // or if they are overlays in multimaterials, they apply only to
-        // group of faces with single material (specified by decalIndex)
-        
-        return ( ( material instanceof THREE.MeshBitmapUVMappingMaterial || 
-                   material instanceof THREE.MeshFaceColorFillMaterial ||
-                   material instanceof THREE.MeshColorFillMaterial
-                 ) 
-                 &&
-                 ! ( materialIndex == element.materialIndex || 
-                     element.materialIndex == material.decalIndex ) );
-        
-    };
-        
 	this.render = function ( scene, camera ) {
 
-		var e, el, element, m, ml, material, pi2 = Math.PI * 2,
+		var e, el, element, m, ml, fm, fml, material,
 		v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y, v5x, v5y, v6x, v6y,
 		width, height, scaleX, scaleY, offsetX, offsetY,
 		bitmap, bitmapWidth, bitmapHeight;
@@ -120,95 +99,7 @@ THREE.CanvasRenderer = function () {
 
 					material = element.material[ m ];
 
-					if ( material instanceof THREE.ParticleCircleMaterial ) {
-
-						if ( _enableLighting ) {
-
-							_light.copyRGB( _ambientLight );
-							calculateLight( scene, element, _light );
-
-							_color.copyRGBA( material.color );
-							_color.multiplySelfRGB( _light );
-							_color.updateStyleString();
-
-						} else {
-
-							_color = material.color;
-
-						}
-
-						width = element.scale.x * _widthHalf;
-						height = element.scale.y * _heightHalf;
-
-						_bboxRect.set( v1x - width, v1y - height, v1x + width, v1y + height );
-
-						if ( !_clipRect.instersects( _bboxRect ) ) {
-
-							continue;
-
-						}
-
-						_context.save();
-						_context.translate( v1x, v1y );
-						_context.rotate( - element.rotation );
-						_context.scale( width, height );
-
-						_context.beginPath();
-						_context.arc( 0, 0, 1, 0, pi2, true );
-						_context.closePath();
-
-						_context.fillStyle = _color.__styleString;
-						_context.fill();
-
-						_context.restore();
-
-					} else if ( material instanceof THREE.ParticleBitmapMaterial ) {
-
-						bitmap = material.bitmap;
-						bitmapWidth = bitmap.width / 2;
-						bitmapHeight = bitmap.height / 2;
-
-						scaleX = element.scale.x * _widthHalf;
-						scaleY = element.scale.y * _heightHalf;
-
-						width = scaleX * bitmapWidth;
-						height = scaleY * bitmapHeight;
-
-						offsetX = material.offset.x * scaleX;
-						offsetY = material.offset.y * scaleY;
-
-						// TODO: Rotations break this...
-
-						_bboxRect.set( v1x + offsetX - width, v1y + offsetY - height, v1x + offsetX + width, v1y + offsetY + height );
-
-						if ( !_clipRect.instersects( _bboxRect ) ) {
-
-							continue;
-
-						}
-
-						_context.save();
-						_context.translate( v1x, v1y );
-						_context.rotate( - element.rotation );
-						_context.scale( scaleX, - scaleY );
-						_context.translate( - bitmapWidth + material.offset.x, - bitmapHeight - material.offset.y );
-
-						_context.drawImage( bitmap, 0, 0 );
-
-						_context.restore();
-
-						/* DEBUG
-						_context.beginPath();
-						_context.moveTo( v1x - 10, v1y );
-						_context.lineTo( v1x + 10, v1y );
-						_context.moveTo( v1x, v1y - 10 );
-						_context.lineTo( v1x, v1y + 10 );
-						_context.closePath();
-						_context.strokeStyle = 'rgb(255,255,0)';
-						_context.stroke();
-						*/
-
-					}
+					renderParticle( v1x, v1y, element, material, scene );
 
 				}
 
@@ -235,33 +126,7 @@ THREE.CanvasRenderer = function () {
 
 					material = element.material[ m ];
 
-					if ( material instanceof THREE.LineColorMaterial ) {
-
-						if ( _enableLighting ) {
-
-							_light.copyRGB( _ambientLight );
-							calculateLight( scene, element, _light );
-
-							_color.copyRGBA( material.color );
-							_color.multiplySelfRGB( _light );
-							_color.updateStyleString();
-
-						} else {
-
-							_color = material.color;
-
-						}
-
-						_context.lineWidth = material.lineWidth;
-						_context.lineJoin = "round";
-						_context.lineCap = "round";
-
-						_context.strokeStyle = _color.__styleString;
-						_context.stroke();
-
-						_bboxRect.inflate( _context.lineWidth );
-
-					}
+					renderLine( v1x, v1y, v2x, v2y, element, material, scene );
 
 				}
 
@@ -293,172 +158,30 @@ THREE.CanvasRenderer = function () {
 
 				}
 
-				for ( m = 0, ml = element.material.length; m < ml; m++ ) {
-
-					material = element.material[ m ];
-                    
-                    if ( this.isFullOverlay( material, m, element ) ) {
-                        
-                        continue;
-                    }
-                    
-					if ( material instanceof THREE.MeshColorFillMaterial ) {
-
-						if ( _enableLighting ) {
-
-							_light.copyRGB( _ambientLight );
-							calculateFaceLight( scene, element, _light );
-
-							_color.copyRGBA( material.color );
-							_color.multiplySelfRGB( _light );
-							_color.updateStyleString();
+				m = 0; ml = element.meshMaterial.length;
 
-						} else {
+				while ( m < ml ) {
 
-							_color = material.color;
+					material = element.meshMaterial[ m ++ ];
 
-						}
-
-						_context.beginPath();
-						_context.moveTo( v1x, v1y );
-						_context.lineTo( v2x, v2y );
-						_context.lineTo( v3x, v3y );
-						_context.lineTo( v1x, v1y );
-						_context.closePath();
-
-						_context.fillStyle = _color.__styleString;
-						_context.fill();
-
-					} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
-
-						if ( _enableLighting ) {
-
-							_light.copyRGB( _ambientLight );
-							calculateFaceLight( scene, element, _light );
-
-							_color.copyRGBA( material.color );
-							_color.multiplySelfRGB( _light );
-							_color.updateStyleString();
-
-						} else {
-
-							_color = material.color;
+					if ( material instanceof THREE.MeshFaceMaterial ) {
 
-						}
-
-						_context.beginPath();
-						_context.moveTo( v1x, v1y );
-						_context.lineTo( v2x, v2y );
-						_context.lineTo( v3x, v3y );
-						_context.lineTo( v1x, v1y );
-						_context.closePath();
-
-						_context.lineWidth = material.lineWidth;
-						_context.lineJoin = "round";
-						_context.lineCap = "round";
-
-						_context.strokeStyle = _color.__styleString;
-						_context.stroke();
-
-						_bboxRect.inflate( _context.lineWidth );
+						fm = 0; fml = element.faceMaterial.length;
 
-					} else if ( material instanceof THREE.MeshFaceColorFillMaterial ) {
+						while ( fm < fml ) {
 
-						if ( _enableLighting ) {
+							material = element.faceMaterial[ fm ++ ];
 
-							_light.copyRGB( _ambientLight );
-							calculateFaceLight( scene, element, _light );
-
-							_color.copyRGBA( element.color );
-							_color.multiplySelfRGB( _light );
-							_color.updateStyleString();
-
-						} else {
-
-							_color = element.color;
+							renderFace3( v1x, v1y, v2x, v2y, v3x, v3y, element, material, scene );
 
 						}
 
-						_context.beginPath();
-						_context.moveTo( v1x, v1y );
-						_context.lineTo( v2x, v2y );
-						_context.lineTo( v3x, v3y );
-						_context.lineTo( v1x, v1y );
-						_context.closePath();
-
-						_context.fillStyle = _color.__styleString;
-						_context.fill();
-
-					} else if ( material instanceof THREE.MeshFaceColorStrokeMaterial ) {
-
-						if ( _enableLighting ) {
-
-							_light.copyRGB( _ambientLight );
-							calculateFaceLight( scene, element, _light );
-
-							_color.copyRGBA( element.color );
-							_color.multiplySelfRGB( _light );
-							_color.updateStyleString();
-
-						} else {
-
-							_color = element.color;
-
-						}
-
-						_context.beginPath();
-						_context.moveTo( v1x, v1y );
-						_context.lineTo( v2x, v2y );
-						_context.lineTo( v3x, v3y );
-						_context.lineTo( v1x, v1y );
-						_context.closePath();
-
-						_context.lineWidth = material.lineWidth;
-						_context.lineJoin = "round";
-						_context.lineCap = "round";
-
-						_context.strokeStyle = _color.__styleString;
-						_context.stroke();
-
-						_bboxRect.inflate( _context.lineWidth );
-
-
-					} else if ( material instanceof THREE.MeshBitmapUVMappingMaterial ) {
-
-						bitmap = material.bitmap;
-						bitmapWidth = bitmap.width - 1;
-						bitmapHeight = bitmap.height - 1;
-
-						/* DEBUG
-						if ( !element.uvs[ 0 ] || !element.uvs[ 1 ] || !element.uvs[ 2 ]) {
-
-							_context.beginPath();
-							_context.moveTo( v1x, v1y );
-							_context.lineTo( v2x, v2y );
-							_context.lineTo( v3x, v3y );
-							_context.lineTo( v1x, v1y );
-							_context.closePath();
-
-							_context.fillStyle = 'rgb(0, 255, 0)';
-							_context.fill();
-
-							continue;
-
-						}
-						*/
-
-						uv1.copy( element.uvs[ 0 ] );
-						uv2.copy( element.uvs[ 1 ] );
-						uv3.copy( element.uvs[ 2 ] );
-
-						uv1.u *= bitmapWidth; uv1.v *= bitmapHeight;
-						uv2.u *= bitmapWidth; uv2.v *= bitmapHeight;
-						uv3.u *= bitmapWidth; uv3.v *= bitmapHeight;
-
-						drawTexturedTriangle( bitmap, v1x, v1y, v2x, v2y, v3x, v3y, uv1.u, uv1.v, uv2.u, uv2.v, uv3.u, uv3.v );
+						continue;
 
 					}
 
+					renderFace3( v1x, v1y, v2x, v2y, v3x, v3y, element, material, scene );
+
 				}
 
 			} else if ( element instanceof THREE.RenderableFace4 ) {
@@ -504,180 +227,30 @@ THREE.CanvasRenderer = function () {
 
 				}
 
-				for ( m = 0, ml = element.material.length; m < ml; m++ ) {
-
-					material = element.material[ m ];
-
-                    if ( this.isFullOverlay( material, m, element ) ) {
-                        
-                        continue;
-                    }
-                    
-					if ( material instanceof THREE.MeshColorFillMaterial ) {
-
-						if ( _enableLighting ) {
-
-							_light.copyRGB( _ambientLight );
-							calculateFaceLight( scene, element, _light );
-
-							_color.copyRGBA( material.color );
-							_color.multiplySelfRGB( _light );
-							_color.updateStyleString();
-
-						} else {
-
-							_color = material.color;
-
-						}
-
-						_context.beginPath();
-						_context.moveTo( v1x, v1y );
-						_context.lineTo( v2x, v2y );
-						_context.lineTo( v3x, v3y );
-						_context.lineTo( v4x, v4y );
-						_context.lineTo( v1x, v1y );
-						_context.closePath();
-
-						_context.fillStyle = _color.__styleString;
-						_context.fill();
-
-
-					} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
-
-						if ( _enableLighting ) {
-
-							_light.copyRGB( _ambientLight );
-							calculateFaceLight( scene, element, _light );
-
-							_color.copyRGBA( material.color );
-							_color.multiplySelfRGB( _light );
-							_color.updateStyleString();
-
-						} else {
-
-							_color = material.color;
-
-						}
-
-						_context.beginPath();
-						_context.moveTo( v1x, v1y );
-						_context.lineTo( v2x, v2y );
-						_context.lineTo( v3x, v3y );
-						_context.lineTo( v4x, v4y );
-						_context.lineTo( v1x, v1y );
-						_context.closePath();
-
-						_context.lineWidth = material.lineWidth;
-						_context.lineJoin = "round";
-						_context.lineCap = "round";
-
-						_context.strokeStyle = _color.__styleString;
-						_context.stroke();
-
-						_bboxRect.inflate( _context.lineWidth );
-
-					} else if ( material instanceof THREE.MeshFaceColorFillMaterial ) {
-
-						if ( _enableLighting ) {
-
-							_light.copyRGB( _ambientLight );
-							calculateFaceLight( scene, element, _light );
-
-							_color.copyRGBA( element.color );
-							_color.multiplySelfRGB( _light );
-							_color.updateStyleString();
-
-						} else {
-
-							_color = element.color;
-
-						}
-
-						_context.beginPath();
-						_context.moveTo( v1x, v1y );
-						_context.lineTo( v2x, v2y );
-						_context.lineTo( v3x, v3y );
-						_context.lineTo( v4x, v4y );
-						_context.lineTo( v1x, v1y );
-						_context.closePath();
-
-						_context.fillStyle = _color.__styleString;
-						_context.fill();
-
-					} else if ( material instanceof THREE.MeshFaceColorStrokeMaterial ) {
-
-						if ( _enableLighting ) {
-
-							_light.copyRGB( _ambientLight );
-							calculateFaceLight( scene, element, _light );
-
-							_color.copyRGBA( element.color );
-							_color.multiplySelfRGB( _light );
-							_color.updateStyleString();
-
-						} else {
-
-							_color = element.color;
-
-						}
-
-						_context.beginPath();
-						_context.moveTo( v1x, v1y );
-						_context.lineTo( v2x, v2y );
-						_context.lineTo( v3x, v3y );
-						_context.lineTo( v4x, v4y );
-						_context.lineTo( v1x, v1y );
-						_context.closePath();
-
-						_context.lineWidth = material.lineWidth;
-						_context.lineJoin = "round";
-						_context.lineCap = "round";
-
-						_context.strokeStyle = _color.__styleString;
-						_context.stroke();
+				m = 0; ml = element.meshMaterial.length;
 
-						_bboxRect.inflate( _context.lineWidth );
+				while ( m < ml ) {
 
-					} else if ( material instanceof THREE.MeshBitmapUVMappingMaterial ) {
+					material = element.meshMaterial[ m ++ ];
 
-						bitmap = material.bitmap;
-						bitmapWidth = bitmap.width - 1;
-						bitmapHeight = bitmap.height - 1;
+					if ( material instanceof THREE.MeshFaceMaterial ) {
 
-						/* DEBUG
-						if ( !element.uvs[ 0 ] || !element.uvs[ 1 ] || !element.uvs[ 2 ] || !element.uvs[ 3 ]) {
+						fm = 0; fml = element.faceMaterial.length;
 
-							_context.beginPath();
-							_context.moveTo( v1x, v1y );
-							_context.lineTo( v2x, v2y );
-							_context.lineTo( v3x, v3y );
-							_context.lineTo( v4x, v4y );
-							_context.lineTo( v1x, v1y );
-							_context.closePath();
+						while ( fm < fml ) {
 
-							_context.fillStyle = 'rgb(255, 0, 255)';
-							_context.fill();
+							material = element.faceMaterial[ fm ++ ];
 
-							continue;
+							renderFace4( v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y, v5x, v5y, v6x, v6y, element, material, scene );
 
 						}
-						*/
 
-						uv1.copy( element.uvs[ 0 ] );
-						uv2.copy( element.uvs[ 1 ] );
-						uv3.copy( element.uvs[ 2 ] );
-						uv4.copy( element.uvs[ 3 ] );
-
-						uv1.u *= bitmapWidth; uv1.v *= bitmapHeight;
-						uv2.u *= bitmapWidth; uv2.v *= bitmapHeight;
-						uv3.u *= bitmapWidth; uv3.v *= bitmapHeight;
-						uv4.u *= bitmapWidth; uv4.v *= bitmapHeight;
-
-						drawTexturedTriangle( bitmap, v1x, v1y, v2x, v2y, v4x, v4y, uv1.u, uv1.v, uv2.u, uv2.v, uv4.u, uv4.v );
-						drawTexturedTriangle( bitmap, v5x, v5y, v3x, v3y, v6x, v6y, uv2.u, uv2.v, uv3.u, uv3.v, uv4.u, uv4.v );
+						continue;
 
 					}
 
+					renderFace4( v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y, v5x, v5y, v6x, v6y, element, material, scene );
+
 				}
 
 			}
@@ -792,7 +365,340 @@ THREE.CanvasRenderer = function () {
 
 	}
 
-	function drawTexturedTriangle( bitmap, v1x, v1y, v2x, v2y, v3x, v3y, uv1u, uv1v, uv2u, uv2v, uv3u, uv3v ) {
+	function renderParticle ( v1x, v1y, element, material, scene ) {
+
+		if ( material instanceof THREE.ParticleCircleMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			width = element.scale.x * _widthHalf;
+			height = element.scale.y * _heightHalf;
+
+			_bboxRect.set( v1x - width, v1y - height, v1x + width, v1y + height );
+
+			if ( !_clipRect.instersects( _bboxRect ) ) {
+
+				return;
+
+			}
+
+			_context.save();
+			_context.translate( v1x, v1y );
+			_context.rotate( - element.rotation );
+			_context.scale( width, height );
+
+			_context.beginPath();
+			_context.arc( 0, 0, 1, 0, _pi2, true );
+			_context.closePath();
+
+			_context.fillStyle = _color.__styleString;
+			_context.fill();
+
+			_context.restore();
+
+		} else if ( material instanceof THREE.ParticleBitmapMaterial ) {
+
+			bitmap = material.bitmap;
+			bitmapWidth = bitmap.width / 2;
+			bitmapHeight = bitmap.height / 2;
+
+			scaleX = element.scale.x * _widthHalf;
+			scaleY = element.scale.y * _heightHalf;
+
+			width = scaleX * bitmapWidth;
+			height = scaleY * bitmapHeight;
+
+			offsetX = material.offset.x * scaleX;
+			offsetY = material.offset.y * scaleY;
+
+			// TODO: Rotations break this...
+
+			_bboxRect.set( v1x + offsetX - width, v1y + offsetY - height, v1x + offsetX + width, v1y + offsetY + height );
+
+			if ( !_clipRect.instersects( _bboxRect ) ) {
+
+				return;
+
+			}
+
+			_context.save();
+			_context.translate( v1x, v1y );
+			_context.rotate( - element.rotation );
+			_context.scale( scaleX, - scaleY );
+			_context.translate( - bitmapWidth + material.offset.x, - bitmapHeight - material.offset.y );
+
+			_context.drawImage( bitmap, 0, 0 );
+
+			_context.restore();
+
+			/* DEBUG
+			_context.beginPath();
+			_context.moveTo( v1x - 10, v1y );
+			_context.lineTo( v1x + 10, v1y );
+			_context.moveTo( v1x, v1y - 10 );
+			_context.lineTo( v1x, v1y + 10 );
+			_context.closePath();
+			_context.strokeStyle = 'rgb(255,255,0)';
+			_context.stroke();
+			*/
+
+		}
+
+	}
+
+	function renderLine( v1x, v1y, v2x, v2y, element, material, scene ) {
+
+		if ( material instanceof THREE.LineColorMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			_context.lineWidth = material.lineWidth;
+			_context.lineJoin = "round";
+			_context.lineCap = "round";
+
+			_context.strokeStyle = _color.__styleString;
+			_context.stroke();
+
+			_bboxRect.inflate( _context.lineWidth );
+
+		}
+
+	}
+
+	function renderFace3( v1x, v1y, v2x, v2y, v3x, v3y, element, material, scene ) {
+
+		if ( material instanceof THREE.MeshColorFillMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateFaceLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			_context.beginPath();
+			_context.moveTo( v1x, v1y );
+			_context.lineTo( v2x, v2y );
+			_context.lineTo( v3x, v3y );
+			_context.lineTo( v1x, v1y );
+			_context.closePath();
+
+			_context.fillStyle = _color.__styleString;
+			_context.fill();
+
+		} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateFaceLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			_context.beginPath();
+			_context.moveTo( v1x, v1y );
+			_context.lineTo( v2x, v2y );
+			_context.lineTo( v3x, v3y );
+			_context.lineTo( v1x, v1y );
+			_context.closePath();
+
+			_context.lineWidth = material.lineWidth;
+			_context.lineJoin = "round";
+			_context.lineCap = "round";
+
+			_context.strokeStyle = _color.__styleString;
+			_context.stroke();
+
+			_bboxRect.inflate( _context.lineWidth );
+
+		} else if ( material instanceof THREE.MeshBitmapMaterial ) {
+
+			bitmap = material.bitmap;
+			bitmapWidth = bitmap.width - 1;
+			bitmapHeight = bitmap.height - 1;
+
+			/* DEBUG
+			if ( !element.uvs[ 0 ] || !element.uvs[ 1 ] || !element.uvs[ 2 ]) {
+
+				_context.beginPath();
+				_context.moveTo( v1x, v1y );
+				_context.lineTo( v2x, v2y );
+				_context.lineTo( v3x, v3y );
+				_context.lineTo( v1x, v1y );
+				_context.closePath();
+
+				_context.fillStyle = 'rgb(0, 255, 0)';
+				_context.fill();
+
+				return;
+
+			}
+			*/
+
+			_uv1.copy( element.uvs[ 0 ] );
+			_uv2.copy( element.uvs[ 1 ] );
+			_uv3.copy( element.uvs[ 2 ] );
+
+			_uv1.u *= bitmapWidth; _uv1.v *= bitmapHeight;
+			_uv2.u *= bitmapWidth; _uv2.v *= bitmapHeight;
+			_uv3.u *= bitmapWidth; _uv3.v *= bitmapHeight;
+
+			drawTexturedTriangle( bitmap, v1x, v1y, v2x, v2y, v3x, v3y, _uv1.u, _uv1.v, _uv2.u, _uv2.v, _uv3.u, _uv3.v );
+
+		}
+
+	}
+
+	function renderFace4 ( v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y, v5x, v5y, v6x, v6y, element, material, scene ) {
+
+		if ( material instanceof THREE.MeshColorFillMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateFaceLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			_context.beginPath();
+			_context.moveTo( v1x, v1y );
+			_context.lineTo( v2x, v2y );
+			_context.lineTo( v3x, v3y );
+			_context.lineTo( v4x, v4y );
+			_context.lineTo( v1x, v1y );
+			_context.closePath();
+
+			_context.fillStyle = _color.__styleString;
+			_context.fill();
+
+
+		} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateFaceLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			_context.beginPath();
+			_context.moveTo( v1x, v1y );
+			_context.lineTo( v2x, v2y );
+			_context.lineTo( v3x, v3y );
+			_context.lineTo( v4x, v4y );
+			_context.lineTo( v1x, v1y );
+			_context.closePath();
+
+			_context.lineWidth = material.lineWidth;
+			_context.lineJoin = "round";
+			_context.lineCap = "round";
+
+			_context.strokeStyle = _color.__styleString;
+			_context.stroke();
+
+			_bboxRect.inflate( _context.lineWidth );
+
+		} else if ( material instanceof THREE.MeshBitmapMaterial ) {
+
+			bitmap = material.bitmap;
+			bitmapWidth = bitmap.width - 1;
+			bitmapHeight = bitmap.height - 1;
+
+			/* DEBUG
+			if ( !element.uvs[ 0 ] || !element.uvs[ 1 ] || !element.uvs[ 2 ] || !element.uvs[ 3 ] || !element.uvs[ 4 ] ) {
+
+				_context.beginPath();
+				_context.moveTo( v1x, v1y );
+				_context.lineTo( v2x, v2y );
+				_context.lineTo( v3x, v3y );
+				_context.lineTo( v4x, v4y );
+				_context.lineTo( v1x, v1y );
+				_context.closePath();
+
+				_context.fillStyle = 'rgb(255, 0, 255)';
+				_context.fill();
+
+				return;
+
+			}
+			*/
+
+			_uv1.copy( element.uvs[ 0 ] );
+			_uv2.copy( element.uvs[ 1 ] );
+			_uv3.copy( element.uvs[ 2 ] );
+			_uv4.copy( element.uvs[ 3 ] );
+
+			_uv1.u *= bitmapWidth; _uv1.v *= bitmapHeight;
+			_uv2.u *= bitmapWidth; _uv2.v *= bitmapHeight;
+			_uv3.u *= bitmapWidth; _uv3.v *= bitmapHeight;
+			_uv4.u *= bitmapWidth; _uv4.v *= bitmapHeight;
+
+			drawTexturedTriangle( bitmap, v1x, v1y, v2x, v2y, v4x, v4y, _uv1.u, _uv1.v, _uv2.u, _uv2.v, _uv4.u, _uv4.v );
+			drawTexturedTriangle( bitmap, v5x, v5y, v3x, v3y, v6x, v6y, _uv2.u, _uv2.v, _uv3.u, _uv3.v, _uv4.u, _uv4.v );
+
+		}
+
+	}
+
+	function drawTexturedTriangle( bitmap, v1x, v1y, v2x, v2y, v3x, v3y, _uv1u, _uv1v, _uv2u, _uv2v, _uv3u, _uv3v ) {
 
 		// Textured triangle drawing by Thatcher Ulrich.
 		// http://tulrich.com/geekstuff/canvas/jsgl.js
@@ -808,19 +714,15 @@ THREE.CanvasRenderer = function () {
 
 		_context.save();
 		_context.clip();
-        
-        // debug triangle outline
-        //_context.strokeStyle = "black";
-        //_context.stroke();
-
-		denom = uv1u * ( uv3v - uv2v ) - uv2u * uv3v + uv3u * uv2v + ( uv2u - uv3u ) * uv1v;
-
-		m11 = - ( uv1v * (v3x - v2x ) - uv2v * v3x + uv3v * v2x + ( uv2v - uv3v ) * v1x ) / denom;
-		m12 = ( uv2v * v3y + uv1v * ( v2y - v3y ) - uv3v * v2y + ( uv3v - uv2v) * v1y ) / denom;
-		m21 = ( uv1u * ( v3x - v2x ) - uv2u * v3x + uv3u * v2x + ( uv2u - uv3u ) * v1x ) / denom;
-		m22 = - ( uv2u * v3y + uv1u * ( v2y - v3y ) - uv3u * v2y + ( uv3u - uv2u ) * v1y ) / denom;
-		dx = ( uv1u * ( uv3v * v2x - uv2v * v3x ) + uv1v * ( uv2u * v3x - uv3u * v2x ) + ( uv3u * uv2v - uv2u * uv3v ) * v1x ) / denom;
-		dy = ( uv1u * ( uv3v * v2y - uv2v * v3y ) + uv1v * ( uv2u * v3y - uv3u * v2y ) + ( uv3u * uv2v - uv2u * uv3v ) * v1y ) / denom;
+
+		denom = _uv1u * ( _uv3v - _uv2v ) - _uv2u * _uv3v + _uv3u * _uv2v + ( _uv2u - _uv3u ) * _uv1v;
+
+		m11 = - ( _uv1v * (v3x - v2x ) - _uv2v * v3x + _uv3v * v2x + ( _uv2v - _uv3v ) * v1x ) / denom;
+		m12 = ( _uv2v * v3y + _uv1v * ( v2y - v3y ) - _uv3v * v2y + ( _uv3v - _uv2v) * v1y ) / denom;
+		m21 = ( _uv1u * ( v3x - v2x ) - _uv2u * v3x + _uv3u * v2x + ( _uv2u - _uv3u ) * v1x ) / denom;
+		m22 = - ( _uv2u * v3y + _uv1u * ( v2y - v3y ) - _uv3u * v2y + ( _uv3u - _uv2u ) * v1y ) / denom;
+		dx = ( _uv1u * ( _uv3v * v2x - _uv2v * v3x ) + _uv1v * ( _uv2u * v3x - _uv3u * v2x ) + ( _uv3u * _uv2v - _uv2u * _uv3v ) * v1x ) / denom;
+		dy = ( _uv1u * ( _uv3v * v2y - _uv2v * v3y ) + _uv1v * ( _uv2u * v3y - _uv3u * v2y ) + ( _uv3u * _uv2v - _uv2u * _uv3v ) * v1y ) / denom;
 
 		_context.transform( m11, m12, m21, m22, dx, dy );
 

+ 4 - 6
src/renderers/Projector.js

@@ -96,9 +96,8 @@ THREE.Projector = function() {
 
 								_face3.z = Math.max( v1.positionScreen.z, Math.max( v2.positionScreen.z, v3.positionScreen.z ) );
 
-								//_face3.material = [ object.material[face.material] ];
-                                _face3.material = object.material;
-                                _face3.materialIndex = face.material;
+								_face3.meshMaterial = object.material;
+								_face3.faceMaterial = face.material;
 								_face3.overdraw = object.overdraw;
 								_face3.uvs = object.geometry.uvs[ f ];
 								_face3.color = face.color;
@@ -137,9 +136,8 @@ THREE.Projector = function() {
 
 								_face4.z = Math.max( v1.positionScreen.z, Math.max( v2.positionScreen.z, Math.max( v3.positionScreen.z, v4.positionScreen.z ) ) );
 
-								//_face4.material = [ object.material[face.material] ];
-                                _face4.material = object.material;
-                                _face4.materialIndex = face.material;
+								_face4.meshMaterial = object.material;
+								_face4.faceMaterial = face.material;
 								_face4.overdraw = object.overdraw;
 								_face4.uvs = object.geometry.uvs[ f ];
 								_face4.color = face.color;

+ 222 - 103
src/renderers/SVGRenderer.js

@@ -19,6 +19,7 @@ THREE.SVGRenderer = function () {
 	_vector3 = new THREE.Vector3(), // Needed for PointLight
 
 	_svgPathPool = [], _svgCirclePool = [],
+	_svgNode, _pathCount, _circleCount,
 	_quality = 1;
 
 	this.domElement = _svg;
@@ -60,8 +61,7 @@ THREE.SVGRenderer = function () {
 
 	this.render = function ( scene, camera ) {
 
-		var e, el, m, ml, element, material,
-		pathCount = 0, circleCount = 0, svgNode,
+		var e, el, m, ml, fm, fml, element, material,
 		v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y,
 		size;
 
@@ -73,6 +73,8 @@ THREE.SVGRenderer = function () {
 
 		_renderList = _projector.projectScene( scene, camera );
 
+		_pathCount = 0; _circleCount = 0;
+
 		_enableLighting = scene.lights.length > 0;
 
 		if ( _enableLighting ) {
@@ -85,155 +87,110 @@ THREE.SVGRenderer = function () {
 
 			element = _renderList[ e ];
 
-			for ( m = 0, ml = element.material.length; m < ml; m++ ) {
-
-				material = element.material[ m ];
-
-				_bboxRect.empty();
-
-				if ( element instanceof THREE.RenderableParticle ) {
+			_bboxRect.empty();
 
-					v1x = element.x * _widthHalf; v1y = element.y * -_heightHalf;
-					size = element.size  * _widthHalf;
+			if ( element instanceof THREE.RenderableParticle ) {
 
-					_bboxRect.set( v1x - size, v1y - size, v1x + size, v1y + size );
+				v1x = element.x * _widthHalf; v1y = element.y * -_heightHalf;
 
-					if ( !_clipRect.instersects( _bboxRect ) ) {
-
-						continue;
-
-					}
+				for ( m = 0, ml = element.material.length; m < ml; m++ ) {
 
-					svgNode = getCircleNode( circleCount++ );
-					svgNode.setAttribute( 'cx', v1x );
-					svgNode.setAttribute( 'cy', v1y );
-					svgNode.setAttribute( 'r', size );
+					material = element.material[ m ];
 
-				} else if ( element instanceof THREE.RenderableFace3 ) {
-
-					v1x = element.v1.x * _widthHalf; v1y = element.v1.y * -_heightHalf;
-					v2x = element.v2.x * _widthHalf; v2y = element.v2.y * -_heightHalf;
-					v3x = element.v3.x * _widthHalf; v3y = element.v3.y * -_heightHalf;
-
-					_bboxRect.addPoint( v1x, v1y );
-					_bboxRect.addPoint( v2x, v2y );
-					_bboxRect.addPoint( v3x, v3y );
-
-					if ( !_clipRect.instersects( _bboxRect ) ) {
-
-						continue;
-
-					}
+					renderParticle( v1x, v1y, element, material, scene );
 
-					svgNode = getPathNode( pathCount++ );
-					svgNode.setAttribute( 'd', 'M ' + v1x + ' ' + v1y + ' L ' + v2x + ' ' + v2y + ' L ' + v3x + ',' + v3y + 'z' );
+				}
 
-				} else if ( element instanceof THREE.RenderableFace4 ) {
+			} else if ( element instanceof THREE.RenderableLine ) {
 
-					v1x = element.v1.x * _widthHalf; v1y = element.v1.y * -_heightHalf;
-					v2x = element.v2.x * _widthHalf; v2y = element.v2.y * -_heightHalf;
-					v3x = element.v3.x * _widthHalf; v3y = element.v3.y * -_heightHalf;
-					v4x = element.v4.x * _widthHalf; v4y = element.v4.y * -_heightHalf;
+				
 
-					_bboxRect.addPoint( v1x, v1y );
-					_bboxRect.addPoint( v2x, v2y );
-					_bboxRect.addPoint( v3x, v3y );
-					_bboxRect.addPoint( v4x, v4y );
+			} else if ( element instanceof THREE.RenderableFace3 ) {
 
-					if ( !_clipRect.instersects( _bboxRect) ) {
+				v1x = element.v1.x * _widthHalf; v1y = element.v1.y * -_heightHalf;
+				v2x = element.v2.x * _widthHalf; v2y = element.v2.y * -_heightHalf;
+				v3x = element.v3.x * _widthHalf; v3y = element.v3.y * -_heightHalf;
 
-						continue;
+				_bboxRect.addPoint( v1x, v1y );
+				_bboxRect.addPoint( v2x, v2y );
+				_bboxRect.addPoint( v3x, v3y );
 
-					}
+				if ( !_clipRect.instersects( _bboxRect ) ) {
 
-					svgNode = getPathNode( pathCount++ );
-					svgNode.setAttribute( 'd', 'M ' + v1x + ' ' + v1y + ' L ' + v2x + ' ' + v2y + ' L ' + v3x + ',' + v3y + ' L ' + v4x + ',' + v4y + 'z' );
+					continue;
 
 				}
 
+				m = 0; ml = element.meshMaterial.length;
 
-				// TODO: Move out of materials loop
-
-				if ( material instanceof THREE.MeshColorFillMaterial ) {
+				while ( m < ml ) {
 
-					if ( _enableLighting ) {
+					material = element.meshMaterial[ m ++ ];
 
-						_light.copyRGB( _ambientLight );
-						calculateFaceLight( scene, element, _light );
+					if ( material instanceof THREE.MeshFaceMaterial ) {
 
-						_color.copyRGBA( material.color );
-						_color.multiplySelfRGB( _light );
-						_color.updateStyleString();
+						fm = 0; fml = element.faceMaterial.length;
 
-					} else {
-
-							_color = material.color;
-
-					}
+						while ( fm < fml ) {
 
-					svgNode.setAttribute( 'style', 'fill: ' + _color.__styleString );
+							material = element.faceMaterial[ fm ++ ];
 
-				} else if ( material instanceof THREE.MeshFaceColorFillMaterial ) {
+							renderFace3( v1x, v1y, v2x, v2y, v3x, v3y, element, material, scene );
 
-					if ( _enableLighting ) {
+						}
 
-						_light.copyRGB( _ambientLight );
-						calculateFaceLight( scene, element, _light );
+						continue;
 
-						_color.copyRGBA( element.color );
-						_color.multiplySelfRGB( _light );
-						_color.updateStyleString();
+					}
 
-					} else {
+					renderFace3( v1x, v1y, v2x, v2y, v3x, v3y, element, material, scene );
 
-							_color = element.color;
+				}
 
-					}
+			} else if ( element instanceof THREE.RenderableFace4 ) {
 
-					svgNode.setAttribute( 'style', 'fill: ' + _color.__styleString );
+				v1x = element.v1.x * _widthHalf; v1y = element.v1.y * -_heightHalf;
+				v2x = element.v2.x * _widthHalf; v2y = element.v2.y * -_heightHalf;
+				v3x = element.v3.x * _widthHalf; v3y = element.v3.y * -_heightHalf;
+				v4x = element.v4.x * _widthHalf; v4y = element.v4.y * -_heightHalf;
 
-				} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
+				_bboxRect.addPoint( v1x, v1y );
+				_bboxRect.addPoint( v2x, v2y );
+				_bboxRect.addPoint( v3x, v3y );
+				_bboxRect.addPoint( v4x, v4y );
 
-					if ( _enableLighting ) {
+				if ( !_clipRect.instersects( _bboxRect) ) {
 
-						_light.copyRGB( _ambientLight );
-						calculateFaceLight( scene, element, _light );
+					continue;
 
-						_color.copyRGBA( material.color );
-						_color.multiplySelfRGB( _light );
-						_color.updateStyleString();
+				}
 
-					} else {
+				m = 0; ml = element.meshMaterial.length;
 
-							_color = material.color;
+				while ( m < ml ) {
 
-					}
+					material = element.meshMaterial[ m ++ ];
 
-					svgNode.setAttribute( 'style', 'fill: none; stroke: ' + _color.__styleString + '; stroke-width: ' + material.lineWidth + '; stroke-linecap: round; stroke-linejoin: round' );
+					if ( material instanceof THREE.MeshFaceMaterial ) {
 
-				} else if ( material instanceof THREE.MeshFaceColorStrokeMaterial ) {
+						fm = 0; fml = element.faceMaterial.length;
 
-					if ( _enableLighting ) {
+						while ( fm < fml ) {
 
-						_light.copyRGB( _ambientLight );
-						calculateFaceLight( scene, element, _light );
+							material = element.faceMaterial[ fm ++ ];
 
-						_color.copyRGBA( element.color );
-						_color.multiplySelfRGB( _light );
-						_color.updateStyleString();
+							renderFace4( v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y, element, material, scene );
 
-					} else {
+						}
 
-						_color = element.color;
+						continue;
 
 					}
 
-					svgNode.setAttribute( 'style', 'fill: none; stroke: ' + _color.__styleString + '; stroke-width: ' + material.lineWidth + '; stroke-linecap: round; stroke-linejoin: round' );
+					renderFace4( v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y, element, material, scene );
 
 				}
 
-				_svg.appendChild( svgNode );
-
 			}
 
 		}
@@ -262,6 +219,32 @@ THREE.SVGRenderer = function () {
 
 	}
 
+	function calculateLight( scene, element, color ) {
+
+		var l, ll, light;
+
+		for ( l = 0, ll = scene.lights.length; l < ll; l++ ) {
+
+			light = scene.lights[ l ];
+
+			if ( light instanceof THREE.DirectionalLight ) {
+
+				color.r += light.color.r;
+				color.g += light.color.g;
+				color.b += light.color.b;
+
+			} else if ( light instanceof THREE.PointLight ) {
+
+				color.r += light.color.r;
+				color.g += light.color.g;
+				color.b += light.color.b;
+
+			}
+
+		}
+
+	}
+
 	function calculateFaceLight( scene, element, color ) {
 
 		var l, ll, light, amount;
@@ -303,7 +286,143 @@ THREE.SVGRenderer = function () {
 
 	}
 
-	function getPathNode( id ) {
+	function renderParticle ( v1x, v1y, element, material, scene ) {
+
+		_svgNode = getCircleNode( _circleCount++ );
+		_svgNode.setAttribute( 'cx', v1x );
+		_svgNode.setAttribute( 'cy', v1y );
+		_svgNode.setAttribute( 'r', element.scale.x * _widthHalf );
+
+		if ( material instanceof THREE.ParticleCircleMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			_svgNode.setAttribute( 'style', 'fill: ' + _color.__styleString );
+
+		}
+
+		_svg.appendChild( _svgNode );
+
+	}
+	
+	function renderLine ( ) {
+	
+		
+	
+	}
+	
+	function renderFace3 ( v1x, v1y, v2x, v2y, v3x, v3y, element, material, scene ) {
+
+		_svgNode = getPathNode( _pathCount ++ );
+		_svgNode.setAttribute( 'd', 'M ' + v1x + ' ' + v1y + ' L ' + v2x + ' ' + v2y + ' L ' + v3x + ',' + v3y + 'z' );
+
+		if ( material instanceof THREE.MeshColorFillMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateFaceLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			_svgNode.setAttribute( 'style', 'fill: ' + _color.__styleString );
+
+		} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateFaceLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			_svgNode.setAttribute( 'style', 'fill: none; stroke: ' + _color.__styleString + '; stroke-width: ' + material.lineWidth + '; stroke-linecap: round; stroke-linejoin: round' );
+
+		}
+
+		_svg.appendChild( _svgNode );
+
+	}
+
+	function renderFace4 ( v1x, v1y, v2x, v2y, v3x, v3y, v4x, v4y, element, material, scene ) {
+
+		_svgNode = getPathNode( _pathCount ++ );
+		_svgNode.setAttribute( 'd', 'M ' + v1x + ' ' + v1y + ' L ' + v2x + ' ' + v2y + ' L ' + v3x + ',' + v3y + ' L ' + v4x + ',' + v4y + 'z' );
+
+		if ( material instanceof THREE.MeshColorFillMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateFaceLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			_svgNode.setAttribute( 'style', 'fill: ' + _color.__styleString );
+
+		} else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
+
+			if ( _enableLighting ) {
+
+				_light.copyRGB( _ambientLight );
+				calculateFaceLight( scene, element, _light );
+
+				_color.copyRGBA( material.color );
+				_color.multiplySelfRGB( _light );
+				_color.updateStyleString();
+
+			} else {
+
+				_color = material.color;
+
+			}
+
+			_svgNode.setAttribute( 'style', 'fill: none; stroke: ' + _color.__styleString + '; stroke-width: ' + material.lineWidth + '; stroke-linecap: round; stroke-linejoin: round' );
+
+		}
+
+		_svg.appendChild( _svgNode );
+
+	}
+
+	function getPathNode ( id ) {
 
 		if ( _svgPathPool[ id ] == null ) {
 
@@ -323,7 +442,7 @@ THREE.SVGRenderer = function () {
 
 	}
 
-	function getCircleNode( id ) {
+	function getCircleNode ( id ) {
 
 		if ( _svgCirclePool[id] == null ) {
 

+ 136 - 179
src/renderers/WebGLRenderer.js

@@ -16,7 +16,7 @@ THREE.WebGLRenderer = function () {
 	initProgram();
 
     // material constants used in shader
-    var COLORFILL = 0, COLORSTROKE = 1, FACECOLORFILL = 2, FACECOLORSTROKE = 3, BITMAP = 4, PHONG = 5;
+    var COLORFILL = 0, COLORSTROKE = 1, BITMAP = 2, PHONG = 3;
     
 	this.setSize = function ( width, height ) {
 
@@ -68,29 +68,26 @@ THREE.WebGLRenderer = function () {
 		}
     };
     
-    this.createBuffers = function ( object, materialIndex ) {
+    this.createBuffers = function ( object, mf ) {
         
-        var materialFace = object.materialFaces[ materialIndex ];
-        var material = object.material[ materialIndex ];
+        var materialFaceGroup = object.materialFaceGroup[ mf ];
         
         var faceArray = [];
         var lineArray = [];
         
         var vertexArray = [];
-        var colorArray = [];
         var normalArray = [];
         var uvArray = [];
         
         var vertexIndex = 0;
 
-        var f, fl, fi, face, faceColor, vertexNormals, normal, uv, v1, v2, v3, v4;
+        var f, fl, fi, face, vertexNormals, normal, uv, v1, v2, v3, v4;
         
-        for ( f = 0, fl = materialFace.faces.length; f < fl; f++ ) {
+        for ( f = 0, fl = materialFaceGroup.faces.length; f < fl; f++ ) {
 
-            fi = materialFace.faces[f];
+            fi = materialFaceGroup.faces[f];
 
             face = object.geometry.faces[ fi ];
-            faceColor = face.color;
             vertexNormals = face.vertexNormals;
             normal = face.normal;
             uv = object.geometry.uvs[ fi ];
@@ -120,10 +117,6 @@ THREE.WebGLRenderer = function () {
                     
                 }
 
-                colorArray.push( faceColor.r, faceColor.g, faceColor.b, faceColor.a );
-                colorArray.push( faceColor.r, faceColor.g, faceColor.b, faceColor.a );
-                colorArray.push( faceColor.r, faceColor.g, faceColor.b, faceColor.a );
-
                 if ( uv ) {
                     
                     uvArray.push( uv[0].u, uv[0].v );
@@ -171,11 +164,6 @@ THREE.WebGLRenderer = function () {
                     
                 }
 
-                colorArray.push( faceColor.r, faceColor.g, faceColor.b, faceColor.a );
-                colorArray.push( faceColor.r, faceColor.g, faceColor.b, faceColor.a );
-                colorArray.push( faceColor.r, faceColor.g, faceColor.b, faceColor.a );
-                colorArray.push( faceColor.r, faceColor.g, faceColor.b, faceColor.a );
-
                 if ( uv ) {
                     
                     uvArray.push( uv[0].u, uv[0].v );
@@ -206,184 +194,167 @@ THREE.WebGLRenderer = function () {
 
         }
         
-        materialFace.__webGLVertexBuffer = _gl.createBuffer();
-        _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFace.__webGLVertexBuffer );
+        materialFaceGroup.__webGLVertexBuffer = _gl.createBuffer();
+        _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLVertexBuffer );
         _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( vertexArray ), _gl.STATIC_DRAW );
 
-        materialFace.__webGLNormalBuffer = _gl.createBuffer();
-        _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFace.__webGLNormalBuffer );
+        materialFaceGroup.__webGLNormalBuffer = _gl.createBuffer();
+        _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLNormalBuffer );
         _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( normalArray ), _gl.STATIC_DRAW );
 
-        materialFace.__webGLColorBuffer = _gl.createBuffer();
-        _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFace.__webGLColorBuffer );
-        _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( colorArray ), _gl.STATIC_DRAW );
-
-        materialFace.__webGLUVBuffer = _gl.createBuffer();
-        _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFace.__webGLUVBuffer );
+        materialFaceGroup.__webGLUVBuffer = _gl.createBuffer();
+        _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLUVBuffer );
         _gl.bufferData( _gl.ARRAY_BUFFER, new Float32Array( uvArray ), _gl.STATIC_DRAW );
 
-        materialFace.__webGLFaceBuffer = _gl.createBuffer();
-        _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFace.__webGLFaceBuffer );
+        materialFaceGroup.__webGLFaceBuffer = _gl.createBuffer();
+        _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLFaceBuffer );
         _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( faceArray ), _gl.STATIC_DRAW );
 
-        materialFace.__webGLLineBuffer = _gl.createBuffer();
-        _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFace.__webGLLineBuffer );
+        materialFaceGroup.__webGLLineBuffer = _gl.createBuffer();
+        _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLLineBuffer );
         _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, new Uint16Array( lineArray ), _gl.STATIC_DRAW );
 
-        materialFace.__webGLFaceCount = faceArray.length;
-        materialFace.__webGLLineCount = lineArray.length;
+        materialFaceGroup.__webGLFaceCount = faceArray.length;
+        materialFaceGroup.__webGLLineCount = lineArray.length;
 
-    }
+    };
     
-    this.renderMesh = function ( object, camera ) {
+    this.renderBuffer = function ( material, materialFaceGroup ) {
         
-        var m, ml, mf, material, materialFace, fi, lineWidth, mAmbient, mDiffuse, mSpecular;
-
-        // create separate VBOs per material
-        for (var mf in object.materialFaces ) {
+        if ( material instanceof THREE.MeshPhongMaterial ) {
 
-            materialFace = object.materialFaces[ mf ];
-            material = object.material[ mf ];
-            if( !material ) continue;
+            mAmbient  = material.ambient;
+            mDiffuse  = material.diffuse;
+            mSpecular = material.specular;
+            
+            _gl.uniform4f( _program.mAmbient,  mAmbient.r,  mAmbient.g,  mAmbient.b,  material.opacity );
+            _gl.uniform4f( _program.mDiffuse,  mDiffuse.r,  mDiffuse.g,  mDiffuse.b,  material.opacity );
+            _gl.uniform4f( _program.mSpecular, mSpecular.r, mSpecular.g, mSpecular.b, material.opacity );
+            
+            _gl.uniform1f( _program.mShininess, material.shininess );
+            
+            _gl.uniform1i( _program.material, PHONG );
+            
+        } else if ( material instanceof THREE.MeshColorFillMaterial ) {
 
-            // initialise on the first access
-            if( !materialFace.__webGLVertexBuffer ) {
+            color = material.color;
+            _gl.uniform4f( _program.uniformColor,  color.r * color.a, color.g * color.a, color.b * color.a, color.a );
+            
+            _gl.uniform1i( _program.material, COLORFILL );
+            
+        } else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
+            
+            lineWidth = material.lineWidth;
+            
+            color = material.color;
+            _gl.uniform4f( _program.uniformColor,  color.r * color.a, color.g * color.a, color.b * color.a, color.a );
+            
+            _gl.uniform1i( _program.material, COLORSTROKE );
+        
+        } else if ( material instanceof THREE.MeshBitmapMaterial ) {
+            
+            if ( !material.__webGLTexture && material.loaded ) {
                 
-                this.createBuffers( object, mf );
+                material.__webGLTexture = _gl.createTexture();
+                _gl.bindTexture( _gl.TEXTURE_2D, material.__webGLTexture );
+                _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, material.bitmap ) ;
+                _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.LINEAR );
+                //_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR_MIPMAP_NEAREST );
+                _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR_MIPMAP_LINEAR );
+                _gl.generateMipmap( _gl.TEXTURE_2D );
+                _gl.bindTexture( _gl.TEXTURE_2D, null );
                 
             }
             
-            for ( m = 0, ml = object.material.length; m < ml; m++ ) {
+            _gl.activeTexture( _gl.TEXTURE0 );
+            _gl.bindTexture( _gl.TEXTURE_2D, material.__webGLTexture );
+            _gl.uniform1i( _program.diffuse,  0 );
+            
+            _gl.uniform1i( _program.material, BITMAP );
+            
+        }
+        
+
+        // vertices
+        _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLVertexBuffer );
+        _gl.vertexAttribPointer( _program.position, 3, _gl.FLOAT, false, 0, 0 );
+
+        // normals
+        _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLNormalBuffer );
+        _gl.vertexAttribPointer( _program.normal, 3, _gl.FLOAT, false, 0, 0 );
+        
+        // uvs
+        
+        if ( material instanceof THREE.MeshBitmapMaterial ) {
+            
+            _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFaceGroup.__webGLUVBuffer );
                 
-                material = object.material[ m ];
+            _gl.enableVertexAttribArray( _program.uv );
+            _gl.vertexAttribPointer( _program.uv, 2, _gl.FLOAT, false, 0, 0 );
                 
-                // these materials can be either the only material for whole mesh
-                // or if they are overlays in multimaterials, they apply only to
-                // group of faces with single material (specified by decalIndex)
+        }
+        else {
                 
-                if ( ( material instanceof THREE.MeshBitmapUVMappingMaterial || 
-                       material instanceof THREE.MeshFaceColorFillMaterial ||
-                       material instanceof THREE.MeshColorFillMaterial
-                     ) 
-                    &&
-                     ! ( m == mf || mf == material.decalIndex ) ) {
-                    
-                    continue;
-                    
-                }
+            _gl.disableVertexAttribArray( _program.uv );
                 
-                if ( material instanceof THREE.MeshPhongMaterial ) {
+        }
 
-                    mAmbient  = material.ambient;
-                    mDiffuse  = material.diffuse;
-                    mSpecular = material.specular;
-                    
-                    _gl.uniform4f( _program.mAmbient,  mAmbient.r,  mAmbient.g,  mAmbient.b,  material.opacity );
-                    _gl.uniform4f( _program.mDiffuse,  mDiffuse.r,  mDiffuse.g,  mDiffuse.b,  material.opacity );
-                    _gl.uniform4f( _program.mSpecular, mSpecular.r, mSpecular.g, mSpecular.b, material.opacity );
-                    
-                    _gl.uniform1f( _program.mShininess, material.shininess );
-                    
-                    _gl.uniform1i( _program.material, PHONG );
-                    
-                } else if ( material instanceof THREE.MeshColorFillMaterial ) {
+        // render triangles
 
-                    color = material.color;
-                    _gl.uniform4f( _program.uniformColor,  color.r * color.a, color.g * color.a, color.b * color.a, color.a );
-                    
-                    _gl.uniform1i( _program.material, COLORFILL );
-                    
-                } else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
-                    
-                    lineWidth = material.lineWidth;
-                    
-                    color = material.color;
-                    _gl.uniform4f( _program.uniformColor,  color.r * color.a, color.g * color.a, color.b * color.a, color.a );
-                    
-                    _gl.uniform1i( _program.material, COLORSTROKE );
-                    
-                } else if ( material instanceof THREE.MeshFaceColorFillMaterial ) {
-                    
-                    _gl.uniform1i( _program.material, FACECOLORFILL );
-                
-                } else if ( material instanceof THREE.MeshFaceColorStrokeMaterial ) {
+        if ( material instanceof THREE.MeshBitmapMaterial || 
+             material instanceof THREE.MeshColorFillMaterial ||
+             material instanceof THREE.MeshPhongMaterial ) {
+            
+            _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLFaceBuffer );
+            _gl.drawElements( _gl.TRIANGLES, materialFaceGroup.__webGLFaceCount, _gl.UNSIGNED_SHORT, 0 );
+            
+        } 
+        
+        // render lines
+        
+        else if ( material instanceof THREE.MeshColorStrokeMaterial ) {
+            
+            _gl.lineWidth( lineWidth );
+            _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFaceGroup.__webGLLineBuffer );
+            _gl.drawElements( _gl.LINES, materialFaceGroup.__webGLLineCount, _gl.UNSIGNED_SHORT, 0 );
+            
+        }
+    };
+    
+    this.renderMesh = function ( object, camera ) {
+        
+        var i, l, m, ml, mf, material, meshMaterial, materialFaceGroup, fi, lineWidth, mAmbient, mDiffuse, mSpecular;
 
-                    lineWidth = material.lineWidth;
-                    
-                    _gl.uniform1i( _program.material, FACECOLORSTROKE );
+        // create separate VBOs per material
+        
+        for ( var mf in object.materialFaceGroup ) {
 
-                } else if ( material instanceof THREE.MeshBitmapUVMappingMaterial ) {
-                    
-                    if ( !material.__webGLTexture && material.loaded ) {
-                        
-                        material.__webGLTexture = _gl.createTexture();
-                        _gl.bindTexture( _gl.TEXTURE_2D, material.__webGLTexture );
-                        _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, _gl.RGBA, _gl.UNSIGNED_BYTE, material.bitmap ) ;
-                        _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.LINEAR );
-                        //_gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR_MIPMAP_NEAREST );
-                        _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.LINEAR_MIPMAP_LINEAR );
-                        _gl.generateMipmap( _gl.TEXTURE_2D );
-                        _gl.bindTexture( _gl.TEXTURE_2D, null );
-                        
-                    }
-                    
-                    _gl.activeTexture( _gl.TEXTURE0 );
-                    _gl.bindTexture( _gl.TEXTURE_2D, material.__webGLTexture );
-                    _gl.uniform1i( _program.diffuse,  0 );
-                    
-                    _gl.uniform1i( _program.material, BITMAP );
-                    
-                }
+            materialFaceGroup = object.materialFaceGroup[ mf ];
+            
+            // initialise on the first access
+            
+            if( ! materialFaceGroup.__webGLVertexBuffer ) {
                 
-
-                // vertices
-                _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFace.__webGLVertexBuffer );
-                _gl.vertexAttribPointer( _program.position, 3, _gl.FLOAT, false, 0, 0 );
-
-                // normals
-                _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFace.__webGLNormalBuffer );
-                _gl.vertexAttribPointer( _program.normal, 3, _gl.FLOAT, false, 0, 0 );
-
-                // colors
-                _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFace.__webGLColorBuffer );
-                _gl.vertexAttribPointer( _program.color, 4, _gl.FLOAT, false, 0, 0 );
+                this.createBuffers( object, mf );
+                
+            }
+            
+            for ( m = 0, ml = object.material.length; m < ml; m++ ) {
                 
-                // uvs
+                meshMaterial = object.material[ m ];
                 
-                if ( material instanceof THREE.MeshBitmapUVMappingMaterial ) {
+                if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
                     
-                    _gl.bindBuffer( _gl.ARRAY_BUFFER, materialFace.__webGLUVBuffer );
-                        
-                    _gl.enableVertexAttribArray( _program.uv );
-                    _gl.vertexAttribPointer( _program.uv, 2, _gl.FLOAT, false, 0, 0 );
-                        
-                }
-                else {
-                        
-                    _gl.disableVertexAttribArray( _program.uv );
+                    for ( i = 0, l = materialFaceGroup.material.length; i < l; i++ ) {
                         
-                }
-
-                // render triangles
-
-                if ( material instanceof THREE.MeshBitmapUVMappingMaterial || 
-                     material instanceof THREE.MeshFaceColorFillMaterial ||
-                     material instanceof THREE.MeshColorFillMaterial ||
-                     material instanceof THREE.MeshPhongMaterial ) {
-                    
-                    _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFace.__webGLFaceBuffer );
-                    _gl.drawElements( _gl.TRIANGLES, materialFace.__webGLFaceCount, _gl.UNSIGNED_SHORT, 0 );
+                        material = materialFaceGroup.material[ i ];
+                        this.renderBuffer( material, materialFaceGroup );
+                    }
                     
-                } 
-                
-                // render lines
-                
-                else if ( material instanceof THREE.MeshColorStrokeMaterial ||
-                          material instanceof THREE.MeshFaceColorStrokeMaterial ) {
+                } else {
                     
-                    _gl.lineWidth( lineWidth );
-                    _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, materialFace.__webGLLineBuffer );
-                    _gl.drawElements( _gl.LINES, materialFace.__webGLLineCount, _gl.UNSIGNED_SHORT, 0 );
+                    material = meshMaterial;
+                    this.renderBuffer( material, materialFaceGroup );
                     
                 }
                 
@@ -513,12 +484,11 @@ THREE.WebGLRenderer = function () {
 			"uniform vec4 uniformColor;",
         
             "varying vec2 vertexUv;",
-			"varying vec4 vertexColor;",
 			"varying vec3 lightWeighting;",
 
             "varying vec3 vNormal;",
         
-            "uniform int material;", // 0 - ColorFill, 1 - ColorStroke, 2 - FaceColorFill, 3 - FaceColorStroke, 4 - Bitmap, 5 - Phong
+            "uniform int material;", // 0 - ColorFill, 1 - ColorStroke, 2 - Bitmap, 3 - Phong
 
             "uniform vec4 mAmbient;",
 			"uniform vec4 mDiffuse;",
@@ -533,7 +503,7 @@ THREE.WebGLRenderer = function () {
                 
                 // Blinn-Phong
                 // based on o3d example
-                "if(material==5) { ", 
+                "if(material==3) { ", 
                     "vec3 lightVectorPoint = normalize(pLightVectorPoint);",
                     "vec3 lightVectorDir = normalize(pLightVectorDirection);",
                     
@@ -571,18 +541,10 @@ THREE.WebGLRenderer = function () {
                     "gl_FragColor = vec4((pointLight.xyz + dirLight.xyz) * lightWeighting, 1.0);",                    
                     
                 // Bitmap: texture
-                "} else if(material==4) {", 
+                "} else if(material==2) {", 
                     "vec4 texelColor = texture2D(diffuse, vertexUv);",
                     "gl_FragColor = vec4(texelColor.rgb * lightWeighting, texelColor.a);",
                 
-                // FaceColorStroke: wireframe using vertex color 
-                "} else if(material==3) {", 
-                    "gl_FragColor = vec4(vertexColor.rgb * lightWeighting, vertexColor.a);",
-                
-                // FaceColorFill: triangle using vertex color
-                "} else if(material==2) {", 
-                    "gl_FragColor = vec4(vertexColor.rgb * lightWeighting, vertexColor.a);",
-                
                 // ColorStroke: wireframe using uniform color
                 "} else if(material==1) {", 
                     "gl_FragColor = vec4(uniformColor.rgb * lightWeighting, uniformColor.a);",
@@ -598,7 +560,6 @@ THREE.WebGLRenderer = function () {
 		_gl.attachShader( _program, getShader( "vertex", [
 			"attribute vec3 position;",
 			"attribute vec3 normal;",
-			"attribute vec4 color;",
             "attribute vec2 uv;",
 
 			"uniform bool enableLighting;",
@@ -653,7 +614,6 @@ THREE.WebGLRenderer = function () {
                 "}",
 
 				"vNormal = transformedNormal;",
-                "vertexColor = color;",
 				"vertexUv = uv;",
                 
 				"gl_Position = projectionMatrix * mvPosition;",
@@ -694,9 +654,6 @@ THREE.WebGLRenderer = function () {
         
         _program.cameraPosition = _gl.getUniformLocation(_program, 'cameraPosition');
 
-		_program.color = _gl.getAttribLocation( _program, "color" );
-		_gl.enableVertexAttribArray( _program.color );
-
 		_program.position = _gl.getAttribLocation( _program, "position" );
 		_gl.enableVertexAttribArray( _program.position );
 

+ 2 - 3
utils/Builder.py

@@ -29,11 +29,10 @@ files.append('objects/Line.js')
 files.append('objects/Mesh.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/MeshPhongMaterial.js')
-files.append('materials/MeshBitmapUVMappingMaterial.js')
+files.append('materials/MeshBitmapMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorStrokeMaterial.js')
-files.append('materials/MeshFaceColorFillMaterial.js')
-files.append('materials/MeshFaceColorStrokeMaterial.js')
+files.append('materials/MeshFaceMaterial.js')
 files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('materials/ParticleDOMMaterial.js')

+ 2 - 3
utils/BuilderCanvas.py

@@ -29,11 +29,10 @@ files.append('objects/Line.js')
 files.append('objects/Mesh.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/MeshPhongMaterial.js')
-files.append('materials/MeshBitmapUVMappingMaterial.js')
+files.append('materials/MeshBitmapMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorStrokeMaterial.js')
-files.append('materials/MeshFaceColorFillMaterial.js')
-files.append('materials/MeshFaceColorStrokeMaterial.js')
+files.append('materials/MeshFaceMaterial.js')
 files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('scenes/Scene.js')

+ 2 - 3
utils/BuilderDebug.py

@@ -29,11 +29,10 @@ files.append('objects/Line.js')
 files.append('objects/Mesh.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/MeshPhongMaterial.js')
-files.append('materials/MeshBitmapUVMappingMaterial.js')
+files.append('materials/MeshBitmapMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorStrokeMaterial.js')
-files.append('materials/MeshFaceColorFillMaterial.js')
-files.append('materials/MeshFaceColorStrokeMaterial.js')
+files.append('materials/MeshFaceMaterial.js')
 files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('materials/ParticleDOMMaterial.js')

+ 3 - 3
utils/BuilderSVG.py

@@ -27,11 +27,11 @@ files.append('objects/Object3D.js')
 files.append('objects/Particle.js')
 files.append('objects/Line.js')
 files.append('objects/Mesh.js')
-files.append('materials/MeshBitmapUVMappingMaterial.js')
+files.append('materials/LineColorMaterial.js')
+files.append('materials/MeshBitmapMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorStrokeMaterial.js')
-files.append('materials/MeshFaceColorFillMaterial.js')
-files.append('materials/MeshFaceColorStrokeMaterial.js')
+files.append('materials/MeshFaceMaterial.js')
 files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('scenes/Scene.js')

+ 2 - 3
utils/BuilderWebGL.py

@@ -29,11 +29,10 @@ files.append('objects/Line.js')
 files.append('objects/Mesh.js')
 files.append('materials/LineColorMaterial.js')
 files.append('materials/MeshPhongMaterial.js')
-files.append('materials/MeshBitmapUVMappingMaterial.js')
+files.append('materials/MeshBitmapMaterial.js')
 files.append('materials/MeshColorFillMaterial.js')
 files.append('materials/MeshColorStrokeMaterial.js')
-files.append('materials/MeshFaceColorFillMaterial.js')
-files.append('materials/MeshFaceColorStrokeMaterial.js')
+files.append('materials/MeshFaceMaterial.js')
 files.append('materials/ParticleBitmapMaterial.js')
 files.append('materials/ParticleCircleMaterial.js')
 files.append('scenes/Scene.js')

+ 1 - 1
utils/REVISION

@@ -1 +1 @@
-24
+25

+ 15 - 15
utils/exporters/convert_obj_threejs.py

@@ -163,18 +163,18 @@ var %(name)s = function ( urlbase ) {
         scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) );
     }
 
-    function f3( a, b, c, material ) {
-        var color = material_color(material);
-        scope.faces.push( new THREE.Face3( a, b, c, null, new THREE.Color(color), material ) );
+    function f3( a, b, c, mi ) {
+        var material = scope.materials[ mi ];
+        scope.faces.push( new THREE.Face3( a, b, c, null, material ) );
     }
 
-    function f4( a, b, c, d, material ) {
-        var color = material_color(material);
-        scope.faces.push( new THREE.Face4( a, b, c, d, null, new THREE.Color(color), material ) );
+    function f4( a, b, c, d, mi ) {
+        var material = scope.materials[ mi ];
+        scope.faces.push( new THREE.Face4( a, b, c, d, null, material ) );
     }
 
-    function f3n( a, b, c, material, n1, n2, n3 ) {
-        var color = material_color(material);
+    function f3n( a, b, c, mi, n1, n2, n3 ) {
+        var material = scope.materials[ mi ];
         var n1x = normals[n1][0];
         var n1y = normals[n1][1];
         var n1z = normals[n1][2];
@@ -186,11 +186,11 @@ var %(name)s = function ( urlbase ) {
         var n3z = normals[n3][2];
         scope.faces.push( new THREE.Face3( a, b, c, 
                           [new THREE.Vector3( n1x, n1y, n1z ), new THREE.Vector3( n2x, n2y, n2z ), new THREE.Vector3( n3x, n3y, n3z )], 
-                          new THREE.Color(color), material ) );
+                          material ) );
     }
 
-    function f4n( a, b, c, d, material, n1, n2, n3, n4 ) {
-        var color = material_color(material);
+    function f4n( a, b, c, d, mi, n1, n2, n3, n4 ) {
+        var material = scope.materials[ mi ];
         var n1x = normals[n1][0];
         var n1y = normals[n1][1];
         var n1z = normals[n1][2];
@@ -205,7 +205,7 @@ var %(name)s = function ( urlbase ) {
         var n4z = normals[n4][2];
         scope.faces.push( new THREE.Face4( a, b, c, d,
                           [new THREE.Vector3( n1x, n1y, n1z ), new THREE.Vector3( n2x, n2y, n2z ), new THREE.Vector3( n3x, n3y, n3z ), new THREE.Vector3( n4x, n4y, n4z )], 
-                          new THREE.Color(color), material ) );
+                          material ) );
     }
 
     function uv( u1, v1, u2, v2, u3, v3, u4, v4 ) {
@@ -220,7 +220,7 @@ var %(name)s = function ( urlbase ) {
     function init_materials() {
         scope.materials = [];
         for(var i=0; i<materials.length; ++i) {
-            scope.materials[i] = create_material( materials[i], urlbase );
+            scope.materials[i] = [ create_material( materials[i], urlbase ) ];
         }
     }
     
@@ -240,7 +240,7 @@ var %(name)s = function ( urlbase ) {
         if( m.map_diffuse && urlbase ) {
             var texture = document.createElement( 'canvas' );
             
-            material = new THREE.MeshBitmapUVMappingMaterial( texture );
+            material = new THREE.MeshBitmapMaterial( texture );
             var image = new Image();
             
             image.onload = function () {
@@ -269,7 +269,7 @@ var %(name)s = function ( urlbase ) {
             material = new THREE.MeshColorFillMaterial( m.a_dbg_color );
         }
         else {
-            material = new THREE.MeshFaceColorFillMaterial( );
+            material = new THREE.MeshColorFillMaterial( 0xffeeeeee );
         }
 
         return material;

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