Преглед изворни кода

Merge branch 'dev-geometry-experiment' of https://github.com/jbaicoianu/three.js into dev

Conflicts:
	src/core/Geometry99.js
	utils/build/includes/common.json
Mr.doob пре 11 година
родитељ
комит
db1947639b

+ 1 - 1
src/core/BufferGeometry.js

@@ -255,7 +255,7 @@ THREE.BufferGeometry.prototype = {
 
 
 				var indices = this.attributes[ "index" ].array;
 				var indices = this.attributes[ "index" ].array;
 
 
-				var offsets = this.offsets;
+				var offsets = (this.offsets.length > 0 ? this.offsets : [ { start: 0, count: indices.length, index: 0 } ]);
 
 
 				for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
 				for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
 
 

+ 465 - 376
src/core/Geometry.js

@@ -5,659 +5,748 @@
  * @author mikael emtinger / http://gomo.se/
  * @author mikael emtinger / http://gomo.se/
  * @author zz85 / http://www.lab4games.net/zz85/blog
  * @author zz85 / http://www.lab4games.net/zz85/blog
  * @author bhouston / http://exocortex.com
  * @author bhouston / http://exocortex.com
+ * @author jbaicoianu / http://baicoianu.com
  */
  */
 
 
-THREE.Geometry = function () {
+THREE.Geometry = function ( ) {
 
 
-	this.id = THREE.GeometryIdCount ++;
-	this.uuid = THREE.Math.generateUUID();
+	THREE.BufferGeometry.call( this );
 
 
-	this.name = '';
-
-	this.vertices = [];
-	this.colors = [];  // one-to-one vertex colors, used in ParticleSystem and Line
-
-	this.faces = [];
-
-	this.faceVertexUvs = [[]];
+	this.addEventListener( 'allocate', this.onGeometryAllocate);
 
 
+	// TODO - implement as BufferGeometry attributes
 	this.morphTargets = [];
 	this.morphTargets = [];
 	this.morphColors = [];
 	this.morphColors = [];
-	this.morphNormals = [];
 
 
-	this.skinWeights = [];
-	this.skinIndices = [];
+};
+
+THREE.Geometry.prototype = Object.create( THREE.IndexedGeometry2.prototype );
+
+Object.defineProperties(THREE.Geometry.prototype, {
+	vertices: { 
+		enumerable: true, 
+		configurable: true, 
+		get: function() { return this.createVertexProxies(); }
+	},
+	faces: {
+		enumerable: true,	
+		get: function() { return this.createFaceProxies() } 
+	},
+	faceVertexUvs: {
+		enumerable: true,	
+		get: function() { return this.createUvProxies() } 
+	},
+	colors: {
+		enumerable: true,	
+		get: function() { return this.createColorProxies() } 
+	},
+	skinIndices: {
+		enumerable: true,	
+		get: function() { return this.createSkinIndexProxies() } 
+	},
+	skinWeights: {
+		enumerable: true,	
+		get: function() { return this.createSkinWeightProxies() } 
+	},
+	// TODO - fill in additional proxies:
+	// - morphColors
+	// - morphNormals
+	// - morphTargets
+
+	verticesNeedUpdate: {
+		enumerable: true,	
+		get: function() { if (this.attributes[ 'position' ]) return this.attributes[ 'position' ].needsUpdate; } ,
+		set: function(v) { if (this.attributes[ 'position' ]) this.attributes[ 'position' ].needsUpdate = v; } 
+	},
+	colorsNeedUpdate: {
+		enumerable: true,	
+		get: function() { if (this.attributes[ 'color' ]) return this.attributes[ 'color' ].needsUpdate; } ,
+		set: function(v) { if (this.attributes[ 'color' ]) this.attributes[ 'color' ].needsUpdate = v; } 
+	},
+	normalsNeedUpdate: {
+		enumerable: true,	
+		get: function() { if (this.attributes[ 'normal' ]) return this.attributes[ 'normal' ].needsUpdate; } ,
+		set: function(v) { if (this.attributes[ 'normal' ]) this.attributes[ 'normal' ].needsUpdate = v; } 
+	},
+});
 
 
-	this.lineDistances = [];
+THREE.Geometry.prototype.createVertexProxies = function(values) {
 
 
-	this.boundingBox = null;
-	this.boundingSphere = null;
+	if (!this.hasOwnProperty('vertices')) {
 
 
-	this.hasTangents = false;
+		// Replace the prototype getter with a local array property
 
 
-	this.dynamic = true; // the intermediate typed arrays will be deleted when set to false
+		Object.defineProperty( this, "vertices", { value: [], writable: true } );
 
 
-	// update flags
+	} else {
 
 
-	this.verticesNeedUpdate = false;
-	this.elementsNeedUpdate = false;
-	this.uvsNeedUpdate = false;
-	this.normalsNeedUpdate = false;
-	this.tangentsNeedUpdate = false;
-	this.colorsNeedUpdate = false;
-	this.lineDistancesNeedUpdate = false;
+		// Start with a new, empty array
 
 
-	this.buffersNeedUpdate = false;
+		this.vertices = [];
 
 
-};
+	}
 
 
-THREE.Geometry.prototype = {
+	// If the attribute buffer has already been populated, set up proxy objects
 
 
-	constructor: THREE.Geometry,
+	this.populateProxyFromBuffer(this.vertices, "position", THREE.TypedVector3, 3);
 
 
-	applyMatrix: function ( matrix ) {
+	// If values were passed in, store them in the buffer via the proxy objects
 
 
-		var normalMatrix = new THREE.Matrix3().getNormalMatrix( matrix );
+	if (values) {
 
 
-		for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
+		for (var i = 0; i < values.length; i++) {
 
 
-			var vertex = this.vertices[ i ];
-			vertex.applyMatrix4( matrix );
+			this.vertices[i].copy(values[i]);
 
 
 		}
 		}
+	}
 
 
-		for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
+	// Return a reference to the newly-created array
 
 
-			var face = this.faces[ i ];
-			face.normal.applyMatrix3( normalMatrix ).normalize();
+	return this.vertices;
 
 
-			for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
+}
 
 
-				face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize();
+THREE.Geometry.prototype.createFaceProxies = function(values) {
 
 
-			}
+	if (!this.hasOwnProperty("faces")) {
 
 
-		}
+		// Replace the prototype getter with a local array property
 
 
-		if ( this.boundingBox instanceof THREE.Box3 ) {
+		Object.defineProperty( this, "faces", { value: [], writable: true } );
 
 
-			this.computeBoundingBox();
+	} else {
 
 
-		}
+		// Start with a new, empty array
 
 
-		if ( this.boundingSphere instanceof THREE.Sphere ) {
+		this.faces = [];
+	}
 
 
-			this.computeBoundingSphere();
+	// If the attribute buffer has already been populated, set up proxy objects
 
 
-		}
+	var faces = this.faces,
+			indexarray = false,
+			positionarray = false,
+			normalarray = false,
+			colorarray = false,
+			tangentarray = false;
 
 
-	},
+	if ( this.attributes[ 'index' ] ) {
+		indexarray = this.attributes[ 'index' ].array;
+	}
+	if ( this.attributes[ 'position' ] ) {
+		positionarray = this.attributes[ 'position' ].array;
+	}
+	if (this.attributes[ 'normal' ]) {
+		normalarray = this.attributes[ 'normal' ].array;
+	}
+	if (this.attributes[ 'color' ]) {
+		colorarray = this.attributes[ 'color' ].array;
+	}
+	if (this.attributes[ 'tangent' ]) {
+		tangentarray = this.attributes[ 'tangent' ].array;
+	}
 
 
-	computeFaceNormals: function () {
+	// TODO - this should be accomplished using "virtual" functions on various classes (IndexedGeometry, SmoothGeometry, etc)
 
 
-		var cb = new THREE.Vector3(), ab = new THREE.Vector3();
+	if (indexarray) {
 
 
-		for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) {
+		for ( var i = 0, l = indexarray.length / 3; i < l; i ++ ) {
 
 
-			var face = this.faces[ f ];
+			var o = i * 3;
 
 
-			var vA = this.vertices[ face.a ];
-			var vB = this.vertices[ face.b ];
-			var vC = this.vertices[ face.c ];
+			var face = new THREE.TypedFace3( indexarray, i * 3 );
+			faces.push(face);
 
 
-			cb.subVectors( vC, vB );
-			ab.subVectors( vA, vB );
-			cb.cross( ab );
+		}
 
 
-			cb.normalize();
+	} else if (positionarray) {
 
 
-			face.normal.copy( cb );
+		for ( var i = 0, l = positionarray.length / 3; i < l; i += 3 ) {
 
 
-		}
+			var o = i * 3;
+			var v1 = i, v2 = i+1, v3 = i+2;
 
 
-	},
+			var face = new THREE.TypedFace3( v1, v2, v3 );
+			faces.push(face);
 
 
-	computeVertexNormals: function ( areaWeighted ) {
+		}
 
 
-		var v, vl, f, fl, face, vertices;
+	}
 
 
-		vertices = new Array( this.vertices.length );
+	// If values were passed in, store them in the buffer via the proxy objects
 
 
-		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
+	if (values) {
 
 
-			vertices[ v ] = new THREE.Vector3();
+		for (var i = 0, l = values.length; i < l; i++) {
 
 
-		}
+			var f = faces[i],
+			    v = values[i];
 
 
-		if ( areaWeighted ) {
+			f.a = v.a;
+			f.b = v.b;
+			f.c = v.c;
 
 
-			// vertex normals weighted by triangle areas
-			// http://www.iquilezles.org/www/articles/normals/normals.htm
+		}
 
 
-			var vA, vB, vC, vD;
-			var cb = new THREE.Vector3(), ab = new THREE.Vector3(),
-				db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();
+	}
 
 
-			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+	if (normalarray) {
 
 
-				face = this.faces[ f ];
+		this.createFaceVertexNormalProxies(values);
 
 
-				vA = this.vertices[ face.a ];
-				vB = this.vertices[ face.b ];
-				vC = this.vertices[ face.c ];
+	}
 
 
-				cb.subVectors( vC, vB );
-				ab.subVectors( vA, vB );
-				cb.cross( ab );
+	if (colorarray) {
 
 
-				vertices[ face.a ].add( cb );
-				vertices[ face.b ].add( cb );
-				vertices[ face.c ].add( cb );
+		this.createFaceVertexColorProxies(values);
 
 
-			}
+	}
 
 
-		} else {
+	if (tangentarray) {
 
 
-			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+		this.createFaceVertexTangentProxies(values);
 
 
-				face = this.faces[ f ];
+	}
 
 
-				vertices[ face.a ].add( face.normal );
-				vertices[ face.b ].add( face.normal );
-				vertices[ face.c ].add( face.normal );
+	// Return a reference to the newly-created array
 
 
-			}
+	return this.faces;
 
 
-		}
+}
 
 
-		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
+THREE.Geometry.prototype.createFaceVertexNormalProxies = function(values) {
 
 
-			vertices[ v ].normalize();
+	if ( this.attributes[ 'normal' ] && this.attributes[ 'normal' ].array ) {
 
 
-		}
+		var normalarray = this.attributes[ 'normal' ].array;
 
 
-		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+		for (var i = 0, l = this.faces.length; i < l; i++) {
 
 
-			face = this.faces[ f ];
+			var f = this.faces[i];
 
 
-			face.vertexNormals[ 0 ] = vertices[ face.a ].clone();
-			face.vertexNormals[ 1 ] = vertices[ face.b ].clone();
-			face.vertexNormals[ 2 ] = vertices[ face.c ].clone();
+			f.vertexNormals = [
+				new THREE.TypedVector3(normalarray, f.a * 3),
+				new THREE.TypedVector3(normalarray, f.b * 3),
+				new THREE.TypedVector3(normalarray, f.c * 3),
+			];
+			f.normal = new THREE.MultiVector3(f.vertexNormals);
 
 
 		}
 		}
+	}
 
 
-	},
+	// If values were passed in, store them in the buffer via the proxy objects
 
 
-	computeMorphNormals: function () {
+	if (values) {
 
 
-		var i, il, f, fl, face;
+		for (var i = 0, l = values.length; i < l; i++) {
 
 
-		// save original normals
-		// - create temp variables on first access
-		//   otherwise just copy (for faster repeated calls)
+			var f = this.faces[i],
+			    v = values[i];
 
 
-		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+			if (v.vertexNormals.length > 0) {
 
 
-			face = this.faces[ f ];
+				for (var j = 0, l2 = f.vertexNormals.length; j < l2; j++) {
 
 
-			if ( ! face.__originalFaceNormal ) {
+					f.vertexNormals[j].copy(v.vertexNormals[j]);
 
 
-				face.__originalFaceNormal = face.normal.clone();
+				}
 
 
-			} else {
+			} else if (v.normal) {
 
 
-				face.__originalFaceNormal.copy( face.normal );
+				f.normal.copy(v.normal);
 
 
 			}
 			}
 
 
-			if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
+		}
 
 
-			for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
+	}
 
 
-				if ( ! face.__originalVertexNormals[ i ] ) {
+}
 
 
-					face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
+THREE.Geometry.prototype.createFaceVertexColorProxies = function(values) {
 
 
-				} else {
+	if ( this.attributes[ 'color' ] && this.attributes[ 'color' ].array ) {
 
 
-					face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
+		var colorarray = this.attributes[ 'color' ].array;
 
 
-				}
+		for (var i = 0, l = this.faces.length; i < l; i++) {
+			var f = this.faces[i];
 
 
+			if ( this.attributes[ 'index' ] ) {
+				f.vertexColors = [
+						new THREE.TypedColor(colorarray, f.a * 3),
+						new THREE.TypedColor(colorarray, f.b * 3),
+						new THREE.TypedColor(colorarray, f.c * 3),
+					];
+			} else {
+				var o = i * 9;
+
+				f.vertexColors = [
+						new THREE.TypedColor(colorarray, o),
+						new THREE.TypedColor(colorarray, o + 3),
+						new THREE.TypedColor(colorarray, o + 6),
+					];
 			}
 			}
+			f.color = new THREE.MultiColor(f.vertexColors);
 
 
 		}
 		}
+	}
 
 
-		// use temp geometry to compute face and vertex normals for each morph
-
-		var tmpGeo = new THREE.Geometry();
-		tmpGeo.faces = this.faces;
-
-		for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
-
-			// create on first access
+	// If values were passed in, store them in the buffer via the proxy objects
 
 
-			if ( ! this.morphNormals[ i ] ) {
+	if (values) {
 
 
-				this.morphNormals[ i ] = {};
-				this.morphNormals[ i ].faceNormals = [];
-				this.morphNormals[ i ].vertexNormals = [];
+		for (var i = 0, l = values.length; i < l; i++) {
 
 
-				var dstNormalsFace = this.morphNormals[ i ].faceNormals;
-				var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
+			var f = this.faces[i],
+			    v = values[i];
 
 
-				var faceNormal, vertexNormals;
+			for (var j = 0, l2 = f.vertexColors.length; j < l2; j++) {
 
 
-				for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+				if (v.vertexColors.length > 0) {
 
 
-					face = this.faces[ f ];
+					f.vertexColors[j].copy(v.vertexColors[j]);
 
 
-					faceNormal = new THREE.Vector3();
-					vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
+				} else if (v.color) {
 
 
-					dstNormalsFace.push( faceNormal );
-					dstNormalsVertex.push( vertexNormals );
+					f.color.copy(v.color);
 
 
 				}
 				}
 
 
 			}
 			}
 
 
-			var morphNormals = this.morphNormals[ i ];
+		}
 
 
-			// set vertices to morph target
+	}
 
 
-			tmpGeo.vertices = this.morphTargets[ i ].vertices;
+}
 
 
-			// compute morph normals
+THREE.Geometry.prototype.createFaceVertexTangentProxies = function(values) {
 
 
-			tmpGeo.computeFaceNormals();
-			tmpGeo.computeVertexNormals();
+	if ( this.attributes[ 'tangent' ] && this.attributes[ 'tangent' ].array ) {
 
 
-			// store morph normals
+		var tangentarray = this.attributes[ 'tangent' ].array;
 
 
-			var faceNormal, vertexNormals;
+		for (var i = 0, l = this.faces.length; i < l; i++) {
 
 
-			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+			var f = this.faces[i];
 
 
-				face = this.faces[ f ];
+			f.vertexTangents = [
+				new THREE.TypedVector3(tangentarray, f.a * 3),
+				new THREE.TypedVector3(tangentarray, f.b * 3),
+				new THREE.TypedVector3(tangentarray, f.c * 3),
+			];
 
 
-				faceNormal = morphNormals.faceNormals[ f ];
-				vertexNormals = morphNormals.vertexNormals[ f ];
+		}
+	}
 
 
-				faceNormal.copy( face.normal );
+	// If values were passed in, store them in the buffer via the proxy objects
 
 
-				vertexNormals.a.copy( face.vertexNormals[ 0 ] );
-				vertexNormals.b.copy( face.vertexNormals[ 1 ] );
-				vertexNormals.c.copy( face.vertexNormals[ 2 ] );
+	if (values) {
 
 
-			}
+		for (var i = 0, l = values.length; i < l; i++) {
 
 
-		}
+			var f = this.faces[i],
+			    v = values[i];
+
+			if (v.vertexTangents.length > 0) {
 
 
-		// restore original normals
+				for (var j = 0, l2 = f.vertexTangents.length; j < l2; j++) {
 
 
-		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+					f.vertexTangents[j].copy(v.vertexTangents[j]);
 
 
-			face = this.faces[ f ];
+				}
 
 
-			face.normal = face.__originalFaceNormal;
-			face.vertexNormals = face.__originalVertexNormals;
+			}
 
 
 		}
 		}
 
 
-	},
-
-	computeTangents: function () {
+	}
 
 
-		// based on http://www.terathon.com/code/tangent.html
-		// tangents go to vertices
+}
 
 
-		var f, fl, v, vl, i, il, vertexIndex,
-			face, uv, vA, vB, vC, uvA, uvB, uvC,
-			x1, x2, y1, y2, z1, z2,
-			s1, s2, t1, t2, r, t, test,
-			tan1 = [], tan2 = [],
-			sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
-			tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
-			n = new THREE.Vector3(), w;
+THREE.Geometry.prototype.createUvProxies = function(values) {
 
 
-		for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
+	// Replace the prototype getter with a local array property
 
 
-			tan1[ v ] = new THREE.Vector3();
-			tan2[ v ] = new THREE.Vector3();
+	if (!this.hasOwnProperty("faceVertexUvs")) {
+		Object.defineProperty( this, "faceVertexUvs", { value: [[]], writable: true } );
+	} else {
+		this.faceVertexUvs = [[]];
+	}
 
 
-		}
+	// If the attribute buffer has already been populated, set up proxy objects
 
 
-		function handleTriangle( context, a, b, c, ua, ub, uc ) {
+	if ( this.attributes[ 'uv' ] && this.attributes[ 'uv' ].array ) {
 
 
-			vA = context.vertices[ a ];
-			vB = context.vertices[ b ];
-			vC = context.vertices[ c ];
+		var faces = this.faces;
+		var uvarray = this.attributes[ 'uv' ].array;
 
 
-			uvA = uv[ ua ];
-			uvB = uv[ ub ];
-			uvC = uv[ uc ];
+		for (var i = 0, l = faces.length; i < l; i++) {
+			var f = faces[i];
 
 
-			x1 = vB.x - vA.x;
-			x2 = vC.x - vA.x;
-			y1 = vB.y - vA.y;
-			y2 = vC.y - vA.y;
-			z1 = vB.z - vA.z;
-			z2 = vC.z - vA.z;
+			this.faceVertexUvs[0][i] = [];
 
 
-			s1 = uvB.x - uvA.x;
-			s2 = uvC.x - uvA.x;
-			t1 = uvB.y - uvA.y;
-			t2 = uvC.y - uvA.y;
+			if ( this.attributes[ 'index' ] ) {
+				this.faceVertexUvs[0][i][0] = new THREE.TypedVector2(uvarray, f.a * 2);
+				this.faceVertexUvs[0][i][1] = new THREE.TypedVector2(uvarray, f.b * 2);
+				this.faceVertexUvs[0][i][2] = new THREE.TypedVector2(uvarray, f.c * 2);
+			} else {
+				var o = i * 6;
+				this.faceVertexUvs[0][i][0] = new THREE.TypedVector2(uvarray, o);
+				this.faceVertexUvs[0][i][1] = new THREE.TypedVector2(uvarray, o + 2);
+				this.faceVertexUvs[0][i][2] = new THREE.TypedVector2(uvarray, o + 4);
+			}
 
 
-			r = 1.0 / ( s1 * t2 - s2 * t1 );
-			sdir.set( ( t2 * x1 - t1 * x2 ) * r,
-					  ( t2 * y1 - t1 * y2 ) * r,
-					  ( t2 * z1 - t1 * z2 ) * r );
-			tdir.set( ( s1 * x2 - s2 * x1 ) * r,
-					  ( s1 * y2 - s2 * y1 ) * r,
-					  ( s1 * z2 - s2 * z1 ) * r );
+		}
+	
+	}
 
 
-			tan1[ a ].add( sdir );
-			tan1[ b ].add( sdir );
-			tan1[ c ].add( sdir );
+	// If values were passed in, store them in the buffer via the proxy objects
 
 
-			tan2[ a ].add( tdir );
-			tan2[ b ].add( tdir );
-			tan2[ c ].add( tdir );
+	if (values) {
 
 
-		}
+		for (var i = 0, l = values.length; i < l; i++) {
 
 
-		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+			for (var j = 0, l2 = values[i].length; j < l2; j++) {
 
 
-			face = this.faces[ f ];
-			uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
+				var uv = values[i][j];
+				this.faceVertexUvs[0][i][j].copy(uv);
 
 
-			handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
+			}
 
 
 		}
 		}
 
 
-		var faceIndex = [ 'a', 'b', 'c', 'd' ];
+	}
 
 
-		for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+	// Return a reference to the newly-created array
 
 
-			face = this.faces[ f ];
+	return this.faceVertexUvs;
 
 
-			for ( i = 0; i < Math.min( face.vertexNormals.length, 3 ); i++ ) {
+}
 
 
-				n.copy( face.vertexNormals[ i ] );
+THREE.Geometry.prototype.createSkinIndexProxies = function(values) {
 
 
-				vertexIndex = face[ faceIndex[ i ] ];
+	// Replace the prototype getter with a local array property
 
 
-				t = tan1[ vertexIndex ];
+	if (!this.hasOwnProperty('skinIndices')) {
+		Object.defineProperty( this, "skinIndices", { value: [], writable: true } );
+	} else {
+		this.skinIndices = [];
+	}
 
 
-				// Gram-Schmidt orthogonalize
+	// If the attribute buffer has already been populated, set up proxy objects
 
 
-				tmp.copy( t );
-				tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize();
+	this.populateProxyFromBuffer(this.skinIndices, "skinIndex", THREE.TypedVector4, 4);
 
 
-				// Calculate handedness
+	// If values were passed in, store them in the buffer via the proxy objects
 
 
-				tmp2.crossVectors( face.vertexNormals[ i ], t );
-				test = tmp2.dot( tan2[ vertexIndex ] );
-				w = (test < 0.0) ? -1.0 : 1.0;
+	if (values) {
 
 
-				face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
+		for (var i = 0; i < values.length; i++) {
 
 
-			}
+			this.skinIndices[i].copy(values[i]);
 
 
 		}
 		}
 
 
-		this.hasTangents = true;
-
-	},
+	}
 
 
-	computeLineDistances: function ( ) {
+	// Return a reference to the newly-created array
 
 
-		var d = 0;
-		var vertices = this.vertices;
+	return this.skinIndices;
 
 
-		for ( var i = 0, il = vertices.length; i < il; i ++ ) {
+}
 
 
-			if ( i > 0 ) {
+THREE.Geometry.prototype.createSkinWeightProxies = function(values) {
 
 
-				d += vertices[ i ].distanceTo( vertices[ i - 1 ] );
+	// Replace the prototype getter with a local array property
 
 
-			}
+	if (!this.hasOwnProperty('skinWeights')) {
+		Object.defineProperty( this, "skinWeights", { value: [], writable: true } );
+	} else {
+		this.skinWeights = [];
+	}
 
 
-			this.lineDistances[ i ] = d;
+	// If the attribute buffer has already been populated, set up proxy objects
 
 
-		}
+	this.populateProxyFromBuffer(this.skinWeights, "skinWeight", THREE.TypedVector4, 4);
 
 
-	},
+	// If values were passed in, store them in the buffer via the proxy objects
 
 
-	computeBoundingBox: function () {
+	if (values) {
 
 
-		if ( this.boundingBox === null ) {
+		for (var i = 0; i < values.length; i++) {
 
 
-			this.boundingBox = new THREE.Box3();
+			this.skinWeights[i].copy(values[i]);
 
 
 		}
 		}
 
 
-		this.boundingBox.setFromPoints( this.vertices );
+	}
 
 
-	},
+	// Return a reference to the newly-created array
 
 
-	computeBoundingSphere: function () {
+	return this.skinWeights;
 
 
-		if ( this.boundingSphere === null ) {
+}
 
 
-			this.boundingSphere = new THREE.Sphere();
+THREE.Geometry.prototype.createColorProxies = function(values) {
 
 
-		}
+	// Replace the prototype getter with a local array property
 
 
-		this.boundingSphere.setFromPoints( this.vertices );
+	if (!this.hasOwnProperty('colors')) {
+		Object.defineProperty( this, "colors", { value: [], writable: true } );
+	} else {
+		this.colors = [];
+	}
 
 
-	},
+	// If the attribute buffer has already been populated, set up proxy objects
 
 
-	/*
-	 * Checks for duplicate vertices with hashmap.
-	 * Duplicated vertices are removed
-	 * and faces' vertices are updated.
-	 */
+	this.populateProxyFromBuffer(this.colors, "color", THREE.TypedColor, 3);
 
 
-	mergeVertices: function () {
+	// If values were passed in, store them in the buffer via the proxy objects
 
 
-		var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
-		var unique = [], changes = [];
+	if (values) {
 
 
-		var v, key;
-		var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
-		var precision = Math.pow( 10, precisionPoints );
-		var i,il, face;
-		var indices, k, j, jl, u;
+		for (var i = 0; i < values.length; i++) {
 
 
-		for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
+			this.colors[i].copy(values[i]);
 
 
-			v = this.vertices[ i ];
-			key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
+		}
 
 
-			if ( verticesMap[ key ] === undefined ) {
+	}
 
 
-				verticesMap[ key ] = i;
-				unique.push( this.vertices[ i ] );
-				changes[ i ] = unique.length - 1;
+	// Return a reference to the newly-created array
 
 
-			} else {
+	return this.colors;
 
 
-				//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
-				changes[ i ] = changes[ verticesMap[ key ] ];
+}
 
 
-			}
+THREE.Geometry.prototype.populateProxyFromBuffer = function(attr, buffername, proxytype, itemsize, offset, count) {
 
 
-		};
+	if ( this.attributes[ buffername ] && this.attributes[ buffername ].array ) {
 
 
+		var array = this.attributes[ buffername ].array;
+		var size = itemsize || this.attributes[ buffername ].itemSize;
+		var start = offset || 0;
+		var count = count || (array.length / size - start);
 
 
-		// if faces are completely degenerate after merging vertices, we
-		// have to remove them from the geometry.
-		var faceIndicesToRemove = [];
+		for ( var i = start, l = start + count; i < l; i ++ ) {
 
 
-		for( i = 0, il = this.faces.length; i < il; i ++ ) {
+			attr.push( new proxytype( array, i * size ) );
 
 
-			face = this.faces[ i ];
+		}
 
 
-			face.a = changes[ face.a ];
-			face.b = changes[ face.b ];
-			face.c = changes[ face.c ];
+	}
 
 
-			indices = [ face.a, face.b, face.c ];
+}
 
 
-			var dupIndex = -1;
+/*
+ * Checks for duplicate vertices with hashmap.
+ * Duplicated vertices are removed
+ * and faces' vertices are updated.
+ */
 
 
-			// if any duplicate vertices are found in a Face3
-			// we have to remove the face as nothing can be saved
-			for ( var n = 0; n < 3; n ++ ) {
-				if ( indices[ n ] == indices[ ( n + 1 ) % 3 ] ) {
+THREE.Geometry.prototype.mergeVertices = function () {
 
 
-					dupIndex = n;
-					faceIndicesToRemove.push( i );
-					break;
+	var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
+	var unique = [], changes = [];
 
 
-				}
-			}
+	var v, key;
+	var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
+	var precision = Math.pow( 10, precisionPoints );
+	var i,il, face;
+	var indices, k, j, jl, u;
 
 
-		}
+	for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
 
 
-		for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
-			var idx = faceIndicesToRemove[ i ];
+		v = this.vertices[ i ];
+		key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision );
 
 
-			this.faces.splice( idx, 1 );
+		if ( verticesMap[ key ] === undefined ) {
 
 
-			for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
+			verticesMap[ key ] = i;
+			unique.push( this.vertices[ i ] );
+			changes[ i ] = unique.length - 1;
 
 
-				this.faceVertexUvs[ j ].splice( idx, 1 );
+		} else {
 
 
-			}
+			//console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
+			changes[ i ] = changes[ verticesMap[ key ] ];
 
 
 		}
 		}
 
 
-		// Use unique set of vertices
+	};
 
 
-		var diff = this.vertices.length - unique.length;
-		this.vertices = unique;
-		return diff;
 
 
-	},
+	// if faces are completely degenerate after merging vertices, we
+	// have to remove them from the geometry.
+	var faceIndicesToRemove = [];
 
 
-	// Geometry splitting
+	for( i = 0, il = this.faces.length; i < il; i ++ ) {
 
 
-	makeGroups: ( function () {
+		face = this.faces[ i ];
 
 
-		var geometryGroupCounter = 0;
-		
-		return function ( usesFaceMaterial, maxVerticesInGroup ) {
+		face.a = changes[ face.a ];
+		face.b = changes[ face.b ];
+		face.c = changes[ face.c ];
 
 
-			var f, fl, face, materialIndex,
-				groupHash, hash_map = {};
+		indices = [ face.a, face.b, face.c ];
 
 
-			var numMorphTargets = this.morphTargets.length;
-			var numMorphNormals = this.morphNormals.length;
+		var dupIndex = -1;
 
 
-			this.geometryGroups = {};
+		// if any duplicate vertices are found in a Face3
+		// we have to remove the face as nothing can be saved
+		for ( var n = 0; n < 3; n ++ ) {
+			if ( indices[ n ] == indices[ ( n + 1 ) % 3 ] ) {
 
 
-			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
+				dupIndex = n;
+				faceIndicesToRemove.push( i );
+				break;
 
 
-				face = this.faces[ f ];
-				materialIndex = usesFaceMaterial ? face.materialIndex : 0;
+			}
+		}
 
 
-				if ( ! ( materialIndex in hash_map ) ) {
+	}
 
 
-					hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };
+	for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) {
+		var idx = faceIndicesToRemove[ i ];
 
 
-				}
+		this.faces.splice( idx, 1 );
 
 
-				groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
+		for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
 
 
-				if ( ! ( groupHash in this.geometryGroups ) ) {
+			this.faceVertexUvs[ j ].splice( idx, 1 );
 
 
-					this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
+		}
 
 
-				}
+	}
 
 
-				if ( this.geometryGroups[ groupHash ].vertices + 3 > maxVerticesInGroup ) {
+	// Use unique set of vertices
 
 
-					hash_map[ materialIndex ].counter += 1;
-					groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
+	var diff = this.vertices.length - unique.length;
+	this.vertices = unique;
+	return diff;
 
 
-					if ( ! ( groupHash in this.geometryGroups ) ) {
+}
 
 
-						this.geometryGroups[ groupHash ] = { 'faces3': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
+THREE.Geometry.prototype.onGeometryAllocate = function (ev) {
 
 
-					}
+	// Prevent allocate event listener from firing multiple times
+	this.removeEventListener( 'allocate', this.onGeometryAllocate);
 
 
-				}
+	if (this.hasOwnProperty('vertices')) {
+		var attr = new THREE.Float32Attribute(this.vertices.length, 3);
+		this.addAttribute('position', attr);
+		this.createVertexProxies(this.vertices);
+	}
+	if (this.hasOwnProperty('faces')) {
+		var idxattr = new THREE.Uint16Attribute(this.faces.length, 3);
+		this.addAttribute('index', idxattr);
+
+		if (this.faces.length > 0) {
+			var hasnormals = (this.hasOwnProperty('normals') || this.faces[0].normal || this.faces[0].vertexNormals.length > 0);
+			    hascolors = (this.hasOwnProperty('colors') || this.faces[0].color || this.faces[0].vertexColors.length > 0),
+			    hastangents = (this.faces[0].vertexTangents.length > 0);
+
+			if (hasnormals) {
+				var normalattr = new THREE.Float32Attribute(this.vertices.length, 3);
+				this.addAttribute('normal', normalattr);
+			}
 
 
-				this.geometryGroups[ groupHash ].faces3.push( f );
-				this.geometryGroups[ groupHash ].vertices += 3;
+			if (hascolors) {
+				var colorattr = new THREE.Float32Attribute(this.faces.length * 3, 3);
+				this.addAttribute('color', colorattr);
+			}
 
 
+			if (hastangents) {
+				var tangentattr = new THREE.Float32Attribute(this.faces.length * 3, 3);
+				this.addAttribute('tangent', tangentattr);
 			}
 			}
+		}
+
+		this.createFaceProxies(this.faces);
+	}
 
 
-			this.geometryGroupsList = [];
+	if (this.hasOwnProperty('faceVertexUvs')) {
 
 
-			for ( var g in this.geometryGroups ) {
+		var uvattr = new THREE.Float32Attribute(this.faces.length * 3, 2);
+		this.addAttribute('uv', uvattr);
+		this.createUvProxies(this.faceVertexUvs[0]);
 
 
-				this.geometryGroups[ g ].id = geometryGroupCounter ++;
+	}
 
 
-				this.geometryGroupsList.push( this.geometryGroups[ g ] );
+	if (this.hasOwnProperty('skinIndices')) {
 
 
-			}
+		var skinidxattr = new THREE.Float32Attribute(this.skinIndices.length, 4);
+		this.addAttribute('skinIndex', skinidxattr);
+		this.createSkinIndexProxies(this.skinIndices);
 
 
-		};
-		
-	} )(),
+	}
 
 
-	clone: function () {
+	if (this.hasOwnProperty('skinWeights')) {
 
 
-		var geometry = new THREE.Geometry();
+		var skinweightattr = new THREE.Float32Attribute(this.skinWeights.length, 4);
+		this.addAttribute('skinWeight', skinweightattr);
+		this.createSkinWeightProxies(this.skinWeights);
 
 
-		var vertices = this.vertices;
+	}
+}
 
 
-		for ( var i = 0, il = vertices.length; i < il; i ++ ) {
+THREE.Geometry.prototype.computeFaceNormals = function() {
 
 
-			geometry.vertices.push( vertices[ i ].clone() );
+	this.dispatchEvent( { type: 'allocate' } );
 
 
-		}
+	return THREE.BufferGeometry.prototype.computeFaceNormals.call(this);
 
 
-		var faces = this.faces;
+}
 
 
-		for ( var i = 0, il = faces.length; i < il; i ++ ) {
+THREE.Geometry.prototype.computeVertexNormals = function() {
 
 
-			geometry.faces.push( faces[ i ].clone() );
+	this.dispatchEvent( { type: 'allocate' } );
 
 
-		}
+	return THREE.BufferGeometry.prototype.computeVertexNormals.call(this);
 
 
-		var uvs = this.faceVertexUvs[ 0 ];
+}
 
 
-		for ( var i = 0, il = uvs.length; i < il; i ++ ) {
+THREE.Geometry.prototype.computeTangents = function() {
 
 
-			var uv = uvs[ i ], uvCopy = [];
+	this.dispatchEvent( { type: 'allocate' } );
 
 
-			for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
+	var ret = THREE.BufferGeometry.prototype.computeTangents.call(this);
 
 
-				uvCopy.push( new THREE.Vector2( uv[ j ].x, uv[ j ].y ) );
+	// FIXME - this doesn't work yet
+	//this.createFaceVertexTangentProxies();
 
 
-			}
+	return ret;
 
 
-			geometry.faceVertexUvs[ 0 ].push( uvCopy );
+}
 
 
-		}
+THREE.Geometry.prototype.computeBoundingSphere = function() {
 
 
-		return geometry;
+	this.dispatchEvent( { type: 'allocate' } );
 
 
-	},
+	return THREE.BufferGeometry.prototype.computeBoundingSphere.call(this);
 
 
-	dispose: function () {
+}
 
 
-		this.dispatchEvent( { type: 'dispose' } );
+THREE.Geometry.prototype.computeBoundingBox = function () {
 
 
-	}
+	this.dispatchEvent( { type: 'allocate' } );
 
 
-};
+	return THREE.BufferGeometry.prototype.computeBoundingBox.call(this);
+
+}
+THREE.Geometry.prototype.clone = function () {
+
+	var buff = THREE.BufferGeometry.prototype.clone.call(this);
+	var geo = new THREE.Geometry();
+	geo.attributes = buff.attributes;
+	geo.offsets = buff.offsets;
+
+	return geo;
+
+}
 
 
 THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
 THREE.EventDispatcher.prototype.apply( THREE.Geometry.prototype );
 
 

+ 1 - 1
src/core/IndexedGeometry2.js

@@ -13,4 +13,4 @@ THREE.IndexedGeometry2 = function ( indices, vertices, normals, uvs ) {
 
 
 };
 };
 
 
-THREE.IndexedGeometry2.prototype = Object.create( THREE.Geometry99.prototype );
+THREE.IndexedGeometry2.prototype = Object.create( THREE.BufferGeometry.prototype );

+ 39 - 0
src/core/TypedFace3.js

@@ -0,0 +1,39 @@
+/**
+ * @author jbaicoianu / http://baicoianu.com/
+ */
+
+THREE.TypedFace3 = function ( array, offset, vertexNormals, vertexColors, vertexTangents ) {
+
+	this.array = array;
+	this.offset = offset;
+	this.vertexNormals = vertexNormals || [];
+	this.vertexColors = vertexColors || [];
+	this.vertexTangents = vertexTangents || [];
+
+	this.normal = new THREE.MultiVector3( this.vertexNormals );
+	this.color = new THREE.MultiColor( this.vertexColors );
+
+	//THREE.Face3.call( this, array[offset], array[offset+1], array[offset+2] /*, normal, color, materialIndex */);
+
+}
+
+THREE.TypedFace3.prototype = Object.create( THREE.Face3.prototype );
+
+Object.defineProperties( THREE.TypedFace3.prototype, {
+	'a': {
+		enumerable: true,	
+		get: function () { return this.array[ this.offset ]; },
+		set: function ( v ) { this.array[ this.offset ] = v; }
+	},
+	'b': {
+		enumerable: true,	
+		get: function () { return this.array[ this.offset + 1 ]; },
+		set: function ( v ) { this.array[ this.offset + 1 ] = v; }
+	},
+	'c': {
+		enumerable: true,	
+		get: function () { return this.array[ this.offset + 2 ]; },
+		set: function ( v ) { this.array[ this.offset + 2 ] = v; }
+	},
+} );
+

+ 2 - 1
src/extras/geometries/PlaneGeometry.js

@@ -81,8 +81,9 @@ THREE.PlaneGeometry = function ( width, height, widthSegments, heightSegments )
 
 
 	}
 	}
 
 
+	THREE.Geometry.call( this );
 	THREE.IndexedGeometry2.call( this, indices, vertices, normals, uvs );
 	THREE.IndexedGeometry2.call( this, indices, vertices, normals, uvs );
 
 
 };
 };
 
 
-THREE.PlaneGeometry.prototype = Object.create( THREE.IndexedGeometry2.prototype );
+THREE.PlaneGeometry.prototype = Object.create( THREE.Geometry.prototype );

+ 38 - 0
src/math/MultiColor.js

@@ -0,0 +1,38 @@
+// Allows updating of multiple THREE.Color objects with the same value
+// Used for face.color -> face.vertexColor[] compatibility layer for non-indexed geometry
+
+THREE.MultiColor = function(links) {
+
+	this.links = links;
+
+}
+
+THREE.MultiColor.prototype = Object.create( THREE.Color.prototype );
+
+THREE.MultiColor.prototype.setAll = function(axis, value) {
+
+	for (var i = 0, l = this.links.length; i < l; i++) {
+
+		this.links[i][axis] = value;
+
+	}
+
+}
+
+// Getters return value from the first linked color
+// Setters set the same value for all linked colors
+Object.defineProperties( THREE.MultiColor.prototype, {
+	'r': {
+		get: function () { return (this.links[0] ? this.links[0].r : 0); },
+		set: function ( v ) { this.setAll('r', v); }
+	},
+	'g': {
+		get: function () { return (this.links[0] ? this.links[0].g : 0); },
+		set: function ( v ) { this.setAll('g', v); }
+	},
+	'b': {
+		get: function () { return (this.links[0] ? this.links[0].b : 0); },
+		set: function ( v ) { this.setAll('b', v); }
+	}
+} );
+

+ 39 - 0
src/math/MultiVector3.js

@@ -0,0 +1,39 @@
+// Allows updating of multiple THREE.Vector3 objects with the same value
+// Used for face.normal -> face.vertexNormal[] compatibility layer for FlatShading
+
+THREE.MultiVector3 = function(links) {
+
+	this.links = links;
+
+}
+
+THREE.MultiVector3.prototype = Object.create( THREE.Vector3.prototype );
+
+THREE.MultiVector3.prototype.setAll = function(axis, value) {
+
+	for (var i = 0, l = this.links.length; i < l; i++) {
+
+		this.links[i][axis] = value;
+
+	}
+
+}
+
+// Getters return value from the first linked vector
+// Setters set the same value for all linked vectors
+Object.defineProperties( THREE.MultiVector3.prototype, {
+	'x': {
+		get: function () { return (this.links[0] ? this.links[0].x : 0); },
+		set: function ( v ) { this.setAll('x', v); }
+	},
+	'y': {
+		get: function () { return (this.links[0] ? this.links[0].y : 0); },
+		set: function ( v ) { this.setAll('y', v); }
+	},
+	'z': {
+		get: function () { return (this.links[0] ? this.links[0].z : 0); },
+		set: function ( v ) { this.setAll('z', v); }
+	}
+} );
+
+

+ 32 - 0
src/math/TypedColor.js

@@ -0,0 +1,32 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author jbaicoianu / http://baicoianu.com/
+ */
+
+THREE.TypedColor = function ( array, offset ) {
+
+	this.array = array;
+	this.offset = offset;
+
+}
+
+THREE.TypedColor.prototype = Object.create( THREE.Color.prototype );
+
+Object.defineProperties( THREE.TypedColor.prototype, {
+	'r': {
+		enumerable: true,	
+		get: function () { return this.array[ this.offset ]; },
+		set: function ( v ) { this.array[ this.offset ] = v; }
+	},
+	'g': {
+		enumerable: true,	
+		get: function () { return this.array[ this.offset + 1 ]; },
+		set: function ( v ) { this.array[ this.offset + 1 ] = v; }
+	},
+	'b': {
+		enumerable: true,	
+		get: function () { return this.array[ this.offset + 2 ]; },
+		set: function ( v ) { this.array[ this.offset + 2 ] = v; }
+	}
+} );
+

+ 33 - 0
src/math/TypedVector4.js

@@ -0,0 +1,33 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author jbaicoianu / http://baicoianu.com/
+ */
+
+THREE.TypedVector4 = function ( array, offset ) {
+	
+	this.array = array;
+	this.offset = offset;
+
+};
+
+THREE.TypedVector4.prototype = Object.create( THREE.Vector4.prototype );
+
+Object.defineProperties( THREE.TypedVector4.prototype, {
+	'x': {
+		get: function () { return this.array[ this.offset ]; },
+		set: function ( v ) { this.array[ this.offset ] = v; }
+	},
+	'y': {
+		get: function () { return this.array[ this.offset + 1 ]; },
+		set: function ( v ) { this.array[ this.offset + 1 ] = v; }
+	},
+	'z': {
+		get: function () { return this.array[ this.offset + 2 ]; },
+		set: function ( v ) { this.array[ this.offset + 2 ] = v; }
+	},
+	'w': {
+		get: function () { return this.array[ this.offset + 3 ]; },
+		set: function ( v ) { this.array[ this.offset + 3 ] = v; }
+	},
+} );
+

+ 3 - 121
src/renderers/WebGLRenderer.js

@@ -615,41 +615,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		} else {
 		} else {
 
 
-			if ( geometry.geometryGroups !== undefined ) {
-
-				for ( var g in geometry.geometryGroups ) {
-
-					var geometryGroup = geometry.geometryGroups[ g ];
-
-					if ( geometryGroup.numMorphTargets !== undefined ) {
-
-						for ( var m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
-
-							_gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
-
-						}
-
-					}
-
-					if ( geometryGroup.numMorphNormals !== undefined ) {
-
-						for ( var m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
-
-							_gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
-
-						}
-
-					}
-
-					deleteBuffers( geometryGroup );
-
-				}
-
-			} else {
-
-				deleteBuffers( geometry );
-
-			}
+			deleteBuffers( geometry );
 
 
 		}
 		}
 
 
@@ -2527,7 +2493,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 					enableAttribute( attributePointer );
 					enableAttribute( attributePointer );
 					_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, startIndex * attributeSize * 4 ); // 4 bytes per Float32
 					_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, startIndex * attributeSize * 4 ); // 4 bytes per Float32
 
 
-				} else if ( material.defaultAttributeValues ) {
+				} else if ( material.defaultAttributeValues && material.defaultAttributeValues[ attributeName ] ) {
 
 
 					if ( material.defaultAttributeValues[ attributeName ].length === 2 ) {
 					if ( material.defaultAttributeValues[ attributeName ].length === 2 ) {
 
 
@@ -3707,46 +3673,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 				geometry.__webglInit = true;
 				geometry.__webglInit = true;
 				geometry.addEventListener( 'dispose', onGeometryDispose );
 				geometry.addEventListener( 'dispose', onGeometryDispose );
+				geometry.dispatchEvent( { type: 'allocate' } );
 
 
 				if ( geometry instanceof THREE.BufferGeometry ) {
 				if ( geometry instanceof THREE.BufferGeometry ) {
 
 
 					initDirectBuffers( geometry );
 					initDirectBuffers( geometry );
 
 
-				} else if ( object instanceof THREE.Mesh ) {
-
-					material = object.material;
-
-					if ( geometry.geometryGroups === undefined ) {
-
-						geometry.makeGroups( material instanceof THREE.MeshFaceMaterial, _glExtensionElementIndexUint ? 4294967296 : 65535  );
-
-					}
-
-					// create separate VBOs per geometry chunk
-
-					for ( g in geometry.geometryGroups ) {
-
-						geometryGroup = geometry.geometryGroups[ g ];
-
-						// initialise VBO on the first access
-
-						if ( ! geometryGroup.__webglVertexBuffer ) {
-
-							createMeshBuffers( geometryGroup );
-							initMeshBuffers( geometryGroup, object );
-
-							geometry.verticesNeedUpdate = true;
-							geometry.morphTargetsNeedUpdate = true;
-							geometry.elementsNeedUpdate = true;
-							geometry.uvsNeedUpdate = true;
-							geometry.normalsNeedUpdate = true;
-							geometry.tangentsNeedUpdate = true;
-							geometry.colorsNeedUpdate = true;
-
-						}
-
-					}
-
 				} else if ( object instanceof THREE.Line ) {
 				} else if ( object instanceof THREE.Line ) {
 
 
 					if ( ! geometry.__webglVertexBuffer ) {
 					if ( ! geometry.__webglVertexBuffer ) {
@@ -3788,16 +3720,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 					addBuffer( scene.__webglObjects, geometry, object );
 					addBuffer( scene.__webglObjects, geometry, object );
 
 
-				} else if ( geometry instanceof THREE.Geometry ) {
-
-					for ( g in geometry.geometryGroups ) {
-
-						geometryGroup = geometry.geometryGroups[ g ];
-
-						addBuffer( scene.__webglObjects, geometryGroup, object );
-
-					}
-
 				}
 				}
 
 
 			} else if ( object instanceof THREE.Line ||
 			} else if ( object instanceof THREE.Line ||
@@ -3866,46 +3788,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			setDirectBuffers( geometry, _gl.DYNAMIC_DRAW );
 			setDirectBuffers( geometry, _gl.DYNAMIC_DRAW );
 
 
-		} else if ( object instanceof THREE.Mesh ) {
-
-			// check all geometry groups
-
-			for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
-
-				geometryGroup = geometry.geometryGroupsList[ i ];
-
-				material = getBufferMaterial( object, geometryGroup );
-
-				if ( geometry.buffersNeedUpdate ) {
-
-					initMeshBuffers( geometryGroup, object );
-
-				}
-
-				customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
-
-				if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate ||
-					 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
-					 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) {
-
-					setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic, material );
-
-				}
-
-			}
-
-			geometry.verticesNeedUpdate = false;
-			geometry.morphTargetsNeedUpdate = false;
-			geometry.elementsNeedUpdate = false;
-			geometry.uvsNeedUpdate = false;
-			geometry.normalsNeedUpdate = false;
-			geometry.colorsNeedUpdate = false;
-			geometry.tangentsNeedUpdate = false;
-
-			geometry.buffersNeedUpdate = false;
-
-			material.attributes && clearCustomAttributes( material );
-
 		} else if ( object instanceof THREE.Line ) {
 		} else if ( object instanceof THREE.Line ) {
 
 
 			material = getBufferMaterial( object, geometry );
 			material = getBufferMaterial( object, geometry );

+ 9 - 2
utils/build/includes/common.json

@@ -5,6 +5,12 @@
 	"src/math/Vector2.js",
 	"src/math/Vector2.js",
 	"src/math/Vector3.js",
 	"src/math/Vector3.js",
 	"src/math/Vector4.js",
 	"src/math/Vector4.js",
+	"src/math/TypedColor.js",
+	"src/math/TypedVector2.js",
+	"src/math/TypedVector3.js",
+	"src/math/TypedVector4.js",
+	"src/math/MultiColor.js",
+	"src/math/MultiVector3.js",
 	"src/math/Euler.js",
 	"src/math/Euler.js",
 	"src/math/Line3.js",
 	"src/math/Line3.js",
 	"src/math/Box2.js",
 	"src/math/Box2.js",
@@ -19,6 +25,7 @@
 	"src/math/Spline.js",
 	"src/math/Spline.js",
 	"src/math/Triangle.js",
 	"src/math/Triangle.js",
 	"src/math/Vertex.js",
 	"src/math/Vertex.js",
+	"src/math/UV.js",
 	"src/core/Clock.js",
 	"src/core/Clock.js",
 	"src/core/EventDispatcher.js",
 	"src/core/EventDispatcher.js",
 	"src/core/Raycaster.js",
 	"src/core/Raycaster.js",
@@ -26,13 +33,13 @@
 	"src/core/Projector.js",
 	"src/core/Projector.js",
 	"src/core/Face3.js",
 	"src/core/Face3.js",
 	"src/core/Face4.js",
 	"src/core/Face4.js",
+	"src/core/TypedFace3.js",
 	"src/core/BufferAttribute.js",
 	"src/core/BufferAttribute.js",
 	"src/core/BufferGeometry.js",
 	"src/core/BufferGeometry.js",
 	"src/core/BufferGeometryManipulator.js",
 	"src/core/BufferGeometryManipulator.js",
-	"src/core/Geometry.js",
 	"src/core/Geometry2.js",
 	"src/core/Geometry2.js",
-	"src/core/Geometry99.js",
 	"src/core/IndexedGeometry2.js",
 	"src/core/IndexedGeometry2.js",
+	"src/core/Geometry.js",
 	"src/cameras/Camera.js",
 	"src/cameras/Camera.js",
 	"src/cameras/OrthographicCamera.js",
 	"src/cameras/OrthographicCamera.js",
 	"src/cameras/PerspectiveCamera.js",
 	"src/cameras/PerspectiveCamera.js",